@Test
public void clique() throws Exception {

    final JoinedRecordTypeBuilder clique = metaDataBuilder.addJoinedRecordType("Clique");
    clique.addConstituent("type_a", "TypeA");
    clique.addConstituent("type_b", "TypeB");
    clique.addConstituent("type_c", "TypeC");
    clique.addJoin("type_a", "type_b_rec_no", "type_b", "rec_no");
    clique.addJoin("type_b", "type_c_rec_no", "type_c", "rec_no");
    clique.addJoin("type_c", "type_a_rec_no", "type_a", "rec_no");
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
        for (int i = 0; i < 3; i++) {
            TestRecordsJoinIndexProto.TypeA.Builder typeA = TestRecordsJoinIndexProto.TypeA.newBuilder();
            typeA.setRecNo(100 + i).setTypeBRecNo(200 + i);
            recordStore.saveRecord(typeA.build());
            TestRecordsJoinIndexProto.TypeB.Builder typeB = TestRecordsJoinIndexProto.TypeB.newBuilder();
            typeB.setRecNo(200 + i).setTypeCRecNo(300 + i);
            recordStore.saveRecord(typeB.build());
            TestRecordsJoinIndexProto.TypeC.Builder typeC = TestRecordsJoinIndexProto.TypeC.newBuilder();
            typeC.setRecNo(300 + i).setTypeARecNo(100 + i);
            recordStore.saveRecord(typeC.build());
        }
        context.commit();
    }
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
        final SyntheticRecordPlanner planner = new SyntheticRecordPlanner(recordStore);
        SyntheticRecordPlan plan1 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("Clique"));
        Multiset<Tuple> expected1 = ImmutableMultiset.of(
                Tuple.from(-1, Tuple.from(100), Tuple.from(200), Tuple.from(300)),
                Tuple.from(-1, Tuple.from(101), Tuple.from(201), Tuple.from(301)),
                Tuple.from(-1, Tuple.from(102), Tuple.from(202), Tuple.from(302)));
        Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected1, results1);
        // Make sure that the extra join condition is checked.
        TestRecordsJoinIndexProto.TypeC.Builder typeC = TestRecordsJoinIndexProto.TypeC.newBuilder();
        typeC.setRecNo(301).setTypeARecNo(999);
        recordStore.saveRecord(typeC.build());
        
        SyntheticRecordPlan plan2 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("Clique"));
        Multiset<Tuple> expected2 = ImmutableMultiset.of(
                Tuple.from(-1, Tuple.from(100), Tuple.from(200), Tuple.from(300)),
                Tuple.from(-1, Tuple.from(102), Tuple.from(202), Tuple.from(302)));
        Multiset<Tuple> results2 = HashMultiset.create(plan2.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected2, results2);
    }
}