| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.rya.indexing.accumulo.temporal; |
| |
| import static org.apache.rya.api.resolver.RdfToRyaConversions.convertStatement; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import org.apache.accumulo.core.client.AccumuloException; |
| import org.apache.accumulo.core.client.AccumuloSecurityException; |
| import org.apache.accumulo.core.client.BatchWriterConfig; |
| import org.apache.accumulo.core.client.Connector; |
| import org.apache.accumulo.core.client.MultiTableBatchWriter; |
| import org.apache.accumulo.core.client.Scanner; |
| import org.apache.accumulo.core.client.TableExistsException; |
| import org.apache.accumulo.core.client.TableNotFoundException; |
| import org.apache.accumulo.core.client.admin.TableOperations; |
| import org.apache.accumulo.core.data.Key; |
| import org.apache.accumulo.core.data.Value; |
| import org.apache.accumulo.core.security.Authorizations; |
| import org.apache.commons.codec.binary.StringUtils; |
| import org.apache.commons.io.output.NullOutputStream; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.io.Text; |
| import org.apache.rya.api.RdfCloudTripleStoreConfiguration; |
| import org.apache.rya.api.domain.RyaStatement; |
| import org.apache.rya.indexing.StatementConstraints; |
| import org.apache.rya.indexing.StatementSerializer; |
| import org.apache.rya.indexing.TemporalInstant; |
| import org.apache.rya.indexing.TemporalInstantRfc3339; |
| import org.apache.rya.indexing.TemporalInterval; |
| import org.apache.rya.indexing.accumulo.ConfigUtils; |
| import org.eclipse.rdf4j.common.iteration.CloseableIteration; |
| import org.eclipse.rdf4j.model.IRI; |
| import org.eclipse.rdf4j.model.Statement; |
| import org.eclipse.rdf4j.model.ValueFactory; |
| import org.eclipse.rdf4j.model.impl.SimpleValueFactory; |
| import org.eclipse.rdf4j.model.vocabulary.RDFS; |
| import org.eclipse.rdf4j.query.QueryEvaluationException; |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| import com.google.common.collect.Lists; |
| |
| /** |
| * JUnit tests for TemporalIndexer and it's implementation AccumuloTemporalIndexer |
| * |
| * If you enjoy this test, please read RyaTemporalIndexerTest and YagoKBTest, which contain |
| * many example SPARQL queries and updates and attempts to test independently of Accumulo: |
| * |
| * extras/indexingSail/src/test/java/org.apache/rya/indexing/accumulo/RyaTemporalIndexerTest.java |
| * {@link org.apache.rya.indexing.accumulo.RyaTemporalIndexerTest} |
| * {@link org.apache.rya.indexing.accumulo.YagoKBTest.java} |
| * |
| * Remember, this class in instantiated fresh for each @test method. |
| * so fields are reset, unless they are static. |
| * |
| * These are covered: |
| * Instance {before, equals, after} given Instance |
| * Instance {before, after, inside} given Interval |
| * Instance {hasBeginning, hasEnd} given Interval |
| * And a few more. |
| * |
| * The temporal predicates are from these ontologies: |
| * http://linkedevents.org/ontology |
| * http://motools.sourceforge.net/event/event.html |
| */ |
| public final class AccumuloTemporalIndexerTest { |
| // Configuration properties, this is reset per test in setup. |
| Configuration conf; |
| // temporal indexer to test, this is created for each test method by setup. |
| AccumuloTemporalIndexer tIndexer; |
| |
| private static final String URI_PROPERTY_EVENT_TIME = "Property:event:time"; |
| private static final String URI_PROPERTY_CIRCA = "Property:circa"; |
| private static final String URI_PROPERTY_AT_TIME = "Property:atTime"; |
| private static final String STAT_COUNT = "count"; |
| private static final String STAT_KEYHASH = "keyhash"; |
| private static final String STAT_VALUEHASH = "valuehash"; |
| private static final StatementConstraints EMPTY_CONSTRAINTS = new StatementConstraints(); |
| |
| // Assign this in setUpBeforeClass, store them in each test. |
| // setup() deletes table before each test. |
| static final Statement spo_B00_E01; |
| static final Statement spo_B03_E20; |
| static final Statement spo_B02_E29; |
| static final Statement spo_B02_E30; |
| static final Statement spo_B02_E40; |
| static final Statement spo_B02_E31; |
| static final Statement spo_B29_E30; |
| static final Statement spo_B30_E32; |
| |
| // Instants: |
| static final Statement spo_B02; |
| static final int SERIES_OF_SECONDS = 41; |
| static final Statement seriesSpo[] = new Statement[SERIES_OF_SECONDS]; |
| |
| // These are shared for several tests. Only the seconds are different. |
| // tvB03_E20 read as: interval Begins 3 seconds, ends at 20 seconds |
| static final TemporalInterval tvB00_E01 = new TemporalInterval(// |
| makeInstant(00), // |
| makeInstant(01)); |
| static final TemporalInterval tvB29_E30= new TemporalInterval(// |
| makeInstant(29), // |
| makeInstant(30)); |
| static final TemporalInterval tvB30_E32= new TemporalInterval(// |
| makeInstant(30), // |
| makeInstant(32)); |
| static final TemporalInterval tvB03_E20 = new TemporalInterval(// |
| makeInstant(03), // |
| makeInstant(20)); |
| // 30 seconds, Begins earlier, ends later |
| static final TemporalInterval tvB02_E30= new TemporalInterval(// |
| makeInstant(02), // |
| makeInstant(30)); |
| // use for interval after |
| static final TemporalInterval tvB02_E29= new TemporalInterval(// |
| makeInstant(02), // |
| makeInstant(29)); |
| // same as above, but ends in the middle |
| static final TemporalInterval tvB02_E31 = new TemporalInterval(// |
| makeInstant(02), // |
| makeInstant(31)); |
| // same as above, but ends even later |
| static final TemporalInterval tvB02_E40 = new TemporalInterval(// |
| makeInstant(02), // |
| makeInstant(40)); |
| // instant, match beginnings of several above, before tiB03_E20 |
| static final TemporalInstant tsB02 = makeInstant(02); |
| // instant, after all above |
| static final TemporalInstant tsB04 = makeInstant(04); |
| |
| // Create a series of instants about times 0 - 40 seconds |
| static final TemporalInstant seriesTs[]; |
| static { |
| seriesTs = new TemporalInstant[SERIES_OF_SECONDS]; |
| for (int i = 0; i <= 40; i++) |
| seriesTs[i] = makeInstant(i); |
| } |
| |
| /** |
| * Make an uniform instant with given seconds. |
| */ |
| static TemporalInstant makeInstant(int secondsMakeMeUnique) { |
| return new TemporalInstantRfc3339(2015, 12, 30, 12, 00, secondsMakeMeUnique); |
| } |
| |
| static { |
| // Setup the statements only once. Each test will store some of these in there own index table. |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| // tiB03_E20 read as: time interval that Begins 3 seconds, ends at 20 seconds, |
| // Each time element the same, except seconds. year, month, .... minute are the same for each statement below. |
| spo_B00_E01 = vf.createStatement(vf.createIRI("foo:event0"), pred1_atTime, vf.createLiteral(tvB00_E01.toString())); |
| spo_B02_E29 = vf.createStatement(vf.createIRI("foo:event2"), pred1_atTime, vf.createLiteral(tvB02_E29.toString())); |
| spo_B02_E30 = vf.createStatement(vf.createIRI("foo:event2"), pred1_atTime, vf.createLiteral(tvB02_E30.toString())); |
| spo_B02_E31 = vf.createStatement(vf.createIRI("foo:event3"), pred1_atTime, vf.createLiteral(tvB02_E31.toString())); |
| spo_B02_E40 = vf.createStatement(vf.createIRI("foo:event4"), pred1_atTime, vf.createLiteral(tvB02_E40.toString())); |
| spo_B03_E20 = vf.createStatement(vf.createIRI("foo:event5"), pred1_atTime, vf.createLiteral(tvB03_E20.toString())); |
| spo_B29_E30 = vf.createStatement(vf.createIRI("foo:event1"), pred1_atTime, vf.createLiteral(tvB29_E30.toString())); |
| spo_B30_E32 = vf.createStatement(vf.createIRI("foo:event1"), pred1_atTime, vf.createLiteral(tvB30_E32.toString())); |
| spo_B02 = vf.createStatement(vf.createIRI("foo:event6"), pred1_atTime, vf.createLiteral(tsB02.getAsReadable())); |
| |
| // Create statements about time instants 0 - 40 seconds |
| for (int i = 0; i < seriesTs.length; i++) { |
| seriesSpo[i] = vf.createStatement(vf.createIRI("foo:event0" + i), pred1_atTime, vf.createLiteral(seriesTs[i].getAsReadable())); |
| } |
| |
| } |
| |
| /** |
| * @throws java.lang.Exception |
| */ |
| @BeforeClass |
| public static void setUpBeforeClass() throws Exception { |
| } |
| |
| /** |
| * @throws java.lang.Exception |
| */ |
| @AfterClass |
| public static void tearDownAfterClass() throws Exception { |
| } |
| |
| /** |
| * @throws java.lang.Exception |
| */ |
| @Before |
| public void setUp() throws Exception { |
| conf = new Configuration(); |
| conf.set(RdfCloudTripleStoreConfiguration.CONF_TBL_PREFIX, "triplestore_"); |
| conf.setBoolean(ConfigUtils.USE_MOCK_INSTANCE, true); |
| // The temporal predicates are from http://linkedevents.org/ontology |
| // and http://motools.sourceforge.net/event/event.html |
| conf.setStrings(ConfigUtils.TEMPORAL_PREDICATES_LIST, "" |
| + URI_PROPERTY_AT_TIME + "," |
| + URI_PROPERTY_CIRCA + "," |
| + URI_PROPERTY_EVENT_TIME); |
| |
| tIndexer = new AccumuloTemporalIndexer(); |
| tIndexer.setConf(conf); |
| Connector connector = ConfigUtils.getConnector(conf); |
| MultiTableBatchWriter mt_bw = connector.createMultiTableBatchWriter(new BatchWriterConfig()); |
| tIndexer.setConnector(connector); |
| tIndexer.setMultiTableBatchWriter(mt_bw); |
| tIndexer.init(); |
| } |
| |
| /** |
| * @throws java.lang.Exception |
| */ |
| @After |
| public void tearDown() throws Exception { |
| String indexTableName = tIndexer.getTableName(); |
| tIndexer.close(); |
| TableOperations tableOps = ConfigUtils.getConnector(conf).tableOperations(); |
| |
| if (tableOps.exists(indexTableName)) |
| tableOps.delete(indexTableName); |
| } |
| |
| /** |
| * Test method for {@link AccumuloTemporalIndexer#TemporalIndexerImpl(org.apache.hadoop.conf.Configuration)} . |
| * |
| * @throws TableExistsException |
| * @throws TableNotFoundException |
| * @throws AccumuloSecurityException |
| * @throws AccumuloException |
| * @throws IOException |
| */ |
| @Test |
| public void testTemporalIndexerImpl() |
| throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IOException { |
| assertNotNull("Constructed.", tIndexer.toString()); |
| } |
| |
| /** |
| * Test method for {@link AccumuloTemporalIndexer#storeStatement(convertStatement(org.eclipse.rdf4j.model.Statement)} |
| * |
| * @throws NoSuchAlgorithmException |
| */ |
| @Test |
| public void testStoreStatement() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException { |
| // count rows expected to store: |
| int rowsStoredExpected = 0; |
| |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA); |
| |
| // Should not be stored because they are not in the predicate list |
| String validDateStringWithThirteens = "1313-12-13T13:13:13Z"; |
| tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj1"), RDFS.LABEL, vf.createLiteral(validDateStringWithThirteens)))); |
| |
| // Test: Should not store an improper date, and log a warning (log warning not tested). |
| final String invalidDateString = "ThisIsAnInvalidDate"; |
| // // Silently logs a warning for bad dates. Old: Set true when we catch the error: |
| // boolean catchErrorThrownCorrectly = false; |
| // try { |
| tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(invalidDateString)))); |
| // } catch (IllegalArgumentException e) { |
| // catchErrorThrownCorrectly = true; |
| // Assert.assertTrue( |
| // "Invalid date parse error should include the invalid string. message=" + e.getMessage(), |
| // e.getMessage().contains(invalidDateString)); |
| // } |
| // Assert.assertTrue("Invalid date parse error should be thrown for this bad date=" + invalidDateString, catchErrorThrownCorrectly); |
| |
| // These are different datetimes instant but from different time zones. |
| // This is an arbitrary zone, BRST=Brazil, better if not local. |
| // same as "2015-01-01T01:59:59Z" |
| final String testDate2014InBRST = "2014-12-31T23:59:59-02:00"; |
| // next year, same as "2017-01-01T01:59:59Z" |
| final String testDate2016InET = "2016-12-31T20:59:59-05:00"; |
| |
| // These should be stored because they are in the predicate list. |
| // BUT they will get converted to the same exact datetime in UTC. |
| Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST)); |
| Statement s4 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET)); |
| tIndexer.storeStatement(convertStatement(s3)); |
| rowsStoredExpected++; |
| tIndexer.storeStatement(convertStatement(s4)); |
| rowsStoredExpected++; |
| |
| // This should not be stored because the object is not a literal |
| tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj5"), pred1_atTime, vf.createIRI("in:valid")))); |
| |
| tIndexer.flush(); |
| |
| int rowsStoredActual = printTables("junit testing: Temporal entities stored in testStoreStatement", null, null); |
| assertEquals("Number of rows stored.", rowsStoredExpected*4, rowsStoredActual); // 4 index entries per statement |
| |
| } |
| |
| @Test |
| public void testDelete() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException { |
| // count rows expected to store: |
| int rowsStoredExpected = 0; |
| |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA); |
| |
| final String testDate2014InBRST = "2014-12-31T23:59:59-02:00"; |
| final String testDate2016InET = "2016-12-31T20:59:59-05:00"; |
| |
| // These should be stored because they are in the predicate list. |
| // BUT they will get converted to the same exact datetime in UTC. |
| Statement s1 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(testDate2014InBRST)); |
| Statement s2 = vf.createStatement(vf.createIRI("foo:subj4"), pred2_circa, vf.createLiteral(testDate2016InET)); |
| tIndexer.storeStatement(convertStatement(s1)); |
| rowsStoredExpected++; |
| tIndexer.storeStatement(convertStatement(s2)); |
| rowsStoredExpected++; |
| |
| tIndexer.flush(); |
| |
| int rowsStoredActual = printTables("junit testing: Temporal entities stored in testDelete before delete", System.out, null); |
| Assert.assertEquals("Number of rows stored.", rowsStoredExpected*4, rowsStoredActual); // 4 index entries per statement |
| |
| tIndexer.deleteStatement(convertStatement(s1)); |
| tIndexer.deleteStatement(convertStatement(s2)); |
| |
| int afterDeleteRowsStoredActual = printTables("junit testing: Temporal entities stored in testDelete after delete", System.out, null); |
| Assert.assertEquals("Number of rows stored after delete.", 0, afterDeleteRowsStoredActual); |
| } |
| |
| @Test |
| public void testStoreStatementWithInterestingLiterals() throws Exception { |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| |
| tIndexer.storeStatement(convertStatement(vf.createStatement( |
| vf.createIRI("foo:subj2"), |
| pred1_atTime, |
| vf.createLiteral("A number of organizations located, gathered, or classed together. [Derived from Concise Oxford English Dictionary, 11th Edition, 2008]")))); |
| |
| int rowsStoredActual = printTables("junit testing: Temporal entities stored in testStoreStatement", null, null); |
| Assert.assertEquals("Number of rows stored.", 0, rowsStoredActual); // 4 index entries per statement |
| } |
| |
| /** |
| * Test method for {@link AccumuloTemporalIndexer#storeStatement(convertStatement(org.eclipse.rdf4j.model.Statement)} |
| * |
| * @throws NoSuchAlgorithmException |
| */ |
| @Test |
| public void testStoreStatementBadInterval() throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, NoSuchAlgorithmException { |
| // count rows expected to store: |
| int rowsStoredExpected = 0; |
| |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| |
| // Test: Should not store an improper date interval, and log a warning (log warning not tested). |
| final String invalidDateIntervalString="[bad,interval]"; |
| // Silently logs a warning for bad dates. |
| tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj1"), pred1_atTime, vf.createLiteral(invalidDateIntervalString)))); |
| |
| final String validDateIntervalString="[2016-12-31T20:59:59-05:00,2016-12-31T21:00:00-05:00]"; |
| tIndexer.storeStatement(convertStatement(vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(validDateIntervalString)))); |
| rowsStoredExpected++; |
| |
| tIndexer.flush(); |
| |
| int rowsStoredActual = printTables("junit testing: Temporal intervals stored in testStoreStatement", null, null); |
| Assert.assertEquals("Only good intervals should be stored.", rowsStoredExpected*2, rowsStoredActual); // 2 index entries per interval statement |
| } |
| |
| @Test |
| public void testStoreStatementsSameTime() throws IOException, NoSuchAlgorithmException, AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException { |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| IRI pred2_circa = vf.createIRI(URI_PROPERTY_CIRCA); |
| |
| // These are the same datetime instant but from different time |
| // zones. |
| // This is an arbitrary zone, BRST=Brazil, better if not local. |
| final String ZONETestDateInBRST = "2014-12-31T23:59:59-02:00"; |
| final String ZONETestDateInZulu = "2015-01-01T01:59:59Z"; |
| final String ZONETestDateInET = "2014-12-31T20:59:59-05:00"; |
| |
| // These all should be stored because they are in the predicate list. |
| // BUT they will get converted to the same exact datetime in UTC. |
| // So we have to make the key distinct! Good luck indexer! |
| Statement s1 = vf.createStatement(vf.createIRI("foo:subj1"), pred2_circa, vf.createLiteral(ZONETestDateInET)); |
| Statement s2 = vf.createStatement(vf.createIRI("foo:subj2"), pred1_atTime, vf.createLiteral(ZONETestDateInZulu)); |
| Statement s3 = vf.createStatement(vf.createIRI("foo:subj3"), pred1_atTime, vf.createLiteral(ZONETestDateInBRST)); |
| int rowsStoredExpected = 0; |
| tIndexer.storeStatement(convertStatement(s1)); |
| rowsStoredExpected++; |
| tIndexer.storeStatement(convertStatement(s2)); |
| rowsStoredExpected++; |
| tIndexer.storeStatement(convertStatement(s3)); |
| rowsStoredExpected++; |
| int rowsStoredActual = printTables("junit testing: Duplicate times stored", null /*System.out*/, null); |
| Assert.assertEquals("Number of Duplicate times stored, 1 means duplicates not handled correctly.", rowsStoredExpected*4, rowsStoredActual); |
| } |
| |
| /** |
| * Test method for {@link AccumuloTemporalIndexer#storeStatements(java.util.Collection)} . |
| * |
| * @throws TableExistsException |
| * @throws TableNotFoundException |
| * @throws AccumuloSecurityException |
| * @throws AccumuloException |
| * @throws IOException |
| * @throws IllegalArgumentException |
| * @throws NoSuchAlgorithmException |
| */ |
| @Test |
| public void testStoreStatements() |
| throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IllegalArgumentException, IOException, |
| NoSuchAlgorithmException { |
| long valueHash = 0; |
| Collection<Statement> statements = new ArrayList<Statement>(70); |
| statements.addAll(Arrays.asList(seriesSpo)); |
| int rowsStoredExpected = statements.size()*4; // instants store 4 each |
| // hash the expected output: |
| for (Statement statement : statements) { |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(statement))); |
| } |
| statements.add(spo_B02_E30); |
| rowsStoredExpected += 2; // intervals store two dates |
| statements.add(spo_B30_E32); |
| rowsStoredExpected += 2; // intervals store two dates |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B02_E30))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B02_E30))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B30_E32))); |
| valueHash = hasher(valueHash, StringUtils.getBytesUtf8(StatementSerializer.writeStatement(spo_B30_E32))); |
| // duplicates will overwrite old ones, no change in the output except timestamps |
| statements.add(spo_B30_E32); |
| statements.add(spo_B30_E32); |
| |
| List<RyaStatement> ryaStatements = Lists.newArrayList(); |
| for (Statement s : statements){ ryaStatements.add(convertStatement(s));} |
| tIndexer.storeStatements(ryaStatements); |
| |
| Map<String, Long> statistics = new HashMap<String, Long>(); |
| int rowsStoredActual = printTables("junit testing: StoreStatements multiple statements", null, statistics); |
| Assert.assertEquals("Number of rows stored.", rowsStoredExpected, rowsStoredActual); // 4 index entries per statement |
| Assert.assertEquals("value hash.", valueHash, statistics.get(STAT_VALUEHASH).longValue()); |
| } |
| |
| /** |
| * test this classe's hash method to check un-ordered results. |
| */ |
| @Test |
| public void testSelfTestHashMethod() { |
| // self test on the hash method: |
| long hash01dup1 = hasher(0, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
| long hash01dup2 = hasher(0, new byte[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }); |
| Assert.assertEquals("same numbers, different sequence, hash should be the same.", hash01dup1, hash01dup2); |
| |
| // this one fails for sum hash, passes for XOR |
| long hash02dup1 = hasher(0, new byte[] { 123, 2, 1, 1 }); |
| hash02dup1 = hasher(hash02dup1, new byte[] { 123, 1, 1, 2 }); |
| long hash02dup2 = hasher(0, new byte[] { 123, 1, 1, 2 }); |
| hash02dup2 = hasher(hash02dup2, new byte[] { 123, 1, 3, 0, 0 }); |
| Assert.assertTrue("Different numbers, should be different hashes: " + hash02dup1 + " != " + hash02dup2, hash02dup1 != hash02dup2); |
| } |
| /** |
| * Test instant equal to a given instant. |
| * From the series: instant {equal, before, after} instant |
| * @throws AccumuloSecurityException |
| * @throws AccumuloException |
| * @throws TableNotFoundException |
| */ |
| @Test |
| public void testQueryInstantEqualsInstant() throws IOException, QueryEvaluationException, TableNotFoundException, AccumuloException, AccumuloSecurityException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| int expectedStoreCount = 5 * 2; // two entries for intervals |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time. |
| int searchForSeconds = 5; |
| int expectedResultCount = 1; |
| for (int s = 0; s <= searchForSeconds + 3; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| expectedStoreCount+=4; //4 entries per statement. |
| } |
| tIndexer.flush(); |
| |
| int rowsStoredActual = printTables("junit testing: testQueryInstantEqualsInstant 0 to 8 seconds and 5 intervals stored. expectedStoreCount="+expectedStoreCount, null /*System.out*/, null); |
| Assert.assertEquals("Should find count of rows.", expectedStoreCount, rowsStoredActual); |
| |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantEqualsInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS); // <== logic here |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[searchForSeconds]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| |
| } |
| |
| /** |
| * Test instant after a given instant. |
| * From the series: instant {equal, before, after} instant |
| * @throws AccumuloSecurityException |
| * @throws AccumuloException |
| * @throws TableNotFoundException |
| */ |
| @Test |
| public void testQueryInstantAfterInstant() throws IOException, QueryEvaluationException, TableNotFoundException, AccumuloException, AccumuloSecurityException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time. |
| int searchForSeconds = 4; |
| int expectedResultCount = 9; |
| for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantAfterInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[searchForSeconds + count + 1]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| /** |
| * Test instant before a given instant. |
| * From the series: instant {equal, before, after} instant |
| */ |
| @Test |
| public void testQueryInstantBeforeInstant() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time. |
| int searchForSeconds = 4; |
| int expectedResultCount = 4; |
| for (int s = 0; s <= searchForSeconds + 15; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| |
| iter = tIndexer.queryInstantBeforeInstant(seriesTs[searchForSeconds], EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[count]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| |
| /** |
| * Test instant before given interval. |
| * From the series: Instance {before, after, inside} given Interval |
| */ |
| @Test |
| public void testQueryInstantBeforeInterval() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time. |
| TemporalInterval searchForSeconds = tvB02_E31; |
| int expectedResultCount = 2; // 00 and 01 seconds. |
| for (int s = 0; s <= 40; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantBeforeInterval(searchForSeconds, EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[count]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| |
| /** |
| * Test instant after given interval. |
| * Instance {before, after, inside} given Interval |
| */ |
| @Test |
| public void testQueryInstantAfterInterval() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time. |
| TemporalInterval searchAfterInterval = tvB02_E31; // from 2 to 31 seconds |
| int endingSeconds = 31; |
| int expectedResultCount = 9; // 32,33,...,40 seconds. |
| for (int s = 0; s <= endingSeconds + expectedResultCount; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantAfterInterval(searchAfterInterval, EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[count + endingSeconds + 1]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| |
| /** |
| * Test instant inside given interval. |
| * Instance {before, after, inside} given Interval |
| */ |
| @Test |
| public void testQueryInstantInsideInterval() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time. |
| TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds |
| int beginningSeconds = 2; // <== logic here, and next few lines. |
| int endingSeconds = 31; |
| int expectedResultCount = endingSeconds - beginningSeconds - 1; // 3,4,...,30 seconds. |
| for (int s = 0; s <= 40; s++) { |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantInsideInterval(searchInsideInterval, EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[count + beginningSeconds + 1]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| /** |
| * Test instant is the Beginning of the given interval. |
| * from the series: Instance {hasBeginning, hasEnd} Interval |
| */ |
| @Test |
| public void testQueryInstantHasBeginningInterval() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time. |
| TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds |
| int searchSeconds = 2; // <== logic here, and next few lines. |
| int expectedResultCount = 1; // 2 seconds. |
| for (int s = 0; s <= 10; s++) { |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantHasBeginningInterval(searchInsideInterval, EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[searchSeconds]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| /** |
| * Test instant is the end of the given interval. |
| * from the series: Instance {hasBeginning, hasEnd} Interval |
| */ |
| @Test |
| public void testQueryInstantHasEndInterval() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instants for s seconds after the uniform time. |
| TemporalInterval searchInsideInterval = tvB02_E31; // from 2 to 31 seconds |
| int searchSeconds = 31; // <== logic here, and next few lines. |
| int expectedResultCount = 1; // 31 seconds. |
| for (int s = 0; s <= 40; s++) { |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryInstantHasEndInterval(searchInsideInterval, EMPTY_CONSTRAINTS); |
| int count = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| Statement nextExpectedStatement = seriesSpo[searchSeconds]; // <== logic here |
| assertTrue("Should match: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count++; |
| } |
| Assert.assertEquals("Should find count of rows.", expectedResultCount, count); |
| } |
| |
| /** |
| * Test method for |
| * {@link org.apache.rya.indexing.accumulo.temporal.AccumuloTemporalIndexer#queryIntervalEquals(TemporalInterval, StatementConstraints)} |
| * . |
| * @throws IOException |
| * @throws QueryEvaluationException |
| * |
| */ |
| @Test |
| public void testQueryIntervalEquals() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| tIndexer.storeStatement(convertStatement(seriesSpo[4])); // instance at 4 seconds |
| tIndexer.flush(); |
| |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryIntervalEquals(tvB02_E40, EMPTY_CONSTRAINTS); |
| // Should be found twice: |
| Assert.assertTrue("queryIntervalEquals: spo_B02_E40 should be found, but actually returned empty results. spo_B02_E40=" + spo_B02_E40, iter.hasNext()); |
| Assert.assertTrue("queryIntervalEquals: spo_B02_E40 should be found, but does not match.", spo_B02_E40.equals(iter.next())); |
| Assert.assertFalse("queryIntervalEquals: Find no more than one, but actually has more.", iter.hasNext()); |
| } |
| |
| /** |
| * Test interval before a given interval, for method: |
| * {@link AccumuloTemporalIndexer#queryIntervalBefore(TemporalInterval, StatementConstraints)}. |
| * |
| * @throws IOException |
| * @throws QueryEvaluationException |
| */ |
| @Test |
| public void testQueryIntervalBefore() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| tIndexer.storeStatement(convertStatement(spo_B00_E01)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| // instants should be ignored. |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| tIndexer.storeStatement(convertStatement(seriesSpo[1])); // instance at 1 seconds |
| tIndexer.storeStatement(convertStatement(seriesSpo[2])); |
| tIndexer.storeStatement(convertStatement(seriesSpo[31])); |
| tIndexer.flush(); |
| |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryIntervalBefore(tvB02_E31, EMPTY_CONSTRAINTS); |
| // Should be found twice: |
| Assert.assertTrue("spo_B00_E01 should be found, but actually returned empty results. spo_B00_E01=" + spo_B00_E01, iter.hasNext()); |
| Assert.assertTrue("spo_B00_E01 should be found, but found another.", spo_B00_E01.equals(iter.next())); |
| Assert.assertFalse("Find no more than one, but actually has more.", iter.hasNext()); |
| } |
| |
| /** |
| * interval is after the given interval. Find interval beginnings after the endings of the given interval. |
| * {@link AccumuloTemporalIndexer#queryIntervalAfter(TemporalInterval, StatementContraints). |
| * |
| * @throws IOException |
| * @throws QueryEvaluationException |
| */ |
| @Test |
| public void testQueryIntervalAfter() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| tIndexer.storeStatement(convertStatement(spo_B00_E01)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E29)); //<- after this one. |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B29_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| // instants should be ignored. |
| tIndexer.storeStatement(convertStatement(spo_B02)); |
| tIndexer.storeStatement(convertStatement(seriesSpo[1])); // instance at 1 seconds |
| tIndexer.storeStatement(convertStatement(seriesSpo[2])); |
| tIndexer.storeStatement(convertStatement(seriesSpo[31])); |
| tIndexer.flush(); |
| |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| iter = tIndexer.queryIntervalAfter(tvB02_E29, EMPTY_CONSTRAINTS); |
| // Should be found twice: |
| Assert.assertTrue("spo_B30_E32 should be found, but actually returned empty results. spo_B30_E32=" + spo_B30_E32, iter.hasNext()); |
| Statement s = iter.next(); |
| Assert.assertTrue("spo_B30_E32 should be found, but found another. spo_B30_E32="+spo_B30_E32+", but found="+s, spo_B30_E32.equals(s)); |
| Assert.assertFalse("Find no more than one, but actually has more.", iter.hasNext()); |
| |
| } |
| |
| /** |
| * Test instant after a given instant WITH two different predicates as constraints. |
| */ |
| @Test |
| public void testQueryWithMultiplePredicates() throws IOException, QueryEvaluationException { |
| // tiB02_E30 read as: Begins 2 seconds, ends at 30 seconds |
| // these should not match as they are not instances. |
| tIndexer.storeStatement(convertStatement(spo_B03_E20)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E30)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E40)); |
| tIndexer.storeStatement(convertStatement(spo_B02_E31)); |
| tIndexer.storeStatement(convertStatement(spo_B30_E32)); |
| |
| // seriesSpo[s] and seriesTs[s] are statements and instant for s seconds after the uniform time. |
| int searchForSeconds = 4; |
| int expectedResultCount = 9; |
| for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here |
| tIndexer.storeStatement(convertStatement(seriesSpo[s])); |
| } |
| ValueFactory vf = SimpleValueFactory.getInstance(); |
| IRI pred3_CIRCA_ = vf.createIRI(URI_PROPERTY_CIRCA); // this one to ignore. |
| IRI pred2_eventTime = vf.createIRI(URI_PROPERTY_EVENT_TIME); |
| IRI pred1_atTime = vf.createIRI(URI_PROPERTY_AT_TIME); |
| |
| // add the predicate = EventTime ; Store in an array for verification. |
| Statement[] SeriesTs_EventTime = new Statement[expectedResultCount+1]; |
| for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here |
| Statement statement = vf.createStatement(vf.createIRI("foo:EventTimeSubj0" + s), pred2_eventTime, vf.createLiteral(seriesTs[s].getAsReadable())); |
| tIndexer.storeStatement(convertStatement(statement)); |
| if (s>searchForSeconds) |
| SeriesTs_EventTime[s - searchForSeconds -1 ] = statement; |
| } |
| // add the predicate = CIRCA ; to be ignored because it is not in the constraints. |
| for (int s = 0; s <= searchForSeconds + expectedResultCount; s++) { // <== logic here |
| Statement statement = vf.createStatement(vf.createIRI("foo:CircaEventSubj0" + s), pred3_CIRCA_, vf.createLiteral(seriesTs[s].getAsReadable())); |
| tIndexer.storeStatement(convertStatement(statement)); |
| } |
| tIndexer.flush(); |
| CloseableIteration<Statement, QueryEvaluationException> iter; |
| StatementConstraints constraints = new StatementConstraints(); |
| constraints.setPredicates(new HashSet<IRI>(Arrays.asList( pred2_eventTime, pred1_atTime ))); |
| |
| iter = tIndexer.queryInstantAfterInstant(seriesTs[searchForSeconds], constraints); // EMPTY_CONSTRAINTS);// |
| int count_AtTime = 0; |
| int count_EventTime = 0; |
| while (iter.hasNext()) { |
| Statement s = iter.next(); |
| //System.out.println("testQueryWithMultiplePredicates result="+s); |
| Statement nextExpectedStatement = seriesSpo[searchForSeconds + count_AtTime + 1]; // <== logic here |
| if (s.getPredicate().equals(pred1_atTime)) { |
| assertTrue("Should match atTime: " + nextExpectedStatement + " == " + s, nextExpectedStatement.equals(s)); |
| count_AtTime++; |
| } |
| else if (s.getPredicate().equals(pred2_eventTime)) { |
| assertTrue("Should match eventTime: " + SeriesTs_EventTime[count_EventTime] + " == " + s, SeriesTs_EventTime[count_EventTime].equals(s)); |
| count_EventTime++; |
| } else { |
| assertTrue("This predicate should not be returned: "+s, false); |
| } |
| |
| } |
| |
| Assert.assertEquals("Should find count of atTime rows.", expectedResultCount, count_AtTime); |
| Assert.assertEquals("Should find count of eventTime rows.", expectedResultCount, count_EventTime); |
| } |
| |
| |
| /** |
| * Test method for {@link AccumuloTemporalIndexer#getIndexablePredicates()} . |
| * |
| * @throws TableExistsException |
| * @throws TableNotFoundException |
| * @throws AccumuloSecurityException |
| * @throws AccumuloException |
| * @throws IOException |
| */ |
| @Test |
| public void testGetIndexablePredicates() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException, IOException { |
| Set<IRI> p = tIndexer.getIndexablePredicates(); |
| Assert.assertEquals("number of predicates returned:", 3, p.size()); |
| } |
| |
| /** |
| * Count all the entries in the temporal index table, return the count. |
| * Uses printTables for reliability. |
| * |
| */ |
| public int countAllRowsInTable() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, NoSuchAlgorithmException { |
| return printTables("Counting rows.", null, null); |
| } |
| |
| /** |
| * Print and gather statistics on the entire index table. |
| * |
| * @param description |
| * Printed to the console to find the test case. |
| * @param out |
| * null or System.out or other output to send a listing. |
| * @param statistics |
| * Hashes, sums, and counts for assertions. |
| * @return Count of entries in the index table. |
| */ |
| public int printTables(String description, PrintStream out, Map<String, Long> statistics) |
| throws TableNotFoundException, AccumuloException, AccumuloSecurityException |
| { |
| if (out == null) { |
| out = new PrintStream(new NullOutputStream()); |
| } |
| out.println("-- start printTables() -- " + description); |
| String FORMAT = "%-20s %-20s %-40s %-40s\n"; |
| int rowsPrinted = 0; |
| long keyHasher = 0; |
| long valueHasher = 0; |
| final String indexTableName = tIndexer.getTableName(); |
| out.println("Reading : " + indexTableName); |
| out.format(FORMAT, "--Row--", "--ColumnFamily--", "--ColumnQualifier--", "--Value--"); |
| |
| Scanner s = ConfigUtils.getConnector(conf).createScanner(indexTableName, Authorizations.EMPTY); |
| for (Entry<Key, org.apache.accumulo.core.data.Value> entry : s) { |
| rowsPrinted++; |
| Key k = entry.getKey(); |
| out.format(FORMAT, toHumanString(k.getRow()), |
| toHumanString(k.getColumnFamily()), |
| toHumanString(k.getColumnQualifier()), |
| toHumanString(entry.getValue())); |
| keyHasher = hasher(keyHasher, (StringUtils.getBytesUtf8(entry.getKey().toStringNoTime()))); |
| valueHasher = hasher(valueHasher, (entry.getValue().get())); |
| } |
| out.println(); |
| |
| if (statistics != null) { |
| statistics.put(STAT_COUNT, (long) rowsPrinted); |
| statistics.put(STAT_KEYHASH, keyHasher); |
| statistics.put(STAT_VALUEHASH, valueHasher); |
| } |
| |
| return rowsPrinted; |
| |
| } |
| |
| /** |
| * Order independent hashcode. |
| * Read more: http://stackoverflow.com/questions/18021643/hashing-a-set-of-integers-in-an-order-independent-way |
| * |
| * @param hashcode |
| * @param list |
| * @return |
| */ |
| private static long hasher(long hashcode, byte[] list) { |
| long sum = 0; |
| for (byte val : list) { |
| sum += 1L + val; |
| } |
| hashcode ^= sum; |
| return hashcode; |
| } |
| |
| /** |
| * convert a non-utf8 byte[] and text and value to string and show unprintable bytes as {xx} where x is hex. |
| * @param value |
| * @return Human readable representation. |
| */ |
| static String toHumanString(Value value) { |
| return toHumanString(value==null?null:value.get()); |
| } |
| static String toHumanString(Text text) { |
| return toHumanString(text==null?null:text.copyBytes()); |
| } |
| static String toHumanString(byte[] bytes) { |
| if (bytes==null) |
| return "{null}"; |
| StringBuilder sb = new StringBuilder(); |
| for (byte b : bytes) { |
| if ((b > 0x7e) || (b < 32)) { |
| sb.append("{"); |
| sb.append(Integer.toHexString( b & 0xff )); // Lop off the sign extended ones. |
| sb.append("}"); |
| } else if (b == '{'||b == '}') { // Escape the literal braces. |
| sb.append("{"); |
| sb.append((char)b); |
| sb.append("}"); |
| } else |
| sb.append((char)b); |
| } |
| return sb.toString(); |
| } |
| } |