('/** {@inheritDoc} */', '')

@Test
  public void testFormattedRowKey() throws Exception {
    final Kiji kiji = getKiji();
    final KijiTableLayout layout = KijiTableLayouts.getTableLayout(KijiTableLayouts.FORMATTED_RKF);
    new InstanceBuilder(kiji)
        .withTable(layout.getName(), layout)
            .withRow("dummy", "str1", "str2", 1, 2L)
                .withFamily("family").withQualifier("column")
                    .withValue(1L, "string-value")
                    .withValue(2L, "string-value2")
            .withRow("dummy", "str1", "str2", 1)
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1", "str2")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
        .build();

    final KijiTable table = kiji.openTable(layout.getName());
    try {
      assertEquals(BaseTool.SUCCESS, runTool(new LsTool(), table.getURI().toString()));
    } finally {
      ResourceUtils.releaseOrLog(table);
    }
  }


('/** {@inheritDoc} */', '')

b'/** {@inheritDoc} */'@Override
  public String getName() {
    return "ls";
  }

@Test
  public void testKijiLsStartAndLimitRow() throws Exception {
    final Kiji kiji = getKiji();
    final KijiTableLayout layout = KijiTableLayouts.getTableLayout(KijiTableLayouts.FOO_TEST);
    kiji.createTable(layout.getDesc());
    final KijiTable table = kiji.openTable(layout.getName());
    try {
      assertEquals(BaseTool.SUCCESS, runTool(new LsTool(), table.getURI().toString()));
      // TODO: Validate output
    } finally {
      ResourceUtils.releaseOrLog(table);
    }
  }


('/** {@inheritDoc} */', '')

@Test
  public void testMultipleArguments() throws Exception {
    final Kiji kiji = getKiji();
    final KijiTableLayout layout = KijiTableLayouts.getTableLayout(KijiTableLayouts.FORMATTED_RKF);
    new InstanceBuilder(kiji)
        .withTable(layout.getName(), layout)
            .withRow("dummy", "str1", "str2", 1, 2L)
                .withFamily("family").withQualifier("column")
                    .withValue(1L, "string-value")
                    .withValue(2L, "string-value2")
            .withRow("dummy", "str1", "str2", 1)
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1", "str2")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
        .build();

    final KijiTableLayout layoutTwo = KijiTableLayouts.getTableLayout(KijiTableLayouts.FOO_TEST);
    kiji.createTable(layoutTwo.getDesc());

    final KijiTable table = kiji.openTable(layout.getName());
    try {
      final KijiTable tableTwo = kiji.openTable(layoutTwo.getName());
      try {
        assertEquals(BaseTool.SUCCESS, runTool(new LsTool(), table.getURI().toString(),
            tableTwo.getURI().toString()));
        assertEquals(9, mToolOutputLines.length);
        assertEquals(BaseTool.SUCCESS, runTool(new LsTool(), kiji.getURI().toString()));
        assertEquals(2, mToolOutputLines.length);
        assertEquals(BaseTool.SUCCESS, runTool(new LsTool(), kiji.getURI().toString(),
            table.getURI().toString()));
        assertEquals(3, mToolOutputLines.length);
      } finally {
        tableTwo.release();
      }
    } finally {
      table.release();
    }
  }


('/** {@inheritDoc} */', '')

b'/** {@inheritDoc} */'@Override
  public String getName() {
    return "scan";
  }

@Test
  public void testFormattedRowKey() throws Exception {
    final Kiji kiji = getKiji();
    final KijiTableLayout layout = KijiTableLayouts.getTableLayout(KijiTableLayouts.FORMATTED_RKF);
    new InstanceBuilder(kiji)
        .withTable(layout.getName(), layout)
            .withRow("dummy", "str1", "str2", 1, 2L)
                .withFamily("family").withQualifier("column")
                    .withValue(1L, "string-value")
                    .withValue(2L, "string-value2")
            .withRow("dummy", "str1", "str2", 1)
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1", "str2")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy", "str1")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
            .withRow("dummy")
                .withFamily("family").withQualifier("column").withValue(1L, "string-value")
        .build();

    final KijiTable table = kiji.openTable(layout.getName());
    try {
      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(), table.getURI().toString()));
      assertEquals(15, mToolOutputLines.length);
    } finally {
      ResourceUtils.releaseOrLog(table);
    }
  }


('/** {@inheritDoc} */', '')

@Test
  public void testKijiScanStartAndLimitRow() throws Exception {
    final Kiji kiji = getKiji();

    TableLayoutDesc desc = KijiTableLayouts.getLayout(KijiTableLayouts.FOO_TEST);
    ((RowKeyFormat2)desc.getKeysFormat()).setEncoding(RowKeyEncoding.RAW);

    final KijiTableLayout layout =  KijiTableLayout.newLayout(desc);
    final long timestamp = 10L;
    new InstanceBuilder(kiji)
        .withTable(layout.getName(), layout)
            .withRow("gwu@usermail.example.com")
                .withFamily("info")
                    .withQualifier("email").withValue(timestamp, "gwu@usermail.example.com")
                    .withQualifier("name").withValue(timestamp, "Garrett Wu")
            .withRow("aaron@usermail.example.com")
                .withFamily("info")
                    .withQualifier("email").withValue(timestamp, "aaron@usermail.example.com")
                    .withQualifier("name").withValue(timestamp, "Aaron Kimball")
            .withRow("christophe@usermail.example.com")
                .withFamily("info")
                    .withQualifier("email")
                        .withValue(timestamp, "christophe@usermail.example.com")
                    .withQualifier("name").withValue(timestamp, "Christophe Bisciglia")
            .withRow("kiyan@usermail.example.com")
                .withFamily("info")
                    .withQualifier("email").withValue(timestamp, "kiyan@usermail.example.com")
                    .withQualifier("name").withValue(timestamp, "Kiyan Ahmadizadeh")
            .withRow("john.doe@gmail.com")
                .withFamily("info")
                    .withQualifier("email").withValue(timestamp, "john.doe@gmail.com")
                    .withQualifier("name").withValue(timestamp, "John Doe")
            .withRow("jane.doe@gmail.com")
                .withFamily("info")
                    .withQualifier("email").withValue(timestamp, "jane.doe@gmail.com")
                    .withQualifier("name").withValue(timestamp, "Jane Doe")
        .build();

    final KijiTable table = kiji.openTable(layout.getName());
    try {
      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(),
          table.getURI().toString() + "info:name"
      ));
      assertEquals(18, mToolOutputLines.length);

      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(),
              table.getURI().toString() + "info:name,info:email"
          ));
      assertEquals(30, mToolOutputLines.length);

        EntityIdFactory eif = EntityIdFactory.getFactory(layout);
        EntityId startEid = eif.getEntityId("christophe@usermail.example.com"); //second row
        EntityId limitEid = eif.getEntityId("john.doe@gmail.com"); //second to last row
        String startHbaseRowKey = Hex.encodeHexString(startEid.getHBaseRowKey());
        String limitHbaseRowKey = Hex.encodeHexString(limitEid.getHBaseRowKey());
      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(),
          table.getURI().toString() + "info:name",
          "--start-row=hbase=hex:" + startHbaseRowKey,  // start at the second row.
          "--limit-row=hbase=hex:" + limitHbaseRowKey   // end at the 2nd to last row (exclusive).
      ));
      assertEquals(9, mToolOutputLines.length);

    } finally {
      ResourceUtils.releaseOrLog(table);
    }
  }


('/** {@inheritDoc} */', '')

@Test
  public void testRangeScanFormattedRKF() throws Exception {
    final Kiji kiji = getKiji();
    final KijiTableLayout layout = KijiTableLayouts.getTableLayout(KijiTableLayouts.FORMATTED_RKF);
    new InstanceBuilder(kiji)
        .withTable(layout.getName(), layout)
            .withRow("NYC", "Technology", "widget", 1, 2)
                .withFamily("family").withQualifier("column")
                    .withValue("Candaules")
            .withRow("NYC", "Technology", "widget", 1, 20)
                .withFamily("family").withQualifier("column")
                    .withValue("Croesus")
            .withRow("NYC", "Technology", "thingie", 2)
                .withFamily("family").withQualifier("column")
                    .withValue("Gyges")
            .withRow("DC", "Technology", "stuff", 123)
                .withFamily("family").withQualifier("column")
                    .withValue("Glaucon")
            .withRow("DC", "Technology", "stuff", 124, 1)
                .withFamily("family").withQualifier("column")
                    .withValue("Lydia")
        .build();

    final KijiTable table = kiji.openTable(layout.getName());
    try {
      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(), table.getURI().toString(),
          "--start-row=['NYC','Technology','widget',1,2]",
          "--limit-row=['NYC','Technology','widget',1,30]",
          "--debug"
          ));
      assertEquals(10, mToolOutputLines.length);
      assertEquals(BaseTool.SUCCESS, runTool(new ScanTool(), table.getURI().toString(),
          "--start-row=['NYC','Technology','widget']",
          "--limit-row=['NYC','Technology','widget',1,20]",
          "--debug"
          ));
    } finally {
      ResourceUtils.releaseOrLog(table);
    }
  }


Register a schema @return Tool exit code @throws IOException in case of an error

b'/**\n   * Register a schema.\n   *\n   * @return Tool exit code.\n   * @throws IOException in case of an error.\n   */'private int registerSchema() throws IOException {
    final KijiSchemaTable table = mKiji.getSchemaTable();
    final File file = new File(mRegisterFlag);
    final Schema schema = new Schema.Parser().parse(file);
    final long id = table.getOrCreateSchemaId(schema);
    final String hash = table.getSchemaHash(schema).toString();
    if (isInteractive()) {
      getPrintStream().print("Schema ID for the given schema is: ");
    }
    getPrintStream().println(id);
    if (isInteractive()) {
      getPrintStream().print("Schema hash for the given schema is: ");
    }
    getPrintStream().println(hash);
    return SUCCESS;
  }

@Test
  public void testRegisterSchema() throws Exception {
    assertEquals(BaseTool.SUCCESS, runTool(new SchemaTableTool(),
        getKiji().getURI().toString(),
        "--register=" + mFile.toString(),
        "--interactive=false"
    ));
    assertEquals(mSimpleSchema, mTable.getSchema(Long.parseLong(mToolOutputLines[0])));
  }


List all schemas in the table @return The Tool exit code @throws IOException in case of an error

b'/**\n   * List all schemas in the table.\n   *\n   * @return The Tool exit code.\n   * @throws IOException in case of an error.\n   */'private int list() throws IOException {
    final KijiSchemaTable schemaTable = mKiji.getSchemaTable();
    long id = 0;
    Schema schema = schemaTable.getSchema(id);
    while (null != schema) {
      getPrintStream().printf("%d: %s%n", id, schema.toString());
      schema = schemaTable.getSchema(++id);
    }

    return SUCCESS;
  }

@Test
  public void testList() throws Exception {
    final long simpleSchemaId = getKiji().getSchemaTable().getOrCreateSchemaId(mSimpleSchema);
    assertEquals(BaseTool.SUCCESS, runTool(new SchemaTableTool(),
        getKiji().getURI().toString(),
        "--list"));
    assertTrue(mToolOutputStr.contains(
        String.format("%d: %s%n", simpleSchemaId, mSimpleSchema.toString())));
  }


Lookup a schema @return Tool exit code @throws IOException in case of an error

