Пример #1
0
        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...
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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();
        }
Пример #7
0
        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 _));
        }
Пример #8
0
        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
        }
Пример #9
0
        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
        }
Пример #10
0
        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);
        }
Пример #11
0
        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();
        }
Пример #12
0
        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
        }
Пример #13
0
        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());
        }
Пример #14
0
        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
        }
Пример #15
0
        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
        }
Пример #16
0
        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();
        }
Пример #17
0
        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());
        }
Пример #18
0
        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);
        }
Пример #19
0
        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());
        }
Пример #20
0
        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());
        }
Пример #21
0
        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());
        }
Пример #22
0
        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());
        }
Пример #23
0
        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();
        }
Пример #24
0
        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();
        }
Пример #25
0
        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());
        }
Пример #26
0
        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 _));
        }
Пример #27
0
        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());
        }
Пример #28
0
        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());
            }
        }
Пример #29
0
        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);
        }
Пример #30
0
 public void Constructor_Throws_OnEpochInFuture()
 {
     var ts = new MockTimeSource(TESTEPOCH);
     new IdGenerator(0, TESTEPOCH.AddTicks(1), MaskConfig.Default, ts);
 }
Пример #31
0
        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());
        }
Пример #32
0
        public void Constructor_Throws_OnEpochInFuture()
        {
            var ts = new MockTimeSource(TESTEPOCH);

            new IdGenerator(0, TESTEPOCH.AddTicks(1), MaskConfig.Default, ts);
        }
Пример #33
0
        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());
        }
Пример #34
0
        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();
        }
Пример #35
0
        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();
        }
Пример #36
0
        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);
        }
Пример #37
0
        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());
        }
Пример #38
0
        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());
        }