public void Test_Bit_Twiddling() { Assert.That(ColaStore.LowestBit(0), Is.EqualTo(0)); Assert.That(ColaStore.HighestBit(0), Is.EqualTo(0)); Assert.That(ColaStore.LowestBit(42), Is.EqualTo(1)); Assert.That(ColaStore.HighestBit(42), Is.EqualTo(5)); for (int i = 1; i < 30; i++) { int x = 1 << i; Assert.That(ColaStore.LowestBit(x), Is.EqualTo(i)); Assert.That(ColaStore.HighestBit(x), Is.EqualTo(i)); Assert.That(ColaStore.HighestBit(x - 1), Is.EqualTo(i - 1)); Assert.That(ColaStore.LowestBit(x - 1), Is.EqualTo(0)); } Assert.That(ColaStore.LowestBit(0x60000000), Is.EqualTo(29)); for (int i = 1; i < 30; i++) { int x = int.MaxValue - ((1 << i) - 1); Assert.That(ColaStore.LowestBit(x), Is.EqualTo(i), "i={0}, x={1} : {2}", i, x.ToString("X8"), Convert.ToString(x, 2)); } }
static void Main(string[] args) { Console.WriteLine(MessageLookup.WELCOME); var randomCustomer = Gateway.GetAdminCustomer(); Console.WriteLine(MessageLookup.DEFAULT_USER(randomCustomer.UserName)); Console.WriteLine(MessageLookup.DEFAULT_PASS(randomCustomer.Password)); Console.WriteLine(MessageLookup.DEFAULT_CREDIT(randomCustomer.Credit)); try { var order = ColaStore.GetOrder(); var groupedColas = order.Colas.GroupBy(c => c.ColaType); foreach (var grouped in groupedColas) { Console.WriteLine($"{Enum.GetName(typeof(ColaType), grouped.Key)} Cola Quantity: {grouped.Count()}"); Console.WriteLine($"{Enum.GetName(typeof(ColaType), grouped.Key)} Cola Total Price: {grouped.Sum(c=>c.Price.Credit)}"); } Console.WriteLine(MessageLookup.EXIT); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadKey(); } }
public void Test_Map_Index_To_Address() { // index => (level, offset) int level, offset; for (int i = 0; i < 1024; i++) { level = ColaStore.FromIndex(i, out offset); Assert.That(((1 << level) - 1) + offset, Is.EqualTo(i), "{0} => ({1}, {2})", i, level, offset); } }
public void Test_ColaStore_Iterator_Seek_Randomized() { const int N = 1000; var store = new ColaStore <int?>(0, Comparer <int?> .Default); var rnd = new Random(); int seed = rnd.Next(); Console.WriteLine("seed = " + seed); rnd = new Random(seed); var list = Enumerable.Range(0, N).ToList(); while (list.Count > 0) { int p = rnd.Next(list.Count); store.Insert(list[p]); list.RemoveAt(p); } store.Debug_Dump(); for (int i = 0; i < N; i++) { var iterator = store.GetIterator(); int p = rnd.Next(N); bool orEqual = rnd.Next(2) == 0; bool res = iterator.Seek(p, orEqual); if (orEqual) { // the key should exist Assert.That(res, Is.True, "Seek({0}, '<=')", p); Assert.That(iterator.Current, Is.EqualTo(p), "Seek({0}, '<=')", p); Assert.That(iterator.Valid, Is.True, "Seek({0}, '<=')", p); } else if (p == 0) { // there is no key before the first Assert.That(res, Is.False, "Seek(0, '<')"); Assert.That(iterator.Current, Is.Null, "Seek(0, '<')"); Assert.That(iterator.Valid, Is.False, "Seek(0, '<')"); } else { // the key should exist Assert.That(res, Is.True, "Seek({0}, '<')", p); Assert.That(iterator.Current, Is.EqualTo(p - 1), "Seek({0}, '<')", p); Assert.That(iterator.Valid, Is.True, "Seek({0}, '<')", p); } } }
public void Test_Map_Address_Index() { // index => (level, offset) for (int level = 0; level <= 10; level++) { int n = 1 << level; for (int offset = 0; offset < n; offset++) { int index = ColaStore.ToIndex(level, offset); Assert.That(index, Is.EqualTo(n - 1 + offset), "({0}, {1}) => {2}", level, offset, index); } } }
public void Test_Map_Offset_To_Index() { //N = 1 // > 0 [0] Assert.That(ColaStore.MapOffsetToIndex(1, 0), Is.EqualTo(0)); Assert.That(() => ColaStore.MapOffsetToIndex(1, 1), Throws.InstanceOf <ArgumentOutOfRangeException>()); //N = 2 // > 0 [_] // > 1 [0, 1] Assert.That(ColaStore.MapOffsetToIndex(2, 0), Is.EqualTo(1)); Assert.That(ColaStore.MapOffsetToIndex(2, 1), Is.EqualTo(2)); Assert.That(() => ColaStore.MapOffsetToIndex(2, 2), Throws.InstanceOf <ArgumentOutOfRangeException>()); //N = 3 // > 0 [2] // > 1 [0, 1] Assert.That(ColaStore.MapOffsetToIndex(3, 0), Is.EqualTo(1)); Assert.That(ColaStore.MapOffsetToIndex(3, 1), Is.EqualTo(2)); Assert.That(ColaStore.MapOffsetToIndex(3, 2), Is.EqualTo(0)); Assert.That(() => ColaStore.MapOffsetToIndex(3, 3), Throws.InstanceOf <ArgumentOutOfRangeException>()); //N = 5 // > 0 [4] // > 1 [_, _] // > 2 [0, 1, 2, 3] Assert.That(ColaStore.MapOffsetToIndex(5, 0), Is.EqualTo(3)); Assert.That(ColaStore.MapOffsetToIndex(5, 1), Is.EqualTo(4)); Assert.That(ColaStore.MapOffsetToIndex(5, 2), Is.EqualTo(5)); Assert.That(ColaStore.MapOffsetToIndex(5, 3), Is.EqualTo(6)); Assert.That(ColaStore.MapOffsetToIndex(5, 4), Is.EqualTo(0)); Assert.That(() => ColaStore.MapOffsetToIndex(5, 5), Throws.InstanceOf <ArgumentOutOfRangeException>()); // N = 10 // > 0 [_] // > 1 [8,9] // > 2 [_,_,_,_] // > 3 [0,1,2,3,4,5,6,7] for (int i = 0; i < 8; i++) { Assert.That(ColaStore.MapOffsetToIndex(10, i), Is.EqualTo(7 + i), "MapOffset(10, {0})", i); } for (int i = 8; i < 10; i++) { Assert.That(ColaStore.MapOffsetToIndex(10, i), Is.EqualTo(1 + (i - 8)), "MapOffset(10, {0})", i); } Assert.That(() => ColaStore.MapOffsetToIndex(10, 123), Throws.InstanceOf <ArgumentOutOfRangeException>()); }
public void Test_ColaStore_Iterator_Seek() { var store = new ColaStore <int?>(0, Comparer <int?> .Default); for (int i = 0; i < 10; i++) { store.Insert(i); } store.Debug_Dump(); var iterator = store.GetIterator(); Assert.That(iterator.Seek(5, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(5)); Assert.That(iterator.Seek(5, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(4)); Assert.That(iterator.Seek(9, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); Assert.That(iterator.Seek(9, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(8)); Assert.That(iterator.Seek(0, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(0)); Assert.That(iterator.Seek(0, false), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Seek(10, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); Assert.That(iterator.Seek(10, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); }
public void Test_MiniBench() { const int N = (1 << 23) - 1; // 10 * 1000 * 1000; var rnd = new Random(); int offset, level; long x; //WARMUP var store = new ColaStore <long>(0, Comparer <long> .Default); store.Insert(1); store.Insert(42); store.Insert(1234); level = store.Find(1, out offset, out x); const int BS = (N + 1) / 128; var timings = new List <TimeSpan>(BS); timings.Add(TimeSpan.Zero); timings.Clear(); #region Sequentially inserted.... Console.WriteLine("Inserting {0} sequential keys into a COLA store", N); GC.Collect(); store = new ColaStore <long>(0, Comparer <long> .Default); long total = 0; var sw = Stopwatch.StartNew(); for (int i = 0; i < N; i++) { int y = rnd.Next(100); level = store.Find(y, out offset, out x); if (level < 0) { store.Insert(i); } else { store.SetAt(level, offset, x); } Interlocked.Increment(ref total); if ((i % BS) == BS - 1) { sw.Stop(); timings.Add(sw.Elapsed); Console.Write("."); sw.Start(); } } sw.Stop(); Console.WriteLine("done"); Console.WriteLine("* Inserted: " + total.ToString("N0") + " keys"); Console.WriteLine("* Elapsed : " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec"); Console.WriteLine("* KPS: " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " key/sec"); Console.WriteLine("* Latency : " + (sw.Elapsed.TotalMilliseconds * 1000000 / total).ToString("N1") + " nanos / insert"); for (int i = 0; i < timings.Count; i++) { Console.WriteLine("" + ((i + 1) * BS).ToString() + "\t" + timings[i].TotalSeconds); } return; // sequential reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(i, out offset, out x); } sw.Stop(); Console.WriteLine("SeqReadOrdered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); // random reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(rnd.Next(N), out offset, out x); } sw.Stop(); Console.WriteLine("RndReadOrdered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); #endregion #region Randomly inserted.... Console.WriteLine("(preparing random insert list)"); var tmp = new long[N]; var values = new long[N]; for (int i = 0; i < N; i++) { tmp[i] = rnd.Next(N); values[i] = i; } Array.Sort(tmp, values); Console.WriteLine("Inserting " + N.ToString("N0") + " sequential keys into a COLA store"); GC.Collect(); store = new ColaStore <long>(0, Comparer <long> .Default); total = 0; timings.Clear(); sw.Restart(); for (int i = 0; i < N; i++) { level = store.Find(i, out offset, out x); store.Insert(values[i]); Interlocked.Increment(ref total); if ((i % BS) == BS - 1) { sw.Stop(); timings.Add(sw.Elapsed); Console.Write("."); sw.Start(); } } sw.Stop(); Console.WriteLine("done"); Console.WriteLine("* Inserted: " + total.ToString("N0") + " keys"); Console.WriteLine("* Elapsed : " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec"); Console.WriteLine("* KPS : " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " key/sec"); Console.WriteLine("* Latency : " + (sw.Elapsed.TotalMilliseconds * 1000000 / total).ToString("N1") + " nanos / insert"); for (int i = 0; i < timings.Count; i++) { Console.WriteLine("" + ((i + 1) * BS).ToString() + "\t" + timings[i].TotalSeconds); } // sequential reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(i, out offset, out x); } sw.Stop(); Console.WriteLine("SeqReadUnordered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); // random reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(rnd.Next(N), out offset, out x); } sw.Stop(); Console.WriteLine("RndReadUnordered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); #endregion }
public void Test_ColaStore_Iterator_Seek_Then_Next_Randomized() { const int N = 1000; const int K = 10; var store = new ColaStore <int?>(0, Comparer <int?> .Default); var rnd = new Random(); int seed = rnd.Next(); Console.WriteLine("seed = " + seed); rnd = new Random(seed); var list = Enumerable.Range(0, N).ToList(); while (list.Count > 0) { int p = rnd.Next(list.Count); store.Insert(list[p]); list.RemoveAt(p); } store.Debug_Dump(); for (int i = 0; i < N; i++) { var iterator = store.GetIterator(); int p = rnd.Next(N); bool orEqual = rnd.Next(2) == 0; if (p == 0 && !orEqual) { continue; //TODO: what to do for this case ? } Assert.That(iterator.Seek(p, orEqual), Is.True); int?x = iterator.Current; Assert.That(x, Is.EqualTo(orEqual ? p : p - 1)); // all the next should be ordered (starting from p) while (x < N - 1) { Assert.That(iterator.Next(), Is.True, "Seek({0}).Current({1}).Next()", p, x); Assert.That(iterator.Current, Is.EqualTo(x + 1), "Seek({0}).Current({1}).Next()", p, x); ++x; } // the following Next() should go past the end Assert.That(iterator.Next(), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Valid, Is.False); // re-seek to the original location Assert.That(iterator.Seek(p, orEqual), Is.True); x = iterator.Current; Assert.That(x, Is.EqualTo(orEqual ? p : p - 1)); // now go backwards while (x > 0) { Assert.That(iterator.Previous(), Is.True, "Seek({0}).Current({1}).Previous()", p, x); Assert.That(iterator.Current, Is.EqualTo(x - 1), "Seek({0}).Current({1}).Previous()", p, x); --x; } // the following Previous() should go past the beginning Assert.That(iterator.Previous(), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Valid, Is.False); if (p >= K && p < N - K) { // jitter dance // start to original location Assert.That(iterator.Seek(p, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(p)); var sb = new StringBuilder(); sb.Append("Seek -> "); for (int j = 0; j < K; j++) { x = iterator.Current; sb.Append(iterator.Current); if (rnd.Next(2) == 0) { // next sb.Append(" -> "); Assert.That(iterator.Next(), Is.True, "{0}", sb); Assert.That(iterator.Current, Is.EqualTo(x + 1), "{0} = ?", sb); } else { // prev sb.Append(" <- "); Assert.That(iterator.Previous(), Is.True, "{0}", sb); Assert.That(iterator.Current, Is.EqualTo(x - 1), "{0} = ?", sb); } } } } }
public void Test_MiniBench() { const int N = (1 << 23) - 1; // 10 * 1000 * 1000; var rnd = new Random(); int offset, level; long x; //WARMUP var store = new ColaStore<long>(0, Comparer<long>.Default); store.Insert(1); store.Insert(42); store.Insert(1234); level = store.Find(1, out offset, out x); const int BS = (N + 1) / 128; var timings = new List<TimeSpan>(BS); timings.Add(TimeSpan.Zero); timings.Clear(); #region Sequentially inserted.... Console.WriteLine("Inserting {0} sequential keys into a COLA store", N); GC.Collect(); store = new ColaStore<long>(0, Comparer<long>.Default); long total = 0; var sw = Stopwatch.StartNew(); for (int i = 0; i < N; i++) { int y = rnd.Next(100); level = store.Find(y, out offset, out x); if (level < 0) store.Insert(i); else store.SetAt(level, offset, x); Interlocked.Increment(ref total); if ((i % BS) == BS - 1) { sw.Stop(); timings.Add(sw.Elapsed); Console.Write("."); sw.Start(); } } sw.Stop(); Console.WriteLine("done"); Console.WriteLine("* Inserted: " + total.ToString("N0") + " keys"); Console.WriteLine("* Elapsed : " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec"); Console.WriteLine("* KPS: " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " key/sec"); Console.WriteLine("* Latency : " + (sw.Elapsed.TotalMilliseconds * 1000000 / total).ToString("N1") + " nanos / insert"); for (int i = 0; i < timings.Count; i++) { Console.WriteLine("" + ((i + 1) * BS).ToString() + "\t" + timings[i].TotalSeconds); } return; // sequential reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(i, out offset, out x); } sw.Stop(); Console.WriteLine("SeqReadOrdered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); // random reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(rnd.Next(N), out offset, out x); } sw.Stop(); Console.WriteLine("RndReadOrdered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); #endregion #region Randomly inserted.... Console.WriteLine("(preparing random insert list)"); var tmp = new long[N]; var values = new long[N]; for (int i = 0; i < N; i++) { tmp[i] = rnd.Next(N); values[i] = i; } Array.Sort(tmp, values); Console.WriteLine("Inserting " + N.ToString("N0") + " sequential keys into a COLA store"); GC.Collect(); store = new ColaStore<long>(0, Comparer<long>.Default); total = 0; timings.Clear(); sw.Restart(); for (int i = 0; i < N; i++) { level = store.Find(i, out offset, out x); store.Insert(values[i]); Interlocked.Increment(ref total); if ((i % BS) == BS - 1) { sw.Stop(); timings.Add(sw.Elapsed); Console.Write("."); sw.Start(); } } sw.Stop(); Console.WriteLine("done"); Console.WriteLine("* Inserted: " + total.ToString("N0") + " keys"); Console.WriteLine("* Elapsed : " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec"); Console.WriteLine("* KPS : " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " key/sec"); Console.WriteLine("* Latency : " + (sw.Elapsed.TotalMilliseconds * 1000000 / total).ToString("N1") + " nanos / insert"); for (int i = 0; i < timings.Count;i++) { Console.WriteLine("" + ((i + 1) * BS).ToString() + "\t" + timings[i].TotalSeconds); } // sequential reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(i, out offset, out x); } sw.Stop(); Console.WriteLine("SeqReadUnordered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); // random reads sw.Restart(); for (int i = 0; i < total; i++) { level = store.Find(rnd.Next(N), out offset, out x); } sw.Stop(); Console.WriteLine("RndReadUnordered: " + total.ToString("N0") + " keys in " + sw.Elapsed.TotalSeconds.ToString("N3") + " sec => " + (total / sw.Elapsed.TotalSeconds).ToString("N0") + " kps"); #endregion }
public void Test_ColaStore_Iterator_Seek_Then_Next_Randomized() { const int N = 1000; const int K = 10; var store = new ColaStore<int?>(0, Comparer<int?>.Default); var rnd = new Random(); int seed = rnd.Next(); Console.WriteLine("seed = " + seed); rnd = new Random(seed); var list = Enumerable.Range(0, N).ToList(); while (list.Count > 0) { int p = rnd.Next(list.Count); store.Insert(list[p]); list.RemoveAt(p); } store.Debug_Dump(); for (int i = 0; i < N; i++) { var iterator = store.GetIterator(); int p = rnd.Next(N); bool orEqual = rnd.Next(2) == 0; if (p == 0 && !orEqual) continue; //TODO: what to do for this case ? Assert.That(iterator.Seek(p, orEqual), Is.True); int? x = iterator.Current; Assert.That(x, Is.EqualTo(orEqual ? p : p - 1)); // all the next should be ordered (starting from p) while (x < N - 1) { Assert.That(iterator.Next(), Is.True, "Seek({0}).Current({1}).Next()", p, x); Assert.That(iterator.Current, Is.EqualTo(x + 1), "Seek({0}).Current({1}).Next()", p, x); ++x; } // the following Next() should go past the end Assert.That(iterator.Next(), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Valid, Is.False); // re-seek to the original location Assert.That(iterator.Seek(p, orEqual), Is.True); x = iterator.Current; Assert.That(x, Is.EqualTo(orEqual ? p : p - 1)); // now go backwards while (x > 0) { Assert.That(iterator.Previous(), Is.True, "Seek({0}).Current({1}).Previous()", p, x); Assert.That(iterator.Current, Is.EqualTo(x - 1), "Seek({0}).Current({1}).Previous()", p, x); --x; } // the following Previous() should go past the beginning Assert.That(iterator.Previous(), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Valid, Is.False); if (p >= K && p < N - K) { // jitter dance // start to original location Assert.That(iterator.Seek(p, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(p)); var sb = new StringBuilder(); sb.Append("Seek -> "); for(int j = 0; j < K; j++) { x = iterator.Current; sb.Append(iterator.Current); if (rnd.Next(2) == 0) { // next sb.Append(" -> "); Assert.That(iterator.Next(), Is.True, "{0}", sb); Assert.That(iterator.Current, Is.EqualTo(x + 1), "{0} = ?", sb); } else { // prev sb.Append(" <- "); Assert.That(iterator.Previous(), Is.True, "{0}", sb); Assert.That(iterator.Current, Is.EqualTo(x - 1), "{0} = ?", sb); } } } } }
public void Test_ColaStore_Iterator_Seek_Randomized() { const int N = 1000; var store = new ColaStore<int?>(0, Comparer<int?>.Default); var rnd = new Random(); int seed = rnd.Next(); Console.WriteLine("seed = " + seed); rnd = new Random(seed); var list = Enumerable.Range(0, N).ToList(); while(list.Count > 0) { int p = rnd.Next(list.Count); store.Insert(list[p]); list.RemoveAt(p); } store.Debug_Dump(); for (int i = 0; i < N; i++) { var iterator = store.GetIterator(); int p = rnd.Next(N); bool orEqual = rnd.Next(2) == 0; bool res = iterator.Seek(p, orEqual); if (orEqual) { // the key should exist Assert.That(res, Is.True, "Seek({0}, '<=')", p); Assert.That(iterator.Current, Is.EqualTo(p), "Seek({0}, '<=')", p); Assert.That(iterator.Valid, Is.True, "Seek({0}, '<=')", p); } else if (p == 0) { // there is no key before the first Assert.That(res, Is.False, "Seek(0, '<')"); Assert.That(iterator.Current, Is.Null, "Seek(0, '<')"); Assert.That(iterator.Valid, Is.False, "Seek(0, '<')"); } else { // the key should exist Assert.That(res, Is.True, "Seek({0}, '<')", p); Assert.That(iterator.Current, Is.EqualTo(p - 1), "Seek({0}, '<')", p); Assert.That(iterator.Valid, Is.True, "Seek({0}, '<')", p); } } }
public void Test_ColaStore_Iterator_Seek() { var store = new ColaStore<int?>(0, Comparer<int?>.Default); for (int i = 0; i < 10; i++) { store.Insert(i); } store.Debug_Dump(); var iterator = store.GetIterator(); Assert.That(iterator.Seek(5, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(5)); Assert.That(iterator.Seek(5, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(4)); Assert.That(iterator.Seek(9, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); Assert.That(iterator.Seek(9, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(8)); Assert.That(iterator.Seek(0, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(0)); Assert.That(iterator.Seek(0, false), Is.False); Assert.That(iterator.Current, Is.Null); Assert.That(iterator.Seek(10, true), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); Assert.That(iterator.Seek(10, false), Is.True); Assert.That(iterator.Current, Is.EqualTo(9)); }