b'/**\n   * Lookup a schema.\n   *\n   * @return Tool exit code.\n   * @throws IOException in case of an error.\n   */'private int lookupSchema() throws IOException {
    final KijiSchemaTable table = mKiji.getSchemaTable();
    final File file = new File(mLookupFlag);
    final Schema schema = new Schema.Parser().parse(file);
    final SchemaEntry sEntry = table.getSchemaEntry(schema);
    final long id = sEntry.getId();
    final BytesKey hash = sEntry.getHash();
    if (isInteractive()) {
      getPrintStream().print("Schema ID for the given schema is: ");
    }
    getPrintStream().println(id);
    if (isInteractive()) {
      getPrintStream().print("Schema hash for the given schema is: ");
    }
    getPrintStream().println(hash);
    return SUCCESS;
  }

@Test
  public void lookupSchema() throws Exception {
    final BytesKey hash = mTable.getSchemaHash(mSimpleSchema);
    final long id = mTable.getOrCreateSchemaId(mSimpleSchema);
    assertEquals(BaseTool.SUCCESS, runTool(new SchemaTableTool(),
        getKiji().getURI().toString(),
        "--lookup=" + mFile.toString(),
        "--interactive=false"
    ));
    assertEquals(id, Long.parseLong(mToolOutputLines[0]));
    assertEquals(hash, new BytesKey(ByteArrayFormatter.parseHex(mToolOutputLines[1], ':')));
  }


('/**\\n   * Parses a space-separated map into a Java map.\\n   *\\n   * @param input Space-separated map.\\n   * @return the parsed Java map.\\n   * @throws IOException on parse error.\\n   */', '')

b'/**\n   * Parses a space-separated map into a Java map.\n   *\n   * @param input Space-separated map.\n   * @return the parsed Java map.\n   * @throws IOException on parse error.\n   */'public Map<String, String> parse(String input) throws IOException {
    final Map<String, String> kvs = Maps.newHashMap();

    for (String pair: input.split(" ")) {
      if (pair.isEmpty()) {
        continue;
      }
      final String[] kvSplit = pair.split("=", 2);
      if (kvSplit.length != 2) {
        throw new IOException(String.format(
            "Invalid argument '%s' in space-separated map '%s'.", pair, input));
      }

      final String key = kvSplit[0];
      final String value = kvSplit[1];

      final String existing = kvs.put(key, value);
      if (existing != null) {
        throw new IOException(String.format(
            "Duplicate key '%s' in space-separated map.'%s'.", key, input));
      }
    }

    return kvs;
  }

@Test
  public void testParseValidMapEmpty() throws Exception {
    final Map<String, String> kvs = mParser.parse("");
    final Map<String, String> expected = ImmutableMap.<String, String>builder().build();
    assertEquals(expected, kvs);
  }


['(\'/**\\\\n   * Gets a builder configured with default Kiji URI fields.\\\\n   *\\\\n   * More precisely, the following defaults are initialized:\\\\n   *
\\\\n   *
The Zookeeper quorum and client port is taken from the Hadoop <tt>Configuration</tt>
\\\\n   *
The Kiji instance name is set to <tt>KConstants.DEFAULT_INSTANCE_NAME</tt>\\\\n   *       (<tt>"default"</tt>).
\\\\n   *
The table name and column names are explicitly left unset.
\\\\n   *
\\\\n   *\\\\n   * @return A builder configured with this Kiji URI.\\\\n   */\', \'\')']

b'/**\n   * Gets a builder configured with default Kiji URI fields.\n   *\n   * More precisely, the following defaults are initialized:\n   *
\n   *
The Zookeeper quorum and client port is taken from the Hadoop <tt>Configuration</tt>
\n   *
The Kiji instance name is set to <tt>KConstants.DEFAULT_INSTANCE_NAME</tt>\n   *       (<tt>"default"</tt>).
\n   *
The table name and column names are explicitly left unset.
\n   *
\n   *\n   * @return A builder configured with this Kiji URI.\n   */'public static HBaseKijiURIBuilder newBuilder() {
    return new HBaseKijiURIBuilder();
  }

@Test
  public void testNoAuthority() {
    try {
      KijiURI.newBuilder("kiji-hbase:///");
      fail("An exception should have been thrown.");
    } catch (KijiURIException kurie) {
      assertEquals("Invalid Kiji URI: 'kiji-hbase:///' : ZooKeeper ensemble missing.",
          kurie.getMessage());
    }
  }


@Test
  public void testParseValidMapOneEntry() throws Exception {
    final Map<String, String> kvs = mParser.parse("key1=value1");
    final Map<String, String> expected =
        ImmutableMap.<String, String>builder().put("key1", "value1").build();
    assertEquals(expected, kvs);
  }


@Test
  public void testParseValidMapManyEntries() throws Exception {
    final Map<String, String> kvs = mParser.parse("key1=value1 key2=value2 key3=value3");
    final Map<String, String> expected = ImmutableMap.<String, String>builder()
        .put("key1", "value1")
        .put("key2", "value2")
        .put("key3", "value3")
        .build();
    assertEquals(expected, kvs);
  }


@Test
  public void testParseValidMapEmptySpaces() throws Exception {
    final Map<String, String> kvs = mParser.parse("    ");
    final Map<String, String> expected = ImmutableMap.<String, String>builder().build();
    assertEquals(expected, kvs);
  }


@Test
  public void testParseValidMapManySpaces() throws Exception {
    final Map<String, String> kvs = mParser.parse(" key1=value1   key2=value2  key3=value3   ");
    final Map<String, String> expected = ImmutableMap.<String, String>builder()
        .put("key1", "value1")
        .put("key2", "value2")
        .put("key3", "value3")
        .build();
    assertEquals(expected, kvs);
  }


@Test
  public void testParseInvalidMapNoEquals() throws Exception {
    try {
      final String input = "key1=value1 invalid key3=value3";
      mParser.parse(input);
      fail(String.format("Space-separated parser should have caught an error in '%s'", input));
    } catch (IOException ioe) {
      LOG.debug("Expected error: {}", ioe);
    }
  }


@Test
  public void testParseInvalidMapDuplicateKey() throws Exception {
    try {
      final String input = "key1=value1 key1=value2";
      mParser.parse(input);
      fail(String.format("Space-separated parser should have caught an error in '%s'", input));
    } catch (IOException ioe) {
      LOG.debug("Expected error: {}", ioe);
    }
  }


['(\'/**\\\\n   * Parses a command-line flag specifying an entity ID.\\\\n   *\\\\n   *
 HBase row key specifications must be prefixed with "hbase=..."\\\\n   *
 Kiji row key specifications may be explicitly prefixed with "kiji=..." if\\\\n   *     necessary. The prefix is not always necessary.\\\\n   *\\\\n   * @param entityFlag Command-line flag specifying an entity ID.\\\\n   * @param layout Layout of the table describing the entity ID format.\\\\n   * @return the entity ID as specified in the flags.\\\\n   * @throws IOException on I/O error.\\\\n   */\', \'\')', "('', '// HBase row key specification\\n')", "('', '// Kiji row key specification\\n')"]

b'/**\n   * Parses a command-line flag specifying an entity ID.\n   *\n   *
 HBase row key specifications must be prefixed with "hbase=..."\n   *
 Kiji row key specifications may be explicitly prefixed with "kiji=..." if\n   *     necessary. The prefix is not always necessary.\n   *\n   * @param entityFlag Command-line flag specifying an entity ID.\n   * @param layout Layout of the table describing the entity ID format.\n   * @return the entity ID as specified in the flags.\n   * @throws IOException on I/O error.\n   */'public static EntityId createEntityIdFromUserInputs(String entityFlag, KijiTableLayout layout)
      throws IOException {
    Preconditions.checkNotNull(entityFlag);

    final EntityIdFactory factory = EntityIdFactory.getFactory(layout);

    if (entityFlag.startsWith(HBASE_ROW_KEY_SPEC_PREFIX)) {
      // HBase row key specification
      final String hbaseSpec = entityFlag.substring(HBASE_ROW_KEY_SPEC_PREFIX.length());
      final byte[] hbaseRowKey = parseBytesFlag(hbaseSpec);
      return factory.getEntityIdFromHBaseRowKey(hbaseRowKey);

    } else {
      // Kiji row key specification
      final String kijiSpec = entityFlag.startsWith(KIJI_ROW_KEY_SPEC_PREFIX)
          ? entityFlag.substring(KIJI_ROW_KEY_SPEC_PREFIX.length())
          : entityFlag;

      return parseKijiRowKey(kijiSpec, factory, layout);
    }
  }

@Test
  public void testTooLargeInt() throws Exception {
    try {
      ToolUtils.createEntityIdFromUserInputs("['dummy', 'str1', 'str2', 2147483648, 10]",
          mFormattedLayout);
      fail("Should fail with EntityIdException.");
    } catch (EntityIdException eie) {
      assertEquals("Invalid type for component 2147483648 at index 3 in kijiRowKey",
          eie.getMessage());
    }
  }


@Test
  public void testTooLargeLong() throws Exception {

    try {
      ToolUtils.createEntityIdFromUserInputs("['dummy', 'str1', 'str2', 5, 9223372036854775808]",
          mFormattedLayout);
      fail("Should fail with EntityIdException.");
    } catch (IOException ioe) {
      assertEquals("Invalid JSON value: '9223372036854775808', expecting string, "
          + "int, long, or null.", ioe.getMessage());
    }
  }


