/**
* Copyright 2013 Cloudera Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kitesdk.data.hbase;
import java.io.IOException;
import org.kitesdk.data.DatasetDescriptor;
import org.kitesdk.data.DatasetReader;
import org.kitesdk.data.DatasetWriter;
import org.kitesdk.data.View;
import org.kitesdk.data.hbase.avro.AvroUtils;
import org.kitesdk.data.hbase.avro.entities.ArrayRecord;
import org.kitesdk.data.hbase.avro.entities.EmbeddedRecord;
import org.kitesdk.data.hbase.avro.entities.TestEntity;
import org.kitesdk.data.hbase.avro.entities.TestEnum;
import org.kitesdk.data.hbase.testing.HBaseTestUtils;
import org.kitesdk.data.spi.AbstractRefinableView;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class DaoViewTest {
private static final String[] NAMES = new String[] { "part1", "part2" };
private static final String testEntity;
private static final String tableName = "testtable";
private static final String managedTableName = "managed_schemas";
private HBaseDatasetRepository repo;
private DaoDataset<TestEntity> ds;
static {
try {
testEntity = AvroUtils
.inputStreamToString(HBaseDatasetRepositoryTest.class
.getResourceAsStream("/TestEntity.avsc"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@BeforeClass
public static void beforeClass() throws Exception {
HBaseTestUtils.getMiniCluster();
// managed table should be created by HBaseDatasetRepository
HBaseTestUtils.util.deleteTable(Bytes.toBytes(managedTableName));
}
@AfterClass
public static void afterClass() throws Exception {
HBaseTestUtils.util.deleteTable(Bytes.toBytes(tableName));
}
@Before
public void setup() throws Exception {
repo = new HBaseDatasetRepository.Builder().configuration(
HBaseTestUtils.getConf()).build();
DatasetDescriptor descriptor = new DatasetDescriptor.Builder()
.schemaLiteral(testEntity).build();
ds = (DaoDataset<TestEntity>) repo.create(
"default", tableName, descriptor, TestEntity.class);
}
@After
public void after() throws Exception {
repo.delete("default", tableName);
HBaseTestUtils.util.truncateTable(Bytes.toBytes(tableName));
HBaseTestUtils.util.truncateTable(Bytes.toBytes(managedTableName));
}
@Test
public void testRange() {
populateTestEntities(10);
final AbstractRefinableView<TestEntity> range = new DaoView<TestEntity>(ds, TestEntity.class)
.fromAfter(NAMES[0], "1").to(NAMES[0], "9")
.fromAfter(NAMES[1], "1").to(NAMES[1], "9");
// Test entity range checks
// Note that these are strings, not ints, so lexicographic ordering is used
Assert.assertTrue(range.includes(newTestEntity("5", "5")));
Assert.assertTrue(range.includes(newTestEntity("5", "55")));
Assert.assertTrue(range.includes(newTestEntity("9", "89")));
Assert.assertTrue(range.includes(newTestEntity("9", "9")));
Assert.assertFalse(range.includes(newTestEntity("1", "1")));
Assert.assertFalse(range.includes(newTestEntity("1", "0")));
Assert.assertFalse(range.includes(newTestEntity("1", "10")));
Assert.assertFalse(range.includes(newTestEntity("9", "99")));
DatasetReader<TestEntity> reader = range.newReader();
int cnt = 2;
try {
for (TestEntity entity : reader) {
Assert.assertEquals(Integer.toString(cnt), entity.getPart1());
Assert.assertEquals(Integer.toString(cnt), entity.getPart2());
cnt++;
}
} finally {
reader.close();
}
Assert.assertEquals(10, cnt);
}
@Test
public void testLimitedReader() {
populateTestEntities(10);
AbstractRefinableView<TestEntity> range = new DaoView<TestEntity>(ds, TestEntity.class)
.from(NAMES[0], "0").to(NAMES[0], "9")
.from(NAMES[1], "0").to(NAMES[1], "9");
validRange(range, 0, 10);
range = new DaoView<TestEntity>(ds, TestEntity.class)
.fromAfter(NAMES[0], "1").to(NAMES[0], "9")
.fromAfter(NAMES[1], "1").to(NAMES[1], "9");
validRange(range, 2, 10);
range = new DaoView<TestEntity>(ds, TestEntity.class)
.from(NAMES[0], "0").toBefore(NAMES[0], "9")
.from(NAMES[1], "0").toBefore(NAMES[1], "9");
validRange(range, 0, 9);
}
@Test
public void testLimitedWriter() {
final View<TestEntity> range = ds
.fromAfter(NAMES[0], "1").to(NAMES[0], "5")
.fromAfter(NAMES[1], "1").to(NAMES[1], "5");
DatasetWriter<TestEntity> writer = range.newWriter();
try {
writer.write(newTestEntity("3", "3"));
writer.write(newTestEntity("5", "5"));
} finally {
writer.close();
}
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidLimitedWriter() {
final View<TestEntity> range = ds
.fromAfter(NAMES[0], "1").to(NAMES[0], "5")
.fromAfter(NAMES[1], "1").to(NAMES[1], "5");
range.newWriter().write(newTestEntity("6", "6"));
}
@Test
public void testEmptyCheck() throws IOException {
DaoView<TestEntity> unbounded = new DaoView<TestEntity>(ds, TestEntity.class);
Assert.assertTrue("New dataset should be empty", unbounded.isEmpty());
populateTestEntities(1);
Assert.assertFalse("Should not be empty after write", unbounded.isEmpty());
Assert.assertFalse("Should find entity 0", unbounded
.with(NAMES[0], "0").with(NAMES[1], "0")
.isEmpty());
Assert.assertTrue("Should not find entity 1", unbounded
.with(NAMES[0], "1").with(NAMES[1], "1")
.isEmpty());
}
private TestEntity newTestEntity(String part1, String part2) {
return TestEntity
.newBuilder()
.setPart1(part1)
.setPart2(part2)
.setField1("field1")
.setField2("field2")
.setField3(new HashMap<String, String>())
.setField4(
EmbeddedRecord.newBuilder().setEmbeddedField1("embeddedField1")
.setEmbeddedField2(2).build())
.setField5(new ArrayList<ArrayRecord>()).setEnum$(TestEnum.ENUM1)
.build();
}
private void populateTestEntities(int num) {
for (int i = 0; i < num; i++) {
ds.put(newTestEntity(Integer.toString(i), Integer.toString(i)));
}
}
private void validRange(View<TestEntity> range, int startIdx, int endIdx) {
int cnt = startIdx;
DatasetReader<TestEntity> reader = range.newReader();
try {
for (TestEntity entity : reader) {
Assert.assertEquals(Integer.toString(cnt), entity.getPart1());
Assert.assertEquals(Integer.toString(cnt), entity.getPart2());
cnt++;
}
} finally {
reader.close();
}
Assert.assertEquals(endIdx, cnt);
}
}