Skip to content

Commit c5d41ef

Browse files
committed
More tests
1 parent d9601b2 commit c5d41ef

File tree

3 files changed

+158
-72
lines changed

3 files changed

+158
-72
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace ServiceControl.MultiInstance.AcceptanceTests.Recoverability;
2+
3+
using System.Threading.Tasks;
4+
using AcceptanceTesting;
5+
using MessageFailures;
6+
using MessageFailures.Api;
7+
using TestSupport;
8+
9+
abstract class WhenRetrying : AcceptanceTest
10+
{
11+
protected Task<SingleResult<FailedMessage>> GetFailedMessage(string uniqueMessageId, string instance, FailedMessageStatus expectedStatus)
12+
{
13+
if (uniqueMessageId == null)
14+
{
15+
return Task.FromResult(SingleResult<FailedMessage>.Empty);
16+
}
17+
18+
return this.TryGet<FailedMessage>("/api/errors/" + uniqueMessageId, f => f.Status == expectedStatus, instance);
19+
}
20+
21+
protected Task<ManyResult<FailedMessageView>> GetAllFailedMessage(string instance, FailedMessageStatus expectedStatus) => this.TryGetMany<FailedMessageView>("/api/errors", f => f.Status == expectedStatus, instance);
22+
}

src/ServiceControl.MultiInstance.AcceptanceTests/Recoverability/WhenRetryingSameMessageMultipleTimes.cs

Lines changed: 44 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,26 @@
66
using AcceptanceTesting;
77
using AcceptanceTesting.EndpointTemplates;
88
using MessageFailures;
9-
using MessageFailures.Api;
109
using NServiceBus;
1110
using NServiceBus.AcceptanceTesting;
1211
using NServiceBus.Settings;
1312
using NUnit.Framework;
1413
using ServiceControl.Infrastructure;
1514
using TestSupport;
1615