@Test
  public void testIntForLong() throws Exception {
    final EntityIdFactory factory = EntityIdFactory.getFactory((RowKeyFormat2) mFormattedLayout
        .getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityId("dummy", "str1", "str2", 5, 10);

    assertEquals(eid, ToolUtils.createEntityIdFromUserInputs("['dummy', 'str1', 'str2', 5, 10]",
        mFormattedLayout));
  }


@Test
  public void testTooFewComponents() throws IOException {
    final EntityIdFactory factory =
        EntityIdFactory.getFactory((RowKeyFormat2) mFormattedLayout.getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityId("dummy", "str1", "str2", 5, null);

    assertEquals(eid,
        ToolUtils.createEntityIdFromUserInputs("['dummy', 'str1', 'str2', 5]", mFormattedLayout));
  }


@Test
  public void testMultipleHostsNoParen() {
    try {
      KijiURI.newBuilder("kiji-hbase://zkhost1,zkhost2:1234/instance/table/col");
      fail("An exception should have been thrown.");
    } catch (KijiURIException kurie) {
      assertEquals("Invalid Kiji URI: 'kiji-hbase://zkhost1,zkhost2:1234/instance/table/col' : "
              + "Multiple ZooKeeper hosts must be parenthesized.", kurie.getMessage());
    }
  }


@Test
  public void testNonNullFollowsNull() throws IOException {

    try {
      ToolUtils
          .createEntityIdFromUserInputs("['dummy', 'str1', 'str2', null, 5]", mFormattedLayout);
      fail("Should fail with EntityIdException.");
    } catch (EntityIdException eie) {
      assertEquals("Non null component follows null component", eie.getMessage());
    }
  }


@Test
  public void testEmptyString() throws IOException {
    final EntityIdFactory factory =
      EntityIdFactory.getFactory((RowKeyFormat2) mFormattedLayout.getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityId("", "", "", null, null);

    assertEquals(eid,
        ToolUtils.createEntityIdFromUserInputs("['', '', '', null, null]", mFormattedLayout));
  }


@Test
  public void testASCIIChars() throws Exception {
    final EntityIdFactory factory =
        EntityIdFactory.getFactory((RowKeyFormat2) mFormattedLayout.getDesc().getKeysFormat());

    for (byte b = 32; b < 127; b++) {
      for (byte b2 = 32; b2 < 127; b2++) {
        final EntityId eid = factory.getEntityId(String.format(
            "dumm%sy", new String(new byte[]{b, b2}, "Utf-8")), "str1", "str2", 5, 10L);

        assertEquals(eid,
            ToolUtils.createEntityIdFromUserInputs(eid.toShellString(), mFormattedLayout));
      }
    }
  }


@Test
  public void testRawParserLoop() throws Exception {
    final EntityIdFactory factory =
      EntityIdFactory.getFactory((RowKeyFormat) mRawLayout.getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityIdFromHBaseRowKey(Bytes.toBytes("rawRowKey"));

    assertEquals(eid,
        ToolUtils.createEntityIdFromUserInputs(eid.toShellString(), mRawLayout));
  }


@Test
  public void testHashedParserLoop() throws Exception {
    final EntityIdFactory factory =
       EntityIdFactory.getFactory((RowKeyFormat) mHashedLayout.getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityId("hashedRowKey");

    assertEquals(eid,
        ToolUtils.createEntityIdFromUserInputs(eid.toShellString(), mHashedLayout));
  }


@Test
  public void testHashPrefixedParserLoop() throws Exception {
    final EntityIdFactory factory =
       EntityIdFactory.getFactory((RowKeyFormat) mHashPrefixedLayout.getDesc().getKeysFormat());
    final EntityId eid = factory.getEntityId("hashPrefixedRowKey");

    assertEquals(
        eid, ToolUtils.createEntityIdFromUserInputs(eid.toShellString(), mHashPrefixedLayout));
  }


@Test
  public void testHBaseEIDtoRawEID() throws Exception {
    final EntityIdFactory factory =
      EntityIdFactory.getFactory((RowKeyFormat) mRawLayout.getDesc().getKeysFormat());
    final EntityId reid = factory.getEntityId("rawEID");
    final EntityId hbeid = HBaseEntityId.fromHBaseRowKey(reid.getHBaseRowKey());

    assertEquals(reid,
        ToolUtils.createEntityIdFromUserInputs(hbeid.toShellString(), mRawLayout));
  }


@Test
  public void testHBaseEIDtoHashedEID() throws Exception {
    final EntityIdFactory factory =
      EntityIdFactory.getFactory((RowKeyFormat) mHashedLayout.getDesc().getKeysFormat());
    final EntityId heid = factory.getEntityId("hashedEID");
    final EntityId hbeid = HBaseEntityId.fromHBaseRowKey(heid.getHBaseRowKey());

    assertEquals(heid,
        ToolUtils.createEntityIdFromUserInputs(hbeid.toShellString(), mHashedLayout));

  }


@Test
  public void testHBaseEIDtoHashPrefixedEID() throws Exception {
    final EntityIdFactory factory =
      EntityIdFactory.getFactory((RowKeyFormat) mHashPrefixedLayout.getDesc().getKeysFormat());
    final EntityId hpeid = factory.getEntityId("hashPrefixedEID");
    final EntityId hbeid = HBaseEntityId.fromHBaseRowKey(hpeid.getHBaseRowKey());

    assertEquals(hpeid,
        ToolUtils.createEntityIdFromUserInputs(hbeid.toShellString(), mHashPrefixedLayout));
  }


@Test
  public void testHBaseEIDtoFormattedEID() throws Exception {
    final EntityIdFactory factory =
        EntityIdFactory.getFactory((RowKeyFormat2) mFormattedLayout.getDesc().getKeysFormat());
    final EntityId feid = factory.getEntityId("dummy", "str1", "str2", 5, 10);
    final EntityId hbeid = HBaseEntityId.fromHBaseRowKey(feid.getHBaseRowKey());

    assertEquals(feid,
        ToolUtils.createEntityIdFromUserInputs(hbeid.toShellString(), mFormattedLayout));
  }


["('/** {@inheritDoc} */', '')", "('', '// In the case that we have enough information to generate a prefix, we will\\n')", '(\'\', "// construct a PrefixFilter that is AND\'ed with the RowFilter.  This way,\\n")', "('', '// when the scan passes the end of the prefix, it can end the filtering\\n')", "('', '// process quickly.\\n')", "('', '// Define a regular expression that effectively creates a mask for the row\\n')", "('', '// key based on the key format and the components passed in.  Prefix hashes\\n')", "('', '// are skipped over, and null components match any value.\\n')", "('', '// ISO-8859-1 is used so that numerals map to valid characters\\n')", "('', '// see http://stackoverflow.com/a/1387184\\n')", "('', '// Use the embedded flag (?s) to turn on single-line mode; this makes the\\n')", '(\'\', "// \'.\' match on line terminators.  The RegexStringComparator uses the DOTALL\\n")', "('', '// flag during construction, but it does not use that flag upon\\n')", "('', '// deserialization.  This bug has been fixed in HBASE-5667, part of the 0.95\\n')", "('', '// release.\\n')", "('', '// ^ matches the beginning of the string\\n')", "('', '// If all of the components included in the hash have been specified,\\n')", "('', '// then match on the value of the hash\\n')", "('', '// Write the hashed bytes to the prefix buffer\\n')", '(\'\', "// match any character exactly \'hash size\' number of times\\n")', "('', '// Only add to the prefix buffer until we hit a null component.  We do this\\n')", "('', '// here, because the prefix is going to expect to have 0x00 component\\n')", "('', '// terminators, which we put in during this loop but not in the loop above.\\n')", "('', '// null integers can be excluded entirely if there are just nulls at\\n')", "('', '// the end of the EntityId, otherwise, match the correct number of\\n')", "('', '// bytes\\n')", "('', '// match each byte in the integer using a regex hex sequence\\n')", "('', '// null longs can be excluded entirely if there are just nulls at\\n')", "('', '// the end of the EntityId, otherwise, match the correct number of\\n')", "('', '// bytes\\n')", "('', '// match each byte in the long using a regex hex sequence\\n')", "('', '// match any non-zero character at least once, followed by a zero\\n')", "('', '// delimiter, or match nothing at all in case the component was at\\n')", "('', '// the end of the EntityId and skipped entirely\\n')", "('', '// FormattedEntityId converts a string component to UTF-8 bytes to\\n')", "('', '// create the HBase key.  RegexStringComparator will convert the\\n')", "('', '// value it sees (ie, the HBase key) to a string using ISO-8859-1.\\n')", "('', '// Therefore, we need to write ISO-8859-1 characters to our regex so\\n')", "('', '// that the comparison happens correctly.\\n')", "('', '// $ matches the end of the string\\n')"]

b'/** {@inheritDoc} */'@Override
  public Filter toHBaseFilter(Context context) throws IOException {
    // In the case that we have enough information to generate a prefix, we will
    // construct a PrefixFilter that is AND'ed with the RowFilter.  This way,
    // when the scan passes the end of the prefix, it can end the filtering
    // process quickly.
    boolean addPrefixFilter = false;
    ByteArrayOutputStream prefixBytes = new ByteArrayOutputStream();

    // Define a regular expression that effectively creates a mask for the row
    // key based on the key format and the components passed in.  Prefix hashes
    // are skipped over, and null components match any value.
    // ISO-8859-1 is used so that numerals map to valid characters
    // see http://stackoverflow.com/a/1387184

    // Use the embedded flag (?s) to turn on single-line mode; this makes the
    // '.' match on line terminators.  The RegexStringComparator uses the DOTALL
    // flag during construction, but it does not use that flag upon
    // deserialization.  This bug has been fixed in HBASE-5667, part of the 0.95
    // release.
    StringBuilder regex = new StringBuilder("(?s)^"); // ^ matches the beginning of the string
    if (null != mRowKeyFormat.getSalt()) {
      if (mRowKeyFormat.getSalt().getHashSize() > 0) {
        // If all of the components included in the hash have been specified,
        // then match on the value of the hash
        Object[] prefixComponents =
            getNonNullPrefixComponents(mComponents, mRowKeyFormat.getRangeScanStartIndex());
        if (prefixComponents.length == mRowKeyFormat.getRangeScanStartIndex()) {
          ByteArrayOutputStream tohash = new ByteArrayOutputStream();
          for (Object component : prefixComponents) {
            byte[] componentBytes = toBytes(component);
            tohash.write(componentBytes, 0, componentBytes.length);
          }
          byte[] hashed = Arrays.copyOfRange(Hasher.hash(tohash.toByteArray()), 0,
              mRowKeyFormat.getSalt().getHashSize());
          for (byte hashedByte : hashed) {
            regex.append(String.format("\\x%02x", hashedByte & 0xFF));
          }

          addPrefixFilter = true;
          // Write the hashed bytes to the prefix buffer
          prefixBytes.write(hashed, 0, hashed.length);
        } else {
          // match any character exactly 'hash size' number of times
          regex.append(".{").append(mRowKeyFormat.getSalt().getHashSize()).append("}");
        }
      }
    }
    // Only add to the prefix buffer until we hit a null component.  We do this
    // here, because the prefix is going to expect to have 0x00 component
    // terminators, which we put in during this loop but not in the loop above.
    boolean hitNullComponent = false;
    for (int i = 0; i < mComponents.length; i++) {
      final Object component = mComponents[i];
      switch (mRowKeyFormat.getComponents().get(i).getType()) {
        case INTEGER:
          if (null == component) {
            // null integers can be excluded entirely if there are just nulls at
            // the end of the EntityId, otherwise, match the correct number of
            // bytes
            regex.append("(.{").append(Bytes.SIZEOF_INT).append("})?");
            hitNullComponent = true;
          } else {
            byte[] tempBytes = toBytes((Integer) component);
            // match each byte in the integer using a regex hex sequence
            for (byte tempByte : tempBytes) {
              regex.append(String.format("\\x%02x", tempByte & 0xFF));
            }
            if (!hitNullComponent) {
              prefixBytes.write(tempBytes, 0, tempBytes.length);
            }
          }
          break;
        case LONG:
          if (null == component) {
            // null longs can be excluded entirely if there are just nulls at
            // the end of the EntityId, otherwise, match the correct number of
            // bytes
            regex.append("(.{").append(Bytes.SIZEOF_LONG).append("})?");
            hitNullComponent = true;
          } else {
            byte[] tempBytes = toBytes((Long) component);
            // match each byte in the long using a regex hex sequence
            for (byte tempByte : tempBytes) {
              regex.append(String.format("\\x%02x", tempByte & 0xFF));
            }
            if (!hitNullComponent) {
              prefixBytes.write(tempBytes, 0, tempBytes.length);
            }
          }
          break;
        case STRING:
          if (null == component) {
            // match any non-zero character at least once, followed by a zero
            // delimiter, or match nothing at all in case the component was at
            // the end of the EntityId and skipped entirely
            regex.append("([^\\x00]+\\x00)?");
            hitNullComponent = true;
          } else {
            // FormattedEntityId converts a string component to UTF-8 bytes to
            // create the HBase key.  RegexStringComparator will convert the
            // value it sees (ie, the HBase key) to a string using ISO-8859-1.
            // Therefore, we need to write ISO-8859-1 characters to our regex so
            // that the comparison happens correctly.
            byte[] utfBytes = toBytes((String) component);
            String isoString = new String(utfBytes, Charsets.ISO_8859_1);
            regex.append(isoString).append("\\x00");
            if (!hitNullComponent) {
              prefixBytes.write(utfBytes, 0, utfBytes.length);
              prefixBytes.write((byte) 0);
            }
          }
          break;
        default:
          throw new IllegalStateException("Unknown component type: "
              + mRowKeyFormat.getComponents().get(i).getType());
      }
    }
    regex.append("$"); // $ matches the end of the string

    final RowFilter regexRowFilter =
        SchemaPlatformBridge.get().createRowFilterFromRegex(CompareOp.EQUAL, regex.toString());
    if (addPrefixFilter) {
      return new FilterList(new PrefixFilter(prefixBytes.toByteArray()), regexRowFilter);
    }
    return regexRowFilter;
  }

@Test
  public void testHashIsCalculatedWhenAllHashComponentsAreSpecified() throws Exception {
    final int hashLength = 2;
    RowKeyFormat2.Builder builder = RowKeyFormat2.newBuilder()
        .setEncoding(RowKeyEncoding.FORMATTED)
        .setSalt(new HashSpec(HashType.MD5, hashLength, false))
        .setRangeScanStartIndex(1);

    List<RowKeyComponent> components = ImmutableList.of(
            new RowKeyComponent("id", INTEGER), // this one is included in the hash
            new RowKeyComponent("ts", LONG));   // this one is not
    builder.setComponents(components);
    RowKeyFormat2 rowKeyFormat = builder.build();

    EntityIdFactory factory = EntityIdFactory.getFactory(rowKeyFormat);
    FormattedEntityIdRowFilter filter = createFilter(rowKeyFormat, 100);
    Object[] componentValues = new Object[] { Integer.valueOf(100), Long.valueOf(900000L) };
    runTest(rowKeyFormat, filter, factory, INCLUDE, componentValues);

    EntityId entityId = factory.getEntityId(componentValues);
    byte[] hbaseKey = entityId.getHBaseRowKey();
    Filter hbaseFilter = filter.toHBaseFilter(null);

    // A row key with a different hash but the same first component should be
    // excluded by the filter. The hash is 0x9f0f
    hbaseKey[0] = (byte) 0x7F;
    hbaseKey[1] = (byte) 0xFF;
    boolean filtered = hbaseFilter.filterRowKey(hbaseKey, 0, hbaseKey.length);
    doInclusionAssert(rowKeyFormat, filter, entityId, hbaseFilter, hbaseKey, EXCLUDE);
  }


@Test
  public void testMultipleHostsMultiplePorts() {
    try {
      KijiURI.newBuilder("kiji-hbase://zkhost1:1234,zkhost2:2345/instance/table/col");
      fail("An exception should have been thrown.");
    } catch (KijiURIException kurie) {
      assertEquals("Invalid Kiji URI: 'kiji-hbase://zkhost1:1234,zkhost2:2345/instance/table/col'"
              + " : Invalid ZooKeeper ensemble cluster identifier.", kurie.getMessage());
    }
  }


('/**\\n   * Register an {@link AutoReferenceCounted} instance to be cleaned up by this\\n   * {@code AutoReferenceCountedReaper} when the {@link AutoReferenceCounted} is determined by\\n   * the JVM to no longer be reachable.\\n   *\\n   * @param autoReferenceCountable to be registered to this reaper.\\n   */', '')

b'/**\n   * Register an {@link AutoReferenceCounted} instance to be cleaned up by this\n   * {@code AutoReferenceCountedReaper} when the {@link AutoReferenceCounted} is determined by\n   * the JVM to no longer be reachable.\n   *\n   * @param autoReferenceCountable to be registered to this reaper.\n   */'public void registerAutoReferenceCounted(AutoReferenceCounted autoReferenceCountable) {
    Preconditions.checkState(mIsOpen,
        "cannot register an AutoReferenceCounted to a closed AutoReferenceCountedReaper.");
    LOG.debug("Registering AutoReferenceCounted {}.", autoReferenceCountable);
    mReferences.add(
        new CloseablePhantomRef(
            autoReferenceCountable,
            mReferenceQueue,
            autoReferenceCountable.getCloseableResources())
    );
  }

@Test
  public void testReaperWillReapAutoReferenceCounted() throws Exception {
    CountDownLatch latch = new CountDownLatch(1);
    mReaper.registerAutoReferenceCounted(new LatchAutoReferenceCountable(latch));
    System.gc(); // Force the phantom ref to be enqueued

    Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
  }


@Test
  public void testCloserWillCloseAutoReferenceCountedInWeakSet() throws Exception {
    Set<AutoReferenceCounted> set =
        Collections.newSetFromMap(
            new MapMaker().weakKeys().<AutoReferenceCounted, Boolean>makeMap());

    final CountDownLatch latch = new CountDownLatch(1);
    AutoReferenceCounted closeable = new LatchAutoReferenceCountable(latch);

    set.add(closeable);
    mReaper.registerAutoReferenceCounted(closeable);
    closeable = null;

    System.gc();
    Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
  }


@Test
  public void testCloserWillCloseAutoReferenceCountedInWeakCache() throws Exception {
    CountDownLatch latch = new CountDownLatch(1);

    final LoadingCache<CountDownLatch, AutoReferenceCounted> cache = CacheBuilder
        .newBuilder()
        .weakValues()
        .build(new CacheLoader<CountDownLatch, AutoReferenceCounted>() {
          @Override
          public AutoReferenceCounted load(CountDownLatch latch) throws Exception {
            AutoReferenceCounted closeable = new LatchAutoReferenceCountable(latch);
            mReaper.registerAutoReferenceCounted(closeable);
            return closeable;
          }
        });

    cache.get(latch); // force creation

    System.gc();
    Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
  }


@Test
  public void testWeakCacheWillBeCleanedUp() throws Exception {
    CountDownLatch latch = new CountDownLatch(2);

    final LoadingCache<CountDownLatch, AutoReferenceCounted> cache = CacheBuilder
        .newBuilder()
        .weakValues()
        .build(new CacheLoader<CountDownLatch, AutoReferenceCounted>() {
          @Override
          public AutoReferenceCounted load(CountDownLatch latch) throws Exception {
            AutoReferenceCounted closeable = new LatchAutoReferenceCountable(latch);
            mReaper.registerAutoReferenceCounted(closeable);
            return closeable;
          }
        });

    cache.get(latch);
    System.gc();
    cache.get(latch);
    System.gc();
    Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
  }


Reports whether the given schema is an optional type ie a union  null Type  @param schema The schema to test @return the optional type if the specified schema describes an optional type null otherwise

b'/**\n   * Reports whether the given schema is an optional type (ie. a union { null, Type }).\n   *\n   * @param schema The schema to test.\n   * @return the optional type, if the specified schema describes an optional type, null otherwise.\n   */'public static Schema getOptionalType(Schema schema) {
    Preconditions.checkArgument(schema.getType() == Schema.Type.UNION);
    final List<Schema> types = schema.getTypes();
    if (types.size() != 2) {
      return null;
    }
    if (types.get(0).getType() == Schema.Type.NULL) {
      return types.get(1);
    } else if (types.get(1).getType() == Schema.Type.NULL) {
      return types.get(0);
    } else {
      return null;
    }
  }

@Test
  public void testGetOptionalType() throws Exception {
    final List<Schema> unionSchemas = Lists.newArrayList(
        INT_SCHEMA,
        NULL_SCHEMA);
    final Schema optionalSchema = Schema.createUnion(unionSchemas);
    final Schema optionalReverseSchema = Schema.createUnion(Lists.reverse(unionSchemas));

    // Ensure that the optional type is retrievable.
    assertEquals(INT_SCHEMA, AvroUtils.getOptionalType(optionalSchema));
    assertEquals(INT_SCHEMA, AvroUtils.getOptionalType(optionalReverseSchema));
  }


('/**\\n   * Reports whether the given schema is an optional type (ie. a union { null, Type }).\\n   *\\n   * @param schema The schema to test.\\n   * @return the optional type, if the specified schema describes an optional type, null otherwise.\\n   */', '')

@Test
  public void testGetNonOptionalType() throws Exception {
    final List<Schema> unionSchemas = Lists.newArrayList(
        INT_SCHEMA,
        STRING_SCHEMA,
        NULL_SCHEMA);
    final Schema nonOptionalSchema = Schema.createUnion(unionSchemas);

    // Ensure that null gets returned when the schema provided isn't an optional type.
    assertEquals(null, AvroUtils.getOptionalType(nonOptionalSchema));
  }


('/**\\n   * Validates that the provided reader schema can be used to decode avro data written with the\\n   * provided writer schema.\\n   *\\n   * @param reader schema to check.\\n   * @param writer schema to check.\\n   * @return a result object identifying any compatibility errors.\\n   */', '')

b'/**\n   * Validates that the provided reader schema can be used to decode avro data written with the\n   * provided writer schema.\n   *\n   * @param reader schema to check.\n   * @param writer schema to check.\n   * @return a result object identifying any compatibility errors.\n   */'public static SchemaPairCompatibility checkReaderWriterCompatibility(
      final Schema reader,
      final Schema writer
  ) {
    final SchemaCompatibilityType compatibility =
        new ReaderWriterCompatiblityChecker()
            .getCompatibility(reader, writer);

    final String message;
    switch (compatibility) {
      case INCOMPATIBLE: {
        message = String.format(
            "Data encoded using writer schema:%n%s%n"
            + "will or may fail to decode using reader schema:%n%s%n",
            writer.toString(true),
            reader.toString(true));
        break;
      }
      case COMPATIBLE: {
        message = READER_WRITER_COMPATIBLE_MESSAGE;
        break;
      }
      default: throw new InternalKijiError("Unknown compatibility: " + compatibility);
    }

    return new SchemaPairCompatibility(
        compatibility,
        reader,
        writer,
        message);
  }

@Test
  public void testValidateSchemaPairMissingField() throws Exception {
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null));
    final Schema reader = Schema.createRecord(readerFields);
    final AvroUtils.SchemaPairCompatibility expectedResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            WRITER_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);

    // Test omitting a field.
    assertEquals(expectedResult, AvroUtils.checkReaderWriterCompatibility(reader, WRITER_SCHEMA));
  }


@Test
  public void testValidateSchemaPairMissingSecondField() throws Exception {
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
    final Schema reader = Schema.createRecord(readerFields);
    final AvroUtils.SchemaPairCompatibility expectedResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            WRITER_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);

    // Test omitting other field.
    assertEquals(expectedResult, AvroUtils.checkReaderWriterCompatibility(reader, WRITER_SCHEMA));
  }


@Test
  public void testValidateSchemaPairAllFields() throws Exception {
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
    final Schema reader = Schema.createRecord(readerFields);
    final AvroUtils.SchemaPairCompatibility expectedResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            WRITER_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);

    // Test with all fields.
    assertEquals(expectedResult, AvroUtils.checkReaderWriterCompatibility(reader, WRITER_SCHEMA));
  }


