1dad64f0eSDag-Erling Smørgrav# 2dad64f0eSDag-Erling Smørgrav# Copyright (c) 2023 Klara, Inc. 3dad64f0eSDag-Erling Smørgrav# 4dad64f0eSDag-Erling Smørgrav# SPDX-License-Identifier: BSD-2-Clause 5dad64f0eSDag-Erling Smørgrav# 6dad64f0eSDag-Erling Smørgrav 7dad64f0eSDag-Erling Smørgrav# 8dad64f0eSDag-Erling Smørgrav# These tests need to run in a multibyte locale with non-localized 9dad64f0eSDag-Erling Smørgrav# error messages. 10dad64f0eSDag-Erling Smørgrav# 11dad64f0eSDag-Erling Smørgravexport LC_CTYPE=C.UTF-8 12dad64f0eSDag-Erling Smørgravexport LC_MESSAGES=C 13dad64f0eSDag-Erling Smørgrav 14dad64f0eSDag-Erling Smørgrav# 15*5c870e1bSDag-Erling Smørgrav# Size of wc's read buffer. 16*5c870e1bSDag-Erling Smørgrav# 17*5c870e1bSDag-Erling SmørgravMAXBSIZE=65536 18*5c870e1bSDag-Erling Smørgrav 19*5c870e1bSDag-Erling Smørgrav# 20dad64f0eSDag-Erling Smørgrav# Sample text containing multibyte characters 21dad64f0eSDag-Erling Smørgrav# 22dad64f0eSDag-Erling Smørgravtv="Der bode en underlig gråsprængt en 23dad64f0eSDag-Erling Smørgravpå den yderste nøgne ø; – 24dad64f0eSDag-Erling Smørgravhan gjorde visst intet menneske mén 25dad64f0eSDag-Erling Smørgravhverken på land eller sjø; 26dad64f0eSDag-Erling Smørgravdog stundom gnistred hans øjne stygt, – 27dad64f0eSDag-Erling Smørgravhelst mod uroligt vejr, – 28dad64f0eSDag-Erling Smørgravog da mente folk, at han var forrykt, 29dad64f0eSDag-Erling Smørgravog da var der få, som uden frykt 30dad64f0eSDag-Erling Smørgravkom Terje Vigen nær. 31dad64f0eSDag-Erling Smørgrav" 32dad64f0eSDag-Erling Smørgravtvl=10 33dad64f0eSDag-Erling Smørgravtvw=55 34dad64f0eSDag-Erling Smørgravtvc=300 35dad64f0eSDag-Erling Smørgravtvm=283 36dad64f0eSDag-Erling SmørgravtvcL=42 37dad64f0eSDag-Erling SmørgravtvmL=39 38dad64f0eSDag-Erling Smørgrav 39dad64f0eSDag-Erling Smørgrav# 40dad64f0eSDag-Erling Smørgrav# Run a series of tests using the same input file. The first argument 41dad64f0eSDag-Erling Smørgrav# is the name of the file. The next three are the expected line, 42dad64f0eSDag-Erling Smørgrav# word, and byte counts. The optional fifth is the expected character 43dad64f0eSDag-Erling Smørgrav# count; if not provided, it is expected to be identical to the byte 44dad64f0eSDag-Erling Smørgrav# count. 45dad64f0eSDag-Erling Smørgrav# 46dad64f0eSDag-Erling Smørgravatf_check_wc() { 47dad64f0eSDag-Erling Smørgrav local file="$1" 48dad64f0eSDag-Erling Smørgrav local l="$2" 49dad64f0eSDag-Erling Smørgrav local w="$3" 50dad64f0eSDag-Erling Smørgrav local c="$4" 51dad64f0eSDag-Erling Smørgrav local m="${5-$4}" 52dad64f0eSDag-Erling Smørgrav 53dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${l} +${w} +${c}\$" wc <"${file}" 54dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${l}\$" wc -l <"${file}" 55dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${w}\$" wc -w <"${file}" 56dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${c}\$" wc -c <"${file}" 57dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${m}\$" wc -m <"${file}" 58dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${l} +${w} +${c} ${file}\$" wc "$file" 59dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${l} ${file}\$" wc -l "$file" 60dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${w} ${file}\$" wc -w "$file" 61dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${c} ${file}\$" wc -c "$file" 62dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +${m} ${file}\$" wc -m "$file" 63dad64f0eSDag-Erling Smørgrav} 64dad64f0eSDag-Erling Smørgrav 65dad64f0eSDag-Erling Smørgravatf_test_case basic 66dad64f0eSDag-Erling Smørgravbasic_head() 67dad64f0eSDag-Erling Smørgrav{ 68dad64f0eSDag-Erling Smørgrav atf_set "descr" "Basic test case" 69dad64f0eSDag-Erling Smørgrav} 70dad64f0eSDag-Erling Smørgravbasic_body() 71dad64f0eSDag-Erling Smørgrav{ 72dad64f0eSDag-Erling Smørgrav printf "a b\n" >foo 73dad64f0eSDag-Erling Smørgrav atf_check_wc foo 1 2 4 74dad64f0eSDag-Erling Smørgrav} 75dad64f0eSDag-Erling Smørgrav 76dad64f0eSDag-Erling Smørgravatf_test_case blank 77dad64f0eSDag-Erling Smørgravblank_head() 78dad64f0eSDag-Erling Smørgrav{ 79dad64f0eSDag-Erling Smørgrav atf_set "descr" "Input containing only blank lines" 80dad64f0eSDag-Erling Smørgrav} 81dad64f0eSDag-Erling Smørgravblank_body() 82dad64f0eSDag-Erling Smørgrav{ 83dad64f0eSDag-Erling Smørgrav printf "\n\n\n" >foo 84dad64f0eSDag-Erling Smørgrav atf_check_wc foo 3 0 3 85dad64f0eSDag-Erling Smørgrav} 86dad64f0eSDag-Erling Smørgrav 87dad64f0eSDag-Erling Smørgravatf_test_case empty 88dad64f0eSDag-Erling Smørgravempty_head() 89dad64f0eSDag-Erling Smørgrav{ 90dad64f0eSDag-Erling Smørgrav atf_set "descr" "Empty input" 91dad64f0eSDag-Erling Smørgrav} 92dad64f0eSDag-Erling Smørgravempty_body() 93dad64f0eSDag-Erling Smørgrav{ 94dad64f0eSDag-Erling Smørgrav printf "" >foo 95dad64f0eSDag-Erling Smørgrav atf_check_wc foo 0 0 0 96dad64f0eSDag-Erling Smørgrav} 97dad64f0eSDag-Erling Smørgrav 98dad64f0eSDag-Erling Smørgravatf_test_case invalid 99dad64f0eSDag-Erling Smørgravinvalid_head() 100dad64f0eSDag-Erling Smørgrav{ 101dad64f0eSDag-Erling Smørgrav atf_set "descr" "Invalid multibyte input" 102dad64f0eSDag-Erling Smørgrav} 103dad64f0eSDag-Erling Smørgravinvalid_body() 104dad64f0eSDag-Erling Smørgrav{ 105dad64f0eSDag-Erling Smørgrav printf "a\377b\n" >foo 106dad64f0eSDag-Erling Smørgrav atf_check \ 107dad64f0eSDag-Erling Smørgrav -e match:"Illegal byte sequence" \ 108dad64f0eSDag-Erling Smørgrav -o match:"^ +4 foo$" \ 109dad64f0eSDag-Erling Smørgrav wc -m foo 110dad64f0eSDag-Erling Smørgrav} 111dad64f0eSDag-Erling Smørgrav 112dad64f0eSDag-Erling Smørgravatf_test_case multiline 113dad64f0eSDag-Erling Smørgravmultiline_head() 114dad64f0eSDag-Erling Smørgrav{ 115dad64f0eSDag-Erling Smørgrav atf_set "descr" "Multiline, multibyte input" 116dad64f0eSDag-Erling Smørgrav} 117dad64f0eSDag-Erling Smørgravmultiline_body() 118dad64f0eSDag-Erling Smørgrav{ 119dad64f0eSDag-Erling Smørgrav printf "%s\n" "$tv" >foo 120dad64f0eSDag-Erling Smørgrav atf_check_wc foo $tvl $tvw $tvc $tvm 121dad64f0eSDag-Erling Smørgrav # longest line in bytes 122dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +$tvc +$tvcL foo" wc -cL foo 123dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +$tvc +$tvcL" wc -cL <foo 124dad64f0eSDag-Erling Smørgrav # longest line in characters 125dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +$tvm +$tvmL foo" wc -mL foo 126dad64f0eSDag-Erling Smørgrav atf_check -o match:"^ +$tvm +$tvmL" wc -mL <foo 127dad64f0eSDag-Erling Smørgrav} 128dad64f0eSDag-Erling Smørgrav 129dad64f0eSDag-Erling Smørgravatf_test_case multiline_repeated 130dad64f0eSDag-Erling Smørgravmultiline_repeated_head() 131dad64f0eSDag-Erling Smørgrav{ 132dad64f0eSDag-Erling Smørgrav atf_set "descr" "Multiline input exceeding the input buffer size" 133dad64f0eSDag-Erling Smørgrav} 134dad64f0eSDag-Erling Smørgravmultiline_repeated_body() 135dad64f0eSDag-Erling Smørgrav{ 136dad64f0eSDag-Erling Smørgrav local c=0 137dad64f0eSDag-Erling Smørgrav while [ $c -lt 1000 ] ; do 138dad64f0eSDag-Erling Smørgrav printf "%1\$s\n%1\$s\n%1\$s\n%1\$s\n%1\$s\n" "$tv" 139dad64f0eSDag-Erling Smørgrav c=$((c+5)) 140dad64f0eSDag-Erling Smørgrav done >foo 141dad64f0eSDag-Erling Smørgrav atf_check_wc foo $((tvl*c)) $((tvw*c)) $((tvc*c)) $((tvm*c)) 142dad64f0eSDag-Erling Smørgrav} 143dad64f0eSDag-Erling Smørgrav 144*5c870e1bSDag-Erling Smørgravatf_test_case nul 145*5c870e1bSDag-Erling Smørgravnul_head() 146*5c870e1bSDag-Erling Smørgrav{ 147*5c870e1bSDag-Erling Smørgrav atf_set "descr" "Input containing NUL" 148*5c870e1bSDag-Erling Smørgrav} 149*5c870e1bSDag-Erling Smørgravnul_body() 150*5c870e1bSDag-Erling Smørgrav{ 151*5c870e1bSDag-Erling Smørgrav printf "a\0b\n" >foo 152*5c870e1bSDag-Erling Smørgrav atf_check_wc foo 1 1 4 153*5c870e1bSDag-Erling Smørgrav} 154*5c870e1bSDag-Erling Smørgrav 155*5c870e1bSDag-Erling Smørgravatf_test_case poop 156*5c870e1bSDag-Erling Smørgravpoop_head() 157*5c870e1bSDag-Erling Smørgrav{ 158*5c870e1bSDag-Erling Smørgrav atf_set "descr" "Multibyte sequence across buffer boundary" 159*5c870e1bSDag-Erling Smørgrav} 160*5c870e1bSDag-Erling Smørgravpoop_body() 161*5c870e1bSDag-Erling Smørgrav{ 162*5c870e1bSDag-Erling Smørgrav local l=0 w=0 c=0 m=0 163*5c870e1bSDag-Erling Smørgrav # The code below produces a stream of 4-byte UTF-8 sequences 164*5c870e1bSDag-Erling Smørgrav # aligned on 5-byte boundaries, ensuring that the first full 165*5c870e1bSDag-Erling Smørgrav # read of length MAXBSIZE will end in a partial sequence — 166*5c870e1bSDag-Erling Smørgrav # unless MAXBSIZE is a multiple of 5 (not possible since it's 167*5c870e1bSDag-Erling Smørgrav # a power of 2) or one less than a multiple of 5 (e.g. 2^18 = 168*5c870e1bSDag-Erling Smørgrav # 262,144 = (52429 * 5) - 1) in which case we prepend a single 169*5c870e1bSDag-Erling Smørgrav # newline to push our sequence out of phase. 170*5c870e1bSDag-Erling Smørgrav atf_check_not_equal 0 $((MAXBSIZE % 5)) 171*5c870e1bSDag-Erling Smørgrav :>foo 172*5c870e1bSDag-Erling Smørgrav if [ $((MAXBSIZE % 5)) -eq 4 ] ; then 173*5c870e1bSDag-Erling Smørgrav printf "\n" 174*5c870e1bSDag-Erling Smørgrav l=$((l + 1)) 175*5c870e1bSDag-Erling Smørgrav c=$((c + 1)) 176*5c870e1bSDag-Erling Smørgrav m=$((m + 1)) 177*5c870e1bSDag-Erling Smørgrav fi >>foo 178*5c870e1bSDag-Erling Smørgrav while [ $c -le $MAXBSIZE ] ; do 179*5c870e1bSDag-Erling Smørgrav printf "...............\n" 180*5c870e1bSDag-Erling Smørgrav l=$((l + 1)) 181*5c870e1bSDag-Erling Smørgrav w=$((w + 1)) 182*5c870e1bSDag-Erling Smørgrav c=$((c + 80)) # 80 bytes 183*5c870e1bSDag-Erling Smørgrav m=$((m + 32)) # 32 multibyte characters 184*5c870e1bSDag-Erling Smørgrav done >>foo 185*5c870e1bSDag-Erling Smørgrav atf_check_wc foo $l $w $c $m 186*5c870e1bSDag-Erling Smørgrav} 187*5c870e1bSDag-Erling Smørgrav 188dad64f0eSDag-Erling Smørgravatf_test_case total 189dad64f0eSDag-Erling Smørgravtotal_head() 190dad64f0eSDag-Erling Smørgrav{ 191dad64f0eSDag-Erling Smørgrav atf_set "descr" "Multiple inputs" 192dad64f0eSDag-Erling Smørgrav} 193dad64f0eSDag-Erling Smørgravtotal_body() 194dad64f0eSDag-Erling Smørgrav{ 195dad64f0eSDag-Erling Smørgrav printf "%s\n" "$tv" >foo 196dad64f0eSDag-Erling Smørgrav printf "%s\n" "$tv" >bar 197dad64f0eSDag-Erling Smørgrav atf_check \ 198dad64f0eSDag-Erling Smørgrav -o match:"^ +$((tvl*2)) +$((tvw*2)) +$((tvc*2)) total$" \ 199dad64f0eSDag-Erling Smørgrav wc foo bar 200dad64f0eSDag-Erling Smørgrav} 201dad64f0eSDag-Erling Smørgrav 202dad64f0eSDag-Erling Smørgravatf_test_case unterminated 203dad64f0eSDag-Erling Smørgravunterminated_head() 204dad64f0eSDag-Erling Smørgrav{ 205dad64f0eSDag-Erling Smørgrav atf_set "descr" "Input not ending in newline" 206dad64f0eSDag-Erling Smørgrav} 207dad64f0eSDag-Erling Smørgravunterminated_body() 208dad64f0eSDag-Erling Smørgrav{ 209dad64f0eSDag-Erling Smørgrav printf "a b" >foo 210dad64f0eSDag-Erling Smørgrav atf_check_wc foo 0 2 3 211dad64f0eSDag-Erling Smørgrav} 212dad64f0eSDag-Erling Smørgrav 213dad64f0eSDag-Erling Smørgravatf_test_case usage 214dad64f0eSDag-Erling Smørgravusage_head() 215dad64f0eSDag-Erling Smørgrav{ 216dad64f0eSDag-Erling Smørgrav atf_set "descr" "Trigger usage message" 217dad64f0eSDag-Erling Smørgrav} 218dad64f0eSDag-Erling Smørgravusage_body() 219dad64f0eSDag-Erling Smørgrav{ 220dad64f0eSDag-Erling Smørgrav atf_check -s exit:1 -e match:"usage: wc" wc -\? 221dad64f0eSDag-Erling Smørgrav} 222dad64f0eSDag-Erling Smørgrav 223dad64f0eSDag-Erling Smørgravatf_test_case whitespace 224dad64f0eSDag-Erling Smørgravwhitespace_head() 225dad64f0eSDag-Erling Smørgrav{ 226dad64f0eSDag-Erling Smørgrav atf_set "descr" "Input containing only whitespace and newlines" 227dad64f0eSDag-Erling Smørgrav} 228dad64f0eSDag-Erling Smørgravwhitespace_body() 229dad64f0eSDag-Erling Smørgrav{ 230dad64f0eSDag-Erling Smørgrav printf "\n \n\t\n" >foo 231dad64f0eSDag-Erling Smørgrav atf_check_wc foo 3 0 5 232dad64f0eSDag-Erling Smørgrav} 233dad64f0eSDag-Erling Smørgrav 234dad64f0eSDag-Erling Smørgravatf_init_test_cases() 235dad64f0eSDag-Erling Smørgrav{ 236dad64f0eSDag-Erling Smørgrav atf_add_test_case basic 237dad64f0eSDag-Erling Smørgrav atf_add_test_case blank 238dad64f0eSDag-Erling Smørgrav atf_add_test_case empty 239dad64f0eSDag-Erling Smørgrav atf_add_test_case invalid 240dad64f0eSDag-Erling Smørgrav atf_add_test_case multiline 241dad64f0eSDag-Erling Smørgrav atf_add_test_case multiline_repeated 242*5c870e1bSDag-Erling Smørgrav atf_add_test_case nul 243*5c870e1bSDag-Erling Smørgrav atf_add_test_case poop 244dad64f0eSDag-Erling Smørgrav atf_add_test_case total 245dad64f0eSDag-Erling Smørgrav atf_add_test_case unterminated 246dad64f0eSDag-Erling Smørgrav atf_add_test_case usage 247dad64f0eSDag-Erling Smørgrav atf_add_test_case whitespace 248dad64f0eSDag-Erling Smørgrav} 249