forked from MiniProfiler/dotnet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStorageBaseTest.cs
More file actions
295 lines (257 loc) · 10.3 KB
/
StorageBaseTest.cs
File metadata and controls
295 lines (257 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Dapper;
using StackExchange.Profiling.Internal;
using StackExchange.Profiling.Storage;
using Xunit;
using Xunit.Abstractions;
namespace StackExchange.Profiling.Tests.Storage
{
public abstract class StorageBaseTest : BaseTest
{
protected StorageFixtureBase Fixture { get; }
protected virtual IAsyncStorage Storage => Fixture.GetStorage();
protected StorageBaseTest(StorageFixtureBase fixture, ITestOutputHelper output) : base(output)
{
Fixture = fixture;
if (fixture.ShouldSkip)
{
Skip.Inconclusive("Couldn't test against: " + (Storage?.GetType() ?? GetType()) + "\n" + fixture.SkipReason);
}
}
[Fact]
public void GetUnviewedIds()
{
var mp1 = GetMiniProfiler("Test1");
var mp2 = GetMiniProfiler("Test2");
var mp3 = GetMiniProfiler("Test3");
Storage.Save(mp1);
Storage.Save(mp2);
Storage.Save(mp3);
var unviewed = Storage.GetUnviewedIds(nameof(GetUnviewedIds));
Assert.Equal(3, unviewed.Count);
Assert.Contains(mp1.Id, unviewed);
Assert.Contains(mp2.Id, unviewed);
Assert.Contains(mp3.Id, unviewed);
}
[Fact]
public async Task GetUnviewedIdsAsync()
{
var mp1 = GetMiniProfiler("Test1");
var mp2 = GetMiniProfiler("Test2");
var mp3 = GetMiniProfiler("Test3");
await Storage.SaveAsync(mp1).ConfigureAwait(false);
await Storage.SaveAsync(mp2).ConfigureAwait(false);
await Storage.SaveAsync(mp3).ConfigureAwait(false);
var unviewed = await Storage.GetUnviewedIdsAsync(nameof(GetUnviewedIdsAsync)).ConfigureAwait(false);
Assert.Equal(3, unviewed.Count);
Assert.Contains(mp1.Id, unviewed);
Assert.Contains(mp2.Id, unviewed);
Assert.Contains(mp3.Id, unviewed);
}
[Fact]
public void List()
{
var mp1 = GetMiniProfiler("Test1");
var mp2 = GetMiniProfiler("Test2");
var mp3 = GetMiniProfiler("Test3");
Storage.Save(mp1);
Storage.Save(mp2);
Storage.Save(mp3);
var stored = Storage.List(200).ToList();
Assert.True(stored.Count >= 3);
Assert.Contains(mp1.Id, stored);
Assert.Contains(mp2.Id, stored);
Assert.Contains(mp3.Id, stored);
}
[Fact]
public async Task ListAsync()
{
var mp1 = GetMiniProfiler("Test1");
var mp2 = GetMiniProfiler("Test2");
var mp3 = GetMiniProfiler("Test3");
Storage.Save(mp1);
Storage.Save(mp2);
Storage.Save(mp3);
var stored = (await Storage.ListAsync(200).ConfigureAwait(false)).ToList();
Assert.True(stored.Count >= 3);
Assert.Contains(mp1.Id, stored);
Assert.Contains(mp2.Id, stored);
Assert.Contains(mp3.Id, stored);
}
[Fact]
public void SaveAndLoad()
{
var mp = GetMiniProfiler();
Storage.Save(mp);
var timings = mp.GetTimingHierarchy();
var fetched = Storage.Load(mp.Id);
Assert.Equal(mp, fetched);
Assert.NotNull(fetched.Options);
Assert.Equal(timings, fetched.GetTimingHierarchy());
}
[Fact]
public async Task SaveAndLoadAsync()
{
var mp = GetMiniProfiler();
await Storage.SaveAsync(mp).ConfigureAwait(false);
var timings = mp.GetTimingHierarchy();
var fetched = await Storage.LoadAsync(mp.Id).ConfigureAwait(false);
Assert.Equal(mp, fetched);
Assert.NotNull(fetched.Options);
Assert.Equal(timings, fetched.GetTimingHierarchy());
}
[Fact]
public void SetViewed()
{
var mp = GetMiniProfiler();
Assert.False(mp.HasUserViewed);
Storage.Save(mp);
Assert.False(mp.HasUserViewed);
var unviewedIds = Storage.GetUnviewedIds(mp.User);
Assert.Contains(mp.Id, unviewedIds);
Storage.SetViewed(mp);
var unviewedIds2 = Storage.GetUnviewedIds(mp.User);
Assert.DoesNotContain(mp.Id, unviewedIds2);
}
[Fact]
public async Task SetViewedAsync()
{
var mp = GetMiniProfiler();
Assert.False(mp.HasUserViewed);
await Storage.SaveAsync(mp).ConfigureAwait(false);
Assert.False(mp.HasUserViewed);
var unviewedIds = await Storage.GetUnviewedIdsAsync(mp.User).ConfigureAwait(false);
Assert.Contains(mp.Id, unviewedIds);
await Storage.SetViewedAsync(mp).ConfigureAwait(false);
var unviewedIds2 = await Storage.GetUnviewedIdsAsync(mp.User).ConfigureAwait(false);
Assert.DoesNotContain(mp.Id, unviewedIds2);
}
[Fact]
public async Task ExpireAndGetUnviewedAsync()
{
Options.Storage = Storage;
var user = "TestUser";
var mps = Enumerable.Range(0, 500)
.Select(i => GetMiniProfiler(user: user))
.ToList();
foreach (var mp in mps)
{
Assert.False(mp.HasUserViewed);
await Storage.SaveAsync(mp).ConfigureAwait(false);
Assert.False(mp.HasUserViewed);
}
var unviewedIds = await Storage.GetUnviewedIdsAsync(user).ConfigureAwait(false);
Assert.All(mps, mp => Assert.Contains(mp.Id, unviewedIds));
var sw = Stopwatch.StartNew();
await Options.ExpireAndGetUnviewedAsync(user);
sw.Stop();
Output.WriteLine($"{nameof(MiniProfilerBaseOptionsExtensions.ExpireAndGetUnviewedAsync)} completed in {sw.ElapsedMilliseconds}ms");
var unviewedIds2 = await Storage.GetUnviewedIdsAsync(user).ConfigureAwait(false);
Assert.InRange(unviewedIds2.Count, 0, Options.MaxUnviewedProfiles);
Assert.Subset(new HashSet<Guid>(unviewedIds), new HashSet<Guid>(unviewedIds2));
}
[Fact]
public void SetUnviewed()
{
var mp = GetMiniProfiler();
Storage.Save(mp);
var unviewedIds = Storage.GetUnviewedIds(mp.User);
Assert.Contains(mp.Id, unviewedIds);
Storage.SetViewed(mp);
var unviewedIds2 = Storage.GetUnviewedIds(mp.User);
Assert.DoesNotContain(mp.Id, unviewedIds2);
Storage.SetUnviewed(mp);
var unviewedIds3 = Storage.GetUnviewedIds(mp.User);
Assert.Contains(mp.Id, unviewedIds3);
}
[Fact]
public async Task SetUnviewedAsync()
{
var mp = GetMiniProfiler();
await Storage.SaveAsync(mp).ConfigureAwait(false);
var unviewedIds = await Storage.GetUnviewedIdsAsync(mp.User).ConfigureAwait(false);
Assert.Contains(mp.Id, unviewedIds);
await Storage.SetViewedAsync(mp).ConfigureAwait(false);
var unviewedIds2 = await Storage.GetUnviewedIdsAsync(mp.User).ConfigureAwait(false);
Assert.DoesNotContain(mp.Id, unviewedIds2);
await Storage.SetUnviewedAsync(mp).ConfigureAwait(false);
var unviewedIds3 = await Storage.GetUnviewedIdsAsync(mp.User).ConfigureAwait(false);
Assert.Contains(mp.Id, unviewedIds3);
}
protected MiniProfiler GetMiniProfiler(string name = "Test", [CallerMemberName]string user = null)
{
var mp = new MiniProfiler(name, Options)
{
User = user
};
using (mp.Step("Foo"))
{
using (mp.CustomTiming("Hey", "There"))
{
// heyyyyyyyyy
}
}
mp.Stop();
return mp;
}
}
public static class DatabaseStorageExtensions
{
/// <summary>
/// Creates the tables for this storage provider to use.
/// </summary>
/// <param name="storage">The storage to create schema for.</param>
public static void CreateSchema(this IAsyncStorage storage)
{
if (storage is DatabaseStorageBase dbs && storage is IDatabaseStorageConnectable dbsc)
{
using (var conn = dbsc.GetConnection())
{
foreach (var script in dbs.TableCreationScripts)
{
conn.Execute(script);
}
}
}
}
/// <summary>
/// Drops the tables for this storage provider.
/// </summary>
/// <param name="storage">The storage to drop schema for.</param>
public static void DropSchema(this IAsyncStorage storage)
{
if (storage is DatabaseStorageBase dbs && storage is IDatabaseStorageConnectable dbsc)
{
using (var conn = dbsc.GetConnection())
{
conn.Execute("Drop Table " + dbs.MiniProfilerClientTimingsTable);
conn.Execute("Drop Table " + dbs.MiniProfilerTimingsTable);
conn.Execute("Drop Table " + dbs.MiniProfilersTable);
}
}
}
}
public abstract class StorageFixtureBase
{
public string TestId { get; } = Guid.NewGuid().ToString("N").Substring(20);
public bool ShouldSkip { get; protected set; }
public string SkipReason { get; protected set; }
public abstract IAsyncStorage GetStorage();
}
public abstract class StorageFixtureBase<TStorage> : StorageFixtureBase, IDisposable where TStorage : IAsyncStorage
{
public TStorage Storage { get; protected set; }
public override IAsyncStorage GetStorage() => Storage;
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
}
}