1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
//===- unittests/Support/SuffixTreeTest.cpp - suffix tree tests -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/SuffixTree.h"
#include "gtest/gtest.h"
#include <vector>
using namespace llvm;
namespace {
// Each example vector has a unique element at the end to represent the end of
// the string
// Tests that The SuffixTree finds a simple repetition of the substring {1, 2}
// {1, 2} twice in the provided string.
TEST(SuffixTreeTest, TestSingleRepetition) {
std::vector<unsigned> SimpleRepetitionData = {1, 2, 1, 2, 3};
SuffixTree ST(SimpleRepetitionData);
std::vector<SuffixTree::RepeatedSubstring> SubStrings;
for (auto It = ST.begin(); It != ST.end(); It++)
SubStrings.push_back(*It);
ASSERT_EQ(SubStrings.size(), 1u);
EXPECT_EQ(SubStrings[0].Length, 2u);
EXPECT_EQ(SubStrings[0].StartIndices.size(), 2u);
for (unsigned StartIdx : SubStrings[0].StartIndices) {
EXPECT_EQ(SimpleRepetitionData[StartIdx], 1u);
EXPECT_EQ(SimpleRepetitionData[StartIdx + 1], 2u);
}
}
// Tests that the SuffixTree is able to find the substrings {1, 2, 3} at
// at indices 0 and 3 as well as the substrings {2, 3} at indices 1 and 4.
// This test also serves as a flag for improvements to the suffix tree.
//
// FIXME: Right now, the longest repeated substring from a specific index is
// returned, this could be improved to return the longest repeated substring, as
// well as those that are smaller.
TEST(SuffixTreeTest, TestLongerRepetition) {
std::vector<unsigned> RepeatedRepetitionData = {1, 2, 3, 1, 2, 3, 4};
SuffixTree ST(RepeatedRepetitionData);
std::vector<SuffixTree::RepeatedSubstring> SubStrings;
for (auto It = ST.begin(); It != ST.end(); It++)
SubStrings.push_back(*It);
EXPECT_EQ(SubStrings.size(), 2u);
unsigned Len;
for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
Len = RS.Length;
bool IsExpectedLen = (Len == 3u || Len == 2u);
bool IsExpectedIndex;
ASSERT_TRUE(IsExpectedLen);
if (Len == 3u) {
for (unsigned StartIdx : RS.StartIndices) {
IsExpectedIndex = (StartIdx == 0u || StartIdx == 3u);
EXPECT_TRUE(IsExpectedIndex);
EXPECT_EQ(RepeatedRepetitionData[StartIdx], 1u);
EXPECT_EQ(RepeatedRepetitionData[StartIdx + 1], 2u);
EXPECT_EQ(RepeatedRepetitionData[StartIdx + 2], 3u);
}
} else {
for (unsigned StartIdx : RS.StartIndices) {
IsExpectedIndex = (StartIdx == 1u || StartIdx == 4u);
EXPECT_TRUE(IsExpectedIndex);
EXPECT_EQ(RepeatedRepetitionData[StartIdx], 2u);
EXPECT_EQ(RepeatedRepetitionData[StartIdx + 1], 3u);
}
}
}
}
// Tests that the SuffixTree is able to find substring {1, 1, 1, 1, 1} at
// indices 0 and 1.
//
// FIXME: Add support for detecting {1, 1} and {1, 1, 1}
TEST(SuffixTreeTest, TestSingleCharacterRepeat) {
std::vector<unsigned> RepeatedRepetitionData = {1, 1, 1, 1, 1, 1, 2};
std::vector<unsigned>::iterator RRDIt, RRDIt2;
SuffixTree ST(RepeatedRepetitionData);
std::vector<SuffixTree::RepeatedSubstring> SubStrings;
for (auto It = ST.begin(); It != ST.end(); It++)
SubStrings.push_back(*It);
EXPECT_EQ(SubStrings.size(), 1u);
for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
EXPECT_EQ(RS.StartIndices.size(),
RepeatedRepetitionData.size() - RS.Length);
for (unsigned StartIdx : SubStrings[0].StartIndices) {
RRDIt = RRDIt2 = RepeatedRepetitionData.begin();
std::advance(RRDIt, StartIdx);
std::advance(RRDIt2, StartIdx + SubStrings[0].Length);
ASSERT_TRUE(
all_of(make_range<std::vector<unsigned>::iterator>(RRDIt, RRDIt2),
[](unsigned Elt) { return Elt == 1; }));
}
}
}
// The suffix tree cannot currently find repeated substrings in strings of the
// form {1, 2, 3, 1, 2, 3}, because the two {1, 2, 3}s are adjacent ("tandem
// repeats")
//
// FIXME: Teach the SuffixTree to recognize these cases.
TEST(SuffixTreeTest, TestTandemRepeat) {
std::vector<unsigned> RepeatedRepetitionData = {1, 2, 3, 1, 2, 3};
SuffixTree ST(RepeatedRepetitionData);
std::vector<SuffixTree::RepeatedSubstring> SubStrings;
for (auto It = ST.begin(); It != ST.end(); It++)
SubStrings.push_back(*It);
EXPECT_EQ(SubStrings.size(), 0u);
}
// Tests that the SuffixTree does not erroneously include values that are not
// in repeated substrings. That is, only finds {1, 1} at indices 0 and 3 and
// does not include 2 and 3.
TEST(SuffixTreeTest, TestExclusion) {
std::vector<unsigned> RepeatedRepetitionData = {1, 1, 2, 1, 1, 3};
std::vector<unsigned>::iterator RRDIt, RRDIt2;
SuffixTree ST(RepeatedRepetitionData);
std::vector<SuffixTree::RepeatedSubstring> SubStrings;
for (auto It = ST.begin(); It != ST.end(); It++)
SubStrings.push_back(*It);
EXPECT_EQ(SubStrings.size(), 1u);
bool IsExpectedIndex;
for (SuffixTree::RepeatedSubstring &RS : SubStrings) {
for (unsigned StartIdx : RS.StartIndices) {
IsExpectedIndex = (StartIdx == 0u || StartIdx == 3u);
EXPECT_TRUE(IsExpectedIndex);
RRDIt = RRDIt2 = RepeatedRepetitionData.begin();
std::advance(RRDIt, StartIdx);
std::advance(RRDIt2, StartIdx + RS.Length);
EXPECT_TRUE(
all_of(make_range<std::vector<unsigned>::iterator>(RRDIt, RRDIt2),
[](unsigned Elt) { return Elt == 1; }));
}
}
}
} // namespace
|