protected List<HiveColumnHandle> getColumnHandles(List<TestColumn> testColumns) {
    List<HiveColumnHandle> columns = new ArrayList<>();
    int nextHiveColumnIndex = 0;
    for (int i = 0; i < testColumns.size(); i++) {
      TestColumn testColumn = testColumns.get(i);
      int columnIndex = testColumn.isPartitionKey() ? -1 : nextHiveColumnIndex++;

      HiveType hiveType = HiveType.valueOf(testColumn.getObjectInspector().getTypeName());
      columns.add(
          new HiveColumnHandle(
              "client_id",
              testColumn.getName(),
              hiveType,
              hiveType.getTypeSignature(),
              columnIndex,
              testColumn.isPartitionKey()));
    }
    return columns;
  }
  protected void checkPageSource(
      ConnectorPageSource pageSource, List<TestColumn> testColumns, List<Type> types)
      throws IOException {
    try {
      MaterializedResult result = materializeSourceDataStream(SESSION, pageSource, types);

      for (MaterializedRow row : result) {
        for (int i = 0, testColumnsSize = testColumns.size(); i < testColumnsSize; i++) {
          TestColumn testColumn = testColumns.get(i);
          Type type = types.get(i);

          Object actualValue = row.getField(i);
          Object expectedValue = testColumn.getExpectedValue();
          if (actualValue == null) {
            assertEquals(null, expectedValue, String.format("Expected non-null for column %d", i));
          } else if (testColumn.getObjectInspector().getTypeName().equals("float")
              || testColumn.getObjectInspector().getTypeName().equals("double")) {
            assertEquals((double) actualValue, (double) expectedValue, EPSILON);
          } else if (testColumn.getObjectInspector().getTypeName().equals("date")) {
            SqlDate expectedDate = new SqlDate(((Long) expectedValue).intValue());
            assertEquals(actualValue, expectedDate);
          } else if (testColumn.getObjectInspector().getTypeName().equals("timestamp")) {
            SqlTimestamp expectedTimestamp =
                new SqlTimestamp((Long) expectedValue, SESSION.getTimeZoneKey());
            assertEquals(actualValue, expectedTimestamp);
          } else if (testColumn.getObjectInspector().getCategory() == Category.PRIMITIVE) {
            if (expectedValue instanceof Slice) {
              expectedValue = ((Slice) expectedValue).toStringUtf8();
            }

            if (actualValue instanceof Slice) {
              actualValue = ((Slice) actualValue).toStringUtf8();
            }
            if (actualValue instanceof SqlVarbinary) {
              actualValue = new String(((SqlVarbinary) actualValue).getBytes(), UTF_8);
            }
            assertEquals(actualValue, expectedValue, String.format("Wrong value for column %d", i));
          } else {
            BlockBuilder builder = type.createBlockBuilder(new BlockBuilderStatus(), 1);
            type.writeObject(builder, expectedValue);
            expectedValue = type.getObjectValue(SESSION, builder.build(), 0);
            assertEquals(
                actualValue,
                expectedValue,
                String.format("Wrong value for column %s", testColumn.getName()));
          }
        }
      }
    } finally {
      pageSource.close();
    }
  }
  protected void checkCursor(RecordCursor cursor, List<TestColumn> testColumns, int numRows)
      throws IOException {
    for (int row = 0; row < numRows; row++) {
      assertTrue(cursor.advanceNextPosition());
      for (int i = 0, testColumnsSize = testColumns.size(); i < testColumnsSize; i++) {
        TestColumn testColumn = testColumns.get(i);

        Object fieldFromCursor;
        Type type =
            HiveType.valueOf(testColumn.getObjectInspector().getTypeName()).getType(TYPE_MANAGER);
        if (cursor.isNull(i)) {
          fieldFromCursor = null;
        } else if (BOOLEAN.equals(type)) {
          fieldFromCursor = cursor.getBoolean(i);
        } else if (BIGINT.equals(type)) {
          fieldFromCursor = cursor.getLong(i);
        } else if (DOUBLE.equals(type)) {
          fieldFromCursor = cursor.getDouble(i);
        } else if (VARCHAR.equals(type)) {
          fieldFromCursor = cursor.getSlice(i);
        } else if (VARBINARY.equals(type)) {
          fieldFromCursor = cursor.getSlice(i);
        } else if (DateType.DATE.equals(type)) {
          fieldFromCursor = cursor.getLong(i);
        } else if (TimestampType.TIMESTAMP.equals(type)) {
          fieldFromCursor = cursor.getLong(i);
        } else if (isStructuralType(type)) {
          fieldFromCursor = cursor.getObject(i);
        } else {
          throw new RuntimeException("unknown type");
        }

        if (fieldFromCursor == null) {
          assertEquals(
              null,
              testColumn.getExpectedValue(),
              String.format("Expected null for column %s", testColumn.getName()));
        } else if (testColumn.getObjectInspector().getTypeName().equals("float")
            || testColumn.getObjectInspector().getTypeName().equals("double")) {
          assertEquals((double) fieldFromCursor, (double) testColumn.getExpectedValue(), EPSILON);
        } else if (testColumn.getObjectInspector().getCategory() == Category.PRIMITIVE) {
          assertEquals(
              fieldFromCursor,
              testColumn.getExpectedValue(),
              String.format("Wrong value for column %s", testColumn.getName()));
        } else {
          Block expected = (Block) testColumn.getExpectedValue();
          Block actual = (Block) fieldFromCursor;
          assertBlockEquals(
              actual, expected, String.format("Wrong value for column %s", testColumn.getName()));
        }
      }
    }
  }