@Test
  public void testValidateSchemaNewFieldWithDefault() throws Exception {
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, IntNode.valueOf(42)));
    final Schema reader = Schema.createRecord(readerFields);
    final AvroUtils.SchemaPairCompatibility expectedResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            WRITER_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);

    // Test new field with default value.
    assertEquals(expectedResult, AvroUtils.checkReaderWriterCompatibility(reader, WRITER_SCHEMA));
  }


@Test
  public void testMultipleColumns() {
    final KijiURI uri =
        KijiURI.newBuilder("kiji-hbase://zkhost1,zkhost2/default/table/col1,col2").build();
    assertEquals("zkhost1", uri.getZookeeperQuorum().get(0));
    assertEquals("zkhost2", uri.getZookeeperQuorum().get(1));
    assertEquals(KijiURI.DEFAULT_ZOOKEEPER_CLIENT_PORT, uri.getZookeeperClientPort());
    assertEquals("default", uri.getInstance());
    assertEquals("table", uri.getTable());
    assertEquals(2, uri.getColumns().size());
  }


@Test
  public void testValidateSchemaNewField() throws Exception {
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, null));
    final Schema reader = Schema.createRecord(readerFields);
    final AvroUtils.SchemaPairCompatibility expectedResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.INCOMPATIBLE,
            reader,
            WRITER_SCHEMA,
            String.format(
                "Data encoded using writer schema:\n%s\n"
                + "will or may fail to decode using reader schema:\n%s\n",
                WRITER_SCHEMA.toString(true),
                reader.toString(true)));

    // Test new field without default value.
    assertEquals(expectedResult, AvroUtils.checkReaderWriterCompatibility(reader, WRITER_SCHEMA));
  }


