public void FromId_Returns_CorrectValue() { var s = new IdStructure(42, 8, 13); var epoch = new DateTimeOffset(2018, 7, 31, 14, 48, 2, TimeSpan.FromHours(2)); // Just some "random" epoch... var ts = new MockTimeSource(5, TimeSpan.FromSeconds(7), epoch); // Set clock at 5 ticks; each tick being 7 seconds... // Set generator ID to 234 var g = new IdGenerator(234, new IdGeneratorOptions(s, ts)); // Generate a bunch of id's long id = 0; for (var i = 0; i < 35; i++) { id = g.CreateId(); } var target = g.FromId(id); Assert.AreEqual(34, target.SequenceNumber); // We generated 35 id's in the same tick, so sequence should be at 34. Assert.AreEqual(234, target.GeneratorId); // With generator id 234 Assert.AreEqual(epoch.Add(TimeSpan.FromSeconds(5 * 7)), target.DateTimeOffset); // And the clock was at 5 ticks, with each tick being // 7 seconds (so 35 seconds from epoch) // And epoch was 2018-7-31 14:48:02 +02:00... }
public void MaskConfig_CalculatesWraparoundInterval_Correctly() { var mc_ms = new MockTimeSource(); // 40 bits of Timestamp should give us about 34 years worth of Id's Assert.AreEqual(34, (int)(new MaskConfig(40, 11, 12).WraparoundInterval(mc_ms).TotalDays / 365.25)); // 41 bits of Timestamp should give us about 69 years worth of Id's Assert.AreEqual(69, (int)(new MaskConfig(41, 11, 11).WraparoundInterval(mc_ms).TotalDays / 365.25)); // 42 bits of Timestamp should give us about 139 years worth of Id's Assert.AreEqual(139, (int)(new MaskConfig(42, 11, 10).WraparoundInterval(mc_ms).TotalDays / 365.25)); var mc_s = new MockTimeSource(TimeSpan.FromSeconds(0.1)); // 40 bits of Timestamp should give us about 3484 years worth of Id's Assert.AreEqual(3484, (int)(new MaskConfig(40, 11, 12).WraparoundInterval(mc_s).TotalDays / 365.25)); // 41 bits of Timestamp should give us about 6968 years worth of Id's Assert.AreEqual(6968, (int)(new MaskConfig(41, 11, 11).WraparoundInterval(mc_s).TotalDays / 365.25)); // 42 bits of Timestamp should give us about 13936 years worth of Id's Assert.AreEqual(13936, (int)(new MaskConfig(42, 11, 10).WraparoundInterval(mc_s).TotalDays / 365.25)); var mc_d = new MockTimeSource(TimeSpan.FromDays(1)); // 21 bits of Timestamp should give us about 5741 years worth of Id's Assert.AreEqual(5741, (int)(new MaskConfig(21, 11, 31).WraparoundInterval(mc_d).TotalDays / 365.25)); // 22 bits of Timestamp should give us about 11483 years worth of Id's Assert.AreEqual(11483, (int)(new MaskConfig(22, 11, 30).WraparoundInterval(mc_d).TotalDays / 365.25)); // 23 bits of Timestamp should give us about 22966 years worth of Id's Assert.AreEqual(22966, (int)(new MaskConfig(23, 11, 39).WraparoundInterval(mc_d).TotalDays / 365.25)); }
public void Constructor_Overloads() { var i = 99; var ts = new MockTimeSource(); var m = MaskConfig.Default; var epoch = DateTimeOffset.UtcNow; // Check all constructor overload variations Assert.AreEqual(i, new IdGenerator(i).Id); Assert.AreEqual(IdGenerator.DefaultEpoch, new IdGenerator(i).Epoch); Assert.AreEqual(i, new IdGenerator(i, epoch).Id); Assert.AreEqual(epoch, new IdGenerator(i, epoch).Epoch); Assert.AreEqual(i, new IdGenerator(i, ts).Id); Assert.AreSame(ts, new IdGenerator(i, ts).TimeSource); Assert.AreEqual(DateTimeOffset.MinValue, new IdGenerator(i, ts).Epoch); Assert.AreEqual(i, new IdGenerator(i, m).Id); Assert.AreSame(m, new IdGenerator(i, m).MaskConfig); Assert.AreEqual(IdGenerator.DefaultEpoch, new IdGenerator(i, m).Epoch); Assert.AreEqual(i, new IdGenerator(i, epoch, m).Id); Assert.AreSame(m, new IdGenerator(i, epoch, m).MaskConfig); Assert.AreEqual(epoch, new IdGenerator(i, epoch, m).Epoch); Assert.AreEqual(i, new IdGenerator(i, m, ts).Id); Assert.AreSame(ts, new IdGenerator(i, m, ts).TimeSource); Assert.AreSame(m, new IdGenerator(i, m, ts).MaskConfig); Assert.AreEqual(DateTimeOffset.MinValue, new IdGenerator(i, m, ts).Epoch); }
public void MaskConfig_CalculatesWraparoundDate_Correctly() { var m = MaskConfig.Default; var mc = new MockTimeSource(TimeSpan.FromMilliseconds(1)); var d = m.WraparoundDate(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), mc); Assert.AreEqual(new DateTime(643346200555520000, DateTimeKind.Utc), d); }
public void IdStructure_Calculates_WraparoundDate_Correctly() { var s = IdStructure.Default; var mc = new MockTimeSource(TimeSpan.FromMilliseconds(1)); var d = s.WraparoundDate(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), mc); Assert.AreEqual(new DateTime(643346200555520000, DateTimeKind.Utc), d); }
public void CreateId_Throws_OnClockBackwards() { var ts = new MockTimeSource(100); var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); g.CreateId(); ts.PreviousTick(); // Set clock back 1 'tick', this results in the time going from "100" to "99" g.CreateId(); }
public void TryCreateId_Returns_False_OnClockBackwards() { var ts = new MockTimeSource(100); var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); Assert.IsTrue(g.TryCreateId(out var _)); ts.PreviousTick(); // Set clock back 1 'tick', this results in the time going from "100" to "99" Assert.IsFalse(g.TryCreateId(out var _)); }
public void CreateId_Throws_OnTimestampWraparound() { var ts = new MockTimeSource(long.MaxValue); // Set clock to 1 'tick' before wraparound var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); Assert.IsTrue(g.CreateId() > 0); // Should succeed; ts.NextTick(); g.CreateId(); // Should fail }
public void TryCreateId_Returns_False_OnTimestampWraparound() { var ts = new MockTimeSource(long.MaxValue); // Set clock to 1 'tick' before wraparound var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); Assert.IsTrue(g.TryCreateId(out var _)); // Should succeed; ts.NextTick(); Assert.IsFalse(g.TryCreateId(out var _)); // Should fail }
public void GeneratorId_ShouldBeMasked_WhenReadFromProperty() { // We setup our generator so that the time is 0 and generator id equals 1023 so that all 10 bits are set // for the generator. var ts = new MockTimeSource(); var g = new IdGenerator(1023, new IdGeneratorOptions(timeSource: ts)); // Make sure all expected bits are set Assert.AreEqual((1 << g.Options.IdStructure.GeneratorIdBits) - 1, g.Id); }
public void CreateId_Throws_OnClockBackwards() { var ts = new MockTimeSource(100); var m = MaskConfig.Default; var g = new IdGenerator(0, TESTEPOCH, m, ts); g.CreateId(); ts.PreviousTick(); // Set clock back 1 'tick', this results in the time going from "100" to "99" g.CreateId(); }
public void Constructor_Throws_OnTimestampWraparound() { var m = MaskConfig.Default; var ts = new MockTimeSource(long.MaxValue); // Set clock to 1 'tick' before wraparound var g = new IdGenerator(0, TESTEPOCH, m, ts); Assert.IsTrue(g.CreateId() > 0); // Should succeed; ts.NextTick(); g.CreateId(); // Should fail }
public void GeneratorId_ShouldBePresent_InID1() { // We setup our generator so that the time is 0 and generator id equals 1023 so that all 10 bits are set // for the generator. var ts = new MockTimeSource(0); var g = new IdGenerator(1023, new IdGeneratorOptions(timeSource: ts)); // Make sure all expected bits are set Assert.AreEqual((1 << g.Options.IdStructure.GeneratorIdBits) - 1 << g.Options.IdStructure.SequenceBits, g.CreateId()); }
public void Constructor_Throws_OnTimestampWraparound() { var mc = MaskConfig.Default; var ts = new MockTimeSource(mc.WraparoundDate(TESTEPOCH).AddMilliseconds(-1)); //Set clock to 1 ms before epoch var g = new IdGenerator(0, TESTEPOCH, MaskConfig.Default, ts); Assert.IsTrue(g.CreateId() > 0); //Should succeed; ts.NextTick(); g.CreateId(); //Should fail }
public void CreateId_Throws_OnClockBackwards() { var ts = new MockTimeSource(DateTime.UtcNow); var m = MaskConfig.Default; var g = new IdGenerator(0, TESTEPOCH, m, ts); g.CreateId(); ts.PreviousTick(); //Set clock back 1 'tick' (ms) g.CreateId(); }
public void Sequence_ShouldIncrease_EveryInvocation() { // We setup our generator so that the time is 0, generator id 0 and we're only left with the sequence // increasing each invocation of CreateId(); var ts = new MockTimeSource(0); var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); Assert.AreEqual(0, g.CreateId()); Assert.AreEqual(1, g.CreateId()); Assert.AreEqual(2, g.CreateId()); }
public void GeneratorId_ShouldBeMasked_WhenReadFromProperty() { // We setup our generator so that the time is 0 and generator id equals 1023 so that all 10 bits are set // for the generator. var ts = new MockTimeSource(); var m = MaskConfig.Default; var g = new IdGenerator(1023, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual((1 << m.GeneratorIdBits) - 1, g.Id); }
public void GeneratorId_ShouldBePresent_InID1() { // We setup our generator so that the time is 0 and generator id equals 1023 so that all 10 bits are set // for the generator. var ts = new MockTimeSource(); var m = MaskConfig.Default; // We use a default mask-config with 11 bits for the generator this time var g = new IdGenerator(1023, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual((1 << m.GeneratorIdBits) - 1 << m.SequenceBits, g.CreateId()); }
public void GeneratorId_ShouldBePresent_InID2() { // We setup our generator so that the time is 0 and generator id equals 4095 so that all 12 bits are set // for the generator. var ts = new MockTimeSource(); var m = new MaskConfig(40, 12, 11); // We use a custom mask-config with 12 bits for the generator this time var g = new IdGenerator(4095, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual(-1 & ((1 << 12) - 1), g.Id); Assert.AreEqual((1 << 12) - 1 << 11, g.CreateId()); }
public void Sequence_ShouldIncrease_EveryInvocation() { // We setup our generator so that the time (current - epoch) results in 0, generator id 0 and we're only // left with the sequence increasing each invocation of CreateId(); var ts = new MockTimeSource(TESTEPOCH); var m = MaskConfig.Default; var g = new IdGenerator(0, TESTEPOCH, MaskConfig.Default, ts); Assert.AreEqual(0, g.CreateId()); Assert.AreEqual(1, g.CreateId()); Assert.AreEqual(2, g.CreateId()); }
public void GeneratorId_ShouldBePresent_InID2() { // We setup our generator so that the time is 0 and generator id equals 4095 so that all 12 bits are set // for the generator. var ts = new MockTimeSource(); var s = new IdStructure(40, 12, 11); // We use a custom IdStructure with 12 bits for the generator this time var g = new IdGenerator(4095, new IdGeneratorOptions(s, ts)); // Make sure all expected bits are set Assert.AreEqual(-1 & ((1 << 12) - 1), g.Id); Assert.AreEqual((1 << 12) - 1 << 11, g.CreateId()); }
public void CreateId_Throws_OnSequenceOverflow() { var ts = new MockTimeSource(); var g = new IdGenerator(0, TESTEPOCH, new MaskConfig(41, 20, 2), ts); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (int i = 0; i < 4; i++) { Assert.AreEqual(i, g.CreateId()); } // However, if we invoke once more we should get an SequenceOverflowException g.CreateId(); }
public void CreateId_Throws_OnSequenceOverflow() { var ts = new MockTimeSource(); var s = new IdStructure(41, 20, 2); var g = new IdGenerator(0, new IdGeneratorOptions(idStructure: s, timeSource: ts)); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (var i = 0; i < 4; i++) { Assert.AreEqual(i, g.CreateId()); } // However, if we invoke once more we should get an SequenceOverflowException g.CreateId(); }
public void Sequence_ShouldReset_EveryNewTick() { // We setup our generator so that the time is 0, generator id 0 and we're only left with the sequence // increasing each invocation of CreateId(); var ts = new MockTimeSource(0); var g = new IdGenerator(0, new IdGeneratorOptions(timeSource: ts)); Assert.AreEqual(0, g.CreateId()); Assert.AreEqual(1, g.CreateId()); ts.NextTick(); // Since the timestamp has increased, we should now have a much higher value (since the timestamp is // shifted left a number of bits (specifically GeneratorIdBits + SequenceBits) Assert.AreEqual((1 << (g.Options.IdStructure.GeneratorIdBits + g.Options.IdStructure.SequenceBits)) + 0, g.CreateId()); Assert.AreEqual((1 << (g.Options.IdStructure.GeneratorIdBits + g.Options.IdStructure.SequenceBits)) + 1, g.CreateId()); }
public void TryCreateId_Returns_False_OnSequenceOverflow() { var ts = new MockTimeSource(); var g = new IdGenerator(0, new MaskConfig(41, 20, 2), ts); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (int i = 0; i < 4; i++) { Assert.IsTrue(g.TryCreateId(out var _)); } // However, if we invoke once more we should get an SequenceOverflowException // which should be indicated by the false return value Assert.IsFalse(g.TryCreateId(out var _)); }
public void Sequence_ShouldReset_EveryNewTick() { // We setup our generator so that the time (current - epoch) results in 0, generator id 0 and we're only // left with the sequence increasing each invocation of CreateId(); var ts = new MockTimeSource(TESTEPOCH); var m = MaskConfig.Default; var g = new IdGenerator(0, TESTEPOCH, m, ts); Assert.AreEqual(0, g.CreateId()); Assert.AreEqual(1, g.CreateId()); ts.NextTick(); // Since the timestamp has increased, we should now have a much higher value (since the timestamp is shifted // left a number of bits (specifically GeneratorIdBits + SequenceBits) Assert.AreEqual((1 << (m.GeneratorIdBits + m.SequenceBits)) + 0, g.CreateId()); Assert.AreEqual((1 << (m.GeneratorIdBits + m.SequenceBits)) + 1, g.CreateId()); }
public void CreateId_Waits_OnSequenceOverflow() { var ts = new MockTimeSource() { AutoincrementAfterCallsNum = 20 }; var g = new IdGenerator(0, new MaskConfig(61, 0, 2), ts) { SpinOnTimeSlotExhausted = true }; // We have a 2-bit sequence; generating 4 id's in a single time slot - wait for other then for (int i = 0; i < 20; i++) { Assert.AreEqual(i, g.CreateId()); } }
public void Constructor_Overloads() { var ts = new MockTimeSource(); var m = MaskConfig.Default; // Check all constructor overload variations Assert.ReferenceEquals(TESTEPOCH, new IdGenerator(0, TESTEPOCH).Epoch); Assert.ReferenceEquals(ts, new IdGenerator(0, ts).TimeSource); Assert.ReferenceEquals(ts, new IdGenerator(0, TESTEPOCH, ts).Epoch); Assert.ReferenceEquals(ts, new IdGenerator(0, TESTEPOCH, ts).TimeSource); Assert.ReferenceEquals(TESTEPOCH, new IdGenerator(0, TESTEPOCH, m).MaskConfig); Assert.ReferenceEquals(m, new IdGenerator(0, TESTEPOCH, m).MaskConfig); Assert.ReferenceEquals(TESTEPOCH, new IdGenerator(0, TESTEPOCH, m, ts).Epoch); Assert.ReferenceEquals(m, new IdGenerator(0, TESTEPOCH, m, ts).MaskConfig); Assert.ReferenceEquals(ts, new IdGenerator(0, TESTEPOCH, m, ts).TimeSource); }
public void Constructor_Throws_OnEpochInFuture() { var ts = new MockTimeSource(TESTEPOCH); new IdGenerator(0, TESTEPOCH.AddTicks(1), MaskConfig.Default, ts); }
public void GeneratorId_ShouldBePresent_InID2() { // We setup our generator so that the time (current - epoch) results in 0, generator id 4095 so that all 12 bits // are set for the generator. var ts = new MockTimeSource(TESTEPOCH); var m = new MaskConfig(40, 12, 11); // We use a custom mask-config with 12 bits for the generator this time var g = new IdGenerator(4095, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual(-1 & ((1 << 12) - 1), g.Id); Assert.AreEqual((1 << 12) - 1 << 11, g.CreateId()); }
public void CreateId_Throws_OnSequenceOverflow() { var ts = new MockTimeSource(TESTEPOCH); var g = new IdGenerator(0, TESTEPOCH, new MaskConfig(41, 20, 2), ts); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (int i = 0; i < 4; i++) Assert.AreEqual(i, g.CreateId()); // However, if we invoke once more we should get an SequenceOverflowException g.CreateId(); }
public void GeneratorId_ShouldBeMasked_WhenReadFromProperty() { // We setup our generator so that the time (current - epoch) results in 0, generator id 1023 so that all 10 // bits are set for the generator. var ts = new MockTimeSource(TESTEPOCH); var m = MaskConfig.Default; var g = new IdGenerator(1023, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual((1 << m.GeneratorIdBits) - 1, g.Id); }
public void GeneratorId_ShouldBePresent_InID1() { // We setup our generator so that the time (current - epoch) results in 0, generator id 1023 so that all 10 bits // are set for the generator. var ts = new MockTimeSource(TESTEPOCH); var m = MaskConfig.Default; // We use a default mask-config with 11 bits for the generator this time var g = new IdGenerator(1023, TESTEPOCH, m, ts); // Make sure all expected bits are set Assert.AreEqual((1 << m.GeneratorIdBits) - 1 << m.SequenceBits, g.CreateId()); }