private static void VerifyCreate(
     PartitionKeyHashRanges.CreateOutcome expectedCreateStatus,
     params PartitionKeyHashRange[] rangesToInsert)
 {
     PartitionKeyHashRanges.CreateOutcome actualCreateStatus = PartitionKeyHashRanges.TryCreate(
         rangesToInsert.OrderBy(x => Guid.NewGuid()),
         out PartitionKeyHashRanges insertedRanges);
     Assert.AreEqual(expectedCreateStatus, actualCreateStatus);
     if (expectedCreateStatus == PartitionKeyHashRanges.CreateOutcome.Success)
     {
         Assert.AreEqual(rangesToInsert.Count(), insertedRanges.Count());
         IEnumerable <(PartitionKeyHashRange, PartitionKeyHashRange)> pairs = insertedRanges.Zip(insertedRanges.Skip(1), (first, second) => (first, second));
         foreach ((PartitionKeyHashRange first, PartitionKeyHashRange second) in pairs)
         {
             Assert.IsTrue(first.CompareTo(second) < 0, "Ranges are not sorted");
         }
     }
 }
        public void TestSplit()
        {
            {
                // Empty partition
                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.RangeNotWideEnough,
                    range: CreateRange(0, 0));
            }

            {
                // Range Not Wide Enough
                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.RangeNotWideEnough,
                    range: CreateRange(0, 1),
                    numRanges: 2);
            }

            {
                // Ranges Need to Be Positive
                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.NumRangesNeedsToBeGreaterThanZero,
                    range: CreateRange(0, 2),
                    numRanges: 0);

                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.NumRangesNeedsToBeGreaterThanZero,
                    range: CreateRange(0, 2),
                    numRanges: -1);
            }

            {
                // Success
                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(0, 2),
                    numRanges: 2,
                    CreateRange(0, 1), CreateRange(1, 2));

                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(0, 3),
                    numRanges: 2,
                    CreateRange(0, 1), CreateRange(1, 3));

                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(0, 3),
                    numRanges: 1,
                    CreateRange(0, 3));
            }

            {
                // Split with open ranges
                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(0, null),
                    numRanges: 2,
                    CreateRange(0, UInt128.MaxValue / 2), CreateRange(UInt128.MaxValue / 2, null));

                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(null, 4),
                    numRanges: 2,
                    CreateRange(null, 2), CreateRange(2, 4));

                VerifySplit(
                    splitOutcome: PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success,
                    range: CreateRange(null, null),
                    numRanges: 2,
                    CreateRange(null, UInt128.MaxValue / 2), CreateRange(UInt128.MaxValue / 2, null));
            }

            void VerifySplit(
                PartitionKeyHashRangeSplitterAndMerger.SplitOutcome splitOutcome,
                PartitionKeyHashRange range,
                int numRanges = 1,
                params PartitionKeyHashRange[] splitRanges)
            {
                PartitionKeyHashRangeSplitterAndMerger.SplitOutcome actualSplitOutcome = PartitionKeyHashRangeSplitterAndMerger.TrySplitRange(
                    partitionKeyHashRange: range,
                    rangeCount: numRanges,
                    splitRanges: out PartitionKeyHashRanges splitRangesActual);

                Assert.AreEqual(splitOutcome, actualSplitOutcome);
                if (splitOutcome == PartitionKeyHashRangeSplitterAndMerger.SplitOutcome.Success)
                {
                    Assert.AreEqual(numRanges, splitRangesActual.Count());
                    Assert.AreEqual(splitRanges.Count(), splitRangesActual.Count());

                    PartitionKeyHashRanges expectedSplitRanges = PartitionKeyHashRanges.Create(splitRanges);

                    IEnumerable <(PartitionKeyHashRange, PartitionKeyHashRange)> expectedAndActual = expectedSplitRanges.Zip(splitRangesActual, (first, second) => (first, second));
                    foreach ((PartitionKeyHashRange expected, PartitionKeyHashRange actual) in expectedAndActual)
                    {
                        Assert.AreEqual(expected, actual);
                    }
                }
            }
        }