Skip to content

Commit e2fabac

Browse files
author
pavlo
committed
feature/appcheck/unit-test
1 parent bc8360f commit e2fabac

24 files changed

+1159
-105
lines changed

FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAdmin.IntegrationTests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp2.1</TargetFramework>
4+
<TargetFramework>net7.0</TargetFramework>
55
<LangVersion>latest</LangVersion>
66
<IsPackable>false</IsPackable>
77
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -30,4 +30,4 @@
3030
</None>
3131
</ItemGroup>
3232

33-
</Project>
33+
</Project>

FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseAdmin.Snippets.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp2.1</TargetFramework>
4+
<TargetFramework>net7.0</TargetFramework>
55
<IsPackable>false</IsPackable>
66
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
77
<CodeAnalysisRuleSet>../../stylecop_test.ruleset</CodeAnalysisRuleSet>
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using FirebaseAdmin.Check;
7+
using Google.Apis.Auth.OAuth2;
8+
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
9+
using Moq;
10+
using Xunit;
11+
12+
namespace FirebaseAdmin.Tests.AppCheck
13+
{
14+
public class AppCheckApiClientTest
15+
{
16+
private readonly string appId = "1:1234:android:1234";
17+
private readonly string testTokenToExchange = "signed-custom-token";
18+
private readonly string noProjectId = "Failed to determine project ID.Initialize the SDK with service "
19+
+ "account credentials or set project ID as an app option. Alternatively, set the "
20+
+ "GOOGLE_CLOUD_PROJECT environment variable.";
21+
22+
[Fact]
23+
public void CreateInvalidApp()
24+
{
25+
Assert.Throws<ArgumentException>(() => new AppCheckApiClient(null));
26+
}
27+
28+
[Fact]
29+
public async Task ExchangeTokenNoProjectId()
30+
{
31+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
32+
33+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
34+
.Throws(new ArgumentException(this.noProjectId));
35+
var result = await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, this.appId));
36+
Assert.Equal(this.noProjectId, result.Message);
37+
}
38+
39+
[Fact]
40+
public async Task ExchangeTokenInvalidAppId()
41+
{
42+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
43+
44+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
45+
.Throws(new ArgumentException(this.noProjectId));
46+
47+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, string.Empty));
48+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, null));
49+
}
50+
51+
[Fact]
52+
public async Task ExchangeTokenInvalidCustomTokenAsync()
53+
{
54+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
55+
56+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
57+
.Throws(new ArgumentException(this.noProjectId));
58+
59+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(string.Empty, this.appId));
60+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(null, this.appId));
61+
}
62+
63+
[Fact]
64+
public async Task ExchangeTokenFullErrorResponseAsync()
65+
{
66+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
67+
68+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
69+
.Throws(new ArgumentException("not-found", "Requested entity not found"));
70+
71+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, this.appId));
72+
}
73+
74+
[Fact]
75+
public async Task ExchangeTokenErrorCodeAsync()
76+
{
77+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
78+
79+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
80+
.Throws(new ArgumentException("unknown-error", "Unknown server error: {}"));
81+
82+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, this.appId));
83+
}
84+
85+
[Fact]
86+
public async Task ExchangeTokenFullNonJsonAsync()
87+
{
88+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
89+
90+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
91+
.Throws(new ArgumentException("unknown-error", "Unexpected response with status: 404 and body: not json"));
92+
93+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, this.appId));
94+
}
95+
96+
[Fact]
97+
public async Task ExchangeTokenAppErrorAsync()
98+
{
99+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
100+
101+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
102+
.Throws(new ArgumentException("network-error", "socket hang up"));
103+
104+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.ExchangeTokenAsync(string.Empty, this.appId));
105+
}
106+
107+
[Fact]
108+
public async Task ExchangeTokenOnSuccessAsync()
109+
{
110+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
111+
112+
appCheckApiClient.Setup(service => service.ExchangeTokenAsync(It.IsAny<string>(), It.IsAny<string>()))
113+
.ReturnsAsync(new AppCheckToken("token", 3000));
114+
115+
var result = await appCheckApiClient.Object.ExchangeTokenAsync(this.testTokenToExchange, this.appId).ConfigureAwait(false);
116+
Assert.NotNull(result);
117+
Assert.Equal("token", result.Token);
118+
Assert.Equal(3000, result.TtlMillis);
119+
}
120+
121+
[Fact]
122+
public async Task VerifyReplayNoProjectIdAsync()
123+
{
124+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
125+
126+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
127+
.Throws(new ArgumentException(this.noProjectId));
128+
129+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange));
130+
}
131+
132+
[Fact]
133+
public async Task VerifyReplayInvaildTokenAsync()
134+
{
135+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
136+
137+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
138+
.Throws(new ArgumentException(this.noProjectId));
139+
140+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(string.Empty));
141+
}
142+
143+
[Fact]
144+
public async Task VerifyReplayFullErrorAsync()
145+
{
146+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
147+
148+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
149+
.Throws(new ArgumentException("not-found", "Requested entity not found"));
150+
151+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange));
152+
}
153+
154+
[Fact]
155+
public async Task VerifyReplayErrorCodeAsync()
156+
{
157+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
158+
159+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
160+
.Throws(new ArgumentException("unknown-error", "Unknown server error: {}"));
161+
162+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange));
163+
}
164+
165+
[Fact]
166+
public async Task VerifyReplayNonJsonAsync()
167+
{
168+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
169+
170+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
171+
.Throws(new ArgumentException("unknown-error", "Unexpected response with status: 404 and body: not json"));
172+
173+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange));
174+
}
175+
176+
[Fact]
177+
public async Task VerifyReplayFirebaseAppErrorAsync()
178+
{
179+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
180+
181+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
182+
.Throws(new ArgumentException("network-error", "socket hang up"));
183+
184+
await Assert.ThrowsAsync<ArgumentException>(() => appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange));
185+
}
186+
187+
[Fact]
188+
public async Task VerifyReplayAlreadyTrueAsync()
189+
{
190+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
191+
192+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
193+
.ReturnsAsync(true);
194+
195+
bool res = await appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange).ConfigureAwait(false);
196+
Assert.True(res);
197+
}
198+
199+
[Fact]
200+
public async Task VerifyReplayAlreadyFlaseAsync()
201+
{
202+
var appCheckApiClient = new Mock<IAppCheckApiClient>();
203+
204+
appCheckApiClient.Setup(service => service.VerifyReplayProtection(It.IsAny<string>()))
205+
.ReturnsAsync(true);
206+
207+
bool res = await appCheckApiClient.Object.VerifyReplayProtection(this.testTokenToExchange).ConfigureAwait(false);
208+
Assert.True(res);
209+
}
210+
}
211+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using FirebaseAdmin.Auth.Jwt;
8+
using FirebaseAdmin.Check;
9+
using Google.Apis.Auth.OAuth2;
10+
using Moq;
11+
using Newtonsoft.Json.Linq;
12+
using Xunit;
13+
14+
namespace FirebaseAdmin.Tests.AppCheck
15+
{
16+
public class AppCheckTokenGeneratorTest
17+
{
18+
public static readonly IEnumerable<object[]> InvalidStrings = new List<object[]>
19+
{
20+
new object[] { null },
21+
new object[] { string.Empty },
22+
};
23+
24+
private const int ThirtyMinInMs = 1800000;
25+
private const int SevenDaysInMs = 604800000;
26+
private static readonly GoogleCredential MockCredential =
27+
GoogleCredential.FromAccessToken("test-token");
28+
29+
private readonly string appId = "test-app-id";
30+
31+
[Fact]
32+
public void ProjectIdFromOptions()
33+
{
34+
var app = FirebaseApp.Create(new AppOptions()
35+
{
36+
Credential = MockCredential,
37+
ProjectId = "explicit-project-id1",
38+
});
39+
var verifier = AppCheckTokenVerify.Create(app);
40+
Assert.Equal("explicit-project-id1", verifier.ProjectId);
41+
}
42+
43+
[Fact]
44+
public void ProjectIdFromServiceAccount()
45+
{
46+
var app = FirebaseApp.Create(new AppOptions()
47+
{
48+
Credential = GoogleCredential.FromFile("./resources/service_account.json"),
49+
});
50+
var verifier = AppCheckTokenVerify.Create(app);
51+
Assert.Equal("test-project", verifier.ProjectId);
52+
}
53+
54+
[Fact]
55+
public async Task InvalidAppId()
56+
{
57+
var options = new AppOptions()
58+
{
59+
Credential = GoogleCredential.FromAccessToken("token"),
60+
};
61+
var app = FirebaseApp.Create(options, "123");
62+
63+
AppCheckTokenGenerator tokenGenerator = AppCheckTokenGenerator.Create(app);
64+
await Assert.ThrowsAsync<ArgumentException>(() => tokenGenerator.CreateCustomTokenAsync(string.Empty));
65+
await Assert.ThrowsAsync<ArgumentException>(() => tokenGenerator.CreateCustomTokenAsync(null));
66+
}
67+
68+
[Fact]
69+
public async Task InvalidOptions()
70+
{
71+
var options = new AppOptions()
72+
{
73+
Credential = GoogleCredential.FromAccessToken("token"),
74+
};
75+
var app = FirebaseApp.Create(options, "1234");
76+
var tokenGernerator = AppCheckTokenGenerator.Create(app);
77+
int[] ttls = new int[] { -100, -1, 0, 10, 1799999, 604800001, 1209600000 };
78+
foreach (var ttl in ttls)
79+
{
80+
var option = new AppCheckTokenOptions(ttl);
81+
82+
var result = await Assert.ThrowsAsync<ArgumentException>(() =>
83+
tokenGernerator.CreateCustomTokenAsync(this.appId, option));
84+
}
85+
}
86+
87+
[Fact]
88+
public void ValidOptions()
89+
{
90+
var options = new AppOptions()
91+
{
92+
Credential = GoogleCredential.FromAccessToken("token"),
93+
};
94+
var app = FirebaseApp.Create(options, "12356");
95+
var tokenGernerator = AppCheckTokenGenerator.Create(app);
96+
int[] ttls = new int[] { ThirtyMinInMs, ThirtyMinInMs + 1, SevenDaysInMs / 2, SevenDaysInMs - 1, SevenDaysInMs };
97+
foreach (var ttl in ttls)
98+
{
99+
var option = new AppCheckTokenOptions(ttl);
100+
101+
var result = tokenGernerator.CreateCustomTokenAsync(this.appId, option);
102+
Assert.NotNull(result);
103+
}
104+
}
105+
106+
[Fact]
107+
public void Dispose()
108+
{
109+
FirebaseApp.DeleteAll();
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)