@Test
  public void testNullableVarLen2() {
    final MaterializedField field =
        MaterializedField.create(EMPTY_SCHEMA_PATH, NullableVarCharHolder.TYPE);

    // Create a new value vector for 1024 integers.
    try (final NullableVarCharVector vector = new NullableVarCharVector(field, allocator)) {
      final NullableVarCharVector.Mutator m = vector.getMutator();
      vector.allocateNew(1024 * 10, 1024);

      m.set(0, STR1);
      m.set(1, STR2);
      m.set(2, STR3);

      // Check the sample strings.
      final NullableVarCharVector.Accessor accessor = vector.getAccessor();
      assertArrayEquals(STR1, accessor.get(0));
      assertArrayEquals(STR2, accessor.get(1));
      assertArrayEquals(STR3, accessor.get(2));

      // Ensure null value throws.
      boolean b = false;
      try {
        vector.getAccessor().get(3);
      } catch (IllegalStateException e) {
        b = true;
      } finally {
        assertTrue(b);
      }
    }
  }
  @Test
  public void testSubstringNegative(
      @Injectable final DrillbitContext bitContext,
      @Injectable UserServer.UserClientConnection connection)
      throws Throwable {

    new NonStrictExpectations() {
      {
        bitContext.getMetrics();
        result = new MetricRegistry();
        bitContext.getAllocator();
        result = new TopLevelAllocator();
        bitContext.getOperatorCreatorRegistry();
        result = new OperatorCreatorRegistry(c);
        bitContext.getConfig();
        result = c;
      }
    };

    PhysicalPlanReader reader =
        new PhysicalPlanReader(
            c, c.getMapper(), CoordinationProtos.DrillbitEndpoint.getDefaultInstance());
    PhysicalPlan plan =
        reader.readPhysicalPlan(
            Files.toString(
                FileUtils.getResourceAsFile("/functions/testSubstringNegative.json"),
                Charsets.UTF_8));
    FunctionImplementationRegistry registry = new FunctionImplementationRegistry(c);
    FragmentContext context =
        new FragmentContext(bitContext, PlanFragment.getDefaultInstance(), connection, registry);
    SimpleRootExec exec =
        new SimpleRootExec(
            ImplCreator.getExec(
                context, (FragmentRoot) plan.getSortedOperators(false).iterator().next()));

    while (exec.next()) {
      NullableVarCharVector c1 =
          exec.getValueVectorById(
              new SchemaPath("col3", ExpressionPosition.UNKNOWN), NullableVarCharVector.class);
      NullableVarCharVector.Accessor a1;
      a1 = c1.getAccessor();

      int count = 0;
      for (int i = 0; i < c1.getAccessor().getValueCount(); i++) {
        if (!a1.isNull(i)) {
          NullableVarCharHolder holder = new NullableVarCharHolder();
          a1.get(i, holder);
          // when offset is negative, substring return empty string.
          assertEquals("", holder.toString());
          ++count;
        }
      }
      assertEquals(50, count);
    }

    if (context.getFailureCause() != null) {
      throw context.getFailureCause();
    }
    assertTrue(!context.isFailed());
  }
  @Test
  public void testReAllocNullableVariableWidthVector() {
    final MaterializedField field =
        MaterializedField.create(EMPTY_SCHEMA_PATH, NullableVarCharHolder.TYPE);

    // Create a new value vector for 1024 integers
    try (final NullableVarCharVector vector =
        (NullableVarCharVector) TypeHelper.getNewVector(field, allocator)) {
      final NullableVarCharVector.Mutator m = vector.getMutator();
      vector.allocateNew();

      int initialCapacity = vector.getValueCapacity();

      // Put values in indexes that fall within the initial allocation
      m.setSafe(0, STR1, 0, STR1.length);
      m.setSafe(initialCapacity - 1, STR2, 0, STR2.length);

      // Now try to put values in space that falls beyond the initial allocation
      m.setSafe(initialCapacity + 200, STR3, 0, STR3.length);

      // Check valueCapacity is more than initial allocation
      assertEquals((initialCapacity + 1) * 2 - 1, vector.getValueCapacity());

      final NullableVarCharVector.Accessor accessor = vector.getAccessor();
      assertArrayEquals(STR1, accessor.get(0));
      assertArrayEquals(STR2, accessor.get(initialCapacity - 1));
      assertArrayEquals(STR3, accessor.get(initialCapacity + 200));

      // Set the valueCount to be more than valueCapacity of current allocation. This is possible
      // for NullableValueVectors
      // as we don't call setSafe for null values, but we do call setValueCount when the current
      // batch is processed.
      m.setValueCount(vector.getValueCapacity() + 200);
    }
  }
  @Test
  public void testNullableVarLen2() {
    // Build an optional varchar field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.VARCHAR).setMode(DataMode.OPTIONAL).setWidth(2);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    NullableVarCharVector v = new NullableVarCharVector(field, allocator);
    NullableVarCharVector.Mutator m = v.getMutator();
    v.allocateNew(1024 * 10, 1024);

    // Create and set 3 sample strings
    String str1 = new String("AAAAA1");
    String str2 = new String("BBBBBBBBB2");
    String str3 = new String("CCCC3");
    m.set(0, str1.getBytes(Charset.forName("UTF-8")));
    m.set(1, str2.getBytes(Charset.forName("UTF-8")));
    m.set(2, str3.getBytes(Charset.forName("UTF-8")));

    // Check the sample strings
    assertEquals(str1, new String(v.getAccessor().get(0), Charset.forName("UTF-8")));
    assertEquals(str2, new String(v.getAccessor().get(1), Charset.forName("UTF-8")));
    assertEquals(str3, new String(v.getAccessor().get(2), Charset.forName("UTF-8")));

    // Ensure null value throws
    boolean b = false;
    try {
      v.getAccessor().get(3);
    } catch (AssertionError e) {
      b = true;
    } finally {
      if (!b) {
        assert false;
      }
    }
  }
  @Test
  public void testNullableVarCharVectorLoad() {
    final MaterializedField field =
        MaterializedField.create(EMPTY_SCHEMA_PATH, NullableVarCharHolder.TYPE);

    // Create a new value vector for 1024 nullable variable length strings.
    final NullableVarCharVector vector1 = new NullableVarCharVector(field, allocator);
    final NullableVarCharVector.Mutator mutator = vector1.getMutator();
    vector1.allocateNew(1024 * 10, 1024);

    // Populate the vector.
    final StringBuilder stringBuilder = new StringBuilder();
    final int valueCount = 10;
    for (int i = 0; i < valueCount; ++i) {
      stringBuilder.append('x');
      mutator.set(i, stringBuilder.toString().getBytes(utf8Charset));
    }

    // Check the contents.
    final NullableVarCharVector.Accessor accessor1 = vector1.getAccessor();
    stringBuilder.setLength(0);
    for (int i = 0; i < valueCount; ++i) {
      stringBuilder.append('x');
      final Object object = accessor1.getObject(i);
      assertEquals(stringBuilder.toString(), object.toString());
    }

    mutator.setValueCount(valueCount);
    assertEquals(valueCount, vector1.getAccessor().getValueCount());

    // Still ok after setting value count?
    stringBuilder.setLength(0);
    for (int i = 0; i < valueCount; ++i) {
      stringBuilder.append('x');
      final Object object = accessor1.getObject(i);
      assertEquals(stringBuilder.toString(), object.toString());
    }

    // Combine into a single buffer so we can load it into a new vector.
    final DrillBuf[] buffers1 = vector1.getBuffers(false);
    final DrillBuf buffer1 = combineBuffers(allocator, buffers1);
    final NullableVarCharVector vector2 = new NullableVarCharVector(field, allocator);
    vector2.load(vector1.getMetadata(), buffer1);

    // Check the vector's contents.
    final NullableVarCharVector.Accessor accessor2 = vector2.getAccessor();
    stringBuilder.setLength(0);
    for (int i = 0; i < valueCount; ++i) {
      stringBuilder.append('x');
      final Object object = accessor2.getObject(i);
      assertEquals(stringBuilder.toString(), object.toString());
    }

    vector1.close();
    vector2.close();
    buffer1.release();
  }