@Test
  public void testValidateArrayWriterSchema() throws Exception {
    final Schema validReader = Schema.createArray(STRING_SCHEMA);
    final Schema invalidReader = Schema.createMap(STRING_SCHEMA);
    final AvroUtils.SchemaPairCompatibility validResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            validReader,
            STRING_ARRAY_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility invalidResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.INCOMPATIBLE,
            invalidReader,
            STRING_ARRAY_SCHEMA,
            String.format(
                "Data encoded using writer schema:\n%s\n"
                + "will or may fail to decode using reader schema:\n%s\n",
                STRING_ARRAY_SCHEMA.toString(true),
                invalidReader.toString(true)));

    assertEquals(
        validResult,
        AvroUtils.checkReaderWriterCompatibility(validReader, STRING_ARRAY_SCHEMA));
    assertEquals(
        invalidResult,
        AvroUtils.checkReaderWriterCompatibility(invalidReader, STRING_ARRAY_SCHEMA));
  }


@Test
  public void testValidatePrimitiveWriterSchema() throws Exception {
    final Schema validReader = Schema.create(Schema.Type.STRING);
    final AvroUtils.SchemaPairCompatibility validResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            validReader,
            STRING_SCHEMA,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility invalidResult =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.INCOMPATIBLE,
            INT_SCHEMA,
            STRING_SCHEMA,
            String.format(
                "Data encoded using writer schema:\n%s\n"
                + "will or may fail to decode using reader schema:\n%s\n",
                STRING_SCHEMA.toString(true),
                INT_SCHEMA.toString(true)));

    assertEquals(
        validResult,
        AvroUtils.checkReaderWriterCompatibility(validReader, STRING_SCHEMA));
    assertEquals(
        invalidResult,
        AvroUtils.checkReaderWriterCompatibility(INT_SCHEMA, STRING_SCHEMA));
  }


@Test
  public void testUnionReaderWriterSubsetIncompatibility() {
    final Schema unionWriter = Schema.createUnion(
        Lists.newArrayList(INT_SCHEMA, STRING_SCHEMA));
    final Schema unionReader = Schema.createUnion(
        Lists.newArrayList(STRING_SCHEMA));
    final SchemaPairCompatibility result =
        AvroUtils.checkReaderWriterCompatibility(unionReader, unionWriter);
    assertEquals(SchemaCompatibilityType.INCOMPATIBLE, result.getType());
  }


@Test
  public void testReaderWriterCompatibility() {
    for (ReaderWriter readerWriter : COMPATIBLE_READER_WRITER_TEST_CASES) {
      final Schema reader = readerWriter.getReader();
      final Schema writer = readerWriter.getWriter();
      LOG.debug("Testing compatibility of reader {} with writer {}.", reader, writer);
      final SchemaPairCompatibility result =
          AvroUtils.checkReaderWriterCompatibility(reader, writer);
      assertEquals(String.format(
          "Expecting reader %s to be compatible with writer %s, but tested incompatible.",
          reader, writer),
          SchemaCompatibilityType.COMPATIBLE, result.getType());
    }
  }


@Test
  public void testReaderWriterIncompatibility() {
    for (ReaderWriter readerWriter : INCOMPATIBLE_READER_WRITER_TEST_CASES) {
      final Schema reader = readerWriter.getReader();
      final Schema writer = readerWriter.getWriter();
      LOG.debug("Testing incompatibility of reader {} with writer {}.", reader, writer);
      final SchemaPairCompatibility result =
          AvroUtils.checkReaderWriterCompatibility(reader, writer);
      assertEquals(String.format(
          "Expecting reader %s to be incompatible with writer %s, but tested compatible.",
          reader, writer),
          SchemaCompatibilityType.INCOMPATIBLE, result.getType());
    }
  }


Validates that the provided reader schemas can be used to decode data written with the provided writer schema @param readers that must be able to be used to decode data encoded with the provided writer schema @param writer schema to check @return a list of compatibility results     Check compatibility between each readerwriter pair

b'/**\n   * Validates that the provided reader schemas can be used to decode data written with the provided\n   * writer schema.\n   *\n   * @param readers that must be able to be used to decode data encoded with the provided writer\n   *     schema.\n   * @param writer schema to check.\n   * @return a list of compatibility results.\n   */'public static SchemaSetCompatibility checkWriterCompatibility(
      Iterator<Schema> readers,
      Schema writer) {
    final List<SchemaPairCompatibility> results = Lists.newArrayList();
    while (readers.hasNext()) {
      // Check compatibility between each reader/writer pair.
      results.add(checkReaderWriterCompatibility(readers.next(), writer));
    }
    return new SchemaSetCompatibility(results);
  }

@Test
  public void testCheckWriterCompatibility() throws Exception {
    // Setup schema fields.
    final List<Schema.Field> writerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
    final List<Schema.Field> readerFields1 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, IntNode.valueOf(42)));
    final List<Schema.Field> readerFields2 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, IntNode.valueOf(42)));
    final List<Schema.Field> readerFields3 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
    final List<Schema.Field> readerFields4 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, null));

    // Setup schemas.
    final Schema writer = Schema.createRecord(writerFields);
    final Schema reader1 = Schema.createRecord(readerFields1);
    final Schema reader2 = Schema.createRecord(readerFields2);
    final Schema reader3 = Schema.createRecord(readerFields3);
    final Schema reader4 = Schema.createRecord(readerFields4);
    final Set<Schema> readers = Sets.newHashSet(
        reader1,
        reader2,
        reader3,
        reader4);

    // Setup expectations.
    final AvroUtils.SchemaPairCompatibility result1 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader1,
            writer,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility result2 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader2,
            writer,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility result3 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader3,
            writer,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility result4 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.INCOMPATIBLE,
            reader4,
            writer,
            String.format(
                "Data encoded using writer schema:\n%s\n"
                + "will or may fail to decode using reader schema:\n%s\n",
                writer.toString(true),
                reader4.toString(true)));

    // Perform the check.
    final AvroUtils.SchemaSetCompatibility results = AvroUtils
        .checkWriterCompatibility(readers.iterator(), writer);

    // Ensure that the results contain the expected values.
    assertEquals(AvroUtils.SchemaCompatibilityType.INCOMPATIBLE, results.getType());
    assertTrue(results.getCauses().contains(result1));
    assertTrue(results.getCauses().contains(result2));
    assertTrue(results.getCauses().contains(result3));
    assertTrue(results.getCauses().contains(result4));
  }


Validates that the provided reader schema can read data written with the provided writer schemas @param reader schema to check @param writers that must be compatible with the provided reader schema @return a list of compatibility results     Check compatibility between each readerwriter pair

b'/**\n   * Validates that the provided reader schema can read data written with the provided writer\n   * schemas.\n   *\n   * @param reader schema to check.\n   * @param writers that must be compatible with the provided reader schema.\n   * @return a list of compatibility results.\n   */'public static SchemaSetCompatibility checkReaderCompatibility(
      Schema reader,
      Iterator<Schema> writers) {
    final List<SchemaPairCompatibility> results = Lists.newArrayList();
    while (writers.hasNext()) {
      // Check compatibility between each reader/writer pair.
      results.add(checkReaderWriterCompatibility(reader, writers.next()));
    }
    return new SchemaSetCompatibility(results);
  }

@Test
  public void testCheckReaderCompatibility() throws Exception {
    // Setup schema fields.
    final List<Schema.Field> writerFields1 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
    final List<Schema.Field> writerFields2 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, null));
    final List<Schema.Field> writerFields3 = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("newfield1", INT_SCHEMA, null, null));
    final List<Schema.Field> readerFields = Lists.newArrayList(
        new Schema.Field("oldfield1", INT_SCHEMA, null, null),
        new Schema.Field("oldfield2", STRING_SCHEMA, null, null));

    // Setup schemas.
    final Schema writer1 = Schema.createRecord(writerFields1);
    final Schema writer2 = Schema.createRecord(writerFields2);
    final Schema writer3 = Schema.createRecord(writerFields3);
    final Schema reader = Schema.createRecord(readerFields);
    final Set<Schema> written = Sets.newHashSet(writer1);
    final Set<Schema> writers = Sets.newHashSet(writer2, writer3);

    // Setup expectations.
    final AvroUtils.SchemaPairCompatibility result1 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            writer1,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility result2 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.COMPATIBLE,
            reader,
            writer2,
            AvroUtils.READER_WRITER_COMPATIBLE_MESSAGE);
    final AvroUtils.SchemaPairCompatibility result3 =
        new AvroUtils.SchemaPairCompatibility(
            AvroUtils.SchemaCompatibilityType.INCOMPATIBLE,
            reader,
            writer3,
            String.format(
                "Data encoded using writer schema:\n%s\n"
                + "will or may fail to decode using reader schema:\n%s\n",
                writer3.toString(true),
                reader.toString(true)));

    // Perform the check.
    final AvroUtils.SchemaSetCompatibility results = AvroUtils
        .checkReaderCompatibility(reader, Iterators.concat(written.iterator(), writers.iterator()));

    // Ensure that the results contain the expected values.
    assertEquals(AvroUtils.SchemaCompatibilityType.INCOMPATIBLE, results.getType());
    assertTrue(results.getCauses().contains(result1));
    assertTrue(results.getCauses().contains(result2));
    assertTrue(results.getCauses().contains(result3));
  }


Compares two AvroSchema objects for equality within the context of the given SchemaTable @param schemaTable SchemaTable with which to resolve schema UIDs @param first one AvroSchema object to compare for equality @param second another AvroSchema object to compare for equality @return whether the two objects represent the same Schema @throws IOException in case of an error reading from the SchemaTable

b'/**\n   * Compares two AvroSchema objects for equality within the context of the given SchemaTable.\n   *\n   * @param schemaTable SchemaTable with which to resolve schema UIDs.\n   * @param first one AvroSchema object to compare for equality.\n   * @param second another AvroSchema object to compare for equality.\n   * @return whether the two objects represent the same Schema.\n   * @throws IOException in case of an error reading from the SchemaTable.\n   */'public static boolean avroSchemaEquals(
      final KijiSchemaTable schemaTable,
      final AvroSchema first,
      final AvroSchema second
  ) throws IOException {
    final AvroSchemaResolver resolver = new SchemaTableAvroResolver(schemaTable);

    return Objects.equal(resolver.apply(first), resolver.apply(second));
  }

