Skip to content

Commit 3576351

Browse files
author
Leo
committed
Testing and refactoring
1 parent 1ccd27a commit 3576351

File tree

6 files changed

+125
-69
lines changed

6 files changed

+125
-69
lines changed

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/InstanceIdClientTest.cs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,14 @@ public async Task BadRequest()
7474

7575
var client = new InstanceIdClient(factory, MockCredential);
7676

77-
await Assert.ThrowsAsync<FirebaseMessagingException>(
77+
var exception = await Assert.ThrowsAsync<FirebaseMessagingException>(
7878
() => client.SubscribeToTopicAsync("test-topic", new List<string> { "abc123" }));
79+
80+
Assert.Equal(ErrorCode.InvalidArgument, exception.ErrorCode);
81+
Assert.Equal("Unexpected HTTP response with status: 400 (Bad Request)\nBad Request", exception.Message);
82+
Assert.Null(exception.MessagingErrorCode);
83+
Assert.NotNull(exception.HttpResponse);
84+
Assert.Null(exception.InnerException);
7985
}
8086

8187
[Fact]
@@ -90,8 +96,14 @@ public async Task Unauthorized()
9096

9197
var client = new InstanceIdClient(factory, MockCredential);
9298

93-
await Assert.ThrowsAsync<FirebaseMessagingException>(
99+
var exception = await Assert.ThrowsAsync<FirebaseMessagingException>(
94100
() => client.SubscribeToTopicAsync("test-topic", new List<string> { "abc123" }));
101+
102+
Assert.Equal(ErrorCode.Unauthenticated, exception.ErrorCode);
103+
Assert.Equal("Unexpected HTTP response with status: 401 (Unauthorized)\nUnauthorized", exception.Message);
104+
Assert.Null(exception.MessagingErrorCode);
105+
Assert.NotNull(exception.HttpResponse);
106+
Assert.Null(exception.InnerException);
95107
}
96108

97109
[Fact]
@@ -106,8 +118,14 @@ public async Task Forbidden()
106118

107119
var client = new InstanceIdClient(factory, MockCredential);
108120

109-
await Assert.ThrowsAsync<FirebaseMessagingException>(
121+
var exception = await Assert.ThrowsAsync<FirebaseMessagingException>(
110122
() => client.SubscribeToTopicAsync("test-topic", new List<string> { "abc123" }));
123+
124+
Assert.Equal(ErrorCode.PermissionDenied, exception.ErrorCode);
125+
Assert.Equal("Unexpected HTTP response with status: 403 (Forbidden)\nForbidden", exception.Message);
126+
Assert.Null(exception.MessagingErrorCode);
127+
Assert.NotNull(exception.HttpResponse);
128+
Assert.Null(exception.InnerException);
111129
}
112130

113131
[Fact]
@@ -122,8 +140,14 @@ public async Task NotFound()
122140

123141
var client = new InstanceIdClient(factory, MockCredential);
124142

125-
await Assert.ThrowsAsync<FirebaseMessagingException>(
143+
var exception = await Assert.ThrowsAsync<FirebaseMessagingException>(
126144
() => client.SubscribeToTopicAsync("test-topic", new List<string> { "abc123" }));
145+
146+
Assert.Equal(ErrorCode.NotFound, exception.ErrorCode);
147+
Assert.Equal("Unexpected HTTP response with status: 404 (Not Found)\nNot Found", exception.Message);
148+
Assert.Null(exception.MessagingErrorCode);
149+
Assert.NotNull(exception.HttpResponse);
150+
Assert.Null(exception.InnerException);
127151
}
128152

129153
[Fact]
@@ -138,8 +162,14 @@ public async Task ServiceUnavailable()
138162

139163
var client = new InstanceIdClient(factory, MockCredential);
140164

