('/**\\n   * Creates and returns a new KijiTableLayout instance as specified by an Avro TableLayoutDesc\\n   * description record.\\n   *\\n   * @param layout The Avro TableLayoutDesc descriptor record that describes the actual layout.\\n   * of the table.\\n   * @return A new table layout.\\n   * @throws InvalidLayoutException If the descriptor is invalid.\\n   */', '')

b'/**\n   * Creates and returns a new KijiTableLayout instance as specified by an Avro TableLayoutDesc\n   * description record.\n   *\n   * @param layout The Avro TableLayoutDesc descriptor record that describes the actual layout.\n   * of the table.\n   * @return A new table layout.\n   * @throws InvalidLayoutException If the descriptor is invalid.\n   */'public static KijiTableLayout newLayout(TableLayoutDesc layout) throws InvalidLayoutException {
    return new KijiTableLayout(layout, null);
  }

@Test
  public void testDeprecatedVersion() throws Exception {
    final TableLayoutDesc validDesc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(makeRawRKF1())
        .setVersion("kiji-1.0")
        .build();
    try {
      KijiTableLayout validLayout = KijiTableLayout.newLayout(validDesc);
    } catch (InvalidLayoutException ile) {
      fail("Deprecated version 'kiji-1.0' should be valid.");
    }

    final TableLayoutDesc invalidDesc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(makeRawRKF1())
        .setVersion("kiji-1.1")
        .build();
    try {
      KijiTableLayout invalidLayout = KijiTableLayout.newLayout(invalidDesc);
      fail("Layout version kiji-1.1 should be invalid.");
    } catch (InvalidLayoutException ile) {
      // Expected.
    }
  }


@Test
  public void testDuplicateFamilyName() throws Exception {
    RowKeyFormat2 format = makeHashPrefixedRowKeyFormat();
    // Reference layout with a single column: "family_name:column_name"
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(format)
        .setVersion(TABLE_LAYOUT_VERSION)
        .setLocalityGroups(Lists.newArrayList(
            LocalityGroupDesc.newBuilder()
                .setName("locality_group_name")
                .setInMemory(false)
                .setTtlSeconds(84600)
                .setMaxVersions(1)
                .setCompressionType(CompressionType.GZ)
                .setFamilies(Lists.newArrayList(
                  FamilyDesc.newBuilder()
                    .setName("family_name")
                    .setColumns(Lists.newArrayList(
                      ColumnDesc.newBuilder()
                        .setName("column_name")
                        .setColumnSchema(CellSchema.newBuilder()
                          .setStorage(SchemaStorage.UID)
                          .setType(SchemaType.INLINE)
                          .setValue("\"string\"")
                          .build())
                        .build(),
                      ColumnDesc.newBuilder()
                        .setName("column2_name")
                        .setColumnSchema(CellSchema.newBuilder()
                          .setStorage(SchemaStorage.UID)
                          .setType(SchemaType.INLINE)
                          .setValue("\"bytes\"")
                          .build())
                        .build()
                    ))
                    .build(),
                  FamilyDesc.newBuilder()
                    .setName("family2_name")
                    .setMapSchema(CellSchema.newBuilder()
                      .setStorage(SchemaStorage.FINAL)
                      .setType(SchemaType.COUNTER)
                      .build())
                    .build()
                ))
                .build(),
            LocalityGroupDesc.newBuilder()
                .setName("locality_group2_name")
                .setInMemory(false)
                .setTtlSeconds(84600)
                .setMaxVersions(1)
                .setCompressionType(CompressionType.GZ)
                .setFamilies(Lists.newArrayList(
                    FamilyDesc.newBuilder()
                        .setName("family_name")
                        .setMapSchema(CellSchema.newBuilder()
                            .setStorage(SchemaStorage.FINAL)
                            .setType(SchemaType.COUNTER)
                            .build())
                        .build()
                ))
                .build()
        ))
        .build();
    try {
      KijiTableLayout.newLayout(desc);
      fail("Invalid layout with duplicate family name did not throw.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected duplicate family error: " + ile);
      assertTrue(ile.getMessage().contains("duplicate family name 'family_name'"));
    }
  }


['(\'/**\\\\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 testClusterIdentifier() {
    final KijiURI uri = KijiURI.newBuilder("kiji-hbase://zkhost:1234").build();
    assertEquals("kiji-hbase", uri.getScheme());
    assertEquals("zkhost", uri.getZookeeperQuorum().get(0));
    assertEquals(1234, uri.getZookeeperClientPort());
    assertEquals(null, uri.getInstance());
    assertEquals(null, uri.getTable());
    assertTrue(uri.getColumns().isEmpty());
  }


@Test
  public void testZeroMaxFilesize() throws Exception {
    // Simple layout with minimal config
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMaxFilesize(0L)
      .build();
    try {
      KijiTableLayout.newLayout(desc);
      fail("max_filesize of 0 didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected max_filesize validation error: " + ile);
      assertThat(ile.getMessage(), containsString("max_filesize must be greater than 0"));
    }
  }


