Skip to content

Commit 37b85f4

Browse files
committed
Update tests
1 parent dcf7a6a commit 37b85f4

File tree

12 files changed

+202
-118
lines changed

12 files changed

+202
-118
lines changed

src/Components/Components/test/Lifetime/ComponentApplicationLifetimeTest.cs

Lines changed: 80 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Buffers;
56
using System.Collections.Generic;
7+
using System.Linq;
68
using System.Threading.Tasks;
7-
using Microsoft.AspNetCore.Components.Lifetime;
9+
using Microsoft.AspNetCore.Components.Infrastructure;
810
using Microsoft.AspNetCore.Components.RenderTree;
911
using Microsoft.Extensions.DependencyInjection;
1012
using Microsoft.Extensions.Logging;
@@ -20,19 +22,19 @@ public class ComponentApplicationLifetimeTest
2022
public async Task RestoreStateAsync_InitializesStateWithDataFromTheProvidedStore()
2123
{
2224
// Arrange
23-
byte[] data = new byte[] { 0, 1, 2, 3, 4 };
24-
var state = new Dictionary<string, byte[]>
25+
var data = new ReadOnlySequence<byte>(new byte[] { 0, 1, 2, 3, 4 });
26+
var state = new Dictionary<string, ReadOnlySequence<byte>>
2527
{
2628
["MyState"] = data
2729
};
2830
var store = new TestStore(state);
29-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
31+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
3032

3133
// Act
3234
await lifetime.RestoreStateAsync(store);
3335

3436
// Assert
35-
Assert.True(lifetime.State.TryTakePersistedState("MyState", out var retrieved));
37+
Assert.True(lifetime.State.TryTake("MyState", out var retrieved));
3638
Assert.Empty(state);
3739
Assert.Equal(data, retrieved);
3840
}
@@ -41,12 +43,12 @@ public async Task RestoreStateAsync_InitializesStateWithDataFromTheProvidedStore
4143
public async Task RestoreStateAsync_ThrowsOnDoubleInitialization()
4244
{
4345
// Arrange
44-
var state = new Dictionary<string, byte[]>
46+
var state = new Dictionary<string, ReadOnlySequence<byte>>
4547
{
46-
["MyState"] = new byte[] { 0, 1, 2, 3, 4 }
48+
["MyState"] = new ReadOnlySequence<byte>(new byte[] { 0, 1, 2, 3, 4 })
4749
};
4850
var store = new TestStore(state);
49-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
51+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
5052

5153
await lifetime.RestoreStateAsync(store);
5254

@@ -58,35 +60,39 @@ public async Task RestoreStateAsync_ThrowsOnDoubleInitialization()
5860
public async Task PersistStateAsync_SavesPersistedStateToTheStore()
5961
{
6062
// Arrange
61-
var state = new Dictionary<string, byte[]>();
63+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
6264
var store = new TestStore(state);
63-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
65+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
6466

6567
var renderer = new TestRenderer();
6668
var data = new byte[] { 1, 2, 3, 4 };
6769

68-
lifetime.State.PersistState("MyState", new byte[] { 1, 2, 3, 4 });
70+
lifetime.State.RegisterOnPersisting(() =>
71+
{
72+
lifetime.State.Persist("MyState", writer => writer.Write(new byte[] { 1, 2, 3, 4 }));
73+
return Task.CompletedTask;
74+
});
6975

7076
// Act
7177
await lifetime.PersistStateAsync(store, renderer);
7278

7379
// Assert
7480
Assert.True(store.State.TryGetValue("MyState", out var persisted));
75-
Assert.Equal(data, persisted);
81+
Assert.Equal(data, persisted.ToArray());
7682
}
7783

7884
[Fact]
7985
public async Task PersistStateAsync_InvokesPauseCallbacksDuringPersist()
8086
{
8187
// Arrange
82-
var state = new Dictionary<string, byte[]>();
88+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
8389
var store = new TestStore(state);
84-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
90+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
8591
var renderer = new TestRenderer();
8692
var data = new byte[] { 1, 2, 3, 4 };
8793
var invoked = false;
8894

89-
lifetime.State.OnPersisting += () => { invoked = true; return default; };
95+
lifetime.State.RegisterOnPersisting(() => { invoked = true; return default; });
9096

9197
// Act
9298
await lifetime.PersistStateAsync(store, renderer);
@@ -99,18 +105,18 @@ public async Task PersistStateAsync_InvokesPauseCallbacksDuringPersist()
99105
public async Task PersistStateAsync_FiresCallbacksInParallel()
100106
{
101107
// Arrange
102-
var state = new Dictionary<string, byte[]>();
108+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
103109
var store = new TestStore(state);
104-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
110+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
105111
var renderer = new TestRenderer();
106112

107113
var sequence = new List<int> { };
108114

109115
var tcs = new TaskCompletionSource();
110116
var tcs2 = new TaskCompletionSource();
111117

112-
lifetime.State.OnPersisting += async () => { sequence.Add(1); await tcs.Task; sequence.Add(3); };
113-
lifetime.State.OnPersisting += async () => { sequence.Add(2); await tcs2.Task; sequence.Add(4); };
118+
lifetime.State.RegisterOnPersisting(async () => { sequence.Add(1); await tcs.Task; sequence.Add(3); });
119+
lifetime.State.RegisterOnPersisting(async () => { sequence.Add(2); await tcs2.Task; sequence.Add(4); });
114120

115121
// Act
116122
var persistTask = lifetime.PersistStateAsync(store, renderer);
@@ -123,22 +129,53 @@ public async Task PersistStateAsync_FiresCallbacksInParallel()
123129
Assert.Equal(new[] { 1, 2, 3, 4 }, sequence);
124130
}
125131

132+
[Fact]
133+
public async Task PersistStateAsync_CallbacksAreRemovedWhenSubscriptionsAreDisposed()
134+
{
135+
// Arrange
136+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
137+
var store = new TestStore(state);
138+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
139+
var renderer = new TestRenderer();
140+
141+
var sequence = new List<int> { };
142+
143+
var tcs = new TaskCompletionSource();
144+
var tcs2 = new TaskCompletionSource();
145+
146+
var subscription1 = lifetime.State.RegisterOnPersisting(async () => { sequence.Add(1); await tcs.Task; sequence.Add(3); });
147+
var subscription2 = lifetime.State.RegisterOnPersisting(async () => { sequence.Add(2); await tcs2.Task; sequence.Add(4); });
148+
149+
// Act
150+
subscription1.Dispose();
151+
subscription2.Dispose();
152+
153+
var persistTask = lifetime.PersistStateAsync(store, renderer);
154+
tcs.SetResult();
155+
tcs2.SetResult();
156+
157+
await persistTask;
158+
159+
// Assert
160+
Assert.Empty(sequence);
161+
}
162+
126163
[Fact]
127164
public async Task PersistStateAsync_ContinuesInvokingPauseCallbacksDuringPersistIfACallbackThrows()
128165
{
129166
// Arrange
130167
var sink = new TestSink();
131168
var loggerFactory = new TestLoggerFactory(sink, true);
132-
var logger = loggerFactory.CreateLogger<ComponentApplicationLifetime>();
133-
var state = new Dictionary<string, byte[]>();
169+
var logger = loggerFactory.CreateLogger<ComponentStatePersistenceManager>();
170+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
134171
var store = new TestStore(state);
135-
var lifetime = new ComponentApplicationLifetime(logger);
172+
var lifetime = new ComponentStatePersistenceManager(logger);
136173
var renderer = new TestRenderer();
137174
var data = new byte[] { 1, 2, 3, 4 };
138175
var invoked = false;
139176

140-
lifetime.State.OnPersisting += () => throw new InvalidOperationException();
141-
lifetime.State.OnPersisting += () => { invoked = true; return Task.CompletedTask; };
177+
lifetime.State.RegisterOnPersisting(() => throw new InvalidOperationException());
178+
lifetime.State.RegisterOnPersisting(() => { invoked = true; return Task.CompletedTask; });
142179

143180
// Act
144181
await lifetime.PersistStateAsync(store, renderer);
@@ -155,16 +192,16 @@ public async Task PersistStateAsync_ContinuesInvokingPauseCallbacksDuringPersist
155192
// Arrange
156193
var sink = new TestSink();
157194
var loggerFactory = new TestLoggerFactory(sink, true);
158-
var logger = loggerFactory.CreateLogger<ComponentApplicationLifetime>();
159-
var state = new Dictionary<string, byte[]>();
195+
var logger = loggerFactory.CreateLogger<ComponentStatePersistenceManager>();
196+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
160197
var store = new TestStore(state);
161-
var lifetime = new ComponentApplicationLifetime(logger);
198+
var lifetime = new ComponentStatePersistenceManager(logger);
162199
var renderer = new TestRenderer();
163200
var invoked = false;
164201
var tcs = new TaskCompletionSource();
165202

166-
lifetime.State.OnPersisting += async () => { await tcs.Task; throw new InvalidOperationException(); };
167-
lifetime.State.OnPersisting += () => { invoked = true; return Task.CompletedTask; };
203+
lifetime.State.RegisterOnPersisting(async () => { await tcs.Task; throw new InvalidOperationException(); });
204+
lifetime.State.RegisterOnPersisting(() => { invoked = true; return Task.CompletedTask; });
168205

169206
// Act
170207
var persistTask = lifetime.PersistStateAsync(store, renderer);
@@ -182,14 +219,18 @@ public async Task PersistStateAsync_ContinuesInvokingPauseCallbacksDuringPersist
182219
public async Task PersistStateAsync_ThrowsWhenDeveloperTriesToPersistStateMultipleTimes()
183220
{
184221
// Arrange
185-
var state = new Dictionary<string, byte[]>();
222+
var state = new Dictionary<string, ReadOnlySequence<byte>>();
186223
var store = new TestStore(state);
187-
var lifetime = new ComponentApplicationLifetime(NullLogger<ComponentApplicationLifetime>.Instance);
224+
var lifetime = new ComponentStatePersistenceManager(NullLogger<ComponentStatePersistenceManager>.Instance);
188225

189226
var renderer = new TestRenderer();
190227
var data = new byte[] { 1, 2, 3, 4 };
191228

192-
lifetime.State.PersistState("MyState", new byte[] { 1, 2, 3, 4 });
229+
lifetime.State.RegisterOnPersisting(() =>
230+
{
231+
lifetime.State.Persist("MyState", writer => writer.Write(new byte[] { 1, 2, 3, 4 }));
232+
return Task.CompletedTask;
233+
});
193234

194235
// Act
195236
await lifetime.PersistStateAsync(store, renderer);
@@ -219,23 +260,24 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
219260
}
220261
}
221262

222-
private class TestStore : IComponentApplicationStateStore
263+
private class TestStore : IPersistentComponentStateStore
223264
{
224-
public TestStore(IDictionary<string, byte[]> initialState)
265+
public TestStore(IDictionary<string, ReadOnlySequence<byte>> initialState)
225266
{
226267
State = initialState;
227268
}
228269

229-
public IDictionary<string, byte[]> State { get; set; }
270+
public IDictionary<string, ReadOnlySequence<byte>> State { get; set; }
230271

231-
public Task<IDictionary<string, byte[]>> GetPersistedStateAsync()
272+
public Task<IDictionary<string, ReadOnlySequence<byte>>> GetPersistedStateAsync()
232273
{
233274
return Task.FromResult(State);
234275
}
235276

236-
public Task PersistStateAsync(IReadOnlyDictionary<string, byte[]> state)
277+
public Task PersistStateAsync(IReadOnlyDictionary<string, ReadOnlySequence<byte>> state)
237278
{
238-
State = new Dictionary<string, byte[]>(state);
279+
// We copy the data here because it's no longer available after this call completes.
280+
State = state.ToDictionary(kvp => kvp.Key, kvp => new ReadOnlySequence<byte>(kvp.Value.ToArray()));
239281
return Task.CompletedTask;
240282
}
241283
}

0 commit comments

Comments
 (0)