@Test
  public void readTest() {
    String insertKey = "user0";
    Map<String, ByteIterator> insertMap = insertRow(insertKey);
    HashSet<String> readFields = new HashSet<>();
    HashMap<String, ByteIterator> readResultMap = new HashMap<>();

    // Test reading a single field
    readFields.add("FIELD0");
    orientDBClient.read(CLASS, insertKey, readFields, readResultMap);
    assertEquals(
        "Assert that result has correct number of fields", readFields.size(), readResultMap.size());
    for (String field : readFields) {
      assertEquals(
          "Assert " + field + " was read correctly",
          insertMap.get(field).toString(),
          readResultMap.get(field).toString());
    }

    readResultMap = new HashMap<>();

    // Test reading all fields
    readFields.add("FIELD1");
    readFields.add("FIELD2");
    orientDBClient.read(CLASS, insertKey, readFields, readResultMap);
    assertEquals(
        "Assert that result has correct number of fields", readFields.size(), readResultMap.size());
    for (String field : readFields) {
      assertEquals(
          "Assert " + field + " was read correctly",
          insertMap.get(field).toString(),
          readResultMap.get(field).toString());
    }
  }
  @Before
  public void setup() throws DBException {
    orientDBClient = new OrientDBClient();

    Properties p = new Properties();
    // TODO: Extract the property names into final variables in OrientDBClient
    p.setProperty("orientdb.url", TEST_DB_URL);

    orientDBClient.setProperties(p);
    orientDBClient.init();
    orientDBConnection = new ODatabaseDocumentTx(TEST_DB_URL).open("admin", "admin");
    orientDBDictionary = orientDBConnection.getMetadata().getIndexManager().getDictionary();
  }
  @Test
  public void scanTest() {
    Map<String, Map<String, ByteIterator>> keyMap = new HashMap<>();
    for (int i = 0; i < 5; i++) {
      String insertKey = KEY_PREFIX + i;
      keyMap.put(insertKey, insertRow(insertKey));
    }

    Set<String> fieldSet = new HashSet<>();
    fieldSet.add("FIELD0");
    fieldSet.add("FIELD1");
    int startIndex = 1;
    int resultRows = 3;

    Vector<HashMap<String, ByteIterator>> resultVector = new Vector<>();
    orientDBClient.scan(CLASS, KEY_PREFIX + startIndex, resultRows, fieldSet, resultVector);

    // Check the resultVector is the correct size
    assertEquals(
        "Assert the correct number of results rows were returned", resultRows, resultVector.size());
    // Check each vector row to make sure we have the correct fields
    int testIndex = startIndex;
    for (HashMap<String, ByteIterator> result : resultVector) {
      assertEquals(
          "Assert that this row has the correct number of fields", fieldSet.size(), result.size());
      for (String field : fieldSet) {
        assertEquals(
            "Assert this field is correct in this row",
            keyMap.get(KEY_PREFIX + testIndex).get(field).toString(),
            result.get(field).toString());
      }
      testIndex++;
    }
  }
  @After
  public void teardown() throws DBException {
    if (orientDBConnection != null) {
      orientDBConnection.close();
    }

    if (orientDBClient != null) {
      orientDBClient.cleanup();
    }
  }
  /*
     Inserts a row of deterministic values for the given insertKey using the orientDBClient.
  */
  private Map<String, ByteIterator> insertRow(String insertKey) {
    HashMap<String, ByteIterator> insertMap = new HashMap<>();
    for (int i = 0; i < 3; i++) {
      insertMap.put(
          FIELD_PREFIX + i,
          new StringByteIterator(buildDeterministicValue(insertKey, FIELD_PREFIX + i)));
    }
    orientDBClient.insert(CLASS, insertKey, insertMap);

    return insertMap;
  }
  @Test
  public void updateTest() {
    String preupdateString = "preupdate";
    String user0 = "user0";
    String user1 = "user1";
    String user2 = "user2";

    // Manually insert three documents
    for (String key : Arrays.asList(user0, user1, user2)) {
      ODocument doc = new ODocument(CLASS);
      for (int i = 0; i < NUM_FIELDS; i++) {
        doc.field(FIELD_PREFIX + i, preupdateString);
      }
      doc.save();
      orientDBDictionary.put(key, doc);
    }

    HashMap<String, ByteIterator> updateMap = new HashMap<>();
    for (int i = 0; i < NUM_FIELDS; i++) {
      updateMap.put(
          FIELD_PREFIX + i,
          new StringByteIterator(buildDeterministicValue(user1, FIELD_PREFIX + i)));
    }

    orientDBClient.update(CLASS, user1, updateMap);

    // Ensure that user0 record was not changed
    ODocument result = orientDBDictionary.get(user0);
    for (int i = 0; i < NUM_FIELDS; i++) {
      assertEquals(
          "Assert first row fields contain preupdateString",
          result.field(FIELD_PREFIX + i),
          preupdateString);
    }

    // Check that all the columns have expected values for user1 record
    result = orientDBDictionary.get(user1);
    for (int i = 0; i < NUM_FIELDS; i++) {
      assertEquals(
          "Assert updated row fields are correct",
          result.field(FIELD_PREFIX + i),
          updateMap.get(FIELD_PREFIX + i).toString());
    }

    // Ensure that user2 record was not changed
    result = orientDBDictionary.get(user2);
    for (int i = 0; i < NUM_FIELDS; i++) {
      assertEquals(
          "Assert third row fields contain preupdateString",
          result.field(FIELD_PREFIX + i),
          preupdateString);
    }
  }
  @Test
  public void deleteTest() {
    String user0 = "user0";
    String user1 = "user1";
    String user2 = "user2";

    insertRow(user0);
    insertRow(user1);
    insertRow(user2);

    orientDBClient.delete(CLASS, user1);

    assertNotNull("Assert user0 still exists", orientDBDictionary.get(user0));
    assertNull("Assert user1 does not exist", orientDBDictionary.get(user1));
    assertNotNull("Assert user2 still exists", orientDBDictionary.get(user2));
  }