@Test
  public void testNegativeMaxFilesize() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMaxFilesize(-1L)
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail("Negative max_filesize didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected max_filesize validation error: " + ile);
      assertThat(ile.getMessage(), containsString("max_filesize must be greater than 0"));
    }
  }


@Test
  public void testZeroMemstoreFlushsize() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMemstoreFlushsize(0L)
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail("Negative memstore_flushsize didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected memstore_flushsize validation error: " + ile);
      assertThat(ile.getMessage(), containsString("memstore_flushsize must be greater than 0"));
    }
  }


@Test
  public void testNegativeMemstoreFlushsize() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMemstoreFlushsize(-1L)
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail("Negative memstore_flushsize didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected memstore_flushsize validation error: " + ile);
      assertThat(ile.getMessage(), containsString("memstore_flushsize must be greater than 0"));
    }
  }


@Test
  public void testMaxfilesizeOnOlderLayoutVersion() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMaxFilesize(10L)
      .setVersion(TABLE_LAYOUT_1_1)
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail(String.format("Expected exception because max_filesize is set on a table layout "
        + "with version prior to %s.", TABLE_LAYOUT_1_2));
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("begins with layout version "
        + TABLE_LAYOUT_1_2));
    }
  }


@Test
  public void testMemstoreFlushsizeOnOlderLayoutVersion() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setMemstoreFlushsize(10L)
      .setVersion(TABLE_LAYOUT_1_1)
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail(String.format("Expected exception because memstore_flushsize is set on a table "
        + "layout with version prior to %s.", TABLE_LAYOUT_1_2));
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("begins with layout version "
        + TABLE_LAYOUT_1_2));
    }
  }


@Test
  public void testZeroBlockSize() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setLocalityGroups(
        Lists.newArrayList(
          LocalityGroupDesc.newBuilder(makeMinimalLocalityGroup())
            .setBlockSize(0)
            .build()))
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail("block_size of 0 didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("block_size must be greater than 0"));
    }
  }


@Test
  public void testNegativeBlockSize() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setLocalityGroups(
        Lists.newArrayList(
          LocalityGroupDesc.newBuilder(makeMinimalLocalityGroup())
            .setBlockSize(-1)
            .build()))
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      fail("Negative block_size didn't throw exception.");
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("block_size must be greater than 0"));
    }
  }


@Test
  public void testBlockSizeOnOlderLayoutVersion() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setVersion(TABLE_LAYOUT_1_1)
      .setLocalityGroups(
        Lists.newArrayList(
          LocalityGroupDesc.newBuilder(makeMinimalLocalityGroup())
            .setBlockSize(10)
            .build()))
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      String failureMsg = String.format("Expected exception because block_size is set on a "
        + "locality group for a table layout with version prior to %s.", TABLE_LAYOUT_1_2);
      fail(failureMsg);
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("begins with layout version "
        + TABLE_LAYOUT_1_2));
    }
  }


@Test
  public void testBloomTypeOnOlderLayoutVersion() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder(makeMinimalValidLayout())
      .setVersion(TABLE_LAYOUT_1_1)
      .setLocalityGroups(
        Lists.newArrayList(
          LocalityGroupDesc.newBuilder(makeMinimalLocalityGroup())
            .setBloomType(BloomType.ROWCOL)
            .build()))
      .build();

    try {
      KijiTableLayout.newLayout(desc);
      String failureMsg = String.format("Expected exception because bloom_type is set on a "
        + "locality group for a table layout with version prior to %s.", TABLE_LAYOUT_1_2);
      fail(failureMsg);
    } catch (InvalidLayoutException ile) {
      // Expected:
      LOG.info("Expected layout version validation error: " + ile);
      assertThat(ile.getMessage(), containsString("begins with layout version "
        + TABLE_LAYOUT_1_2));
    }
  }


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


@Test
  public void testInvalidLocalityGroupTTLSeconds() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(makeRawRKF1())
        .setVersion(TABLE_LAYOUT_VERSION)
        .setLocalityGroups(Lists.newArrayList(LocalityGroupDesc.newBuilder()
            .setName("default")
            .setCompressionType(CompressionType.NONE)
            .setTtlSeconds(-1)
            .setMaxVersions(1)
            .setInMemory(false)
            .build()))
        .build();
    try {
      KijiTableLayout.newLayout(desc);
      fail("Invalid locality group with negative TTL seconds did not throw");
    } catch (InvalidLayoutException ile) {
      assertTrue(ile.getMessage().contains("Invalid TTL seconds for locality group"));
    }
  }


@Test
  public void testInvalidLocalityGroupMaxVersions() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(makeHashedRKF1())
        .setVersion(TABLE_LAYOUT_VERSION)
        .setLocalityGroups(Lists.newArrayList(LocalityGroupDesc.newBuilder()
            .setName("default")
            .setCompressionType(CompressionType.NONE)
            .setTtlSeconds(1)
            .setMaxVersions(-1)
            .setInMemory(false)
            .build()))
        .build();
    try {
      KijiTableLayout.newLayout(desc);
      fail("Invalid locality group with negative max versions did not throw");
    } catch (InvalidLayoutException ile) {
      assertTrue(ile.getMessage().contains("Invalid max versions for locality group"));
    }
  }