17-
class WhenRetryingSameMessageMultipleTimes : AcceptanceTest
16+
class WhenRetryingSameMessageMultipleTimes : WhenRetrying
1817
{
19-
[Test]
20-
public async Task WithNoEdit()
18+
public enum RetryType
2119
{
22-
await Define<MyContext>()
23-
.WithEndpoint<FailureEndpoint>(b => b.When(bus => bus.SendLocal(new MyMessage())).DoNotFailOnErrorMessages())
24-
.Done(async c =>
25-
{
26-
if (c.RetryCount < 3)
27-
{
28-
var result = await GetFailedMessage(c, ServiceControlInstanceName, FailedMessageStatus.Unresolved);
29-
if (result.HasResult)
30-
{
31-
if (result.Item.ProcessingAttempts.Count == c.RetryCount + 1)
32-
{
33-
await this.Post<object>($"/api/errors/{result.Item.UniqueMessageId}/retry", null, null,
34-
ServiceControlInstanceName);
35-
c.RetryCount++;
36-
}
37-
}
38-
39-
return false;
40-
}
41-
42-
return await GetFailedMessage(c, ServiceControlInstanceName, FailedMessageStatus.Resolved);
43-
})
44-
.Run(TimeSpan.FromMinutes(2));
20+
NoEdit,
21+
Edit
4522
}
4623

47-
[Test]
48-
public async Task WithEdit()
24+
[TestCase(new[] { RetryType.NoEdit, RetryType.NoEdit, RetryType.Edit })]
25+
[TestCase(new[] { RetryType.Edit, RetryType.NoEdit, RetryType.Edit })]
26+
[TestCase(new[] { RetryType.NoEdit, RetryType.Edit, RetryType.NoEdit })]
27+
[TestCase(new[] { RetryType.Edit, RetryType.Edit, RetryType.NoEdit })]
28+
public async Task WithMixOfRetryTypes(RetryType[] retryTypes)
4929
{
5030
CustomServiceControlPrimarySettings = s => { s.AllowMessageEditing = true; };
5131

@@ -54,9 +34,16 @@ await Define<MyContext>()
5434
b.When(bus => bus.SendLocal(new MyMessage())).DoNotFailOnErrorMessages())
5535
.Done(async c =>
5636
{
57-
if (c.RetryCount < 3)
37+
if (c.RetryCount >= retryTypes.Length)
38+
{
39+
return !(await GetAllFailedMessage(ServiceControlInstanceName, FailedMessageStatus.Unresolved))
40+
.HasResult;
41+
}
42+
43+
if (retryTypes[c.RetryCount] == RetryType.Edit)
5844
{
59-
var results = await GetAllFailedMessage(ServiceControlInstanceName, FailedMessageStatus.Unresolved);
45+
var results = await GetAllFailedMessage(ServiceControlInstanceName,
46+
FailedMessageStatus.Unresolved);
6047
if (!results.HasResult)
6148
{
6249
return false;
@@ -65,84 +52,69 @@ await Define<MyContext>()
6552
var result = results.Items.Single();
6653

6754
c.MessageId = result.MessageId;
55+
}
6856

69-
var failedMessage = await GetFailedMessage(c, ServiceControlInstanceName, FailedMessageStatus.Unresolved);
70-
if (!failedMessage.HasResult)
71-
{
72-
return false;
73-
}
57+
var failedMessage = await GetFailedMessage(c.UniqueMessageId, ServiceControlInstanceName, FailedMessageStatus.Unresolved);
58+
if (!failedMessage.HasResult)
59+
{
60+
return false;
61+
}
7462

63+
if (retryTypes[c.RetryCount] == RetryType.Edit)
64+
{
7565
await this.Post<object>($"/api/edit/{failedMessage.Item.UniqueMessageId}",
7666
new
7767
{
78-
MessageBody = $"{{ \"Name\": \"John{c.RetryCount}\" }}",
68+
MessageBody = $"{{ \"Name\": \"Hello {c.RetryCount}\" }}",
7969
MessageHeaders = failedMessage.Item.ProcessingAttempts[^1].Headers
8070
}, null,
8171
ServiceControlInstanceName);
82-
c.RetryCount++;
83-
84-
return false;
72+
}
73+
else
74+
{
75+
await this.Post<object>($"/api/errors/{failedMessage.Item.UniqueMessageId}/retry", null, null,
76+
ServiceControlInstanceName);
8577
}
8678

87-
return !(await GetAllFailedMessage(ServiceControlInstanceName, FailedMessageStatus.Unresolved)).HasResult;
88-
})
89-
.Run(TimeSpan.FromMinutes(2));
90-
}
91-
92-
Task<SingleResult<FailedMessage>> GetFailedMessage(MyContext c, string instance, FailedMessageStatus expectedStatus)
93-
{
94-
if (c.MessageId == null)
95-
{
96-
return Task.FromResult(SingleResult<FailedMessage>.Empty);
97-
}
79+
c.RetryCount++;
9880

99-
return this.TryGet<FailedMessage>("/api/errors/" + c.UniqueMessageId, f => f.Status == expectedStatus, instance);
100-
}
81+
return false;
10182

102-
Task<ManyResult<FailedMessageView>> GetAllFailedMessage(string instance, FailedMessageStatus expectedStatus)
103-
{
104-
return this.TryGetMany<FailedMessageView>("/api/errors", f => f.Status == expectedStatus, instance);
83+
})
84+
.Run(TimeSpan.FromMinutes(2));
10585
}
10686

