Package org.lilyproject.indexer.derefmap

Source Code of org.lilyproject.indexer.derefmap.DerefMapBasicTest

/*
* Copyright 2012 NGDATA nv
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.indexer.derefmap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.lilyproject.hadooptestfw.TestHelper;
import org.lilyproject.repository.api.AbsoluteRecordId;
import org.lilyproject.repository.api.IdGenerator;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.RecordId;
import org.lilyproject.repository.api.SchemaId;
import org.lilyproject.repository.impl.id.AbsoluteRecordIdImpl;
import org.lilyproject.repotestfw.RepositorySetup;
import org.lilyproject.util.hbase.LilyHBaseSchema.Table;
import org.lilyproject.util.io.Closer;

/**
* This tests the functionality of the {@link DerefMapHbaseImpl}. Note there is also a DerefMapIndexTest which
* tests it in real indexing scenario's.
*
*
*/
public class DerefMapBasicTest {
    private final static RepositorySetup repoSetup = new RepositorySetup();
    public static final String REPO_NAME = "DerefMapBasicTestRepo";

    private static IdGenerator ids;
    private static DerefMapHbaseImpl derefMap;

    private static int nextIdPrefix = 0;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        TestHelper.setupLogging("org.lilyproject.indexer");

        repoSetup.setupCore();
        repoSetup.setupRepository(REPO_NAME);
        LRepository repository = repoSetup.getRepositoryManager().getRepository(REPO_NAME);
        ids = repository.getIdGenerator();