@Test
  public void testFinalColumnSchemaClassInvalid() throws Exception {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(makeHashPrefixedRKF1())
        .setVersion(TABLE_LAYOUT_VERSION)
        .setLocalityGroups(Lists.newArrayList(
            LocalityGroupDesc.newBuilder()
            .setName("locality_group_name")
            .setInMemory(false)
            .setTtlSeconds(84600)
            .setMaxVersions(1)
            .setCompressionType(CompressionType.GZ)
            .setFamilies(Lists.newArrayList(
                FamilyDesc.newBuilder()
                    .setName("family_name")
                    .setColumns(Lists.newArrayList(
                        ColumnDesc.newBuilder()
                            .setName("column_name")
                            .setColumnSchema(CellSchema.newBuilder()
                                 .setStorage(SchemaStorage.FINAL)
                                 .setType(SchemaType.CLASS)
                                 .setValue("dummy.Class")
                                 .build())
                            .build()))
                    .build()))
            .build()))
        .build();
    try {
      KijiTableLayout.newLayout(desc);
      fail("Final column schema must be inline");
    } catch (InvalidLayoutException ile) {
      assertTrue(ile.getMessage().contains("Invalid final column schema"));
    }
  }


('/**\\n   * Get the hash size for a given row key format.\\n   *\\n   * @param rowKeyFormat Format of row keys of type RowKeyFormat or RowKeyFormat2.\\n   * @return The size of the hash prefix.\\n   */', '')

b'/**\n   * Get the hash size for a given row key format.\n   *\n   * @param rowKeyFormat Format of row keys of type RowKeyFormat or RowKeyFormat2.\n   * @return The size of the hash prefix.\n   */'public static int getHashSize(Object rowKeyFormat) {
    if (rowKeyFormat instanceof RowKeyFormat) {
      return ((RowKeyFormat) rowKeyFormat).getHashSize();
    } else if (rowKeyFormat instanceof RowKeyFormat2) {
      RowKeyFormat2 format2 = (RowKeyFormat2) rowKeyFormat;
      if (null == format2.getSalt()) {
        throw new RuntimeException("This RowKeyFormat2 instance does not specify salt/hashing.");
      } else {
        return format2.getSalt().getHashSize();
      }
    } else {
      throw new RuntimeException("Unsupported Row Key Format");
    }
  }

@Test
  public void testKijiTableHashSize() throws Exception {
    // default hash size for RowKeyFormat2 is 16
    assertEquals(16, KijiTableLayout.getHashSize(makeHashPrefixedRowKeyFormat()));
    // default hash size for RowKeyFormat is 0
    assertEquals(0, KijiTableLayout.getHashSize(makeHashPrefixedRKF1()));
  }


@Test
  public void testSuppressMaterializationRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(suppressMaterializationRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
  }


@Test
  public void testBadSuppressMaterializationRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(badSuppressMaterializationRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    try {
      final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
      fail("An exception should have been thrown.");
    } catch (InvalidLayoutException ile) {
      assertEquals("Range scans are not supported if suppress_key_materialization is true. Please "
          + "set range_scan_start_index to components.size", ile.getMessage());
    }
  }


@Test
  public void testNoComponentsRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(noComponentsRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    try {
      final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
      fail("An exception should have been thrown.");
    } catch (InvalidLayoutException ile) {
      assertEquals("At least 1 component is required in row key format.", ile.getMessage());
    }
  }


@Test
  public void testBadNullableIndexRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(badNullableIndexRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    try {
      final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
      fail("An exception should have been thrown.");
    } catch (InvalidLayoutException ile) {
      assertEquals(
          "Invalid index for nullable component. The second component onwards can be set to null.",
          ile.getMessage());
    }
  }


@Test
  public void badRangeScanIndexRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(badRangeScanIndexRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    try {
      final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
      fail("An exception should have been thrown.");
    } catch (InvalidLayoutException ile) {
      assertEquals(
          "Invalid range scan index. Range scans are supported starting with the second component.",
          ile.getMessage());
    }
  }


@Test
  public void badCompNameRKF() throws InvalidLayoutException {
    final TableLayoutDesc desc = TableLayoutDesc.newBuilder()
        .setName("table_name")
        .setKeysFormat(badCompNameRowKeyFormat())
        .setVersion(TABLE_LAYOUT_VERSION)
        .build();
    try {
      final KijiTableLayout ktl = KijiTableLayout.newLayout(desc);
      fail("An exception should have been thrown.");
    } catch (InvalidLayoutException ile) {
      assertEquals("Names should begin with a letter followed by a combination of letters, numbers "
          + "and underscores.", ile.getMessage());
    }
  }