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