/* * Copyright 2017 Pilosa Corp. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package integrationtest; import com.pilosa.client.*; import com.pilosa.client.csv.*; import com.pilosa.client.exceptions.HttpConflict; import com.pilosa.client.exceptions.PilosaException; import com.pilosa.client.orm.*; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URL; import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; import static org.junit.Assert.*; // Note that this integration test creates many random indexes. // It's recommended to run an ephemeral Pilosa server. // E.g., with docker: // $ docker run -it --rm --name pilosa -p 10101:10101 pilosa:latest @Category(IntegrationTest.class) public class PilosaClientIT { private Schema schema; private Index colIndex; private Index index; private Index keyIndex; private Field field; private Field keyField; @Before public void setUp() throws IOException { try (PilosaClient client = getClient()) { this.schema = client.readSchema(); this.index = schema.index(getRandomIndexName()); this.index.field("another-field"); this.index.field("test"); this.index.field("count-test"); this.index.field("topn_test"); this.colIndex = schema.index(this.index.getName() + "-opts"); FieldOptions fieldOptions = FieldOptions.withDefaults(); this.field = this.colIndex.field("collab", fieldOptions); fieldOptions = FieldOptions.builder() .setKeys(true) .build(); this.keyField = this.index.field("index-key-field", fieldOptions); IndexOptions indexOptions = IndexOptions.builder() .setKeys(true) .build(); this.keyIndex = schema.index("key-index", indexOptions); client.syncSchema(this.schema); } } @After public void tearDown() throws IOException { try (PilosaClient client = getClient()) { client.deleteIndex(this.index); client.deleteIndex(this.colIndex); client.deleteIndex(this.keyIndex); } catch (PilosaException ex) { // pass } } @Test public void createClientTest() throws IOException { try (PilosaClient client = PilosaClient.withURI(URI.address(":10101"))) { assertNotNull(client); } try (PilosaClient client = PilosaClient.withCluster(Cluster.defaultCluster())) { assertNotNull(client); } } @Test public void responseDefaultsTest() throws IOException { try (PilosaClient client = getClient()) { QueryResponse response = client.query(this.field.topN(5)); assertNotNull(response.getResult().getRow()); assertNotNull(response.getResult().getCountItems()); response = client.query(this.field.row(99999)); assertNotNull(response.getResult().getRow()); assertNotNull(response.getResult().getCountItems()); } } @Test public void createFieldWithTimeQuantumTest() throws IOException { FieldOptions options = FieldOptions.builder() .fieldTime(TimeQuantum.YEAR_MONTH_DAY) .build(); Field field = this.index.field("field-with-timequantum", options); try (PilosaClient client = getClient()) { client.ensureField(field); Schema schema = client.readSchema(); Field info = findField(schema, field); assertNotNull(info); assertEquals(TimeQuantum.YEAR_MONTH_DAY, info.getOptions().getTimeQuantum()); } } @Test public void testSchema() throws IOException { try (PilosaClient client = getClient()) { Schema schema = client.readSchema(); assertTrue(schema.getIndexes().size() >= 1); assertTrue(schema.getIndexes().entrySet().iterator().next().getValue().getFields().size() >= 1); FieldOptions fieldOptions = FieldOptions.builder() .fieldSet(CacheType.LRU, 9999) .build(); Field field = this.index.field("schema-test-field", fieldOptions); client.ensureField(field); schema = client.readSchema(); Index index = schema.getIndexes().get(this.index.getName()); IndexOptions indexOptions = index.getOptions(); assertTrue(indexOptions.isTrackExistence()); assertFalse(indexOptions.isKeys()); assertNotEquals(0, index.getShardWidth()); Field f = index.getFields().get("schema-test-field"); FieldOptions fo = f.getOptions(); assertEquals(FieldType.SET, fo.getFieldType()); assertEquals(9999, fo.getCacheSize()); assertEquals(CacheType.LRU, fo.getCacheType()); fieldOptions = FieldOptions.builder() .fieldInt(-10, 10) .build(); field = this.index.field("schema-test-field-int", fieldOptions); client.ensureField(field); schema = client.readSchema(); f = schema.getIndexes().get(this.index.getName()).getFields().get("schema-test-field-int"); fo = f.getOptions(); assertEquals(FieldType.INT, fo.getFieldType()); // Disabled the following checks, since Pilosa master doesn't report the actual min and max. // assertEquals(-10, fo.getMin()); // assertEquals(10, fo.getMax()); fieldOptions = FieldOptions.builder() .fieldTime(TimeQuantum.YEAR_MONTH_DAY) .build(); field = this.index.field("schema-test-field-time", fieldOptions); client.ensureField(field); schema = client.readSchema(); f = schema.getIndexes().get(this.index.getName()).getFields().get("schema-test-field-time"); fo = f.getOptions(); assertEquals(FieldType.TIME, fo.getFieldType()); assertEquals(TimeQuantum.YEAR_MONTH_DAY, fo.getTimeQuantum()); } } @Test public void queryTest() throws IOException { try (PilosaClient client = getClient()) { Field field = this.index.field("query-test"); client.ensureField(field); QueryResponse response = client.query(field.set(555, 10)); assertNotNull(response.getResult()); } } @Test public void queryWithColumnsTest() throws IOException { try (PilosaClient client = getClient()) { Field field = this.index.field("query-test"); client.ensureField(field); client.query(field.set(100, 1000)); Map<String, Object> columnAttrs = new HashMap<>(1); columnAttrs.put("name", "bombo"); client.query(this.index.setColumnAttrs(1000, columnAttrs)); QueryOptions queryOptions = QueryOptions.builder() .setColumnAttributes(true) .build(); QueryResponse response = client.query(field.row(100), queryOptions); assertNotNull(response.getColumn()); assertEquals(1000, response.getColumn().getID()); assertEquals(columnAttrs, response.getColumn().getAttributes()); response = client.query(field.row(300)); assertNull(response.getColumn()); } } @Test public void protobufCreateIndexDeleteIndexTest() throws IOException { final Index indexName = Index.create("to-be-deleted-" + this.index.getName()); Field field = indexName.field("delfield"); try (PilosaClient client = getClient()) { try { client.createIndex(indexName); client.createField(field); client.query(field.set(1, 2)); } finally { client.deleteIndex(indexName); } } } @Test(expected = PilosaException.class) public void failedConnectionTest() throws IOException { try (PilosaClient client = PilosaClient.withAddress("http://non-existent-sub.pilosa.com:22222")) { client.query(this.field.set(15, 10)); } } @Test(expected = PilosaException.class) public void unknownSchemeTest() throws IOException { try (PilosaClient client = PilosaClient.withAddress("notknown://:15555")) { client.query(this.field.set(15, 10)); } } @Test(expected = PilosaException.class) public void parseErrorTest() throws IOException { try (PilosaClient client = getClient()) { QueryResponse response = client.query(this.index.rawQuery("SetBit(id=5, field=\"test\", col_id:=10)")); System.out.println(response); } } @Test public void ormCountTest() throws IOException { try (PilosaClient client = getClient()) { Field countField = this.index.field("count-test"); client.ensureField(countField); PqlBatchQuery qry = this.index.batchQuery(); qry.add(countField.set(10, 20)); qry.add(countField.set(10, 21)); qry.add(countField.set(15, 25)); client.query(qry); QueryResponse response = client.query(this.index.count(countField.row(10))); assertEquals(2, response.getResult().getCount()); } } @Test public void newOrmTest() throws IOException { try (PilosaClient client = getClient()) { client.query(this.colIndex.batchQuery( this.field.set(5, 20), this.field.set(10, 20), this.field.set(10, 30))); QueryResponse response1 = client.query(this.field.row(10)); assertEquals(0, response1.getColumns().size()); RowResult row1 = response1.getResult().getRow(); assertEquals(0, row1.getAttributes().size()); assertEquals(2, row1.getColumns().size()); assertEquals(20, (long) row1.getColumns().get(0)); Map<String, Object> columnAttrs = new HashMap<>(1); columnAttrs.put("name", "bombo"); client.query(this.colIndex.setColumnAttrs(20, columnAttrs)); QueryOptions queryOptions = QueryOptions.builder() .setColumnAttributes(true) .build(); QueryResponse response2 = client.query(this.field.row(10), queryOptions); ColumnItem column = response2.getColumn(); assertNotNull(column); assertEquals(20, column.getID()); Map<String, Object> rowAttrs = new HashMap<>(1); rowAttrs.put("active", true); rowAttrs.put("unsigned", 5); rowAttrs.put("height", 1.81); rowAttrs.put("name", "Mr. Pi"); client.query(this.field.setRowAttrs(10, rowAttrs)); QueryResponse response3 = client.query(this.field.row(10)); RowResult row = response3.getResult().getRow(); assertEquals(2, row.getColumns().size()); assertEquals(4, row.getAttributes().size()); assertEquals(true, row.getAttributes().get("active")); assertEquals(5L, row.getAttributes().get("unsigned")); assertEquals(1.81, row.getAttributes().get("height")); assertEquals("Mr. Pi", row.getAttributes().get("name")); client.httpRequest("POST", "/recalculate-caches"); Field topnField = this.index.field("topn_test"); client.query(topnField.set(155, 551)); QueryResponse response4 = client.query(topnField.topN(1)); List<CountResultItem> items = response4.getResult().getCountItems(); assertEquals(1, items.size()); CountResultItem item = items.get(0); assertEquals(155, item.getID()); assertEquals(1, item.getCount()); QueryResponse response5 = client.query(this.field.topN(10, null, "name", "Mr. Pi")); items = response5.getResult().getCountItems(); assertEquals(1, items.size()); assertEquals(10, items.get(0).getID()); assertEquals(2, items.get(0).getCount()); } } @Test public void testTopN() throws IOException, InterruptedException { try (PilosaClient client = getClient()) { Field field = this.index.field("topn_test"); client.ensureField(field); client.query(this.index.batchQuery( field.set(10, 5), field.set(10, 10), field.set(10, 15), field.set(20, 5), field.set(30, 5) )); // The following is required to make this test pass. See: https://github.com/pilosa/pilosa/issues/625 client.httpRequest("POST", "/recalculate-caches"); QueryResponse response = client.query(field.topN(2)); List<CountResultItem> items = response.getResult().getCountItems(); assertEquals(2, items.size()); CountResultItem item = items.get(0); assertEquals(10, item.getID()); assertEquals(3, item.getCount()); } } @Test public void testKeys() throws IOException { try (PilosaClient client = getClient()) { FieldOptions options = FieldOptions.builder() .setKeys(true) .build(); Field field = this.keyIndex.field("keys-test", options); client.syncSchema(this.schema); client.query(field.set("stringRow", "stringCol")); QueryResponse response = client.query(field.row("stringRow")); List<String> target = new ArrayList<>(); target.add("stringCol"); assertEquals(target, response.getResult().getRow().getKeys()); // tests: https://github.com/pilosa/java-pilosa/issues/157 options = FieldOptions.builder() .fieldBool() .build(); this.keyIndex.field("keys-bool-test", options); client.syncSchema(this.schema); Schema schema1 = client.readSchema(); Field field1 = schema1.getIndexes().get("key-index").getFields().get("keys-bool-test"); client.ensureField(field1); } } @Test public void testNot() throws IOException { IndexOptions options = IndexOptions.builder() .setTrackExistence(true) .build(); Index index = this.schema.index("not-test", options); Field field = index.field("f1"); try (PilosaClient client = getClient()) { client.syncSchema(this.schema); try { client.query(index.batchQuery( field.set(1, 10), field.set(1, 11), field.set(2, 11), field.set(2, 12), field.set(2, 13) )); QueryResponse response = client.query(index.not(field.row(1))); List<Long> target = new ArrayList<>(); target.add(12L); target.add(13L); assertEquals(target, response.getResult().getRow().getColumns()); } finally { client.deleteIndex(index); } } } @Test public void testStore() throws IOException { Index index = this.schema.index("store-test"); Field fromField = index.field("from-field"); Field toField = index.field("to-field"); try (PilosaClient client = getClient()) { client.syncSchema(this.schema); try { client.query(index.batchQuery( fromField.set(10, 100), fromField.set(10, 200), toField.store(fromField.row(10), 1) )); QueryResponse response = client.query(toField.row(1)); List<Long> target = new ArrayList<>(); target.add(100L); target.add(200L); assertEquals(target, response.getResult().getRow().getColumns()); } finally { client.deleteIndex(index); } } } @Test public void testGroupBy() throws IOException { Field field = index.field("groupby-field"); Field readyField = index.field("ready"); try (PilosaClient client = getClient()) { client.createField(field); client.createField(readyField); client.query(index.batchQuery( field.set(1, 100), field.set(1, 200), field.set(1, 300), field.set(2, 200), field.set(2, 300), readyField.set(1, 100), readyField.set(1, 200) )); QueryResponse response = client.query(index.groupBy(field.rows())); List<FieldRow> fieldRows1 = Collections.singletonList(FieldRow.create("groupby-field", 1)); List<FieldRow> fieldRows2 = Collections.singletonList(FieldRow.create("groupby-field", 2)); List<GroupCount> target = Arrays.asList( GroupCount.create(fieldRows1, 3), GroupCount.create(fieldRows2, 2)); assertEquals(target, response.getResult().getGroupCounts()); response = client.query(index.groupBy(1, field.rows())); target = Collections.singletonList(GroupCount.create(fieldRows1, 3)); assertEquals(target, response.getResult().getGroupCounts()); response = client.query(index.groupBy(readyField.row(1), field.rows())); target = Arrays.asList( GroupCount.create(fieldRows1, 2), GroupCount.create(fieldRows2, 1) ); assertEquals(target, response.getResult().getGroupCounts()); response = client.query(index.groupBy(1, readyField.row(1), field.rows())); target = Collections.singletonList( GroupCount.create(fieldRows1, 2) ); assertEquals(target, response.getResult().getGroupCounts()); } } @Test(expected = PilosaException.class) public void queryFailsWithError() throws IOException { try (PilosaClient client = getClient()) { client.query(this.index.rawQuery("invalid query")); } } @Test(expected = HttpConflict.class) public void createExistingDatabaseFails() throws IOException { try (PilosaClient client = getClient()) { client.createIndex(this.colIndex); } } @Test(expected = HttpConflict.class) public void createExistingFieldFails() throws IOException { try (PilosaClient client = getClient()) { client.createField(this.field); } } @Test(expected = PilosaException.class) public void failedDeleteIndexTest() throws IOException { try (PilosaClient client = PilosaClient.withAddress("http://non-existent-sub.pilosa.com:22222")) { client.deleteIndex(Index.create("non-existent")); } } @Test public void ensureIndexExistsTest() throws IOException { try (PilosaClient client = getClient()) { final Index index = Index.create(this.index.getName() + "-ensure"); client.ensureIndex(index); client.createField(index.field("frm")); client.ensureIndex(index); // shouldn't throw an exception client.deleteIndex(index); } } @Test public void ensureFieldExistsTest() throws IOException { try (PilosaClient client = getClient()) { final Index index = Index.create(this.index.getName() + "-ensure-field"); try { client.createIndex(index); final Field field = index.field("field"); client.ensureField(field); client.ensureField(field); // shouldn't throw an exception client.query(field.set(1, 10)); } finally { client.deleteIndex(index); } } } @Test public void deleteFieldTest() throws IOException { try (PilosaClient client = getClient()) { final Field field = index.field("to-delete"); client.ensureField(field); client.deleteField(field); // the following should succeed client.createField(field); } } @Test public void importRowIDColumnIDTest() throws IOException { try (PilosaClient client = this.getClient()) { LineDeserializer deserializer = new RowIDColumnIDDeserializer(); RecordIterator iterator = csvRecordIterator("row_id-column_id.csv", deserializer); Field field = this.index.field("importfield-rowid-colid"); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = index.batchQuery( field.row(1L), field.row(5L), field.row(3L) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(10L, 20L, 41L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } } } @Test public void importRowIDColumnIDTimestampTest() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIteratorWithTimestamp.columnsWithIDs(); FieldOptions fieldOptions = FieldOptions.builder() .fieldTime(TimeQuantum.YEAR_MONTH_DAY_HOUR) .build(); Field field = this.index.field("importfield-time", fieldOptions); client.ensureField(field); ImportOptions importOptions = ImportOptions.builder().build(); client.importField(field, iterator, importOptions); PqlBatchQuery bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(3L, 1L, 5L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } target = Arrays.asList(5L); Calendar start = new GregorianCalendar(2016, 1, 1, 0, 0, 0); Calendar end = new GregorianCalendar(2019, 1, 1, 0, 0, 0); response = client.query(field.row(10, start.getTime(), end.getTime())); assertEquals(target, response.getResult().getRow().getColumns()); // test clear import iterator = StaticColumnIterator.columnsWithIDs(); importOptions = ImportOptions.builder() .setClear(true) .build(); client.importField(field, iterator, importOptions); bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); response = client.query(bq); target = new ArrayList<>(0); results = response.getResults(); for (QueryResult result : results) { RowResult br = result.getRow(); assertEquals(target, br.getColumns()); } } } @Test public void importRowIDColumnIDManualAddressTest() throws IOException { try (PilosaClient client = this.getClientManualAddress()) { LineDeserializer deserializer = new RowIDColumnIDDeserializer(); RecordIterator iterator = csvRecordIterator("row_id-column_id.csv", deserializer); Field field = this.index.field("importfield-rowid-colid"); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = index.batchQuery( field.row(1L), field.row(5L), field.row(3L) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(10L, 20L, 41L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } } } @Test public void importRowIDColumnKeyManualAddressTest() throws IOException { try (PilosaClient client = this.getClient()) { LineDeserializer deserializer = new RowIDColumnKeyDeserializer(); RecordIterator iterator = csvRecordIterator("row_id-column_key.csv", deserializer); Field field = this.keyIndex.field("importfield-rowid-colkey"); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = this.keyIndex.batchQuery( field.row(1L), field.row(5L), field.row(3L) ); QueryResponse response = client.query(bq); List<String> target = Arrays.asList("ten", "twenty", "forty-one"); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getKeys().get(0)); } } } @Test public void importRowIDColumnKeyTest() throws IOException { try (PilosaClient client = this.getClient()) { LineDeserializer deserializer = new RowIDColumnKeyDeserializer(); RecordIterator iterator = csvRecordIterator("row_id-column_key.csv", deserializer); Field field = this.keyIndex.field("importfield-rowid-colkey"); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = this.keyIndex.batchQuery( field.row(1L), field.row(5L), field.row(3L) ); QueryResponse response = client.query(bq); List<String> target = Arrays.asList("ten", "twenty", "forty-one"); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getKeys().get(0)); } } } @Test public void importRowKeyColumnIDTest() throws IOException { try (PilosaClient client = this.getClient()) { LineDeserializer deserializer = new RowKeyColumnIDDeserializer(); RecordIterator iterator = csvRecordIterator("row_key-column_id.csv", deserializer); FieldOptions fieldOptions = FieldOptions.builder() .setKeys(true) .build(); Field field = this.index.field("importfield-rowkey-colid", fieldOptions); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = index.batchQuery( field.row("one"), field.row("five"), field.row("three") ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(10L, 20L, 41L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } } } @Test public void importRowKeyColumnKeyTest() throws IOException { try (PilosaClient client = this.getClient()) { LineDeserializer deserializer = new RowKeyColumnKeyDeserializer(); RecordIterator iterator = csvRecordIterator("row_key-column_key.csv", deserializer); FieldOptions options = FieldOptions.builder() .setKeys(true) .build(); Field field = this.keyIndex.field("importfield-rowkey-columnkey", options); client.ensureField(field); client.importField(field, iterator); PqlBatchQuery bq = keyIndex.batchQuery( field.row("one"), field.row("five"), field.row("three") ); QueryResponse response = client.query(bq); List<String> target = Arrays.asList("ten", "twenty", "forty-one"); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getKeys().get(0)); } } } @Test public void importRoaringTest() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); Field field = this.index.field("importfield-roaring"); client.ensureField(field); ImportOptions importOptions = ImportOptions.builder() .setRoaring(true) .build(); client.importField(field, iterator, importOptions); PqlBatchQuery bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(3L, 1L, 5L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } // test clear import iterator = StaticColumnIterator.columnsWithIDs(); importOptions = ImportOptions.builder() .setRoaring(true) .setClear(true) .build(); client.importField(field, iterator, importOptions); bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); response = client.query(bq); target = new ArrayList<>(0); results = response.getResults(); for (QueryResult result : results) { RowResult br = result.getRow(); assertEquals(target, br.getColumns()); } } } @Test public void importRoaringTimeFieldTest() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIteratorWithTimestamp.columnsWithIDs(); FieldOptions fieldOptions = FieldOptions.builder() .fieldTime(TimeQuantum.YEAR_MONTH_DAY_HOUR) .build(); Field field = this.index.field("importfield-roaring-time", fieldOptions); client.ensureField(field); ImportOptions importOptions = ImportOptions.builder() .setRoaring(true) .build(); client.importField(field, iterator, importOptions); PqlBatchQuery bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(3L, 1L, 5L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } target = Arrays.asList(5L); Calendar start = new GregorianCalendar(2016, 1, 1, 0, 0, 0); Calendar end = new GregorianCalendar(2019, 1, 1, 0, 0, 0); response = client.query(field.row(10, start.getTime(), end.getTime())); assertEquals(target, response.getResult().getRow().getColumns()); // test clear import iterator = StaticColumnIterator.columnsWithIDs(); importOptions = ImportOptions.builder() .setRoaring(true) .setClear(true) .build(); client.importField(field, iterator, importOptions); bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); response = client.query(bq); target = new ArrayList<>(0); results = response.getResults(); for (QueryResult result : results) { RowResult br = result.getRow(); assertEquals(target, br.getColumns()); } } } @Test public void importFieldValuesTest() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIterator.fieldValuesWithIDs(); FieldOptions options = FieldOptions.builder() .fieldInt(0, 100) .build(); Field field = this.index.field("importvaluefield", options); client.ensureField(field); client.importField(field, iterator); Field field2 = this.index.field("importvaluefield-set"); client.ensureField(field2); PqlBatchQuery bq = this.index.batchQuery( field2.set(1, 10), field2.set(1, 7) ); client.query(bq); QueryResponse response = client.query(field.sum(field2.row(1))); assertEquals(8, response.getResult().getValue()); // test clear import iterator = StaticColumnIterator.fieldValuesWithIDs(); ImportOptions importOptions = ImportOptions.builder() .setClear(true) .build(); client.importField(field, iterator, importOptions); response = client.query(field.sum(field2.row(1))); assertEquals(0, response.getResult().getValue()); } } @Test public void importFieldValuesWithKeysTest() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIterator.fieldValuesWithKeys(); FieldOptions options = FieldOptions.builder() .fieldInt(0, 100) .setKeys(true) .build(); Field field = this.keyIndex.field("importvaluefieldkeys", options); client.ensureField(field); client.importField(field, iterator); FieldOptions options2 = FieldOptions.builder() .setKeys(true) .build(); Field field2 = this.keyIndex.field("importvaluefieldkeys-set", options2); client.ensureField(field2); PqlBatchQuery bq = this.keyIndex.batchQuery( field2.set("one", "ten"), field2.set("one", "seven") ); client.query(bq); QueryResponse response = client.query(field.sum(field2.row("one"))); assertEquals(8, response.getResult().getValue()); } } @Test public void importTestWithBatch() throws IOException { try (PilosaClient client = this.getClient()) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); Field field = this.index.field("importfield"); client.ensureField(field); ImportOptions options = ImportOptions.builder(). setStrategy(ImportOptions.Strategy.BATCH). setBatchSize(3). setThreadCount(1). build(); client.importField(field, iterator, options); PqlBatchQuery bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); QueryResponse response = client.query(bq); List<Long> target = Arrays.asList(3L, 1L, 5L); List<QueryResult> results = response.getResults(); for (int i = 0; i < results.size(); i++) { RowResult br = results.get(i).getRow(); assertEquals(target.get(i), br.getColumns().get(0)); } // test clear imports options = ImportOptions.builder() .setClear(true) .build(); iterator = StaticColumnIterator.columnsWithIDs(); client.importField(field, iterator, options); bq = index.batchQuery( field.row(2), field.row(7), field.row(10) ); response = client.query(bq); results = response.getResults(); target = new ArrayList<>(0); for (QueryResult result : results) { RowResult br = result.getRow(); assertEquals(target, br.getColumns()); } } } @Test public void importTest2() throws IOException { class ImportMonitor implements Runnable { @Override public void run() { while (true) { try { ImportStatusUpdate statusUpdate = this.statusQueue.take(); assertEquals(String.format("thread:%d imported:%d columns for shard:%d in:%d ms", statusUpdate.getThreadID(), statusUpdate.getImportedCount(), statusUpdate.getShard(), statusUpdate.getTimeMs()), statusUpdate.toString()); // for coverage } catch (InterruptedException e) { break; } } } ImportMonitor(final BlockingQueue<ImportStatusUpdate> statusQueue) { this.statusQueue = statusQueue; } private final BlockingQueue<ImportStatusUpdate> statusQueue; } try (PilosaClient client = this.getClient()) { long maxID = 300_000_000; long maxColumns = 100_000; BlockingQueue<ImportStatusUpdate> statusQueue = new LinkedBlockingDeque<>(1000); ImportMonitor monitor = new ImportMonitor(statusQueue); Thread monitorThread = new Thread(monitor); monitorThread.setDaemon(true); monitorThread.start(); RecordIterator iterator = new XColumnIterator(maxID, maxColumns); Field field = this.index.field("importfield2"); client.ensureField(field); ImportOptions options = ImportOptions.builder() .setBatchSize(100000) .setThreadCount(2) .setStrategy(ImportOptions.Strategy.TIMEOUT) .setTimeoutMs(5) .build(); client.importField(field, iterator, options, statusQueue); monitorThread.interrupt(); } } @Test public void workerInterruptedTest() throws IOException { class Importer implements Runnable { Importer(PilosaClient client, Field field) { this.client = client; this.field = field; } @Override public void run() { RecordIterator iterator = new XColumnIterator(1_000, 1_000); BlockingQueue<ImportStatusUpdate> statusQueue = new LinkedBlockingDeque<>(1); Field field = this.field; this.client.ensureField(field); ImportOptions options = ImportOptions.builder() .setStrategy(ImportOptions.Strategy.BATCH) .setBatchSize(500) .setThreadCount(1) .build(); this.client.importField(field, iterator, options, statusQueue); } PilosaClient client; Field field; } try (PilosaClient client = this.getClient()) { Field field = this.index.field("importfield-queue-interrupt"); client.ensureField(field); Thread importer = new Thread(new Importer(client, field)); importer.setDaemon(true); importer.start(); try { Thread.sleep(200); } catch (InterruptedException e) { fail("interruption was not expected here"); } importer.interrupt(); } } @Test public void workerImportRemainingColumnsInterruptedTest() throws IOException { class Importer implements Runnable { Importer(PilosaClient client, Field field) { this.client = client; this.field = field; } @Override public void run() { RecordIterator iterator = new XColumnIterator(1_000, 1_500); // There should be 10_000/3_000 == 3 batch status updates // And another one for the remaining records // Block after the 3 so we have a chance to interrupt the worker thread // while importing remaining records... BlockingQueue<ImportStatusUpdate> statusQueue = new LinkedBlockingDeque<>(1); Field field = this.field; this.client.ensureField(field); ImportOptions options = ImportOptions.builder() .setStrategy(ImportOptions.Strategy.BATCH) .setBatchSize(1_000) .setThreadCount(1) .build(); this.client.importField(field, iterator, options, statusQueue); } PilosaClient client; Field field; } try (PilosaClient client = this.getClient()) { Field field = this.index.field("importfield-queue-interrupt"); client.ensureField(field); Thread importer = new Thread(new Importer(client, field)); // importer.setDaemon(true); importer.start(); try { Thread.sleep(100); } catch (InterruptedException e) { fail("interruption was not expected here"); } importer.interrupt(); } } @Test public void getSchemaTest() throws IOException { try (PilosaClient client = this.getClient()) { Schema schema = client.readSchema(); assertTrue(schema.getIndexes().size() > 0); } } @Test public void getEmptySchemaTest() throws IOException { try (PilosaClient client = this.getClient()) { client.deleteIndex(this.index); client.deleteIndex(this.colIndex); client.deleteIndex(this.keyIndex); Schema schema = client.readSchema(); assertEquals(0, schema.getIndexes().size()); } } @Test public void syncSchemaTest() throws IOException { Index index = null; try (PilosaClient client = this.getClient()) { Schema schema = client.readSchema(); IndexOptions indexOptions = IndexOptions.builder() .setKeys(true) .setTrackExistence(true) .build(); index = schema.index("index11", indexOptions); FieldOptions fieldOptions = FieldOptions.builder() .setKeys(true) .fieldSet(CacheType.RANKED, 50000) .build(); index.field("index11-f1", fieldOptions); client.syncSchema(schema); Schema schema2 = client.readSchema(); Index index2 = schema2.index("index11"); assertEquals(index, index2); Schema schema3 = Schema.defaultSchema(); client.syncSchema(schema3); Index index3 = schema3.index("index11"); assertEquals(index, index3); Schema schema4 = Schema.defaultSchema(); Index index4 = schema4.index("index11", indexOptions); client.syncSchema(schema4); assertEquals(index, index4); } finally { try (PilosaClient client = this.getClient()) { if (index != null) { client.deleteIndex(index); } } } } @Test public void rangeFieldTest() throws IOException { try (PilosaClient client = getClient()) { FieldOptions options = FieldOptions.builder() .fieldInt(10, 20) .build(); Field field = this.index.field("rangefield", options); client.ensureField(field); Field field2 = this.index.field("rangefield-test"); client.ensureField(field2); client.query(this.index.batchQuery( field2.set(1, 10), field2.set(1, 100), field.setValue(10, 11), field.setValue(100, 15) )); QueryResponse response = client.query(field.sum(field2.row(1))); assertEquals(26, response.getResult().getValue()); assertEquals(2, response.getResult().getCount()); response = client.query(field.min()); assertEquals(11, response.getResult().getValue()); assertEquals(1, response.getResult().getCount()); response = client.query(field.min(field2.row(1))); assertEquals(11, response.getResult().getValue()); assertEquals(1, response.getResult().getCount()); response = client.query(field.max()); assertEquals(15, response.getResult().getValue()); assertEquals(1, response.getResult().getCount()); response = client.query(field.max(field2.row(1))); assertEquals(15, response.getResult().getValue()); assertEquals(1, response.getResult().getCount()); response = client.query(field.lessThan(15)); assertEquals(1, response.getResults().size()); assertEquals(10, (long) response.getResult().getRow().getColumns().get(0)); } } @Test public void excludeAttrsColumnsTest() throws IOException { try (PilosaClient client = getClient()) { Map<String, Object> attrs = new HashMap<>(1); attrs.put("foo", "bar"); client.query(colIndex.batchQuery( field.set(1, 100), field.setRowAttrs(1, attrs) )); QueryResponse response; QueryOptions options; // test exclude records. options = QueryOptions.builder() .setExcludeColumns(true) .build(); response = client.query(field.row(1), options); assertEquals(0, response.getResult().getRow().getColumns().size()); assertEquals(1, response.getResult().getRow().getAttributes().size()); // test exclude attributes. options = QueryOptions.builder() .setExcludeAttributes(true) .build(); response = client.query(field.row(1), options); assertEquals(1, response.getResult().getRow().getColumns().size()); assertEquals(0, response.getResult().getRow().getAttributes().size()); } } @Test public void httpRequestTest() throws IOException { try (PilosaClient client = getClient()) { client.httpRequest("GET", "/status"); } } @Test public void shardsTest() throws IOException { try (PilosaClient client = getClient()) { final long shardWidth = ClientOptions.DEFAULT_SHARD_WIDTH; client.query(colIndex.batchQuery( field.set(1, 100), field.set(1, shardWidth), field.set(1, shardWidth * 3) )); QueryOptions options = QueryOptions.builder() .setShards(0L, 3L) .build(); QueryResponse response = client.query(field.row(1), options); List<Long> columns = response.getResult().getRow().getColumns(); assertEquals(2, columns.size()); assertEquals(100, (long) columns.get(0)); assertEquals(shardWidth * 3, (long) columns.get(1)); } } @Test public void warningResponseTest() throws IOException, InterruptedException { String path = String.format("/index/%s/query", this.colIndex.getName()); String msg = "299 pilosa/2.0 \"Deprecated PQL version: PQL v2 will remove support for SetBit() in Pilosa 2.1. Please update your client to support Set() (See https://docs.pilosa.com/pql#versioning).\" \"Sat, 25 Aug 2019 23:34:45 GMT\""; HttpServer server = warningResponseHttpServer(path, msg); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.field.row(1)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void importFailNot200() throws IOException { HttpServer server = runImportFailsHttpServer(); try (PilosaClient client = PilosaClient.withAddress(":15999")) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); try { client.importField(this.index.field("importfield"), iterator); } finally { if (server != null) { server.stop(0); } } } } @Test public void importFail200Test() throws IOException { HttpServer server = runContentSizeLyingHttpServer("/internal/fragment/nodes"); try (PilosaClient client = PilosaClient.withAddress(":15999")) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); try { client.importField(this.index.field("importfield"), iterator); } catch (PilosaException ex) { // pass return; } finally { if (server != null) { server.stop(0); } } } fail("Expected PilosaException to be thrown"); } @Test(expected = PilosaException.class) public void queryFail404Test() throws IOException { HttpServer server = runContentSizeLyingHttpServer("/404"); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.field.set(15, 10)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void fail304EmptyResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/index/foo", 304); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.createIndex(Index.create("foo")); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failQueryEmptyResponseTest() throws IOException { String path = String.format("/index/%s/query", this.field.getIndex().getName()); HttpServer server = runContent0HttpServer(path, 304); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.field.set(15, 10)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failFetchFieldNodesEmptyResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/internal/fragment/nodes", 204); try (PilosaClient client = PilosaClient.withAddress(":15999")) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); try { client.importField(this.index.field("importfield"), iterator); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failFetchCoordinatorNodeEmptyResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/status", 204); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.keyField.set("foo", 1)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failFetchCoordinator200Test() throws IOException { HttpServer server = runContentSizeLyingHttpServer("/status"); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.keyField.set("foo", 1)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failSchemaEmptyResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/schema", 204); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.readServerSchema(); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failSchema200Test() throws IOException { HttpServer server = runContentSizeLyingHttpServer("/schema"); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.readServerSchema(); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failSchema400IOError() throws IOException { HttpServer server = runContentSizeLyingHttpServer400("/schema"); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.readServerSchema(); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failOverTest() { Cluster c = Cluster.defaultCluster(); for (int i = 0; i < 20; i++) { c.addHost(URI.address(String.format("n%d.nonexistent-improbable:5000", i))); } PilosaClient client = PilosaClient.withCluster(c); client.readServerSchema(); } @Test(expected = PilosaException.class) public void failOverCoordinatorTest() throws IOException, InterruptedException { HttpServer server = runNonexistentCoordinatorHttpServer(); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { Map<String, Object> attrs = new HashMap<>(1); attrs.put("foo", "bar"); client.query(this.keyIndex.setColumnAttrs("foo", attrs)); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = RuntimeException.class) public void invalidPilosaClientFails() throws IOException { Cluster cluster = Cluster.withHost(URI.address(getBindAddress())); ClientOptions options = ClientOptions.builder().build(); try (PilosaClient client = new InvalidPilosaClient(cluster, options)) { RecordIterator iterator = StaticColumnIterator.columnsWithIDs(); Field field = this.index.field("importfield"); client.importField(field, iterator); } } @Test(expected = PilosaException.class) public void failUnknownErrorResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/schema", 504); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.readServerSchema(); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failNoCoordinatorTest() throws IOException { HttpServer server = runNoCoordinatorHttpServer(); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { client.query(this.keyField.set(1, "foo")); } finally { if (server != null) { server.stop(0); } } } } @Test(expected = PilosaException.class) public void failKeyEmptyResponseTest() throws IOException { HttpServer server = runContent0HttpServer("/internal/translate/keys", 204); try (PilosaClient client = PilosaClient.withAddress(":15999")) { try { Internal.TranslateKeysRequest.Builder requestBuilder = Internal.TranslateKeysRequest.newBuilder(); client.translateKeys(requestBuilder.build()); } finally { if (server != null) { server.stop(0); } } } } @Test public void testTranslateRowKeys() throws IOException { IndexOptions options = IndexOptions.builder() .setTrackExistence(true) .setKeys(true) .build(); Index index = this.schema.index("translate-test", options); FieldOptions fieldOptions = FieldOptions.builder() .setKeys(true) .build(); Field field = index.field("f1", fieldOptions); try (PilosaClient client = getClient()) { client.syncSchema(this.schema); try { String[] smallBatch = {"one", "two", "three", "four", "five", "six", "seven", "eight", "#@`1"}; long[] result = client.translateRowKeys(field, smallBatch); long[] result2 = client.translateRowKeys(field, smallBatch); assertArrayEquals(result2, result); } finally { client.deleteIndex(index); } } } @Test public void testTranslateColumnKeys() throws IOException { IndexOptions options = IndexOptions.builder() .setTrackExistence(true) .setKeys(true) .build(); Index index = this.schema.index("translate-test", options); try (PilosaClient client = getClient()) { client.syncSchema(this.schema); try { String[] smallBatch = {"one", "two", "three", "four", "five", "six", "seven", "eight", "#@`1"}; long[] result = client.translateColumnKeys(index, smallBatch); long[] result2 = client.translateColumnKeys(index, smallBatch); assertArrayEquals(result2, result); String[] diffBatch = {"two", "three", "four", "five", "six", "seven", "eight", "#@`1", "nine"}; long[] result3 = client.translateColumnKeys(index, diffBatch); assertEquals(result2[1], result3[0]); assertNotEquals(result2[0], result3[0]); } finally { client.deleteIndex(index); } } } @Test public void testTranslateColumnKeysEmptyRequest() throws IOException { IndexOptions options = IndexOptions.builder() .setTrackExistence(true) .setKeys(true) .build(); Index index = this.schema.index("translate-test", options); try (PilosaClient client = getClient()) { client.syncSchema(this.schema); String[] empty = {}; try { long[] results = client.translateColumnKeys(index, empty); assertEquals(0, results.length); } finally { client.deleteIndex(index); } } } private static int counter = 0; private static String getRandomIndexName() { return String.format("testdb-%d", ++counter); } private HttpServer runImportFailsHttpServer() { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext("/internal/fragment/nodes", new FragmentNodesHandler()); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer runContentSizeLyingHttpServer(String path) { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(path, new ContentSizeLyingHandler()); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer runContentSizeLyingHttpServer400(String path) { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(path, new ContentSizeLyingHandler(400)); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer runContent0HttpServer(String path, int statusCode) { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(path, new Content0Handler(statusCode)); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer runNoCoordinatorHttpServer() { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext("/status", new NoCoordinatorHandler()); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer runNonexistentCoordinatorHttpServer() { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext("/status", new NonexistentCoordinatorHandler()); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } private HttpServer warningResponseHttpServer(String path, String warningMessage) { final int port = 15999; try { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(path, new WarningResponseHandler(warningMessage)); server.setExecutor(null); server.start(); return server; } catch (IOException ex) { fail(ex.getMessage()); } return null; } static class FragmentNodesHandler implements HttpHandler { @Override public void handle(HttpExchange r) throws IOException { String response = "[{\"scheme\":\"http\", \"host\":\"localhost:15999\"}]"; r.sendResponseHeaders(200, response.length()); try (OutputStream os = r.getResponseBody()) { os.write(response.getBytes()); } } } static class ContentSizeLyingHandler implements HttpHandler { ContentSizeLyingHandler() { this(200); } ContentSizeLyingHandler(int statusCode) { super(); this.statusCode = statusCode; } @Override public void handle(HttpExchange r) throws IOException { r.sendResponseHeaders(statusCode, 42); OutputStream os = r.getResponseBody(); os.close(); } private int statusCode; } static class Content0Handler implements HttpHandler { Content0Handler(int statusCode) { super(); this.statusCode = statusCode; } @Override public void handle(HttpExchange r) throws IOException { r.sendResponseHeaders(this.statusCode, -1); r.close(); } private int statusCode; } static class NoCoordinatorHandler implements HttpHandler { @Override public void handle(HttpExchange r) throws IOException { String response = "{\"state\":\"NORMAL\",\"nodes\":[{\"id\":\"0f5c2ffc-1244-47d0-a83d-f5a25abba9bc\",\"uri\":{\"scheme\":\"http\",\"host\":\"localhost\",\"port\":10101}}],\"localID\":\"0f5c2ffc-1244-47d0-a83d-f5a25abba9bc\"}"; r.sendResponseHeaders(200, response.getBytes().length); try (OutputStream os = r.getResponseBody()) { os.write(response.getBytes()); } r.close(); } } static class NonexistentCoordinatorHandler implements HttpHandler { @Override public void handle(HttpExchange r) throws IOException { String response = "{\"state\":\"NORMAL\",\"nodes\":[{\"isCoordinator\":true, \"id\":\"0f5c2ffc-1244-47d0-a83d-f5a25abba9bc\",\"uri\":{\"scheme\":\"http\",\"host\":\"nonexistent\",\"port\":4444}}],\"localID\":\"0f5c2ffc-1244-47d0-a83d-f5a25abba9bc\"}"; r.sendResponseHeaders(200, response.getBytes().length); try (OutputStream os = r.getResponseBody()) { os.write(response.getBytes()); } r.close(); } } static class WarningResponseHandler implements HttpHandler { WarningResponseHandler(String warningHeader) { super(); this.warningHeader = warningHeader; } @Override public void handle(HttpExchange r) throws IOException { try (OutputStream os = r.getResponseBody()) { r.getResponseHeaders().set("warning", warningHeader); byte[] responseBytes = {0x12, 0x04, 0x0a, 0x00, 0x30, 0x01}; r.sendResponseHeaders(200, responseBytes.length); os.write(responseBytes); } r.close(); } private String warningHeader; } private Index findIndex(Schema schema, Index target) { for (Map.Entry<String, Index> entry : schema.getIndexes().entrySet()) { if (entry.getKey().equals(target.getName())) { return entry.getValue(); } } return null; } private Field findField(Schema schema, Field target) { Index index = findIndex(schema, target.getIndex()); if (index != null) { for (Map.Entry<String, Field> entry : index.getFields().entrySet()) { if (entry.getKey().equals(target.getName())) { return entry.getValue(); } } } return null; } private PilosaClient getClient() { String bindAddress = getBindAddress(); Cluster cluster = Cluster.withHost(URI.address(bindAddress)); ClientOptions.Builder optionsBuilder = ClientOptions.builder(); long shardWidth = getShardWidth(); if (shardWidth > 0) { optionsBuilder.setShardWidth(shardWidth); } return new InsecurePilosaClientIT(cluster, optionsBuilder.build()); } private PilosaClient getClientManualAddress() { String bindAddress = getBindAddress(); ClientOptions.Builder optionsBuilder = ClientOptions.builder() .setManualServerAddress(true); long shardWidth = getShardWidth(); if (shardWidth > 0) { optionsBuilder.setShardWidth(shardWidth); } return new InsecurePilosaClientIT(bindAddress, optionsBuilder.build()); } private String getBindAddress() { String bindAddress = System.getenv("PILOSA_BIND"); if (bindAddress == null) { bindAddress = "http://:10101"; } return bindAddress; } private boolean isLegacyModeOff() { String legacyModeOffStr = System.getenv("LEGACY_MODE_OFF"); return legacyModeOffStr != null && legacyModeOffStr.equals("true"); } private long getShardWidth() { String shardWidthStr = System.getenv("SHARD_WIDTH"); return (shardWidthStr == null) ? 0 : Long.parseLong(shardWidthStr); } private RecordIterator csvRecordIterator(String path, LineDeserializer deserializer) throws FileNotFoundException { ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL uri = loader.getResource(path); if (uri == null) { fail(String.format("%s not found", path)); } return FileRecordIterator.fromPath(uri.getPath(), deserializer); } } class StaticColumnIterator implements RecordIterator { private List<Record> records; private int index = 0; public static StaticColumnIterator columnsWithIDs() { return new StaticColumnIterator(false, false); } public static StaticColumnIterator columnsWithKeys() { return new StaticColumnIterator(true, false); } public static StaticColumnIterator fieldValuesWithIDs() { return new StaticColumnIterator(false, true); } public static StaticColumnIterator fieldValuesWithKeys() { return new StaticColumnIterator(true, true); } private StaticColumnIterator(boolean keys, boolean intValues) { this.records = new ArrayList<>(3); if (keys) { if (intValues) { this.records.add(FieldValue.create("ten", 7)); this.records.add(FieldValue.create("seven", 1)); } else { this.records.add(Column.create("ten", "five")); this.records.add(Column.create("two", "three")); this.records.add(Column.create("seven", "one")); } } else { if (intValues) { this.records.add(FieldValue.create(10, 7)); this.records.add(FieldValue.create(7, 1)); } else { this.records.add(Column.create(10, 5)); this.records.add(Column.create(2, 3)); this.records.add(Column.create(7, 1)); } } } @Override public boolean hasNext() { return this.index < this.records.size(); } @Override public Record next() { return this.records.get(index++); } @Override public void remove() { // We have this just to avoid compilation problems on JDK 7 } } class StaticColumnIteratorWithTimestamp implements RecordIterator { private List<Record> records; private int index = 0; public static StaticColumnIteratorWithTimestamp columnsWithIDs() { return new StaticColumnIteratorWithTimestamp(false, false); } public static StaticColumnIteratorWithTimestamp columnsWithKeys() { return new StaticColumnIteratorWithTimestamp(true, false); } public static StaticColumnIteratorWithTimestamp fieldValuesWithIDs() { return new StaticColumnIteratorWithTimestamp(false, true); } public static StaticColumnIteratorWithTimestamp fieldValuesWithKeys() { return new StaticColumnIteratorWithTimestamp(true, true); } private StaticColumnIteratorWithTimestamp(boolean keys, boolean intValues) { this.records = new ArrayList<>(3); if (keys) { if (intValues) { this.records.add(FieldValue.create("ten", 7)); this.records.add(FieldValue.create("seven", 1)); } else { this.records.add(Column.create("ten", "five")); this.records.add(Column.create("two", "three")); this.records.add(Column.create("seven", "one")); } } else { if (intValues) { this.records.add(FieldValue.create(10, 7)); this.records.add(FieldValue.create(7, 1)); } else { this.records.add(Column.create(10, 5, 1542199376000000000L)); this.records.add(Column.create(2, 3, 1520268300000000000L)); this.records.add(Column.create(7, 1, 1330965900000000000L)); } } } @Override public boolean hasNext() { return this.index < this.records.size(); } @Override public Record next() { return this.records.get(index++); } @Override public void remove() { // We have this just to avoid compilation problems on JDK 7 } } class InvalidPilosaClient extends InsecurePilosaClientIT { InvalidPilosaClient(Cluster cluster, ClientOptions options) { super(cluster, options); } } class XColumnIterator implements RecordIterator { XColumnIterator(long maxID, long maxColumns) { this.maxID = maxID; this.maxColumns = maxColumns; } public boolean hasNext() { return this.maxColumns > 0; } public Column next() { this.maxColumns -= 1; long rowID = (long) (Math.random() * this.maxID); long columnID = (long) (Math.random() * this.maxID); return Column.create(rowID, columnID); } @Override public void remove() { } private long maxID; private long maxColumns; }