Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d565c48084 |
217
Core.Tests/GuidV8Tests/NewGuid.cs
Normal file
217
Core.Tests/GuidV8Tests/NewGuid.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
namespace Just.Core.Tests.GuidV8Tests;
|
||||
|
||||
public class NewGuid
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
public void Guids_Differing_By_Seconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
|
||||
{
|
||||
var rng = new Random(25);
|
||||
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
|
||||
SortedList<DateTime, Guid> expected = new(seconds.Length);
|
||||
foreach (var s in seconds)
|
||||
{
|
||||
var timestamp = referenceTime.AddSeconds(s);
|
||||
expected.Add(timestamp, GuidV8.NewGuid(timestamp, entropy));
|
||||
}
|
||||
|
||||
var sut = expected.Values.ToArray();
|
||||
rng.Shuffle(sut);
|
||||
|
||||
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
|
||||
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
public void Guids_Differing_By_Milliseconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
|
||||
{
|
||||
var rng = new Random(25);
|
||||
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
|
||||
SortedList<DateTime, Guid> expected = new(seconds.Length);
|
||||
foreach (var s in seconds)
|
||||
{
|
||||
var timestamp = referenceTime.AddMilliseconds(s);
|
||||
expected.Add(timestamp, GuidV8.NewGuid(timestamp, entropy));
|
||||
}
|
||||
|
||||
var sut = expected.Values.ToArray();
|
||||
rng.Shuffle(sut);
|
||||
|
||||
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
|
||||
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
|
||||
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
|
||||
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
|
||||
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
|
||||
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
|
||||
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
|
||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||
[InlineData(GuidV8Entropy.Weak,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
[InlineData(GuidV8Entropy.Strong,
|
||||
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
|
||||
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
|
||||
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
|
||||
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
|
||||
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
|
||||
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
|
||||
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
|
||||
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
|
||||
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
|
||||
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
|
||||
public void Guids_Differing_By_Microseconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
|
||||
{
|
||||
var rng = new Random(25);
|
||||
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
|
||||
SortedList<DateTime, Guid> expected = new(seconds.Length);
|
||||
foreach (var s in seconds)
|
||||
{
|
||||
var timestamp = referenceTime.AddMicroseconds(s);
|
||||
expected.Add(timestamp, GuidV8.NewGuid(timestamp, entropy));
|
||||
}
|
||||
|
||||
var sut = expected.Values.ToArray();
|
||||
rng.Shuffle(sut);
|
||||
|
||||
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
|
||||
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
|
||||
}
|
||||
}
|
||||
40
Core/GuidV8.cs
Normal file
40
Core/GuidV8.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Just.Core;
|
||||
|
||||
public enum GuidV8Entropy { Strong, Weak }
|
||||
|
||||
public static class GuidV8
|
||||
{
|
||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Guid NewGuid(GuidV8Entropy entropy = GuidV8Entropy.Strong) => NewGuid(DateTime.UtcNow, entropy);
|
||||
|
||||
[Pure]
|
||||
public static Guid NewGuid(DateTime dateTime, GuidV8Entropy entropy = GuidV8Entropy.Strong)
|
||||
{
|
||||
var timestamp = dateTime.ToBinary() & 0x3FFF_FFFF_FFFF_FFFF;
|
||||
|
||||
Span<byte> ts = stackalloc byte[8];
|
||||
MemoryMarshal.Write(ts, timestamp);
|
||||
|
||||
Span<byte> bytes = stackalloc byte[16];
|
||||
|
||||
ts[4..].CopyTo(bytes[..4]);
|
||||
ts[2..4].CopyTo(bytes[4..6]);
|
||||
ts[..2].CopyTo(bytes[6..8]);
|
||||
|
||||
bytes[7] = (byte)((bytes[7] & 0x0f) | 0x80);
|
||||
|
||||
if (entropy == GuidV8Entropy.Strong)
|
||||
{
|
||||
RandomNumberGenerator.Fill(bytes[8..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Random.Shared.NextBytes(bytes[8..]);
|
||||
}
|
||||
|
||||
return new Guid(bytes);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user