@Override
 public long nextValue() throws IOException {
   assertThread("Sorted numeric doc values", creationThread);
   assert valueUpto < in.docValueCount()
       : "valueUpto=" + valueUpto + " in.docValueCount()=" + in.docValueCount();
   valueUpto++;
   return in.nextValue();
 }
 @Override
 public int nextDoc() throws IOException {
   assertThread("Sorted numeric doc values", creationThread);
   int docID = in.nextDoc();
   assert docID > lastDocID;
   assert docID == NO_MORE_DOCS || docID < maxDoc;
   assert docID == in.docID();
   lastDocID = docID;
   valueUpto = 0;
   return docID;
 }
 @Override
 public int advance(int target) throws IOException {
   assertThread("Sorted numeric doc values", creationThread);
   assert target >= 0;
   assert target >= in.docID();
   int docID = in.advance(target);
   assert docID == in.docID();
   assert docID >= target;
   assert docID == NO_MORE_DOCS || docID < maxDoc;
   lastDocID = docID;
   valueUpto = 0;
   return docID;
 }
  private static void duelFieldDataLong(
      Random random,
      AtomicReaderContext context,
      IndexNumericFieldData left,
      IndexNumericFieldData right)
      throws Exception {
    AtomicNumericFieldData leftData =
        random.nextBoolean() ? left.load(context) : left.loadDirect(context);
    AtomicNumericFieldData rightData =
        random.nextBoolean() ? right.load(context) : right.loadDirect(context);

    int numDocs = context.reader().maxDoc();
    SortedNumericDocValues leftLongValues = leftData.getLongValues();
    SortedNumericDocValues rightLongValues = rightData.getLongValues();
    for (int i = 0; i < numDocs; i++) {
      leftLongValues.setDocument(i);
      rightLongValues.setDocument(i);
      int numValues = leftLongValues.count();
      long previous = 0;
      assertThat(numValues, equalTo(rightLongValues.count()));
      for (int j = 0; j < numValues; j++) {
        long current;
        assertThat(leftLongValues.valueAt(j), equalTo(current = rightLongValues.valueAt(j)));
        if (j > 0) {
          assertThat(previous, lessThan(current));
        }
        previous = current;
      }
    }
  }
 @Override
 public long cost() {
   assertThread("Sorted numeric doc values", creationThread);
   long cost = in.cost();
   assert cost >= 0;
   return cost;
 }
  public void testSortedNumeric() throws Exception {
    Directory dir = newDirectory();

    IndexWriterConfig iwc = newIndexWriterConfig(random(), null);
    iwc.setMergePolicy(newLogMergePolicy());
    RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc);

    int numDocs = TEST_NIGHTLY ? atLeast(500) : atLeast(50);
    for (int i = 0; i < numDocs; i++) {
      Document doc = new Document();
      int numValues = random().nextInt(5);
      for (int j = 0; j < numValues; j++) {
        doc.add(
            new SortedNumericDocValuesField(
                "nums", TestUtil.nextLong(random(), Long.MIN_VALUE, Long.MAX_VALUE)));
      }
      iw.addDocument(doc);
      if (random().nextInt(17) == 0) {
        iw.commit();
      }
    }
    DirectoryReader ir = iw.getReader();
    iw.forceMerge(1);
    DirectoryReader ir2 = iw.getReader();
    LeafReader merged = getOnlyLeafReader(ir2);
    iw.close();

    SortedNumericDocValues multi = MultiDocValues.getSortedNumericValues(ir, "nums");
    SortedNumericDocValues single = merged.getSortedNumericDocValues("nums");
    if (multi == null) {
      assertNull(single);
    } else {
      // check values
      for (int i = 0; i < numDocs; i++) {
        single.setDocument(i);
        ArrayList<Long> expectedList = new ArrayList<>();
        for (int j = 0; j < single.count(); j++) {
          expectedList.add(single.valueAt(j));
        }

        multi.setDocument(i);
        assertEquals(expectedList.size(), multi.count());
        for (int j = 0; j < single.count(); j++) {
          assertEquals(expectedList.get(j).longValue(), multi.valueAt(j));
        }
      }
    }

    ir.close();
    ir2.close();
    dir.close();
  }
 @Override
 public int docValueCount() {
   assertThread("Sorted numeric doc values", creationThread);
   assert in.docValueCount() > 0;
   return in.docValueCount();
 }
 @Override
 public int docID() {
   return in.docID();
 }