@Test
  public void testAvroSchemaEquals() throws IOException {
    final KijiSchemaTable schemaTable = getKiji().getSchemaTable();

    final long stringUID = schemaTable.getOrCreateSchemaId(STRING_SCHEMA);
    final long intUID = schemaTable.getOrCreateSchemaId(INT_SCHEMA);
    final String stringJSON = STRING_SCHEMA.toString();
    final String intJSON = INT_SCHEMA.toString();

    final AvroSchema stringUIDAS = AvroSchema.newBuilder().setUid(stringUID).build();
    final AvroSchema stringJSONAS = AvroSchema.newBuilder().setJson(stringJSON).build();
    final AvroSchema intUIDAS = AvroSchema.newBuilder().setUid(intUID).build();
    final AvroSchema intJSONAS = AvroSchema.newBuilder().setJson(intJSON).build();

    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, stringUIDAS, stringUIDAS));
    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, stringUIDAS, stringJSONAS));
    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, stringJSONAS, stringUIDAS));
    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, intUIDAS, intUIDAS));
    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, intUIDAS, intJSONAS));
    assertTrue(AvroUtils.avroSchemaEquals(schemaTable, intJSONAS, intUIDAS));

    assertFalse(AvroUtils.avroSchemaEquals(schemaTable, stringUIDAS, intUIDAS));
    assertFalse(AvroUtils.avroSchemaEquals(schemaTable, stringUIDAS, intJSONAS));
    assertFalse(AvroUtils.avroSchemaEquals(schemaTable, stringJSONAS, intJSONAS));
    assertFalse(AvroUtils.avroSchemaEquals(schemaTable, stringJSONAS, intUIDAS));
  }


('/**\\n   * Check whether a collection of AvroSchema objects contains a given AvroSchema element, resolving\\n   * UIDs using the given KijiSchemaTable.\\n   *\\n   * @param schemaTable KijiSchemaTable with which to resolve schema UIDs.\\n   * @param schemaCollection collection of AvroSchemas to check for the presence of the given\\n   *     element.\\n   * @param element AvroSchema for whose presence to check in schemaCollection.\\n   * @return whether schemaCollection contains element after resolving UIDs using schemaTable.\\n   * @throws IOException in case of an error reading from the schema table.\\n   */', '')

('', '// If none match, return false.\n')

b'/**\n   * Check whether a collection of AvroSchema objects contains a given AvroSchema element, resolving\n   * UIDs using the given KijiSchemaTable.\n   *\n   * @param schemaTable KijiSchemaTable with which to resolve schema UIDs.\n   * @param schemaCollection collection of AvroSchemas to check for the presence of the given\n   *     element.\n   * @param element AvroSchema for whose presence to check in schemaCollection.\n   * @return whether schemaCollection contains element after resolving UIDs using schemaTable.\n   * @throws IOException in case of an error reading from the schema table.\n   */'public static boolean avroSchemaCollectionContains(
      final KijiSchemaTable schemaTable,
      final Collection<AvroSchema> schemaCollection,
      final AvroSchema element
  ) throws IOException {
    for (AvroSchema schema : schemaCollection) {
      if (avroSchemaEquals(schemaTable, schema, element)) {
        return true;
      }
    }
    // If none match, return false.
    return false;
  }

@Test
  public void testAvroSchemaListContains() throws IOException {
    final KijiSchemaTable schemaTable = getKiji().getSchemaTable();

    final long stringUID = schemaTable.getOrCreateSchemaId(STRING_SCHEMA);
    final long intUID = schemaTable.getOrCreateSchemaId(INT_SCHEMA);
    final String stringJSON = STRING_SCHEMA.toString();
    final String intJSON = INT_SCHEMA.toString();

    final AvroSchema stringUIDAS = AvroSchema.newBuilder().setUid(stringUID).build();
    final AvroSchema stringJSONAS = AvroSchema.newBuilder().setJson(stringJSON).build();
    final AvroSchema intUIDAS = AvroSchema.newBuilder().setUid(intUID).build();
    final AvroSchema intJSONAS = AvroSchema.newBuilder().setJson(intJSON).build();

    final List<AvroSchema> stringList = Lists.newArrayList(stringJSONAS, stringUIDAS);
    final List<AvroSchema> intList = Lists.newArrayList(intJSONAS, intUIDAS);
    final List<AvroSchema> bothList = Lists.newArrayList(stringJSONAS, intUIDAS);

    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, stringList, stringJSONAS));
    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, stringList, stringUIDAS));
    assertFalse(AvroUtils.avroSchemaCollectionContains(schemaTable, stringList, intUIDAS));
    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, intList, intJSONAS));
    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, intList, intUIDAS));
    assertFalse(AvroUtils.avroSchemaCollectionContains(schemaTable, intList, stringUIDAS));
    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, bothList, stringJSONAS));
    assertTrue(AvroUtils.avroSchemaCollectionContains(schemaTable, bothList, intUIDAS));
  }


@Test
  public void testExtraPath() {
    try {
      KijiURI.newBuilder("kiji-hbase://(zkhost1,zkhost2):1234/instance/table/col/extra");
      fail("An exception should have been thrown.");
    } catch (KijiURIException kurie) {
      assertEquals("Invalid Kiji URI: 'kiji-hbase://(zkhost1,zkhost2):1234/"
              + "instance/table/col/extra' : Too many path segments.", kurie.getMessage());
    }
  }


('/**\\n   * Decodes a JSON encoded record.\\n   *\\n   * @param json JSON tree to decode, encoded as a string.\\n   * @param schema Avro schema of the value to decode.\\n   * @return the decoded value.\\n   * @throws IOException on error.\\n   */', '')

b'/**\n   * Decodes a JSON encoded record.\n   *\n   * @param json JSON tree to decode, encoded as a string.\n   * @param schema Avro schema of the value to decode.\n   * @return the decoded value.\n   * @throws IOException on error.\n   */'public static Object fromJsonString(String json, Schema schema) throws IOException {
    final ObjectMapper mapper = new ObjectMapper();
    final JsonParser parser = new JsonFactory().createJsonParser(json)
        .enable(Feature.ALLOW_COMMENTS)
        .enable(Feature.ALLOW_SINGLE_QUOTES)
        .enable(Feature.ALLOW_UNQUOTED_FIELD_NAMES);
    final JsonNode root = mapper.readTree(parser);
    return fromJsonNode(root, schema);
  }

@Test
  public void testPrimitivesFromJson() throws Exception {
    assertEquals((Integer) 1, FromJson.fromJsonString("1", Schema.create(Schema.Type.INT)));
    assertEquals((Long) 1L, FromJson.fromJsonString("1", Schema.create(Schema.Type.LONG)));
    assertEquals((Float) 1.0f, FromJson.fromJsonString("1", Schema.create(Schema.Type.FLOAT)));
    assertEquals((Double) 1.0, FromJson.fromJsonString("1", Schema.create(Schema.Type.DOUBLE)));
    assertEquals((Float) 1.0f, FromJson.fromJsonString("1.0", Schema.create(Schema.Type.FLOAT)));
    assertEquals((Double) 1.0, FromJson.fromJsonString("1.0", Schema.create(Schema.Type.DOUBLE)));
    assertEquals("Text", FromJson.fromJsonString("'Text'", Schema.create(Schema.Type.STRING)));
    assertEquals("Text", FromJson.fromJsonString("\"Text\"", Schema.create(Schema.Type.STRING)));
    assertEquals(true, FromJson.fromJsonString("true", Schema.create(Schema.Type.BOOLEAN)));
    assertEquals(false, FromJson.fromJsonString("false", Schema.create(Schema.Type.BOOLEAN)));
  }


Hashes the input string @param input The string to hash @return The 128bit MD5 hash of the input