141-
await Assert.ThrowsAsync<FirebaseMessagingException>(
165+
var exception = await Assert.ThrowsAsync<FirebaseMessagingException>(
142166
() => client.SubscribeToTopicAsync("test-topic", new List<string> { "abc123" }));
167+
168+
Assert.Equal(ErrorCode.Unavailable, exception.ErrorCode);
169+
Assert.Equal("Unexpected HTTP response with status: 503 (Service Unavailable)\nService Unavailable", exception.Message);
170+
Assert.Null(exception.MessagingErrorCode);
171+
Assert.NotNull(exception.HttpResponse);
172+
Assert.Null(exception.InnerException);
143173
}
144174
}
145175
}

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/TopicManagementResponseTest.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,22 @@ public class TopicManagementResponseTest
1111
[Fact]
1212
public void SuccessfulReponse()
1313
{
14-
var topicManagementResults = new List<string> { null };
15-
var response = new TopicManagementResponse(topicManagementResults);
14+
var json = @"{""results"": [{}, {}]}";
15+
var instanceIdServiceResponse = JsonConvert.DeserializeObject<InstanceIdServiceResponse>(json);
16+
var response = new TopicManagementResponse(instanceIdServiceResponse);
1617

17-
Assert.Empty(response.Errors);
18-
Assert.Equal(1, response.SuccessCount);
18+
Assert.Equal(0, response.FailureCount);
19+
Assert.Equal(2, response.SuccessCount);
1920
}
2021

