1*a3a45f30SXin Li // Copyright 2017 The Chromium OS Authors. All rights reserved.
2*a3a45f30SXin Li // Use of this source code is governed by a BSD-style license that can be
3*a3a45f30SXin Li // found in the LICENSE file.
4*a3a45f30SXin Li
5*a3a45f30SXin Li #include "bsdiff/suffix_array_index.h"
6*a3a45f30SXin Li
7*a3a45f30SXin Li #include <stdlib.h>
8*a3a45f30SXin Li
9*a3a45f30SXin Li #include <algorithm>
10*a3a45f30SXin Li #include <string>
11*a3a45f30SXin Li #include <utility>
12*a3a45f30SXin Li #include <vector>
13*a3a45f30SXin Li
14*a3a45f30SXin Li #include <gtest/gtest.h>
15*a3a45f30SXin Li
16*a3a45f30SXin Li namespace bsdiff {
17*a3a45f30SXin Li
18*a3a45f30SXin Li class SuffixArrayIndexTest : public ::testing::Test {
19*a3a45f30SXin Li protected:
InitSA(const std::string & text)20*a3a45f30SXin Li void InitSA(const std::string& text) {
21*a3a45f30SXin Li text_.resize(text.size());
22*a3a45f30SXin Li std::copy(text.begin(), text.end(), text_.data());
23*a3a45f30SXin Li sai_ = CreateSuffixArrayIndex(text_.data(), text_.size());
24*a3a45f30SXin Li }
25*a3a45f30SXin Li
SearchPrefix(const std::string & pattern,size_t * out_length,uint64_t * out_pos)26*a3a45f30SXin Li void SearchPrefix(const std::string& pattern,
27*a3a45f30SXin Li size_t* out_length,
28*a3a45f30SXin Li uint64_t* out_pos) {
29*a3a45f30SXin Li sai_->SearchPrefix(reinterpret_cast<const uint8_t*>(pattern.data()),
30*a3a45f30SXin Li pattern.size(), out_length, out_pos);
31*a3a45f30SXin Li // Check that the returned values are indeed a valid prefix.
32*a3a45f30SXin Li EXPECT_LE(*out_length, pattern.size());
33*a3a45f30SXin Li ASSERT_LT(*out_pos, text_.size());
34*a3a45f30SXin Li ASSERT_LE(*out_pos + *out_length, text_.size());
35*a3a45f30SXin Li EXPECT_EQ(0, memcmp(text_.data() + *out_pos, pattern.data(), *out_length));
36*a3a45f30SXin Li }
37*a3a45f30SXin Li
38*a3a45f30SXin Li std::vector<uint8_t> text_;
39*a3a45f30SXin Li std::unique_ptr<SuffixArrayIndexInterface> sai_;
40*a3a45f30SXin Li };
41*a3a45f30SXin Li
42*a3a45f30SXin Li // Test that the suffix array index can be initialized with an example text.
TEST_F(SuffixArrayIndexTest,MississippiTest)43*a3a45f30SXin Li TEST_F(SuffixArrayIndexTest, MississippiTest) {
44*a3a45f30SXin Li InitSA("mississippi");
45*a3a45f30SXin Li }
46*a3a45f30SXin Li
TEST_F(SuffixArrayIndexTest,EmptySuffixArrayTest)47*a3a45f30SXin Li TEST_F(SuffixArrayIndexTest, EmptySuffixArrayTest) {
48*a3a45f30SXin Li InitSA("");
49*a3a45f30SXin Li }
50*a3a45f30SXin Li
51*a3a45f30SXin Li // Test various corner cases while searching for prefixes.
TEST_F(SuffixArrayIndexTest,SearchPrefixTest)52*a3a45f30SXin Li TEST_F(SuffixArrayIndexTest, SearchPrefixTest) {
53*a3a45f30SXin Li InitSA("abc1_abc2_abc3_ab_abcd");
54*a3a45f30SXin Li
55*a3a45f30SXin Li uint64_t pos;
56*a3a45f30SXin Li size_t length;
57*a3a45f30SXin Li // The string is not found at all.
58*a3a45f30SXin Li SearchPrefix("zzz", &length, &pos); // lexicographically highest.
59*a3a45f30SXin Li EXPECT_EQ(0U, length);
60*a3a45f30SXin Li
61*a3a45f30SXin Li SearchPrefix(" ", &length, &pos); // lexicographically lowest.
62*a3a45f30SXin Li EXPECT_EQ(0U, length);
63*a3a45f30SXin Li
64*a3a45f30SXin Li // The exact pattern is found multiple times.
65*a3a45f30SXin Li SearchPrefix("abc", &length, &pos);
66*a3a45f30SXin Li EXPECT_EQ(3U, length);
67*a3a45f30SXin Li
68*a3a45f30SXin Li // The exact pattern is found only one time, at the end of the string.
69*a3a45f30SXin Li SearchPrefix("abcd", &length, &pos);
70*a3a45f30SXin Li EXPECT_EQ(4U, length);
71*a3a45f30SXin Li EXPECT_EQ(18U, pos);
72*a3a45f30SXin Li
73*a3a45f30SXin Li // The string is not found, but a prefix is found.
74*a3a45f30SXin Li SearchPrefix("abcW", &length, &pos);
75*a3a45f30SXin Li EXPECT_EQ(3U, length);
76*a3a45f30SXin Li }
77*a3a45f30SXin Li
78*a3a45f30SXin Li } // namespace bsdiff
79