1 /*
2 * Copyright (c) 2015-2016, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30
31 #include <cstring>
32
33 #include "gtest/gtest.h"
34 #include "hs.h"
35 #include "test_util.h"
36
37 using namespace std;
38 using namespace testing;
39
TEST(ExtParam,LargeMinOffset)40 TEST(ExtParam, LargeMinOffset) {
41 hs_expr_ext ext;
42 memset(&ext, 0, sizeof(ext));
43 ext.min_offset = 100000;
44 ext.flags = HS_EXT_FLAG_MIN_OFFSET;
45
46 pattern p("hatstand.*teakettle", 0, 0, ext);
47 hs_database_t *db = buildDB(p, HS_MODE_NOSTREAM);
48 ASSERT_TRUE(db != nullptr);
49
50 hs_scratch_t *scratch = nullptr;
51 hs_error_t err = hs_alloc_scratch(db, &scratch);
52 ASSERT_EQ(HS_SUCCESS, err);
53 ASSERT_TRUE(scratch != nullptr);
54
55 CallBackContext c;
56
57 // First, scan a matching corpus that's shorter than our min_offset and
58 // ensure it doesn't match.
59 string corpus = "hatstand" + string(80000, '_') + "teakettle";
60 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
61 (void *)&c);
62 ASSERT_EQ(HS_SUCCESS, err);
63 ASSERT_EQ(0U, c.matches.size());
64
65 // Try exactly at the min_offset.
66 corpus = "hatstand" + string(99983, '_') + "teakettle";
67 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
68 (void *)&c);
69 ASSERT_EQ(HS_SUCCESS, err);
70 ASSERT_EQ(1U, c.matches.size());
71 ASSERT_EQ(MatchRecord(100000, 0), c.matches[0]);
72
73 err = hs_free_scratch(scratch);
74 ASSERT_EQ(HS_SUCCESS, err);
75 hs_free_database(db);
76 }
77
TEST(ExtParam,LargeExactOffset)78 TEST(ExtParam, LargeExactOffset) {
79 hs_expr_ext ext;
80 memset(&ext, 0, sizeof(ext));
81 ext.min_offset = 200000;
82 ext.max_offset = 200000;
83 ext.flags = HS_EXT_FLAG_MIN_OFFSET | HS_EXT_FLAG_MAX_OFFSET;
84
85 pattern p("hatstand.*teakettle", 0, 0, ext);
86 hs_database_t *db = buildDB(p, HS_MODE_NOSTREAM);
87 ASSERT_TRUE(db != nullptr);
88
89 hs_scratch_t *scratch = nullptr;
90 hs_error_t err = hs_alloc_scratch(db, &scratch);
91 ASSERT_EQ(HS_SUCCESS, err);
92 ASSERT_TRUE(scratch != nullptr);
93
94 CallBackContext c;
95
96 // First, scan a matching corpus that's shorter than our min_offset and
97 // ensure it doesn't match.
98 string corpus = "hatstand" + string(199982, '_') + "teakettle";
99 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
100 (void *)&c);
101 ASSERT_EQ(HS_SUCCESS, err);
102 ASSERT_EQ(0U, c.matches.size());
103
104 // Try the exact match.
105 corpus = "hatstand" + string(199983, '_') + "teakettle";
106 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
107 (void *)&c);
108 ASSERT_EQ(HS_SUCCESS, err);
109 ASSERT_EQ(1U, c.matches.size());
110 ASSERT_EQ(MatchRecord(200000, 0), c.matches[0]);
111
112 // Try one byte too far.
113 c.clear();
114 corpus = "hatstand" + string(199984, '_') + "teakettle";
115 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
116 (void *)&c);
117 ASSERT_EQ(HS_SUCCESS, err);
118 ASSERT_EQ(0U, c.matches.size());
119
120 err = hs_free_scratch(scratch);
121 ASSERT_EQ(HS_SUCCESS, err);
122 hs_free_database(db);
123 }
124
TEST(ExtParam,LargeMinLength)125 TEST(ExtParam, LargeMinLength) {
126 hs_expr_ext ext;
127 memset(&ext, 0, sizeof(ext));
128 ext.min_length = 100000;
129 ext.flags = HS_EXT_FLAG_MIN_LENGTH;
130
131 pattern p("hatstand.*teakettle", 0, 0, ext);
132 hs_database_t *db = buildDB(p, HS_MODE_NOSTREAM);
133 ASSERT_TRUE(db != nullptr);
134
135 hs_scratch_t *scratch = nullptr;
136 hs_error_t err = hs_alloc_scratch(db, &scratch);
137 ASSERT_EQ(HS_SUCCESS, err);
138 ASSERT_TRUE(scratch != nullptr);
139
140 CallBackContext c;
141
142 // First, scan a matching corpus that contains a match that's a bit too
143 // short.
144 string corpus = string(10000, '_') + "hatstand" + string(80000, '_') + "teakettle";
145 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
146 (void *)&c);
147 ASSERT_EQ(HS_SUCCESS, err);
148 ASSERT_EQ(0U, c.matches.size());
149
150 // Now, a match of the right length.
151 corpus = string(10000, '_') + "hatstand" + string(99983, '_') + "teakettle";
152 err = hs_scan(db, corpus.c_str(), corpus.length(), 0, scratch, record_cb,
153 (void *)&c);
154 ASSERT_EQ(HS_SUCCESS, err);
155 ASSERT_EQ(1U, c.matches.size());
156 ASSERT_EQ(MatchRecord(110000, 0), c.matches[0]);
157
158 err = hs_free_scratch(scratch);
159 ASSERT_EQ(HS_SUCCESS, err);
160 hs_free_database(db);
161 }
162