t_grep.sh revision 1.8 1 # $NetBSD: t_grep.sh,v 1.8 2024/11/23 09:38:02 rillig Exp $
2 #
3 # Copyright (c) 2008, 2009, 2021, 2024 The NetBSD Foundation, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26 #
27
28 atf_test_case basic
29 basic_head()
30 {
31 atf_set "descr" "Checks basic functionality"
32 }
33 basic_body()
34 {
35 atf_check -o file:"$(atf_get_srcdir)/d_basic.out" -x \
36 'jot 10000 | grep 123'
37 }
38
39 atf_test_case binary
40 binary_head()
41 {
42 atf_set "descr" "Checks handling of binary files"
43 }
44 binary_body()
45 {
46 dd if=/dev/zero count=1 of=test.file
47 echo -n "foobar" >> test.file
48 atf_check -o file:"$(atf_get_srcdir)/d_binary.out" grep foobar test.file
49 }
50
51 atf_test_case recurse
52 recurse_head()
53 {
54 atf_set "descr" "Checks recursive searching"
55 }
56 recurse_body()
57 {
58 mkdir -p recurse/a/f recurse/d
59 echo -e "cod\ndover sole\nhaddock\nhalibut\npilchard" > recurse/d/fish
60 echo -e "cod\nhaddock\nplaice" > recurse/a/f/favourite-fish
61
62 atf_check -o file:"$(atf_get_srcdir)/d_recurse.out" -x "grep -r haddock recurse | sort"
63 }
64
65 atf_test_case recurse_noarg
66 recurse_noarg_head()
67 {
68 atf_set "descr" "Checks recursive searching without file argument"
69 }
70 recurse_noarg_body()
71 {
72 mkdir -p recurse/a/f recurse/d
73 echo -e "cod\ndover sole\nhaddock\nhalibut\npilchard" > recurse/d/fish
74 echo -e "cod\nhaddock\nplaice" > recurse/a/f/favourite-fish
75
76 atf_check -o file:"$(atf_get_srcdir)/d_recurse_noarg.out" -x "cd recurse && grep -r haddock | sort"
77 }
78
79 atf_test_case recurse_symlink
80 recurse_symlink_head()
81 {
82 atf_set "descr" "Checks symbolic link recursion"
83 }
84 recurse_symlink_body()
85 {
86 mkdir -p test/c/d
87 (cd test/c/d && ln -s ../d .)
88 echo "Test string" > test/c/match
89
90 atf_check -o file:"$(atf_get_srcdir)/d_recurse_symlink.out" \
91 -e file:"$(atf_get_srcdir)/d_recurse_symlink.err" \
92 grep -r string test
93 }
94
95 atf_test_case word_regexps
96 word_regexps_head()
97 {
98 atf_set "descr" "Checks word-regexps"
99 }
100 word_regexps_body()
101 {
102 atf_check -o file:"$(atf_get_srcdir)/d_word_regexps.out" \
103 grep -w separated $(atf_get_srcdir)/d_input
104 }
105
106 atf_test_case word_locale
107 word_locale_head()
108 {
109 atf_set "descr" "Checks word search with locale"
110 }
111 word_locale_body()
112 {
113 echo "array[]" > "input"
114
115 # In the default locale, word search works.
116 atf_check -o file:"input" \
117 env LC_ALL=C grep "array" "input"
118 atf_check -o file:"input" \
119 env LC_ALL=C grep -w "array" "input"
120
121 # XXX: In an UTF-8 locale, GNU Grep treats '[' as a word character.
122 atf_check -s exit:1 -o empty \
123 env LC_ALL="C.UTF-8" grep -w "array" "input"
124 }
125
126 atf_test_case word_in_line
127 word_in_line_head()
128 {
129 atf_set "descr" "Checks word search in different locations of a line"
130 }
131 word_in_line_body()
132 {
133 # See usr.bin/grep/util.c, "Check for whole word match", which
134 # looks suspiciously wrong. And indeed, NetBSD grep does not
135 # survive this test. GNU Grep does.
136
137 echo "begin middle end" > "input"
138
139 # A word at the beginning of a line is found.
140 atf_check -o file:"input" \
141 env LC_ALL=C grep -w "begin" "input"
142
143 # A word in the middle of a line is found.
144 atf_check -o file:"input" \
145 env LC_ALL=C grep -w "middle" "input"
146
147 # A word at the end of a line is found.
148 atf_check -o file:"input" \
149 env LC_ALL=C grep -w "end" "input"
150
151 # A subword at the beginning of a line is not found.
152 atf_check -s exit:1 -o empty \
153 env LC_ALL=C grep -w "be" "input"
154
155 # A subword in the middle of a line is not found.
156 atf_check -s exit:1 -o empty \
157 env LC_ALL=C grep -w "mid" "input"
158 atf_check -s exit:1 -o empty \
159 env LC_ALL=C grep -w "dle" "input"
160
161 # A subword at the end of a line is not found.
162 atf_check -s exit:1 -o empty \
163 env LC_ALL=C grep -w "nd" "input"
164 }
165
166 atf_test_case word_in_line_utf8
167 word_in_line_utf8_head()
168 {
169 atf_set "descr" "Checks word search at the beginning of a line"
170 }
171 word_in_line_utf8_body()
172 {
173 # See usr.bin/grep/util.c, "Check for whole word match", which
174 # looks suspiciously wrong. And indeed, NetBSD grep does not
175 # survive this test. GNU Grep does.
176
177 echo "begin middle end" > "input"
178
179 # A word at the beginning of a line is found.
180 atf_check -o file:"input" \
181 env LC_ALL="C.UTF-8" grep -w "begin" "input"
182
183 # A word in the middle of a line is found.
184 atf_check -o file:"input" \
185 env LC_ALL="C.UTF-8" grep -w "middle" "input"
186
187 # A word at the end of a line is found.
188 atf_check -o file:"input" \
189 env LC_ALL="C.UTF-8" grep -w "end" "input"
190
191 # A subword at the beginning of a line is not found.
192 atf_check -s exit:1 -o empty \
193 env LC_ALL="C.UTF-8" grep -w "be" "input"
194
195 # A subword in the middle of a line is not found.
196 atf_check -s exit:1 -o empty \
197 env LC_ALL="C.UTF-8" grep -w "mid" "input"
198 atf_check -s exit:1 -o empty \
199 env LC_ALL="C.UTF-8" grep -w "dle" "input"
200
201 # A subword at the end of a line is not found.
202 atf_check -s exit:1 -o empty \
203 env LC_ALL="C.UTF-8" grep -w "nd" "input"
204 }
205
206 atf_test_case begin_end
207 begin_end_head()
208 {
209 atf_set "descr" "Checks handling of line beginnings and ends"
210 }
211 begin_end_body()
212 {
213 atf_check -o file:"$(atf_get_srcdir)/d_begin_end_a.out" \
214 grep ^Front "$(atf_get_srcdir)/d_input"
215
216 atf_check -o file:"$(atf_get_srcdir)/d_begin_end_b.out" \
217 grep ending$ "$(atf_get_srcdir)/d_input"
218 }
219
220 atf_test_case ignore_case
221 ignore_case_head()
222 {
223 atf_set "descr" "Checks ignore-case option"
224 }
225 ignore_case_body()
226 {
227 atf_check -o file:"$(atf_get_srcdir)/d_ignore_case.out" \
228 grep -i Upper "$(atf_get_srcdir)/d_input"
229 }
230
231 atf_test_case invert
232 invert_head()
233 {
234 atf_set "descr" "Checks selecting non-matching lines with -v option"
235 }
236 invert_body()
237 {
238 atf_check -o file:"$(atf_get_srcdir)/d_invert.out" \
239 grep -v fish "$(atf_get_srcdir)/d_invert.in"
240 }
241
242 atf_test_case whole_line
243 whole_line_head()
244 {
245 atf_set "descr" "Checks whole-line matching with -x flag"
246 }
247 whole_line_body()
248 {
249 atf_check -o file:"$(atf_get_srcdir)/d_whole_line.out" \
250 grep -x matchme "$(atf_get_srcdir)/d_input"
251 }
252
253 atf_test_case negative
254 negative_head()
255 {
256 atf_set "descr" "Checks handling of files with no matches"
257 }
258 negative_body()
259 {
260 atf_check -s ne:0 grep "not a hope in hell" "$(atf_get_srcdir)/d_input"
261 }
262
263 atf_test_case context
264 context_head()
265 {
266 atf_set "descr" "Checks displaying context with -A, -B and -C flags"
267 }
268 context_body()
269 {
270 cp $(atf_get_srcdir)/d_context_*.* .
271
272 atf_check -o file:d_context_a.out grep -C2 bamboo d_context_a.in
273 atf_check -o file:d_context_b.out grep -A3 tilt d_context_a.in
274 atf_check -o file:d_context_c.out grep -B4 Whig d_context_a.in
275 atf_check -o file:d_context_d.out grep -C1 pig d_context_a.in d_context_b.in
276 }
277
278 atf_test_case file_exp
279 file_exp_head()
280 {
281 atf_set "descr" "Checks reading expressions from file"
282 }
283 file_exp_body()
284 {
285 atf_check -o file:"$(atf_get_srcdir)/d_file_exp.out" -x \
286 'jot 21 -1 1.00 | grep -f '"$(atf_get_srcdir)"'/d_file_exp.in'
287 }
288
289 atf_test_case egrep
290 egrep_head()
291 {
292 atf_set "descr" "Checks matching special characters with egrep"
293 }
294 egrep_body()
295 {
296 atf_check -o file:"$(atf_get_srcdir)/d_egrep.out" \
297 egrep '\?|\*$$' "$(atf_get_srcdir)/d_input"
298 }
299
300 atf_test_case zgrep
301 zgrep_head()
302 {
303 atf_set "descr" "Checks handling of gzipped files with zgrep"
304 }
305 zgrep_body()
306 {
307 cp "$(atf_get_srcdir)/d_input" .
308 gzip d_input || atf_fail "gzip failed"
309
310 atf_check -o file:"$(atf_get_srcdir)/d_zgrep.out" zgrep -h line d_input.gz
311 }
312
313 atf_test_case nonexistent
314 nonexistent_head()
315 {
316 atf_set "descr" "Checks that -s flag suppresses error" \
317 "messages about nonexistent files"
318 }
319 nonexistent_body()
320 {
321 atf_check -s ne:0 grep -s foobar nonexistent
322 }
323
324 atf_test_case context2
325 context2_head()
326 {
327 atf_set "descr" "Checks displaying context with -z flag"
328 }
329 context2_body()
330 {
331 printf "haddock\000cod\000plaice\000" > test1
332 printf "mackeral\000cod\000crab\000" > test2
333
334 atf_check -o file:"$(atf_get_srcdir)/d_context2_a.out" \
335 grep -z -A1 cod test1 test2
336
337 atf_check -o file:"$(atf_get_srcdir)/d_context2_b.out" \
338 grep -z -B1 cod test1 test2
339
340 atf_check -o file:"$(atf_get_srcdir)/d_context2_c.out" \
341 grep -z -C1 cod test1 test2
342 }
343
344 atf_test_case pr_58849
345 pr_58849_head()
346 {
347 atf_set "descr" "Checks overlapping patterns in whole-line search"
348 }
349 pr_58849_body()
350 {
351 printf '%s\n' __bss_start__ __bss_end__ hello > input
352
353 # The line '__bss_end__' must not occur in the output.
354 atf_check -o inline:'__bss_start__\nhello\n' \
355 grep -Fvx -e _end -e __bss_end__ input
356
357 # Listing the most specific pattern first works around PR bin/58849.
358 atf_check -o inline:'__bss_start__\nhello\n' \
359 grep -Fvx -e __bss_end__ -e _end input
360 }
361
362 atf_init_test_cases()
363 {
364 atf_add_test_case basic
365 atf_add_test_case binary
366 atf_add_test_case recurse
367 atf_add_test_case recurse_noarg
368 atf_add_test_case recurse_symlink
369 atf_add_test_case word_regexps
370 atf_add_test_case word_locale
371 atf_add_test_case word_in_line
372 atf_add_test_case word_in_line_utf8
373 atf_add_test_case begin_end
374 atf_add_test_case ignore_case
375 atf_add_test_case invert
376 atf_add_test_case whole_line
377 atf_add_test_case negative
378 atf_add_test_case context
379 atf_add_test_case file_exp
380 atf_add_test_case egrep
381 atf_add_test_case zgrep
382 atf_add_test_case nonexistent
383 atf_add_test_case context2
384 atf_add_test_case pr_58849
385 }
386