/** * @return intersection of this group with specified * @see #intersect(BlocksGroup, BlocksGroup) */ public BlocksGroup intersect(BlocksGroup other) { return intersect(this, other); }
/** * @return true, if this group subsumed by specified group * @see #subsumedBy(BlocksGroup, BlocksGroup, int) */ public boolean subsumedBy(BlocksGroup other, int indexCorrection) { return subsumedBy(this, other, indexCorrection); }
/** * Factory method. * * @return new empty group */ public static BlocksGroup empty() { return new BlocksGroup(); }
/** * Given: * <pre> * c1: a[1-1] * c2: a[2-2] * </pre> * Expected: c1 not in c2, c2 not in c1 */ @Test public void start_index_in_C1_less_than_in_C2() { CloneGroup c1 = newCloneGroup(1, newClonePart("a", 1)); CloneGroup c2 = newCloneGroup(1, newClonePart("a", 2)); assertThat(Filter.containsIn(c1, c2), is(false)); }
@Test public void testIntersect() { BlocksGroup group1 = newBlocksGroup(newBlock("a", 1), newBlock("b", 2)); BlocksGroup group2 = newBlocksGroup(newBlock("a", 2), newBlock("b", 3)); BlocksGroup intersection = group1.intersect(group2); assertThat(intersection.size(), is(2)); }
/** * Performs detection and returns list of clone groups between file (which represented as a collection of blocks) and index. * Note that this method ignores blocks for this file, that will be retrieved from index. */ public static List<CloneGroup> detect(CloneIndex cloneIndex, Collection<Block> fileBlocks) { if (fileBlocks.isEmpty()) { return Collections.emptyList(); } OriginalCloneDetectionAlgorithm reporter = new OriginalCloneDetectionAlgorithm(cloneIndex); reporter.findClones(fileBlocks); return reporter.filter.getResult(); } }
@Test public void testSubsumedBy() { BlocksGroup group1 = newBlocksGroup(newBlock("a", 1), newBlock("b", 2)); BlocksGroup group2 = newBlocksGroup(newBlock("a", 2), newBlock("b", 3), newBlock("c", 4)); // block "c" from group2 does not have corresponding block in group1 assertThat(group2.subsumedBy(group1, 1), is(false)); }
@Test public void shouldReturnSize() { BlocksGroup group = newBlocksGroup(newBlock("a", 1), newBlock("b", 2)); assertThat(group.size(), is(2)); }
/** * Running time - O(N*2*C), where N - number of clones, which was found earlier and C - time of {@link #containsIn(CloneGroup, CloneGroup)}. */ public void add(CloneGroup current) { Iterator<CloneGroup> i = filtered.iterator(); while (i.hasNext()) { CloneGroup earlier = i.next(); // Note that following two conditions cannot be true together - proof by contradiction: // let C be the current clone and A and B were found earlier // then since relation is transitive - (A in C) and (C in B) => (A in B) // so A should be filtered earlier if (Filter.containsIn(current, earlier)) { // current clone fully covered by clone, which was found earlier return; } if (Filter.containsIn(earlier, current)) { // current clone fully covers clone, which was found earlier i.remove(); } } filtered.add(current); }
public static BlocksGroup newBlocksGroup(Block... blocks) { BlocksGroup result = BlocksGroup.empty(); for (Block block : blocks) { result.blocks.add(block); } return result; }
public List<Block[]> pairs(BlocksGroup other, int len) { return pairs(this, other, len); }
@Override protected List<CloneGroup> detect(CloneIndex index, Block[] fileBlocks) { return OriginalCloneDetectionAlgorithm.detect(index, Arrays.asList(fileBlocks)); }
/** * Given: * <pre> * c1: a[0-0], a[2-2], b[0-0], b[2-2] * c2: a[0-2], b[0-2] * </pre> * Expected: * <pre> * c1 in c2 (all parts of c1 covered by parts of c2 and all resources the same) * c2 not in c1 (not all parts of c2 covered by parts of c1 and all resources the same) * </pre> */ @Test public void one_part_of_C2_covers_two_parts_of_C1() { // Note that line numbers don't matter for method which we test. CloneGroup c1 = newCloneGroup(1, newClonePart("a", 0), newClonePart("a", 2), newClonePart("b", 0), newClonePart("b", 2)); CloneGroup c2 = newCloneGroup(3, newClonePart("a", 0), newClonePart("b", 0)); assertThat(Filter.containsIn(c1, c2), is(true)); assertThat(Filter.containsIn(c2, c1), is(false)); }
assertThat(newBlocksGroup(newBlock("a", 2), newBlock("b", 0)) .intersect(newBlocksGroup(newBlock("a", 3), newBlock("b", 1))) .size(), is(2)); assertThat(newBlocksGroup(newBlock("a", 3), newBlock("b", 1)) .intersect(newBlocksGroup(newBlock("a", 4), newBlock("b", 2), newBlock("c", 0))) .size(), is(2)); assertThat(newBlocksGroup(newBlock("a", 4), newBlock("b", 2)) .intersect(newBlocksGroup(newBlock("a", 5), newBlock("b", 3), newBlock("c", 1))) .size(), is(2)); assertThat(newBlocksGroup(newBlock("a", 5), newBlock("b", 3)) .intersect(newBlocksGroup(newBlock("a", 6), newBlock("c", 2))) .size(), is(1)); assertThat(newBlocksGroup(newBlock("a", 4), newBlock("b", 2), newBlock("c", 0)) .intersect(newBlocksGroup(newBlock("a", 5), newBlock("b", 3), newBlock("c", 1))) .size(), is(3)); assertThat(newBlocksGroup(newBlock("a", 5), newBlock("b", 3), newBlock("c", 1)) .intersect(newBlocksGroup(newBlock("a", 6), newBlock("c", 2))) .size(), is(2)); assertThat(newBlocksGroup(newBlock("a", 6), newBlock("c", 7)) .intersect(newBlocksGroup(newBlock("a", 7))) .size(), is(1));
@Test public void testSubsumedBy2() { BlocksGroup group1 = newBlocksGroup(newBlock("a", 1), newBlock("b", 2)); BlocksGroup group2 = newBlocksGroup(newBlock("a", 2), newBlock("b", 3)); BlocksGroup group3 = newBlocksGroup(newBlock("a", 3), newBlock("b", 4)); BlocksGroup group4 = newBlocksGroup(newBlock("a", 4), newBlock("b", 5)); assertThat(group2.subsumedBy(group1, 1), is(true)); // correction of index - 1 assertThat(group3.subsumedBy(group1, 2), is(true)); // correction of index - 2 assertThat(group3.subsumedBy(group2, 1), is(true)); // correction of index - 1 assertThat(group4.subsumedBy(group1, 3), is(true)); // correction of index - 3 assertThat(group4.subsumedBy(group2, 2), is(true)); // correction of index - 2 assertThat(group4.subsumedBy(group3, 1), is(true)); // correction of index - 1 }
/** * Given: * <pre> * c1: a[0-0], a[2-2] * c2: a[0-2], b[0-2] * </pre> * Expected: * <pre> * c1 not in c2 (all parts of c1 covered by parts of c2, but different resources) * c2 not in c1 (not all parts of c2 covered by parts of c1 and different resources) * </pre> */ @Test public void different_resources() { CloneGroup c1 = newCloneGroup(1, newClonePart("a", 0), newClonePart("a", 2)); CloneGroup c2 = newCloneGroup(3, newClonePart("a", 0), newClonePart("b", 0)); assertThat(Filter.containsIn(c1, c2), is(false)); assertThat(Filter.containsIn(c2, c1), is(false)); }
/** * Given: * <pre> * c1: a[2-2] * c2: a[0-1], a[2-3] * </pre> * Expected: * <pre> * c1 in c2 * c2 not in c1 * </pre> */ @Test public void second_part_of_C2_covers_first_part_of_C1() { CloneGroup c1 = newCloneGroup(1, newClonePart("a", 2)); CloneGroup c2 = newCloneGroup(2, newClonePart("a", 0), newClonePart("a", 2)); assertThat(Filter.containsIn(c1, c2), is(true)); assertThat(Filter.containsIn(c2, c1), is(false)); }
/** * Given: * <pre> * c1: a[1-1] * c2: a[1-1] * </pre> * Expected: * reflexive - c1 in c1, * antisymmetric - c1 in c2, c2 in c1, because c1 = c2 */ @Test public void reflexive_and_antisymmetric() { CloneGroup c1 = newCloneGroup(1, newClonePart("a", 1)); CloneGroup c2 = newCloneGroup(1, newClonePart("a", 1)); assertThat(Filter.containsIn(c1, c1), is(true)); assertThat(Filter.containsIn(c1, c2), is(true)); assertThat(Filter.containsIn(c2, c1), is(true)); }
/** * Given: * <pre> * c1: a[0-2] * c2: a[0-0] * </pre> * Expected: * <pre> * c1 not in c2 * </pre> */ @Test public void length_of_C1_bigger_than_length_of_C2() { CloneGroup c1 = spy(newCloneGroup(3, newClonePart("a", 0))); CloneGroup c2 = spy(newCloneGroup(1, newClonePart("a", 0))); assertThat(Filter.containsIn(c1, c2), is(false)); // containsIn method should check only origin and length - no need to compare all parts verify(c1).getCloneUnitLength(); verify(c2).getCloneUnitLength(); verifyNoMoreInteractions(c1); verifyNoMoreInteractions(c2); }