package org.rakam.collection; import com.google.common.collect.ImmutableSet; import org.rakam.analysis.metadata.AbstractMetastore; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.rakam.collection.FieldType.LONG; import static org.rakam.collection.FieldType.STRING; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public abstract class TestMetastore { private static final String PROJECT_NAME = TestMetastore.class.getName().replace(".", "_").toLowerCase(); public abstract AbstractMetastore getMetastore(); @AfterMethod public void tearDownMethod() throws Exception { getMetastore().deleteProject(PROJECT_NAME); } @Test public void testCreateProject() throws Exception { getMetastore().createProject(PROJECT_NAME); assertTrue(getMetastore().getProjects().contains(PROJECT_NAME)); } @Test public void testCreateCollection() throws Exception { getMetastore().createProject(PROJECT_NAME); ImmutableSet<SchemaField> schema = ImmutableSet.of(new SchemaField("test", STRING)); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "test", schema); assertEquals(getMetastore().getCollection(PROJECT_NAME, "test"), schema); } @Test public void testCreateFields() throws Exception { getMetastore().createProject(PROJECT_NAME); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "test", ImmutableSet.of()); ImmutableSet<SchemaField> schema = ImmutableSet.of(new SchemaField("test", STRING)); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "test", schema); assertEquals(getMetastore().getCollection(PROJECT_NAME, "test"), schema); } @Test public void testDeleteProject() throws Exception { getMetastore().createProject(PROJECT_NAME); getMetastore().deleteProject(PROJECT_NAME); assertFalse(getMetastore().getProjects().contains(PROJECT_NAME)); } @Test public void testCollectionMethods() throws Exception { getMetastore().createProject(PROJECT_NAME); ImmutableSet<SchemaField> schema = ImmutableSet.of(new SchemaField("test1", STRING), new SchemaField("test2", STRING)); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection1", schema); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection2", schema); assertEquals(ImmutableSet.of("testcollection1", "testcollection2"), ImmutableSet.copyOf(getMetastore().getCollectionNames(PROJECT_NAME))); Map<String, List<SchemaField>> testing = getMetastore().getCollections(PROJECT_NAME); assertEquals(testing.size(), 2); assertEquals(ImmutableSet.copyOf(testing.get("testcollection1")), schema); assertEquals(ImmutableSet.copyOf(testing.get("testcollection2")), schema); } @Test public void testCollectionFieldsOrdering() throws Exception { getMetastore().createProject(PROJECT_NAME); ImmutableSet.Builder<SchemaField> builder = ImmutableSet.builder(); for (FieldType fieldType : FieldType.values()) { builder.add(new SchemaField(fieldType.name(), fieldType)); } getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection", builder.build()); for (int i = 0; i < 100; i++) { assertEquals(getMetastore().getCollection(PROJECT_NAME, "testcollection"), builder.build()); } } @Test public void testDuplicateFields() throws Exception { getMetastore().createProject(PROJECT_NAME); ImmutableSet.Builder<SchemaField> builder = ImmutableSet.builder(); for (FieldType fieldType : FieldType.values()) { builder.add(new SchemaField(fieldType.name(), fieldType)); } getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection", ImmutableSet.of(new SchemaField("test", LONG))); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection", ImmutableSet.of(new SchemaField("test", LONG))); assertEquals(ImmutableSet.copyOf(getMetastore().getCollection(PROJECT_NAME, "testcollection")), ImmutableSet.of(new SchemaField("test", LONG), new SchemaField("test", LONG))); } @Test(expectedExceptions = IllegalStateException.class) public void testInvalidDuplicateFieldNames() throws Exception { getMetastore().createProject(PROJECT_NAME); getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection", ImmutableSet.of(new SchemaField("test", STRING), new SchemaField("test", LONG))); } @Test public void testAllSchemaTypes() throws Exception { getMetastore().createProject(PROJECT_NAME); ImmutableSet.Builder<SchemaField> builder = ImmutableSet.builder(); for (FieldType fieldType : FieldType.values()) { builder.add(new SchemaField(fieldType.name(), fieldType)); } getMetastore().getOrCreateCollectionFields(PROJECT_NAME, "testcollection", builder.build()); assertEquals(getMetastore().getCollection(PROJECT_NAME, "testcollection"), builder.build()); } /** * The schema change requests may be performed from any Rakam node in a cluster and they have to be consistent. **/ @Test public void testConcurrentSchemaChanges() throws Exception { getMetastore().createProject("test"); List<List<SchemaField>> collect = IntStream.range(0, 10).parallel().mapToObj(i -> getMetastore().getOrCreateCollectionFieldList("test", "test", ImmutableSet.of(new SchemaField("test" + i, STRING)))) .collect(Collectors.toList()); Set<SchemaField> allSchemas = ImmutableSet.copyOf(collect.stream().sorted((o1, o2) -> o2.size() - o1.size()).findFirst().get()); for (List<SchemaField> schemaFields : collect) { for (int i = 0; i < schemaFields.size(); i++) { assertTrue(allSchemas.contains(schemaFields.get(i)), String.format("%s not in %s", schemaFields.get(i), allSchemas)); } } } }