        derefMap = (DerefMapHbaseImpl) DerefMapHbaseImpl.create(REPO_NAME,"test", repoSetup.getHadoopConf(), null, ids);
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        Closer.close(repoSetup);
    }

    private static AbsoluteRecordId absId(RecordId recordId) {
        return new AbsoluteRecordIdImpl(Table.RECORD.name, recordId);
    }

    @Test
    public void emptyDependencies() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId dummyField = ids.getSchemaId(UUID.randomUUID());
        final RecordId id1 = ids.newRecordId(idPrefix + "id1");

        final HashMap<DependencyEntry, Set<SchemaId>> empty =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        derefMap.updateDependants(absId(id1), dummyVtag, empty);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(id1), dummyVtag);
        assertTrue(found.isEmpty());

        final DependantRecordIdsIterator dependants = derefMap.findDependantsOf(absId(id1), dummyField, dummyVtag);
        assertFalse(dependants.hasNext());
    }

    @Test
    public void oneDependency() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId dependencyField = ids.getSchemaId(UUID.randomUUID());
        final SchemaId anotherField = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + idPrefix + "dependant");
        final RecordId dependency = ids.newRecordId(idPrefix + idPrefix + "dependency");
        final RecordId dependencyAfterUpdate = ids.newRecordId(idPrefix + idPrefix + "dependencyAfterUpdate");

        // the dependant depends on the dependencyField of the dependency
        final HashMap<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        dependencies.put(new DependencyEntry(absId(dependency)), Sets.newHashSet(dependencyField));
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(1, found.size());
        assertEquals(absId(dependency), found.iterator().next().getDependency());

        // check that the dependant is found as only dependant of the dependency via the dependencyField
        DependantRecordIdsIterator dependants =
                derefMap.findDependantsOf(absId(dependency), dependencyField, dummyVtag);
        assertTrue(dependants.hasNext());
        assertEquals(absId(dependant), dependants.next());
        assertFalse(dependants.hasNext());

        // idem but with a set of fields among which the dependencyField
        dependants = derefMap.findDependantsOf(absId(dependency), Sets.newHashSet(dependencyField, anotherField), dummyVtag);
        assertTrue(dependants.hasNext());
        assertEquals(absId(dependant), dependants.next());
        assertFalse(dependants.hasNext());

        // check that nothing is found as dependency of the dependant
        assertFalse(derefMap.findDependantsOf(absId(dependant), dependencyField, dummyVtag).hasNext());

        // check that nothing is found as dependency of the dependency via another field than the dependencyField
        assertFalse(derefMap.findDependantsOf(absId(dependency), anotherField, dummyVtag).hasNext());

        // now update the dependency to be from the dependant to the dependencyAfterUpdate (via the same field)
        final HashMap<DependencyEntry, Set<SchemaId>> updatedDependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        updatedDependencies
                .put(new DependencyEntry(absId(dependencyAfterUpdate)), Sets.newHashSet(dependencyField));
        derefMap.updateDependants(absId(dependant), dummyVtag, updatedDependencies);

        // consistency check
        final Set<DependencyEntry> foundAfterUpdate = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(1, foundAfterUpdate.size());
        assertEquals(absId(dependencyAfterUpdate), foundAfterUpdate.iterator().next().getDependency());

        // check that the dependant is found as only dependant of the dependencyAfterUpdate via the dependencyField
        final DependantRecordIdsIterator dependantsAfterUpdate =
                derefMap.findDependantsOf(absId(dependencyAfterUpdate), dependencyField, dummyVtag);
        assertTrue(dependantsAfterUpdate.hasNext());
        assertEquals(absId(dependant), dependantsAfterUpdate.next());
        assertFalse(dependantsAfterUpdate.hasNext());

        // check that nothing is found any longer as dependency on the previous dependency (from before the update)
        assertFalse(derefMap.findDependantsOf(absId(dependency), dependencyField, dummyVtag).hasNext());
    }

    @Test
    public void oneDependencyWithMoreDimensionedVariants() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x"));
        final RecordId dependency = ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x", "foo", "y"));

        // the dependant depends on the dependencyField of the dependency via a "+foo" dereferencing rule
        final HashMap<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        dependencies.put(new DependencyEntry(absId(dependency),
                ImmutableSet.of("foo")), Sets.<SchemaId>newHashSet());
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(1, found.size());
        final DependencyEntry foundDependencyEntry = found.iterator().next();
        assertEquals(absId(ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x"))), foundDependencyEntry.getDependency());
        assertEquals(Sets.newHashSet("foo"), foundDependencyEntry.getMoreDimensionedVariants());

        // check that the dependant is found as only dependant of the dependency (without specifying a field)
        DependantRecordIdsIterator dependants = derefMap.findDependantsOf(absId(dependency));
        assertTrue(dependants.hasNext());
        assertEquals(absId(dependant), dependants.next());
        assertFalse(dependants.hasNext());

        // check that other records (which would in reality not yet exist at index time) that match the "+foo" rule
        // are returned as dependants of our dependant (such that in reality reindexation of the dependant happens)

        final RecordId shouldTriggerOurDependant =
                ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x", "foo", "another-value"));
        dependants = derefMap.findDependantsOf(absId(shouldTriggerOurDependant));
        assertTrue(dependants.hasNext());
        assertEquals(absId(dependant), dependants.next());
        assertFalse(dependants.hasNext());

        // doesn't have the foo property
        final RecordId shouldNotTriggerOurDependant1 = ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant1)).hasNext());

        // doesn't have the bar property
        final RecordId shouldNotTriggerOurDependant2 = ids.newRecordId(idPrefix + "master", ImmutableMap.of("foo", "x"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant2)).hasNext());

        // wrong value for the bar property
        final RecordId shouldNotTriggerOurDependant3 =
                ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "y", "foo", "another-value"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant3)).hasNext());

        // additional unmatched property
        final RecordId shouldNotTriggerOurDependant4 =
                ids.newRecordId(idPrefix + "master", ImmutableMap.of("bar", "x", "foo", "another-value", "baz", "z"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant4)).hasNext());

        // another master
        final RecordId shouldNotTriggerOurDependant5 =
                ids.newRecordId(idPrefix + "another-master", ImmutableMap.of("bar", "x", "foo", "another-value"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant5)).hasNext());

        // wrong properties
        final RecordId shouldNotTriggerOurDependant6 = ids.newRecordId(idPrefix + "master", ImmutableMap.of("a", "b", "c", "d"));
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant6)).hasNext());

        // no properties
        final RecordId shouldNotTriggerOurDependant7 = ids.newRecordId(idPrefix + "master", ImmutableMap.<String, String>of());
        assertFalse(derefMap.findDependantsOf(absId(shouldNotTriggerOurDependant7)).hasNext());
    }

    /**
     * Simulates what would happen in case of a dereference expression like n:link1=>n:link2=>n:field.
     */
    @Test
    public void chainOfDependencies() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField1 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField2 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId field = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + "dependant");
        final RecordId dependency1 = ids.newRecordId(idPrefix + "dependency1");
        final RecordId dependency2 = ids.newRecordId(idPrefix + "dependency2");

        // scenario: dependant has linkField1 -> dependency1 which has linkField2 -> dependency2 which has field "field"
        final Map<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        // 1) dependant depends on dependency1 from which it uses linkField2
        dependencies.put(new DependencyEntry(absId(dependency1)), Sets.newHashSet(linkField2));
        // 2) dependant depends on dependency2 from which it uses field
        dependencies.put(new DependencyEntry(absId(dependency2)), Sets.newHashSet(field));
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(2, found.size());

        // check that the dependant is found as only dependant of the dependencies via the corresponding fields
        DependantRecordIdsIterator viaDependency1AndLinkField1 =
                derefMap.findDependantsOf(absId(dependency1), linkField1, dummyVtag);
        assertFalse(viaDependency1AndLinkField1.hasNext());

        DependantRecordIdsIterator viaDependency2AndLinkField1 =
                derefMap.findDependantsOf(absId(dependency2), linkField1, dummyVtag);
        assertFalse(viaDependency2AndLinkField1.hasNext());

        DependantRecordIdsIterator viaDependency1AndLinkField2 =
                derefMap.findDependantsOf(absId(dependency1), linkField2, dummyVtag);
        assertTrue(viaDependency1AndLinkField2.hasNext());
        assertEquals(absId(dependant), viaDependency1AndLinkField2.next());
        assertFalse(viaDependency1AndLinkField2.hasNext());

        DependantRecordIdsIterator viaDependency2AndLinkField2 =
                derefMap.findDependantsOf(absId(dependency2), linkField2, dummyVtag);
        assertFalse(viaDependency2AndLinkField2.hasNext());

        DependantRecordIdsIterator viaDependency2AndField =
                derefMap.findDependantsOf(absId(dependency2), field, dummyVtag);
        assertTrue(viaDependency2AndField.hasNext());
        assertEquals(absId(dependant), viaDependency2AndField.next());
        assertFalse(viaDependency2AndField.hasNext());

        DependantRecordIdsIterator viaDependency1WithoutSpecifyingField =
                derefMap.findDependantsOf(absId(dependency1));
        assertTrue(viaDependency1WithoutSpecifyingField.hasNext());
        assertEquals(absId(dependant), viaDependency1WithoutSpecifyingField.next());
        assertFalse(viaDependency1WithoutSpecifyingField.hasNext());

        DependantRecordIdsIterator viaDependency2WithoutSpecifyingField =
                derefMap.findDependantsOf(absId(dependency2));
        assertTrue(viaDependency2WithoutSpecifyingField.hasNext());
        assertEquals(absId(dependant), viaDependency2WithoutSpecifyingField.next());
        assertFalse(viaDependency2WithoutSpecifyingField.hasNext());
    }

    /**
     * Simulates what would happen in case of a dereference expression like n:link1=>n:link2=>n:link3.
     */
    @Test
    public void chainOfDependenciesWhichDoesNotEndInField() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField1 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField2 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField3 = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + "dependant");
        final RecordId dependency1 = ids.newRecordId(idPrefix + "dependency1");
        final RecordId dependency2 = ids.newRecordId(idPrefix + "dependency2");
        final RecordId dependency3 = ids.newRecordId(idPrefix + "dependency3");

        // scenario: dependant has linkField1 -> dependency1 which has linkField2 -> dependency2 which has linkField3 -> dependency3
        final Map<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        // 1) dependant depends on dependency1 from which it uses linkField2
        dependencies.put(new DependencyEntry(absId(dependency1)),
                Sets.newHashSet(linkField2));
        // 2) dependant depends on dependency2 from which it uses linkField3 which points to dependency3
        dependencies.put(new DependencyEntry(absId(dependency2)),
                Sets.newHashSet(linkField3));
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(2, found.size());

        // check that the dependant is found as only dependant of the dependencies via the corresponding fields
        DependantRecordIdsIterator viaDependency1AndLinkField2 =
                derefMap.findDependantsOf(absId(dependency1), linkField2, dummyVtag);
        assertTrue(viaDependency1AndLinkField2.hasNext());
        assertEquals(absId(dependant), viaDependency1AndLinkField2.next());
        assertFalse(viaDependency1AndLinkField2.hasNext());

        DependantRecordIdsIterator viaDependency2AndLinkField3 =
                derefMap.findDependantsOf(absId(dependency2), linkField3, dummyVtag);
        assertTrue(viaDependency2AndLinkField3.hasNext());
        assertEquals(absId(dependant), viaDependency2AndLinkField3.next());
        assertFalse(viaDependency2AndLinkField3.hasNext());
    }

    /**
     * Simulates what would happen in case of a dereference expression like +prop1=>n:link1=>+prop2=>n:field.
     */
    @Test
    public void chainOfDependenciesIncludingMoreDimensionedVariantProperties() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId linkField1 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId field = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + "dependant");
        final RecordId dependantWithProp1 = ids.newRecordId(idPrefix + "dependant", ImmutableMap.of("prop1", "x"));
        final RecordId dependency1 = ids.newRecordId(idPrefix + "dependency1");
        final RecordId dependency1WithProp2 = ids.newRecordId(idPrefix + "dependency1", ImmutableMap.of("prop2", "y"));

        // scenario: dependant depends on all dependant +prop1 records. One such a record (dependantWithProp1) exists
        // with a linkField1 pointing to dependency1. Via the +prop2 rule, we end up with all dependency1 + prop2
        // records, of which there is one instance (dependency1WithProp2). Of this instance, we use the field "field".
        final Map<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        // 1) dependant depends on all similar with prop1, of which it uses linkField1
        dependencies
                .put(new DependencyEntry(absId(dependant), ImmutableSet.of("prop1")), Sets.newHashSet(linkField1));
        // 2) dependant depends on dependency1WithProp2 (and all similar with prop2) from which it uses field "field"
        dependencies.put(new DependencyEntry(absId(dependency1WithProp2), ImmutableSet.of("prop2")),
                Sets.newHashSet(field));
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(2, found.size());

        // check that the dependant is found as only dependant of the dependencies via the corresponding fields (in a few scenarios)

        // scenario1: as if a dependency1 with prop2=value is being created
        final RecordId someRecordLikeDependency1WithProp2 =
                ids.newRecordId(idPrefix + "dependency1", ImmutableMap.of("prop2", "value"));
        DependantRecordIdsIterator scenario1 =
                derefMap.findDependantsOf(absId(someRecordLikeDependency1WithProp2), field, dummyVtag);
        assertTrue(scenario1.hasNext());
        assertEquals(absId(dependant), scenario1.next());
        assertFalse(scenario1.hasNext());

        // scenario2: as if a new record like dependant is created with prop1=value
        final RecordId someRecordLikeDependantWithProp1 =
                ids.newRecordId(idPrefix + "dependant", ImmutableMap.of("prop1", "value"));
        DependantRecordIdsIterator scenario2 =
                derefMap.findDependantsOf(absId(someRecordLikeDependantWithProp1), linkField1, dummyVtag);
        assertTrue(scenario2.hasNext());
        assertEquals(absId(dependant), scenario2.next());
        assertFalse(scenario2.hasNext());
    }

    @Test
    public void multipleDependencies() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId dependencyField = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant = ids.newRecordId(idPrefix + "dependant");
        final RecordId dependency1 = ids.newRecordId(idPrefix + "dependency1");
        final RecordId dependency2 = ids.newRecordId(idPrefix + "dependency2");

        // the dependant depends on the dependencyField of the dependency1 and dependency2
        final HashMap<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        dependencies.put(new DependencyEntry(absId(dependency1)), Sets.newHashSet(dependencyField));
        dependencies.put(new DependencyEntry(absId(dependency2)), Sets.newHashSet(dependencyField));
        derefMap.updateDependants(absId(dependant), dummyVtag, dependencies);

        // consistency check
        final Set<DependencyEntry> found = derefMap.findDependencies(absId(dependant), dummyVtag);
        assertEquals(2, found.size());

        // check that the dependant is found as only dependant of the dependency1 via the dependencyField
        final DependantRecordIdsIterator dependantsOf1 =
                derefMap.findDependantsOf(absId(dependency1), dependencyField, dummyVtag);
        assertTrue(dependantsOf1.hasNext());
        assertEquals(absId(dependant), dependantsOf1.next());
        assertFalse(dependantsOf1.hasNext());

        // check that the dependant is also found as only dependant of the dependency2 via the dependencyField
        final DependantRecordIdsIterator dependantsOf2 =
                derefMap.findDependantsOf(absId(dependency2), dependencyField, dummyVtag);
        assertTrue(dependantsOf2.hasNext());
        assertEquals(absId(dependant), dependantsOf2.next());
        assertFalse(dependantsOf2.hasNext());
    }

    @Test
    public void multipleVariantsDependingOnMaster() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId dependencyField = ids.getSchemaId(UUID.randomUUID());

        final RecordId master = ids.newRecordId(idPrefix + "myrecord");
        final RecordId v1variant = ids.newRecordId(idPrefix + "myrecord", Collections.singletonMap("v1", "x"));
        final RecordId v1v2variant = ids.newRecordId(idPrefix + "myrecord", map("v1", "x", "v2", "y"));

        final HashMap<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        dependencies.put(new DependencyEntry(absId(master)), Sets.newHashSet(dependencyField));
        derefMap.updateDependants(absId(v1variant), dummyVtag, dependencies);
        derefMap.updateDependants(absId(v1v2variant), dummyVtag, dependencies);

        Set<AbsoluteRecordId> recordIds = asRecordIds(derefMap.findDependantsOf(absId(master)));
        assertEquals(recordIds, Sets.newHashSet(absId(v1variant), absId(v1v2variant)));
    }

    @Test
    public void multipleDependants() throws Exception {
        String idPrefix = newIdPrefix();

        final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
        final SchemaId dependencyField = ids.getSchemaId(UUID.randomUUID());
        final RecordId dependant1 = ids.newRecordId(idPrefix + "dependant1");
        final RecordId dependant2 = ids.newRecordId(idPrefix + "dependant2");
        final RecordId dependency = ids.newRecordId(idPrefix + "dependency");

        // the dependant1 and dependant2 depend on the dependencyField of the dependency
        final HashMap<DependencyEntry, Set<SchemaId>> dependencies =
                new HashMap<DependencyEntry, Set<SchemaId>>();
        dependencies.put(new DependencyEntry(absId(dependency)),
                Sets.newHashSet(dependencyField));
        derefMap.updateDependants(absId(dependant1), dummyVtag, dependencies);
        derefMap.updateDependants(absId(dependant2), dummyVtag, dependencies);

        // consistency check dependant1
        final Set<DependencyEntry> dependenciesOf1 = derefMap.findDependencies(absId(dependant1), dummyVtag);
        assertEquals(1, dependenciesOf1.size());
        assertEquals(absId(dependency.getMaster()), dependenciesOf1.iterator().next().getDependency());

        // consistency check dependant2
        final Set<DependencyEntry> dependenciesOf2 = derefMap.findDependencies(absId(dependant1), dummyVtag);
        assertEquals(1, dependenciesOf2.size());
        assertEquals(absId(dependency.getMaster()), dependenciesOf2.iterator().next().getDependency());

        // check that both dependant1 and dependant2 are found as dependants of the dependency
        final DependantRecordIdsIterator dependants =
                derefMap.findDependantsOf(absId(dependency), dependencyField, dummyVtag);
        assertTrue(dependants.hasNext());
        final AbsoluteRecordId firstFoundDependant = dependants.next();
        assertTrue(dependants.hasNext());
        final AbsoluteRecordId secondFoundDependant = dependants.next();
        assertFalse(dependants.hasNext());

        // check that the two found dependants are dependant1 and dependant2 (order doesn't matter)
        assertTrue((absId(dependant1).equals(firstFoundDependant) && absId(dependant2).equals(secondFoundDependant)) ||
                (absId(dependant2).equals(firstFoundDependant) && absId(dependant1).equals(secondFoundDependant)));
    }

    @Test
    public void resultIndependentOfOrder() throws Exception {
        for (int i = 0; i < 10; i++) {
            final SchemaId dummyVtag = ids.getSchemaId(UUID.randomUUID());
            final SchemaId dependencyField = ids.getSchemaId(UUID.randomUUID());

            final RecordId master = ids.newRecordId();
            final RecordId var1 = ids.newRecordId(master, Collections.singletonMap("prop1", "x"));
            final RecordId var2 = ids.newRecordId(master, map("prop1", "x", "prop2", "y"));

            Set<SchemaId> fields = Sets.newHashSet(dependencyField);

            Map<DependencyEntry, Set<SchemaId>> dependencies = Maps.newHashMap();
            dependencies.put(new DependencyEntry(absId(master)), fields);
            dependencies.put(new DependencyEntry(absId(var2)), fields);

            derefMap.updateDependants(absId(var1), dummyVtag, dependencies);

            Set<AbsoluteRecordId> recordIds = asRecordIds(derefMap.findDependantsOf(absId(var2)));
            assertEquals("Iteration " + i, Sets.newHashSet(absId(var1)), recordIds);
        }
    }

    @Test
    public void twoVTagsDependingOnOneRecord() throws Exception {
        final SchemaId tag1 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId tag2 = ids.getSchemaId(UUID.randomUUID());
        final SchemaId field = ids.getSchemaId(UUID.randomUUID());
        final Set<SchemaId> fields = Sets.newHashSet(field);

        final RecordId a = ids.newRecordId();
        final RecordId b = ids.newRecordId();

        derefMap.updateDependants(absId(a), tag1,
                Collections.singletonMap(new DependencyEntry(absId(b)), fields));

        assertEquals(Sets.newHashSet(absId(a)), asRecordIds(derefMap.findDependantsOf(absId(b), field, tag1)));
        assertEquals(Sets.newHashSet(), asRecordIds(derefMap.findDependantsOf(absId(b), field, tag2)));

        derefMap.updateDependants(absId(a), tag2,
                Collections.singletonMap(new DependencyEntry(absId(b)), fields));

        assertEquals(Sets.newHashSet(absId(a)), asRecordIds(derefMap.findDependantsOf(
                                                absId(b), field, tag1)));
        assertEquals(Sets.newHashSet(absId(a)), asRecordIds(derefMap.findDependantsOf(
                                                absId(b), field, tag2)));
    }

    private Set<AbsoluteRecordId> asRecordIds(DependantRecordIdsIterator iter) throws IOException {
        Set<AbsoluteRecordId> result = Sets.newHashSet();
        while (iter.hasNext()) {
            result.add(iter.next());
        }
        return result;
    }

    private Map<String, String> map(String... keyOrValue) {
        Map<String, String> map = Maps.newHashMap();
        for (int i = 0; i < keyOrValue.length; i += 2) {
            map.put(keyOrValue[i], keyOrValue[i + 1]);
        }
        return map;
    }

    private String newIdPrefix() {
        return String.format("TEST%3d", nextIdPrefix++);
    }


}
TOP

Related Classes of org.lilyproject.indexer.derefmap.DerefMapBasicTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.