107-
public class FailureEndpoint : EndpointConfigurationBuilder
87+
class FailureEndpoint : EndpointConfigurationBuilder
10888
{
10989
public FailureEndpoint() => EndpointSetup<DefaultServerWithoutAudit>(c => { c.NoRetries(); });
11090

111-
public class MyMessageHandler : IHandleMessages<MyMessage>
91+
public class MyMessageHandler(MyContext testContext, IReadOnlySettings settings)
92+
: IHandleMessages<MyMessage>
11293
{
113-
readonly MyContext testContext;
114-
readonly IReadOnlySettings settings;
115-
116-
public MyMessageHandler(MyContext testContext, IReadOnlySettings settings)
117-
{
118-
this.testContext = testContext;
119-
this.settings = settings;
120-
}
121-
12294
public Task Handle(MyMessage message, IMessageHandlerContext context)
12395
{
12496
testContext.MessageId = context.MessageId.Replace(@"\", "-");
12597
testContext.EndpointNameOfReceivingEndpoint = settings.EndpointName();
126-
Console.Out.WriteLine("Handling message");
12798

12899
if (testContext.RetryCount < 3)
129100
{
130-
Console.Out.WriteLine("Throwing exception for MyMessage");
101+
Console.Out.WriteLine("Throwing exception");
131102
throw new Exception("Simulated exception");
132103
}
133104

105+
Console.Out.WriteLine("Handling message");
106+
134107
return Task.CompletedTask;
135108
}
136109
}
137110
}
138111

139-
140-
public class MyMessage : ICommand
112+
class MyMessage : ICommand
141113
{
142114
public string Name { get; set; }
143115
}
144116

145-
public class MyContext : ScenarioContext
117+
class MyContext : ScenarioContext
146118
{
147119
public string MessageId { get; set; }
148120

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
namespace ServiceControl.MultiInstance.AcceptanceTests.Recoverability;
2+
3+
using System;
4+
using System.Threading.Tasks;
5+
using AcceptanceTesting;
6+
using AcceptanceTesting.EndpointTemplates;
7+
using MessageFailures;
8+
using NServiceBus;
9+
using NServiceBus.AcceptanceTesting;
10+
using NServiceBus.Settings;
11+
using NUnit.Framework;
12+
using TestSupport;
13+
using ServiceControl.Infrastructure;
14+
15+
class WhenRetryingWithEdit : WhenRetrying
16+
{
17+
[Test]
18+
public async Task ShouldCreateNewMessageAndResolveEditedMessage()
19+
{
20+
CustomServiceControlPrimarySettings = s => { s.AllowMessageEditing = true; };
21+
22+
await Define<MyContext>()
23+
.WithEndpoint<FailureEndpoint>(b =>
24+
b.When(bus => bus.SendLocal(new MyMessage { Password = "Bad password!" })).DoNotFailOnErrorMessages())
25+
.Done(async c =>
26+
{
27+
if (!c.ErrorRetried)
28+
{
29+
var failedMessage = await GetFailedMessage(c.UniqueMessageId, ServiceControlInstanceName,
30+
FailedMessageStatus.Unresolved);
31+
if (!failedMessage.HasResult)
32+
{
33+
return false;
34+
}
35+
36+
await this.Post<object>($"/api/edit/{failedMessage.Item.UniqueMessageId}",
37+
new
38+
{
39+
MessageBody = "{ \"Password\": \"VerySecretPassword\" }",
40+
MessageHeaders = failedMessage.Item.ProcessingAttempts[^1].Headers
41+
}, null,
42+
ServiceControlInstanceName);
43+
c.ErrorRetried = true;
44+
45+
return false;
46+
}
47+
48+
var failedResolvedMessage = await GetFailedMessage(c.UniqueMessageId, ServiceControlInstanceName, FailedMessageStatus.Resolved);
49+
50+
return failedResolvedMessage.HasResult;
51+
})
52+
.Run(TimeSpan.FromMinutes(2));
53+
}
54+
55+
class FailureEndpoint : EndpointConfigurationBuilder
56+
{
57+
public FailureEndpoint() => EndpointSetup<DefaultServerWithoutAudit>(c => { c.NoRetries(); });
58+
59+
public class MyMessageHandler(MyContext testContext, IReadOnlySettings settings) : IHandleMessages<MyMessage>
60+
{
61+
public Task Handle(MyMessage message, IMessageHandlerContext context)
62+
{
63+
if (message.Password == "VerySecretPassword")
64+
{
65+
Console.Out.WriteLine("Handling message");
66+
return Task.CompletedTask;
67+
}
68+
69+
testContext.MessageId = context.MessageId.Replace(@"\", "-");
70+
testContext.EndpointNameOfReceivingEndpoint = settings.EndpointName();
71+
72+
Console.Out.WriteLine("Throwing exception");
73+
throw new Exception("Simulated exception");
74+
}
75+
}
76+
}
77+
78+
class MyMessage : ICommand
79+
{
80+
public string Password { get; set; }
81+
}
82+
83+
class MyContext : ScenarioContext
84+
{
85+
public string MessageId { get; set; }
86+
87+
public string EndpointNameOfReceivingEndpoint { get; set; }
88+
89+
public string UniqueMessageId => DeterministicGuid.MakeId(MessageId, EndpointNameOfReceivingEndpoint).ToString();
90+
public bool ErrorRetried { get; set; }
91+
}
92+
}

0 commit comments

Comments
 (0)