2122
[Fact]
2223
public void UnsuccessfulResponse()
2324
{
24-
var topicManagementResults = new List<string> { null, "NOT_FOUND" };
25-
var response = new TopicManagementResponse(topicManagementResults);
25+
var json = @"{""results"": [{}, {""error"":""NOT_FOUND""}]}";
26+
var instanceIdServiceResponse = JsonConvert.DeserializeObject<InstanceIdServiceResponse>(json);
27+
var response = new TopicManagementResponse(instanceIdServiceResponse);
2628

27-
Assert.Single(response.Errors);
29+
Assert.Equal(1, response.FailureCount);
2830
Assert.Equal(1, response.SuccessCount);
2931
Assert.NotEmpty(response.Errors);
3032
Assert.Equal("registration-token-not-registered", response.Errors[0].Reason);
@@ -45,15 +47,17 @@ public void EmptyResponse()
4547
{
4648
Assert.Throws<ArgumentException>(() =>
4749
{
48-
new TopicManagementResponse(new List<string>());
50+
var instanceIdServiceResponse = new InstanceIdServiceResponse();
51+
new TopicManagementResponse(instanceIdServiceResponse);
4952
});
5053
}
5154

5255
[Fact]
5356
public void UnknownError()
5457
{
55-
var topicManagementResults = new List<string> { "NOT_A_REAL_ERROR_CODE" };
56-
var response = new TopicManagementResponse(topicManagementResults);
58+
var json = @"{""results"": [{}, {""error"":""NOT_FOUND""}]}";
59+
var instanceIdServiceResponse = JsonConvert.DeserializeObject<InstanceIdServiceResponse>(json);
60+
var response = new TopicManagementResponse(instanceIdServiceResponse);
5761

5862
Assert.Single(response.Errors);
5963
Assert.Equal("unknown-error", response.Errors[0].Reason);
@@ -63,8 +67,9 @@ public void UnknownError()
6367
[Fact]
6468
public void UnexpectedResponse()
6569
{
66-
var topicManagementResults = new List<string> { "NOT_A_REAL_CODE" };
67-
var response = new TopicManagementResponse(topicManagementResults);
70+
var json = @"{""results"": [{""unexpected"":""NOT_A_REAL_CODE""}]}";
71+
var instanceIdServiceResponse = JsonConvert.DeserializeObject<InstanceIdServiceResponse>(json);
72+
var response = new TopicManagementResponse(instanceIdServiceResponse);
6873

6974
Assert.Single(response.Errors);
7075
Assert.Equal("unknown-error", response.Errors[0].Reason);
@@ -74,8 +79,9 @@ public void UnexpectedResponse()
7479
[Fact]
7580
public void CountsSuccessAndErrors()
7681
{
77-
var topicManagementResults = new List<string> { "NOT_FOUND", null, "INVALID_ARGUMENT", null, null };
78-
var response = new TopicManagementResponse(topicManagementResults);
82+
var json = @"{""results"": [{""error"": ""NOT_FOUND""}, {}, {""error"": ""INVALID_ARGUMENT""}, {}, {}]}";
83+
var instanceIdServiceResponse = JsonConvert.DeserializeObject<InstanceIdServiceResponse>(json);
84+
var response = new TopicManagementResponse(instanceIdServiceResponse);
7985

8086
Assert.Equal(2, response.FailureCount);
8187
Assert.Equal(3, response.SuccessCount);

FirebaseAdmin/FirebaseAdmin/Messaging/ErrorInfo.cs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ namespace FirebaseAdmin.Messaging
77
/// </summary>
88
public sealed class ErrorInfo
99
{
10+
private static readonly string UnknownError = "unknown-error";
11+
1012
// Server error codes as defined in https://developers.google.com/instance-id/reference/server
1113
// TODO: Should we handle other error codes here (e.g. PERMISSION_DENIED)?
12-
private static IReadOnlyDictionary<string, string> errorCodes;
13-
private readonly string unknownError = "unknown-error";
14+
private static readonly IReadOnlyDictionary<string, string> ErrorCodes = new Dictionary<string, string>
15+
{
16+
{ "INVALID_ARGUMENT", "invalid-argument" },
17+
{ "NOT_FOUND", "registration-token-not-registered" },
18+
{ "INTERNAL", "internal-error" },
19+
{ "TOO_MANY_TOPICS", "too-many-topics" },
20+
};
1421

1522
/// <summary>
1623
/// Initializes a new instance of the <see cref="ErrorInfo"/> class.
@@ -19,17 +26,9 @@ public sealed class ErrorInfo
1926
/// <param name="reason">Reason for the error.</param>
2027
public ErrorInfo(int index, string reason)
2128
{
22-
errorCodes = new Dictionary<string, string>
23-
{
24-
{ "INVALID_ARGUMENT", "invalid-argument" },
25-
{ "NOT_FOUND", "registration-token-not-registered" },
26-
{ "INTERNAL", "internal-error" },
27-
{ "TOO_MANY_TOPICS", "too-many-topics" },
28-
};
29-
3029
this.Index = index;
31-
this.Reason = errorCodes.ContainsKey(reason)
32-
? errorCodes[reason] : this.unknownError;
30+
this.Reason = ErrorCodes.ContainsKey(reason)
31+
? ErrorCodes[reason] : UnknownError;
3332
}
3433

3534
/// <summary>

FirebaseAdmin/FirebaseAdmin/Messaging/InstanceIdClient.cs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ private async Task<TopicManagementResponse> SendInstanceIdRequest(string topic,
118118
throw new ArgumentException("unexpected response from topic management service");
119119
}
120120

121-
var results = instanceIdServiceResponse.Results.Select(r => r.Error).ToList();
122-
return new TopicManagementResponse(results);
121+
return new TopicManagementResponse(instanceIdServiceResponse);
123122
}
124123
catch (HttpRequestException e)
125124
{
@@ -145,24 +144,24 @@ private void ValidateRegistrationTokenList(List<string> registrationTokens)
145144
{
146145
if (registrationTokens == null)
147146
{
148-
throw new FirebaseMessagingException(ErrorCode.InvalidArgument, "Registration token list must not be null");
147+
throw new ArgumentNullException("Registration token list must not be null");
149148
}
150149

151150
if (registrationTokens.Count() == 0)
152151
{
153-
throw new FirebaseMessagingException(ErrorCode.InvalidArgument, "Registration token list must not be empty");
152+
throw new ArgumentException("Registration token list must not be empty");
154153
}
155154

156155
if (registrationTokens.Count() > 1000)
157156
{
158-
throw new FirebaseMessagingException(ErrorCode.InvalidArgument, "Registration token list must not contain more than 1000 tokens");
157+
throw new ArgumentException("Registration token list must not contain more than 1000 tokens");
159158
}
160159

161160
foreach (var registrationToken in registrationTokens)
162161
{
163162
if (string.IsNullOrEmpty(registrationToken))
164163
{
165-
throw new FirebaseMessagingException(ErrorCode.InvalidArgument, "Registration token must not be null");
164+
throw new ArgumentNullException("Registration tokens must not be null");
166165
}
167166
}
168167
}
@@ -187,23 +186,5 @@ private class InstanceIdServiceRequest
187186
[JsonProperty("registration_tokens")]
188187
public List<string> RegistrationTokens { get; set; }
189188
}
190-
191-
private class InstanceIdServiceResponse
192-
{
193-
[JsonProperty("results")]
194-
public List<InstanceIdServiceResponseElement> Results { get; private set; }
195-
196-
public int ErrorCount => Results?.Count(results => results.HasError) ?? 0;
197-
198-
public int ResultCount => Results?.Count() ?? 0;
199-
200-
public class InstanceIdServiceResponseElement
201-
{
202-
[JsonProperty("error")]
203-
public string Error { get; private set; }
204-
205-
public bool HasError => !string.IsNullOrEmpty(Error);
206-
}
207-
}
208189
}
209190
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Newtonsoft.Json;
4+
5+
namespace FirebaseAdmin.Messaging
6+
{
7+
/// <summary>
8+
/// Response from an operation that subscribes or unsubscribes registration tokens to a topic.
9+
/// See <see cref="FirebaseMessaging.SubscribeToTopicAsync(string, List{string})"/> and <see cref="FirebaseMessaging.UnsubscribeFromTopicAsync(string, List{string})"/>.
10+
/// </summary>
11+
internal class InstanceIdServiceResponse
12+
{
13+
/// <summary>
14+
/// Gets the errors returned by the operation.
15+
/// </summary>
16+
[JsonProperty("results")]
17+
public List<InstanceIdServiceResponseElement> Results { get; private set; }
18+
19+
/// <summary>
20+
/// Gets the number of errors returned by the operation.
21+
/// </summary>
22+
public int ErrorCount => Results?.Count(results => results.HasError) ?? 0;
23+
24+
/// <summary>
25+
/// Gets the number of results returned by the operation.
26+
/// </summary>
27+
public int ResultCount => Results?.Count() ?? 0;
28+
29+
/// <summary>
30+
/// An instance Id response error.
31+
/// </summary>
32+
public class InstanceIdServiceResponseElement
33+
{
34+
/// <summary>
35+
/// Gets a value indicating the error in this element of the response array. If this is empty this indicates success.
36+
/// </summary>
37+
[JsonProperty("error")]
38+
public string Error { get; private set; }
39+
40+
/// <summary>
41+
/// Gets a value indicating whether this response element in the response array is an error, as an empty element indicates success.
42+
/// </summary>
43+
public bool HasError => !string.IsNullOrEmpty(Error);
44+
}
45+
}
46+
}

FirebaseAdmin/FirebaseAdmin/Messaging/TopicManagementResponse.cs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
using System;
1616
using System.Collections.Generic;
17-
using System.Linq;
1817

1918
namespace FirebaseAdmin.Messaging
2019
{
@@ -26,26 +25,21 @@ public sealed class TopicManagementResponse
2625
/// <summary>
2726
/// Initializes a new instance of the <see cref="TopicManagementResponse"/> class.
2827
/// </summary>
29-
/// <param name="topicManagementResults">The results from the response produced by FCM topic management operations.</param>
30-
public TopicManagementResponse(List<string> topicManagementResults)
28+
/// <param name="instanceIdServiceResponse">The results from the response produced by FCM topic management operations.</param>
29+
internal TopicManagementResponse(InstanceIdServiceResponse instanceIdServiceResponse)
3130
{
32-
if (topicManagementResults == null)
31+
if (instanceIdServiceResponse == null || instanceIdServiceResponse.ResultCount == 0)
3332
{
34-
throw new ArgumentNullException("Topic management response list is null");
35-
}
36-
37-
if (topicManagementResults.Count() == 0)
38-
{
39-
throw new ArgumentException("Topic management response list is empty");
33+
throw new ArgumentException("unexpected response from topic management service");
4034
}
4135

4236
var resultErrors = new List<ErrorInfo>();
43-
for (var i = 0; i < topicManagementResults.Count(); i++)
37+
for (var i = 0; i < instanceIdServiceResponse.Results.Count; i++)
4438
{
45-
var topicManagementResult = topicManagementResults[i];
46-
if (!string.IsNullOrEmpty(topicManagementResult))
39+
var result = instanceIdServiceResponse.Results[i];
40+
if (result.HasError)
4741
{
48-
resultErrors.Add(new ErrorInfo(i, topicManagementResult));
42+
resultErrors.Add(new ErrorInfo(i, result.Error));
4943
}
5044
else
5145
{

0 commit comments

Comments
 (0)