b'/**\n   * Hashes the input string.\n   *\n   * @param input The string to hash.\n   * @return The 128-bit MD5 hash of the input.\n   */'public static byte[] hash(String input) {
    try {
      return hash(input.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

@Test
  public void testHash() {
    assertArrayEquals(Hasher.hash("foo"), Hasher.hash("foo"));

    // 16 bytes = 128-bit MD5.
    assertEquals(16, Hasher.hash("bar").length);

    assertFalse(Arrays.equals(Hasher.hash("foo"), Hasher.hash("bar")));
  }


Determines whether a string is a valid Java identifier pA valid Java identifier may not start with a number but may contain any combination of letters digits underscores or dollar signsp pSee the a hrefhttpjavasuncomdocsbooksjlsthirdeditionhtmllexicalhtml38 Java Language Specificationap @param identifier The identifier to test for validity @return Whether the identifier was valid

b'/**\n   * Determines whether a string is a valid Java identifier.\n   *\n   *
A valid Java identifier may not start with a number, but may contain any\n   * combination of letters, digits, underscores, or dollar signs.
\n   *\n   *
See the \n   * Java Language Specification
\n   *\n   * @param identifier The identifier to test for validity.\n   * @return Whether the identifier was valid.\n   */'public static boolean isValidIdentifier(String identifier) {
    if (identifier.isEmpty() || !Character.isJavaIdentifierStart(identifier.charAt(0))) {
      return false;
    }
    for (int i = 1; i < identifier.length(); i++) {
      if (!Character.isJavaIdentifierPart(identifier.charAt(i))) {
        return false;
      }
    }
    return true;
  }

@Test
  public void testIsValidIdentifier() {
    assertFalse(JavaIdentifiers.isValidIdentifier(""));
    assertTrue(JavaIdentifiers.isValidIdentifier("a"));
    assertTrue(JavaIdentifiers.isValidIdentifier("B"));
    assertTrue(JavaIdentifiers.isValidIdentifier("_"));
    assertFalse(JavaIdentifiers.isValidIdentifier("-"));
    assertFalse(JavaIdentifiers.isValidIdentifier("."));
    assertFalse(JavaIdentifiers.isValidIdentifier("0"));
    assertTrue(JavaIdentifiers.isValidIdentifier("_1"));
    assertTrue(JavaIdentifiers.isValidIdentifier("_c"));
    assertTrue(JavaIdentifiers.isValidIdentifier("_giw07nf"));
    assertTrue(JavaIdentifiers.isValidIdentifier("giw07nf"));
    assertFalse(JavaIdentifiers.isValidIdentifier("2giw07nf"));
  }


Determines whether a string could be the name of a Java class pIf this method returns true it does not necessarily mean that the Java class with codeclassNamecode exists it only means that one could write a Java class with that fullyqualified namep @param className A string to test @return Whether the class name was valid     A valid class name is a bunch of valid Java identifiers separated by dots

b'/**\n   * Determines whether a string could be the name of a Java class.\n   *\n   *
If this method returns true, it does not necessarily mean that the Java class with\n   * className exists; it only means that one could write a Java class with\n   * that fully-qualified name.
\n   *\n   * @param className A string to test.\n   * @return Whether the class name was valid.\n   */'public static boolean isValidClassName(String className) {
    // A valid class name is a bunch of valid Java identifiers separated by dots.
    for (String part : StringUtils.splitByWholeSeparatorPreserveAllTokens(className, ".")) {
      if (!isValidIdentifier(part)) {
        return false;
      }
    }
    return true;
  }

@Test
  public void testIsValidClassName() {
    assertTrue(JavaIdentifiers.isValidClassName("org.kiji.schema.Foo"));
    assertFalse(JavaIdentifiers.isValidClassName("org.kiji.schema..Foo"));
    assertTrue(JavaIdentifiers.isValidClassName("org.kiji.schema.Foo$Bar"));
    assertTrue(JavaIdentifiers.isValidClassName("Foo"));
    assertFalse(JavaIdentifiers.isValidClassName("Foo."));
    assertFalse(JavaIdentifiers.isValidClassName(".Foo"));
    assertTrue(JavaIdentifiers.isValidClassName("_Foo"));
    assertTrue(JavaIdentifiers.isValidClassName("com._Foo"));
    assertFalse(JavaIdentifiers.isValidClassName("com.8Foo"));
    assertTrue(JavaIdentifiers.isValidClassName("com.Foo8"));
  }


Utility class may not be instantiated

b'/** Utility class may not be instantiated. */'private JvmId() {
  }

@Test
  public void testJvmId() throws Exception {
    final String jvmId = JvmId.get();
    LOG.info("JVM ID: {}", jvmId);
    assertEquals(jvmId, JvmId.get());
  }


('/**\\n   * @return true if name is a valid name for a table, locality group, family,\\n   *     or column name, and false otherwise.\\n   * @param name the name to check.\\n   */', '')

b'/**\n   * @return true if name is a valid name for a table, locality group, family,\n   *     or column name, and false otherwise.\n   * @param name the name to check.\n   */'public static boolean isValidLayoutName(CharSequence name) {
    return VALID_LAYOUT_NAME_PATTERN.matcher(name).matches();
  }

@Test
  public void testIsValidIdentifier() {
    assertFalse(KijiNameValidator.isValidLayoutName(""));
    assertFalse(KijiNameValidator.isValidLayoutName("0123"));
    assertFalse(KijiNameValidator.isValidLayoutName("0123abc"));
    assertFalse(KijiNameValidator.isValidLayoutName("-asdb"));
    assertFalse(KijiNameValidator.isValidLayoutName("abc-def"));
    assertFalse(KijiNameValidator.isValidLayoutName("abcdef$"));
    assertFalse(KijiNameValidator.isValidLayoutName("abcdef-"));
    assertFalse(KijiNameValidator.isValidLayoutName("abcdef("));
    assertFalse(KijiNameValidator.isValidLayoutName("(bcdef"));
    assertFalse(KijiNameValidator.isValidLayoutName("(bcdef)"));

    assertTrue(KijiNameValidator.isValidLayoutName("_"));
    assertTrue(KijiNameValidator.isValidLayoutName("foo"));
    assertTrue(KijiNameValidator.isValidLayoutName("FOO"));
    assertTrue(KijiNameValidator.isValidLayoutName("FooBar"));
    assertTrue(KijiNameValidator.isValidLayoutName("foo123"));
    assertTrue(KijiNameValidator.isValidLayoutName("foo_bar"));

    assertFalse(KijiNameValidator.isValidLayoutName("abc:def"));
    assertFalse(KijiNameValidator.isValidLayoutName("abc\\def"));
    assertFalse(KijiNameValidator.isValidLayoutName("abc/def"));
    assertFalse(KijiNameValidator.isValidLayoutName("abc=def"));
    assertFalse(KijiNameValidator.isValidLayoutName("abc+def"));
  }


@return true if name is a valid alias for a table locality group family or column name and false otherwise @param name the name to check

b'/**\n   * @return true if name is a valid alias for a table, locality group, family,\n   *     or column name, and false otherwise.\n   * @param name the name to check.\n   */'public static boolean isValidAlias(CharSequence name) {
    return VALID_ALIAS_PATTERN.matcher(name).matches();
  }

@Test
  public void testIsValidAlias() {
    assertFalse(KijiNameValidator.isValidAlias(""));
    assertTrue(KijiNameValidator.isValidAlias("0123")); // Digits are ok in a leading capacity.
    assertTrue(KijiNameValidator.isValidAlias("0123abc"));
    assertTrue(KijiNameValidator.isValidAlias("abc-def")); // Dashes are ok in aliases...
    assertTrue(KijiNameValidator.isValidAlias("-asdb")); // Even as the first character.
    assertTrue(KijiNameValidator.isValidAlias("asdb-")); // Even as the first character.
    assertFalse(KijiNameValidator.isValidAlias("abcdef("));
    assertFalse(KijiNameValidator.isValidAlias("(bcdef"));
    assertFalse(KijiNameValidator.isValidAlias("(bcdef)"));

    assertTrue(KijiNameValidator.isValidAlias("_"));
    assertTrue(KijiNameValidator.isValidAlias("foo"));
    assertTrue(KijiNameValidator.isValidAlias("FOO"));
    assertTrue(KijiNameValidator.isValidAlias("FooBar"));
    assertTrue(KijiNameValidator.isValidAlias("foo123"));
    assertTrue(KijiNameValidator.isValidAlias("foo_bar"));

    assertFalse(KijiNameValidator.isValidAlias("abc:def"));
    assertFalse(KijiNameValidator.isValidAlias("abc\\def"));
    assertFalse(KijiNameValidator.isValidAlias("abc/def"));
    assertFalse(KijiNameValidator.isValidAlias("abc=def"));
    assertFalse(KijiNameValidator.isValidAlias("abc+def"));
  }


('/**\\n   * @return true if name is a valid name for a Kiji instance and false otherwise.\\n   * @param name the name to check.\\n   */', '')

b'/**\n   * @return true if name is a valid name for a Kiji instance and false otherwise.\n   * @param name the name to check.\n   */'public static boolean isValidKijiName(CharSequence name) {
    return VALID_INSTANCE_PATTERN.matcher(name).matches();
  }

@Test
  public void testIsValidInstanceName() {
    assertFalse(KijiNameValidator.isValidKijiName("")); // empty string is disallowed here.
    assertTrue(KijiNameValidator.isValidKijiName("0123")); // leading digits are okay.
    assertTrue(KijiNameValidator.isValidKijiName("0123abc")); // leading digits are okay.
    assertFalse(KijiNameValidator.isValidKijiName("-asdb"));
    assertFalse(KijiNameValidator.isValidKijiName("abc-def"));
    assertFalse(KijiNameValidator.isValidKijiName("abcd-"));
    assertFalse(KijiNameValidator.isValidKijiName("abcd$"));

    assertTrue(KijiNameValidator.isValidKijiName("_"));
    assertTrue(KijiNameValidator.isValidKijiName("foo"));
    assertTrue(KijiNameValidator.isValidKijiName("FOO"));
    assertTrue(KijiNameValidator.isValidKijiName("FooBar"));
    assertTrue(KijiNameValidator.isValidKijiName("foo123"));
    assertTrue(KijiNameValidator.isValidKijiName("foo_bar"));

    assertFalse(KijiNameValidator.isValidKijiName("abc:def"));
    assertFalse(KijiNameValidator.isValidKijiName("abc\\def"));
    assertFalse(KijiNameValidator.isValidKijiName("abc/def"));
    assertFalse(KijiNameValidator.isValidKijiName("abc=def"));
    assertFalse(KijiNameValidator.isValidKijiName("abc+def"));
  }


Returns the string representation of this ProtocolVersion that was initially parsed to create this ProtocolVersion Use @link toCanonicalString to get a string representation that preserves the equals relationship @inheritDoc

b'/**\n   * Returns the string representation of this ProtocolVersion that was initially\n   * parsed to create this ProtocolVersion. Use {@link #toCanonicalString()} to get\n   * a string representation that preserves the equals() relationship.\n   *\n   * {@inheritDoc}\n   */'@Override
  public String toString() {
    return mParsedStr;
  }

@Test
  public void testToString() {
    ProtocolVersion pv1 = ProtocolVersion.parse("proto-1.2");
    ProtocolVersion pv2 = ProtocolVersion.parse("proto-1.2.0");

    assertEquals("proto-1.2", pv1.toString());
    assertEquals("proto-1.2.0", pv2.toString());
    assertTrue(pv1.equals(pv2));
    assertEquals("proto-1.2.0", pv1.toCanonicalString());
    assertEquals("proto-1.2.0", pv2.toCanonicalString());
  }


@inheritDoc

b'/** {@inheritDoc} */'@Override
  public boolean equals(Object other) {
    if (null == other) {
      return false;
    } else if (this == other) {
      return true;
    } else if (!(other instanceof ProtocolVersion)) {
      return false;
    }

    ProtocolVersion otherVer = (ProtocolVersion) other;

    if (!checkEquality(mProtocol, otherVer.mProtocol)) {
      return false;
    }

    return getMajorVersion() == otherVer.getMajorVersion()
        && getMinorVersion() == otherVer.getMinorVersion()
        && getRevision() == otherVer.getRevision();
  }

@Test
  public void testEquals() {
    ProtocolVersion pv1 = ProtocolVersion.parse("proto-1.2.3");
    ProtocolVersion pv2 = ProtocolVersion.parse("proto-1.2.3");
    assertTrue(pv1.equals(pv2));
    assertTrue(pv2.equals(pv1));
    assertEquals(pv1.hashCode(), pv2.hashCode());
    assertEquals(0, pv1.compareTo(pv2));
    assertEquals(0, pv2.compareTo(pv1));

    // Required for our equals() method to imply the same hash code.
    assertEquals(0, Integer.valueOf(0).hashCode());
  }


['(\'/**\\\\n   * Gets a builder configured with default Kiji URI fields.\\\\n   *\\\\n   * More precisely, the following defaults are initialized:\\\\n   *
\\\\n   *
The Zookeeper quorum and client port is taken from the Hadoop <tt>Configuration</tt>
\\\\n   *
The Kiji instance name is set to <tt>KConstants.DEFAULT_INSTANCE_NAME</tt>\\\\n   *       (<tt>"default"</tt>).
\\\\n   *
The table name and column names are explicitly left unset.
\\\\n   *
\\\\n   *\\\\n   * @return A builder configured with this Kiji URI.\\\\n   */\', \'\')']

b'/**\n   * Gets a builder configured with default Kiji URI fields.\n   *\n   * More precisely, the following defaults are initialized:\n   *
\n   *
The Zookeeper quorum and client port is taken from the Hadoop <tt>Configuration</tt>
\n   *
The Kiji instance name is set to <tt>KConstants.DEFAULT_INSTANCE_NAME</tt>\n   *       (<tt>"default"</tt>).
\n   *
The table name and column names are explicitly left unset.
\n   *
\n   *\n   * @return A builder configured with this Kiji URI.\n   */'public static HBaseKijiURIBuilder newBuilder() {
    return new HBaseKijiURIBuilder();
  }

@Test
  public void testURIWithQuery() {
    final KijiURI uri =
        KijiURI.newBuilder("kiji-hbase://(zkhost1,zkhost2):1234/instance/table/col?query").build();
    assertEquals("zkhost1", uri.getZookeeperQuorum().get(0));
    assertEquals("zkhost2", uri.getZookeeperQuorum().get(1));
    assertEquals(1234, uri.getZookeeperClientPort());
    assertEquals("instance", uri.getInstance());
    assertEquals("table", uri.getTable());
    assertEquals("col", uri.getColumns().get(0).getName());
  }


['(\'/**\\\\n   * Static factory method that creates new ProtocolVersion instances.\\\\n   *\\\\n   *
This method parses its argument as a string of the form:\\\\n   * <tt>protocol-maj.min.rev</tt>. All fields except the major digit are optional.\\\\n   * maj, min, and rev must be non-negative integers. protocol is a string; the trailing\\\\n   * dash character is not part of the protocol name. The protocol name may not include\\\\n   * a \\\\\\\'-\\\\\\\' character and must not start with a digit.\\\\n   * If the protocol name is not specified, then the dash must be omitted.
\\\\n   *\\\\n   *
The following are examples of legal protocol versions:
\\\\n   *
\\\\n   *
"data-1.0"
\\\\n   *
"kiji-1.2.3"
\\\\n   *
"1.3.1"
\\\\n   *
"76"
\\\\n   *
"2.3"
\\\\n   *
"spec-1"
\\\\n   *
\\\\n   *\\\\n   *
The following are illegal:
\\\\n   *
\\\\n   *
"foo" (no version number)
\\\\n   *
"foo1.2" (no dash after the protocol name)
\\\\n   *
"-foo-1.2" (protocol may not start with a dash)
\\\\n   *
"1.2.3.4" (only 3-component version numbers are supported)
\\\\n   *
"bar-1.2.3.4" (only 3-component version numbers are supported)
\\\\n   *
"-1.2.3" (version numbers may not be negative)
\\\\n   *
"1.-2" (version numbers may not be negative)
\\\\n   *
"1.x" (version numbers must be integers)
\\\\n   *
"foo-1.x" (version numbers must be integers)
\\\\n   *
"2foo-1.3" (protocol names may not start with a digit)
\\\\n   *
"foo-bar-1.x" (protocol names may not contain a dash)
\\\\n   *
"" (the empty string is not allowed as a version)
\\\\n   *
null
\\\\n   *
\\\\n   *\\\\n   * @param verString the version string to parse.\\\\n   * @return a new, parsed ProtocolVersion instance.\\\\n   * @throws IllegalArgumentException if the version string cannot be parsed according\\\\n   *     to the rules above.\\\\n   */\', \'\')', '(\'\', "// Start by parsing a protocol name. Scan forward to the \'-\'.\\n")', '(\'\', "// only use the string part after the \'-\' for ver numbers.\\n")']

b'/**\n   * Static factory method that creates new ProtocolVersion instances.\n   *\n   *
This method parses its argument as a string of the form:\n   * <tt>protocol-maj.min.rev</tt>. All fields except the major digit are optional.\n   * maj, min, and rev must be non-negative integers. protocol is a string; the trailing\n   * dash character is not part of the protocol name. The protocol name may not include\n   * a \'-\' character and must not start with a digit.\n   * If the protocol name is not specified, then the dash must be omitted.
\n   *\n   *
The following are examples of legal protocol versions:
\n   *
\n   *
"data-1.0"
\n   *
"kiji-1.2.3"
\n   *
"1.3.1"
\n   *
"76"
\n   *
"2.3"
\n   *
"spec-1"
\n   *
\n   *\n   *
The following are illegal:
\n   *
\n   *
"foo" (no version number)
\n   *
"foo1.2" (no dash after the protocol name)
\n   *
"-foo-1.2" (protocol may not start with a dash)
\n   *
"1.2.3.4" (only 3-component version numbers are supported)
\n   *
"bar-1.2.3.4" (only 3-component version numbers are supported)
\n   *
"-1.2.3" (version numbers may not be negative)
\n   *
"1.-2" (version numbers may not be negative)
\n   *
"1.x" (version numbers must be integers)
\n   *
"foo-1.x" (version numbers must be integers)
\n   *
"2foo-1.3" (protocol names may not start with a digit)
\n   *
"foo-bar-1.x" (protocol names may not contain a dash)
\n   *
"" (the empty string is not allowed as a version)
\n   *
null
\n   *
\n   *\n   * @param verString the version string to parse.\n   * @return a new, parsed ProtocolVersion instance.\n   * @throws IllegalArgumentException if the version string cannot be parsed according\n   *     to the rules above.\n   */'public static ProtocolVersion parse(String verString) {
    Preconditions.checkArgument(null != verString, "verString may not be null");
    Preconditions.checkArgument(!verString.isEmpty(), "verString may not be empty");
    Preconditions.checkArgument(verString.charAt(0) != '-', "verString may not start with a dash");

    String proto = null;
    int major = 0;
    int minor = 0;
    int rev = 0;

    int pos = 0;
    String numericPart = verString;
    if (!Character.isDigit(verString.charAt(pos))) {
      // Start by parsing a protocol name. Scan forward to the '-'.
      String[] nameParts = verString.split("-");
      if (nameParts.length != 2) {
        throw new IllegalArgumentException("verString may contain at most one dash character, "
            + "separating the protocol name from the version number.");
      }

      proto = nameParts[0];
      numericPart = nameParts[1]; // only use the string part after the '-' for ver numbers.
    }

    String[] verParts = numericPart.split("\\.");
    if (verParts.length > 3) {
      throw new IllegalArgumentException("Version numbers may have at most three components.");
    }

    try {
      major = Integer.parseInt(verParts[0]);
      if (verParts.length > 1) {
        minor = Integer.parseInt(verParts[1]);
      }
      if (verParts.length > 2) {
        rev = Integer.parseInt(verParts[2]);
      }
    } catch (NumberFormatException nfe) {
      throw new IllegalArgumentException("Could not parse numeric version info in " + verString);
    }

    if (major < 0) {
      throw new IllegalArgumentException("Major version number must be non-negative.");
    }
    if (minor < 0) {
      throw new IllegalArgumentException("Minor version number must be non-negative.");
    }
    if (rev < 0) {
      throw new IllegalArgumentException("Revision number must be non-negative.");
    }

    return new ProtocolVersion(verString, proto, major, minor, rev);
  }

@Test
  public void testCompare() {
    List<ProtocolVersion> list = Arrays.asList(
        ProtocolVersion.parse("proto-1.10.0"),
        ProtocolVersion.parse("proto-1.3.1"),
        ProtocolVersion.parse("proto-2.1"),
        ProtocolVersion.parse("proto-0.4"),
        ProtocolVersion.parse("proto-2.0.0"),
        ProtocolVersion.parse("proto-1"),
        ProtocolVersion.parse("proto-1.1"),
        ProtocolVersion.parse("other-0.9"));

    List<ProtocolVersion> expected = Arrays.asList(
        ProtocolVersion.parse("other-0.9"),
        ProtocolVersion.parse("proto-0.4"),
        ProtocolVersion.parse("proto-1"),
        ProtocolVersion.parse("proto-1.1"),
        ProtocolVersion.parse("proto-1.3.1"),
        ProtocolVersion.parse("proto-1.10.0"),
        ProtocolVersion.parse("proto-2.0.0"),
        ProtocolVersion.parse("proto-2.1"));

    Collections.sort(list);
    assertEquals(expected, list);
  }


Returns true if both are null or both are nonnull and thing1equalsthing2 @param thing1 an element to check @param thing2 the other element to check @return true if theyre both null or if thing1equalsthing2 false otherwise     theyre both null

b"/**\n   * Returns true if both are null, or both are non-null and\n   * thing1.equals(thing2).\n   *\n   * @param thing1 an element to check\n   * @param thing2 the other element to check\n   * @return true if they're both null, or if thing1.equals(thing2);\n   *   false otherwise.\n   */"static boolean checkEquality(Object thing1, Object thing2) {
    if (null == thing1 && null != thing2) {
      return false;
    }

    if (null != thing1 && null == thing2) {
      return false;
    }

    if (thing1 != null) {
      return thing1.equals(thing2);
    } else {
      assert null == thing2;
      return true; // they're both null.
    }
  }

@Test
  public void testCheckEquality() {
    assertTrue(ProtocolVersion.checkEquality(null, null));
    assertTrue(ProtocolVersion.checkEquality("hi", "hi"));
    assertFalse(ProtocolVersion.checkEquality("hi", null));
    assertFalse(ProtocolVersion.checkEquality(null, "hi"));
    assertTrue(ProtocolVersion.checkEquality(Integer.valueOf(32), Integer.valueOf(32)));
    assertFalse(ProtocolVersion.checkEquality(Integer.valueOf(32), Integer.valueOf(7)));
    assertFalse(ProtocolVersion.checkEquality(Integer.valueOf(32), "ohai"));
    assertFalse(ProtocolVersion.checkEquality("meep", "ohai"));
  }


@Test
  public void testNoJustProto() {
    try {
      ProtocolVersion.parse("proto");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may contain at most one dash character, separating the protocol "
          + "name from the version number.", iae.getMessage());
    }
  }


@Test
  public void testNoJustProto2() {
    try {
      ProtocolVersion.parse("proto-");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may contain at most one dash character, separating the protocol "
          + "name from the version number.", iae.getMessage());
    }
  }


@Test
  public void testDashRequired() {
    try {
      ProtocolVersion.parse("foo1.4");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may contain at most one dash character, separating the protocol "
          + "name from the version number.", iae.getMessage());
    }
  }


@Test
  public void testNoLeadingDash() {
    try {
      ProtocolVersion.parse("-foo-1.4");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may not start with a dash", iae.getMessage());
    }
  }


@Test
  public void testNoMoreThan3() {
    try {
      ProtocolVersion.parse("1.2.3.4");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Version numbers may have at most three components.", iae.getMessage());
    }
  }


@Test
  public void testNoMoreThan3withProto() {
    try {
      ProtocolVersion.parse("proto-1.2.3.4");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Version numbers may have at most three components.", iae.getMessage());
    }
  }


@Test
  public void testNoLeadingDashWithoutProto() {
    try {
      ProtocolVersion.parse("-1.2.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may not start with a dash", iae.getMessage());
    }
  }


@Test
  public void testNoLeadingDashes() {
    try {
      ProtocolVersion.parse("--1.2.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may not start with a dash", iae.getMessage());
    }
  }


@Test
  public void testURIWithFragment() {
    final KijiURI uri =
        KijiURI.newBuilder("kiji-hbase://(zkhost1,zkhost2):1234/instance/table/col#frag").build();
    assertEquals("zkhost1", uri.getZookeeperQuorum().get(0));
    assertEquals("zkhost2", uri.getZookeeperQuorum().get(1));
    assertEquals(1234, uri.getZookeeperClientPort());
    assertEquals("instance", uri.getInstance());
    assertEquals("table", uri.getTable());
    assertEquals("col", uri.getColumns().get(0).getName());
  }


@Test
  public void testNoMultiDash() {
    try {
      ProtocolVersion.parse("proto--1.2.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may contain at most one dash character, separating the protocol "
          + "name from the version number.", iae.getMessage());
    }
  }


@Test
  public void testNoDashInProto() {
    try {
      ProtocolVersion.parse("proto-col-1.2.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may contain at most one dash character, separating the protocol "
          + "name from the version number.", iae.getMessage());
    }
  }


@Test
  public void testNoNegativeMinor() {
    try {
      ProtocolVersion.parse("1.-2");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Minor version number must be non-negative.", iae.getMessage());
    }
  }


@Test
  public void testNoNegativeRev() {
    try {
      ProtocolVersion.parse("1.2.-3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Revision number must be non-negative.", iae.getMessage());
    }
  }


@Test
  public void testNoMultiDots() {
    try {
      ProtocolVersion.parse("1..2");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Could not parse numeric version info in 1..2", iae.getMessage());
    }
  }


@Test
  public void testNoMultiDots2() {
    try {
      ProtocolVersion.parse("1..2.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Version numbers may have at most three components.", iae.getMessage());
    }
  }


@Test
  public void testNoNamedMinor() {
    try {
      ProtocolVersion.parse("1.x");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Could not parse numeric version info in 1.x", iae.getMessage());
    }
  }


@Test
  public void testNoNamedMinorWithProto() {
    try {
      ProtocolVersion.parse("proto-1.x");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Could not parse numeric version info in proto-1.x", iae.getMessage());
    }
  }


@Test
  public void testNoLeadingNumber() {
    try {
      ProtocolVersion.parse("2foo-1.3");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("Could not parse numeric version info in 2foo-1.3", iae.getMessage());
    }
  }


@Test
  public void testNoEmptyString() {
    try {
      ProtocolVersion.parse("");
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may not be empty", iae.getMessage());
    }
  }


@Test
  public void testPartialURIZookeeper() {
    final KijiURI uri = KijiURI.newBuilder("kiji-hbase://zkhost:1234").build();
    assertEquals("zkhost", uri.getZookeeperQuorum().get(0));
    assertEquals(1234, uri.getZookeeperClientPort());
    assertEquals(null, uri.getInstance());
  }


@Test
  public void testNoNull() {
    try {
      ProtocolVersion.parse(null);
      fail("Should fail with an IllegalArgumentException");
    } catch (IllegalArgumentException iae) {
      assertEquals("verString may not be null", iae.getMessage());
    }
  }