1 1.9 martin # $NetBSD: t_db.sh,v 1.9 2020/03/12 14:10:59 martin Exp $ 2 1.1 pgoyette # 3 1.1 pgoyette # Copyright (c) 2008 The NetBSD Foundation, Inc. 4 1.1 pgoyette # All rights reserved. 5 1.1 pgoyette # 6 1.1 pgoyette # Redistribution and use in source and binary forms, with or without 7 1.1 pgoyette # modification, are permitted provided that the following conditions 8 1.1 pgoyette # are met: 9 1.1 pgoyette # 1. Redistributions of source code must retain the above copyright 10 1.1 pgoyette # notice, this list of conditions and the following disclaimer. 11 1.1 pgoyette # 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pgoyette # notice, this list of conditions and the following disclaimer in the 13 1.1 pgoyette # documentation and/or other materials provided with the distribution. 14 1.1 pgoyette # 15 1.1 pgoyette # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 1.1 pgoyette # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 1.1 pgoyette # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 1.1 pgoyette # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 1.1 pgoyette # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 1.1 pgoyette # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 1.1 pgoyette # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 1.1 pgoyette # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 1.1 pgoyette # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 1.1 pgoyette # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.1 pgoyette # POSSIBILITY OF SUCH DAMAGE. 26 1.1 pgoyette # 27 1.1 pgoyette 28 1.6 christos prog_db() 29 1.1 pgoyette { 30 1.1 pgoyette echo $(atf_get_srcdir)/h_db 31 1.1 pgoyette } 32 1.1 pgoyette 33 1.6 christos prog_lfsr() 34 1.6 christos { 35 1.6 christos echo $(atf_get_srcdir)/h_lfsr 36 1.6 christos } 37 1.6 christos 38 1.1 pgoyette dict() 39 1.1 pgoyette { 40 1.1 pgoyette if [ -f /usr/share/dict/words ]; then 41 1.1 pgoyette echo /usr/share/dict/words 42 1.1 pgoyette elif [ -f /usr/dict/words ]; then 43 1.1 pgoyette echo /usr/dict/words 44 1.1 pgoyette else 45 1.1 pgoyette atf_fail "no dictionary found" 46 1.1 pgoyette fi 47 1.1 pgoyette } 48 1.1 pgoyette 49 1.1 pgoyette SEVEN_SEVEN="abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg" 50 1.1 pgoyette 51 1.1 pgoyette atf_test_case small_btree 52 1.1 pgoyette small_btree_head() 53 1.1 pgoyette { 54 1.1 pgoyette atf_set "descr" \ 55 1.1 pgoyette "Checks btree database using small keys and small data" \ 56 1.1 pgoyette "pairs: takes the first hundred entries in the dictionary," \ 57 1.1 pgoyette "and makes them be key/data pairs." 58 1.1 pgoyette } 59 1.1 pgoyette small_btree_body() 60 1.1 pgoyette { 61 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 62 1.1 pgoyette mkdir ${TMPDIR} 63 1.1 pgoyette 64 1.1 pgoyette sed 200q $(dict) >exp 65 1.1 pgoyette 66 1.1 pgoyette for i in `sed 200q $(dict)`; do 67 1.1 pgoyette echo p 68 1.1 pgoyette echo k$i 69 1.1 pgoyette echo d$i 70 1.1 pgoyette echo g 71 1.1 pgoyette echo k$i 72 1.1 pgoyette done >in 73 1.1 pgoyette 74 1.6 christos atf_check -o file:exp "$(prog_db)" btree in 75 1.1 pgoyette } 76 1.1 pgoyette 77 1.1 pgoyette atf_test_case small_hash 78 1.1 pgoyette small_hash_head() 79 1.1 pgoyette { 80 1.1 pgoyette atf_set "descr" \ 81 1.1 pgoyette "Checks hash database using small keys and small data" \ 82 1.1 pgoyette "pairs: takes the first hundred entries in the dictionary," \ 83 1.1 pgoyette "and makes them be key/data pairs." 84 1.1 pgoyette } 85 1.1 pgoyette small_hash_body() 86 1.1 pgoyette { 87 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 88 1.1 pgoyette mkdir ${TMPDIR} 89 1.1 pgoyette 90 1.1 pgoyette sed 200q $(dict) >exp 91 1.1 pgoyette 92 1.1 pgoyette for i in `sed 200q $(dict)`; do 93 1.1 pgoyette echo p 94 1.1 pgoyette echo k$i 95 1.1 pgoyette echo d$i 96 1.1 pgoyette echo g 97 1.1 pgoyette echo k$i 98 1.1 pgoyette done >in 99 1.1 pgoyette 100 1.6 christos atf_check -o file:exp "$(prog_db)" hash in 101 1.1 pgoyette } 102 1.1 pgoyette 103 1.1 pgoyette atf_test_case small_recno 104 1.1 pgoyette small_recno_head() 105 1.1 pgoyette { 106 1.1 pgoyette atf_set "descr" \ 107 1.1 pgoyette "Checks recno database using small keys and small data" \ 108 1.1 pgoyette "pairs: takes the first hundred entries in the dictionary," \ 109 1.1 pgoyette "and makes them be key/data pairs." 110 1.1 pgoyette } 111 1.1 pgoyette small_recno_body() 112 1.1 pgoyette { 113 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 114 1.1 pgoyette mkdir ${TMPDIR} 115 1.1 pgoyette 116 1.1 pgoyette sed 200q $(dict) >exp 117 1.1 pgoyette 118 1.1 pgoyette sed 200q $(dict) | 119 1.1 pgoyette awk '{ 120 1.1 pgoyette ++i; 121 1.1 pgoyette printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); 122 1.1 pgoyette }' >in 123 1.1 pgoyette 124 1.6 christos atf_check -o file:exp "$(prog_db)" recno in 125 1.1 pgoyette } 126 1.1 pgoyette 127 1.1 pgoyette atf_test_case medium_btree 128 1.1 pgoyette medium_btree_head() 129 1.1 pgoyette { 130 1.1 pgoyette atf_set "descr" \ 131 1.1 pgoyette "Checks btree database using small keys and medium" \ 132 1.1 pgoyette "data pairs: takes the first 200 entries in the" \ 133 1.1 pgoyette "dictionary, and gives them each a medium size data entry." 134 1.1 pgoyette } 135 1.1 pgoyette medium_btree_body() 136 1.1 pgoyette { 137 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 138 1.1 pgoyette mkdir ${TMPDIR} 139 1.1 pgoyette 140 1.1 pgoyette mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz 141 1.1 pgoyette echo $mdata | 142 1.1 pgoyette awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp 143 1.1 pgoyette 144 1.1 pgoyette for i in $(sed 200q $(dict)); do 145 1.1 pgoyette echo p 146 1.1 pgoyette echo k$i 147 1.1 pgoyette echo d$mdata 148 1.1 pgoyette echo g 149 1.1 pgoyette echo k$i 150 1.1 pgoyette done >in 151 1.1 pgoyette 152 1.6 christos atf_check -o file:exp "$(prog_db)" btree in 153 1.1 pgoyette } 154 1.1 pgoyette 155 1.1 pgoyette atf_test_case medium_hash 156 1.1 pgoyette medium_hash_head() 157 1.1 pgoyette { 158 1.1 pgoyette atf_set "descr" \ 159 1.1 pgoyette "Checks hash database using small keys and medium" \ 160 1.1 pgoyette "data pairs: takes the first 200 entries in the" \ 161 1.1 pgoyette "dictionary, and gives them each a medium size data entry." 162 1.1 pgoyette } 163 1.1 pgoyette medium_hash_body() 164 1.1 pgoyette { 165 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 166 1.1 pgoyette mkdir ${TMPDIR} 167 1.1 pgoyette 168 1.1 pgoyette mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz 169 1.1 pgoyette echo $mdata | 170 1.1 pgoyette awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp 171 1.1 pgoyette 172 1.1 pgoyette for i in $(sed 200q $(dict)); do 173 1.1 pgoyette echo p 174 1.1 pgoyette echo k$i 175 1.1 pgoyette echo d$mdata 176 1.1 pgoyette echo g 177 1.1 pgoyette echo k$i 178 1.1 pgoyette done >in 179 1.1 pgoyette 180 1.6 christos atf_check -o file:exp "$(prog_db)" hash in 181 1.1 pgoyette } 182 1.1 pgoyette 183 1.1 pgoyette atf_test_case medium_recno 184 1.1 pgoyette medium_recno_head() 185 1.1 pgoyette { 186 1.1 pgoyette atf_set "descr" \ 187 1.1 pgoyette "Checks recno database using small keys and medium" \ 188 1.1 pgoyette "data pairs: takes the first 200 entries in the" \ 189 1.1 pgoyette "dictionary, and gives them each a medium size data entry." 190 1.1 pgoyette } 191 1.1 pgoyette medium_recno_body() 192 1.1 pgoyette { 193 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 194 1.1 pgoyette mkdir ${TMPDIR} 195 1.1 pgoyette 196 1.1 pgoyette mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz 197 1.1 pgoyette echo $mdata | 198 1.1 pgoyette awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp 199 1.1 pgoyette 200 1.1 pgoyette echo $mdata | 201 1.1 pgoyette awk '{ for (i = 1; i < 201; ++i) 202 1.1 pgoyette printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); 203 1.1 pgoyette }' >in 204 1.1 pgoyette 205 1.6 christos atf_check -o file:exp "$(prog_db)" recno in 206 1.1 pgoyette } 207 1.1 pgoyette 208 1.1 pgoyette atf_test_case big_btree 209 1.1 pgoyette big_btree_head() 210 1.1 pgoyette { 211 1.1 pgoyette atf_set "descr" \ 212 1.1 pgoyette "Checks btree database using small keys and big data" \ 213 1.1 pgoyette "pairs: inserts the programs in /bin with their paths" \ 214 1.1 pgoyette "as their keys." 215 1.1 pgoyette } 216 1.1 pgoyette big_btree_body() 217 1.1 pgoyette { 218 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 219 1.1 pgoyette mkdir ${TMPDIR} 220 1.1 pgoyette 221 1.1 pgoyette (find /bin -type f -print | xargs cat) >exp 222 1.1 pgoyette 223 1.1 pgoyette for psize in 512 16384 65536; do 224 1.1 pgoyette echo "checking page size: $psize" 225 1.1 pgoyette 226 1.1 pgoyette for i in `find /bin -type f -print`; do 227 1.1 pgoyette echo p 228 1.1 pgoyette echo k$i 229 1.1 pgoyette echo D$i 230 1.1 pgoyette echo g 231 1.1 pgoyette echo k$i 232 1.1 pgoyette done >in 233 1.1 pgoyette 234 1.6 christos atf_check "$(prog_db)" -o out btree in 235 1.1 pgoyette cmp -s exp out || atf_fail "test failed for page size: $psize" 236 1.1 pgoyette done 237 1.1 pgoyette } 238 1.1 pgoyette 239 1.1 pgoyette atf_test_case big_hash 240 1.1 pgoyette big_hash_head() 241 1.1 pgoyette { 242 1.1 pgoyette atf_set "descr" \ 243 1.1 pgoyette "Checks hash database using small keys and big data" \ 244 1.1 pgoyette "pairs: inserts the programs in /bin with their paths" \ 245 1.1 pgoyette "as their keys." 246 1.1 pgoyette } 247 1.1 pgoyette big_hash_body() 248 1.1 pgoyette { 249 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 250 1.1 pgoyette mkdir ${TMPDIR} 251 1.1 pgoyette 252 1.1 pgoyette (find /bin -type f -print | xargs cat) >exp 253 1.1 pgoyette 254 1.1 pgoyette for i in `find /bin -type f -print`; do 255 1.1 pgoyette echo p 256 1.1 pgoyette echo k$i 257 1.1 pgoyette echo D$i 258 1.1 pgoyette echo g 259 1.1 pgoyette echo k$i 260 1.1 pgoyette done >in 261 1.1 pgoyette 262 1.6 christos atf_check "$(prog_db)" -o out hash in 263 1.1 pgoyette cmp -s exp out || atf_fail "test failed" 264 1.1 pgoyette } 265 1.1 pgoyette 266 1.1 pgoyette atf_test_case big_recno 267 1.1 pgoyette big_recno_head() 268 1.1 pgoyette { 269 1.1 pgoyette atf_set "descr" \ 270 1.1 pgoyette "Checks recno database using small keys and big data" \ 271 1.1 pgoyette "pairs: inserts the programs in /bin with their paths" \ 272 1.1 pgoyette "as their keys." 273 1.1 pgoyette } 274 1.1 pgoyette big_recno_body() 275 1.1 pgoyette { 276 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 277 1.1 pgoyette mkdir ${TMPDIR} 278 1.1 pgoyette 279 1.1 pgoyette (find /bin -type f -print | xargs cat) >exp 280 1.1 pgoyette 281 1.1 pgoyette find /bin -type f -print | 282 1.1 pgoyette awk '{ 283 1.1 pgoyette ++i; 284 1.1 pgoyette printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i); 285 1.1 pgoyette }' >in 286 1.1 pgoyette 287 1.1 pgoyette for psize in 512 16384 65536; do 288 1.1 pgoyette echo "checking page size: $psize" 289 1.1 pgoyette 290 1.6 christos atf_check "$(prog_db)" -o out recno in 291 1.1 pgoyette cmp -s exp out || atf_fail "test failed for page size: $psize" 292 1.1 pgoyette done 293 1.1 pgoyette } 294 1.1 pgoyette 295 1.1 pgoyette atf_test_case random_recno 296 1.1 pgoyette random_recno_head() 297 1.1 pgoyette { 298 1.1 pgoyette atf_set "descr" "Checks recno database using random entries" 299 1.1 pgoyette } 300 1.1 pgoyette random_recno_body() 301 1.1 pgoyette { 302 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 303 1.1 pgoyette mkdir ${TMPDIR} 304 1.1 pgoyette 305 1.1 pgoyette echo $SEVEN_SEVEN | 306 1.1 pgoyette awk '{ 307 1.1 pgoyette for (i = 37; i <= 37 + 88 * 17; i += 17) { 308 1.1 pgoyette if (i % 41) 309 1.1 pgoyette s = substr($0, 1, i % 41); 310 1.1 pgoyette else 311 1.1 pgoyette s = substr($0, 1); 312 1.1 pgoyette printf("input key %d: %s\n", i, s); 313 1.1 pgoyette } 314 1.1 pgoyette for (i = 1; i <= 15; ++i) { 315 1.1 pgoyette if (i % 41) 316 1.1 pgoyette s = substr($0, 1, i % 41); 317 1.1 pgoyette else 318 1.1 pgoyette s = substr($0, 1); 319 1.1 pgoyette printf("input key %d: %s\n", i, s); 320 1.1 pgoyette } 321 1.1 pgoyette for (i = 19234; i <= 19234 + 61 * 27; i += 27) { 322 1.1 pgoyette if (i % 41) 323 1.1 pgoyette s = substr($0, 1, i % 41); 324 1.1 pgoyette else 325 1.1 pgoyette s = substr($0, 1); 326 1.1 pgoyette printf("input key %d: %s\n", i, s); 327 1.1 pgoyette } 328 1.1 pgoyette exit 329 1.1 pgoyette }' >exp 330 1.1 pgoyette 331 1.1 pgoyette cat exp | 332 1.1 pgoyette awk 'BEGIN { 333 1.1 pgoyette i = 37; 334 1.1 pgoyette incr = 17; 335 1.1 pgoyette } 336 1.1 pgoyette { 337 1.1 pgoyette printf("p\nk%d\nd%s\n", i, $0); 338 1.1 pgoyette if (i == 19234 + 61 * 27) 339 1.1 pgoyette exit; 340 1.1 pgoyette if (i == 37 + 88 * 17) { 341 1.1 pgoyette i = 1; 342 1.1 pgoyette incr = 1; 343 1.1 pgoyette } else if (i == 15) { 344 1.1 pgoyette i = 19234; 345 1.1 pgoyette incr = 27; 346 1.1 pgoyette } else 347 1.1 pgoyette i += incr; 348 1.1 pgoyette } 349 1.1 pgoyette END { 350 1.1 pgoyette for (i = 37; i <= 37 + 88 * 17; i += 17) 351 1.1 pgoyette printf("g\nk%d\n", i); 352 1.1 pgoyette for (i = 1; i <= 15; ++i) 353 1.1 pgoyette printf("g\nk%d\n", i); 354 1.1 pgoyette for (i = 19234; i <= 19234 + 61 * 27; i += 27) 355 1.1 pgoyette printf("g\nk%d\n", i); 356 1.1 pgoyette }' >in 357 1.1 pgoyette 358 1.6 christos atf_check -o file:exp "$(prog_db)" recno in 359 1.1 pgoyette } 360 1.1 pgoyette 361 1.1 pgoyette atf_test_case reverse_recno 362 1.1 pgoyette reverse_recno_head() 363 1.1 pgoyette { 364 1.1 pgoyette atf_set "descr" "Checks recno database using reverse order entries" 365 1.1 pgoyette } 366 1.1 pgoyette reverse_recno_body() 367 1.1 pgoyette { 368 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 369 1.1 pgoyette mkdir ${TMPDIR} 370 1.1 pgoyette 371 1.1 pgoyette echo $SEVEN_SEVEN | 372 1.1 pgoyette awk ' { 373 1.1 pgoyette for (i = 1500; i; --i) { 374 1.1 pgoyette if (i % 34) 375 1.1 pgoyette s = substr($0, 1, i % 34); 376 1.1 pgoyette else 377 1.1 pgoyette s = substr($0, 1); 378 1.1 pgoyette printf("input key %d: %s\n", i, s); 379 1.1 pgoyette } 380 1.1 pgoyette exit; 381 1.1 pgoyette }' >exp 382 1.1 pgoyette 383 1.1 pgoyette cat exp | 384 1.1 pgoyette awk 'BEGIN { 385 1.1 pgoyette i = 1500; 386 1.1 pgoyette } 387 1.1 pgoyette { 388 1.1 pgoyette printf("p\nk%d\nd%s\n", i, $0); 389 1.1 pgoyette --i; 390 1.1 pgoyette } 391 1.1 pgoyette END { 392 1.1 pgoyette for (i = 1500; i; --i) 393 1.1 pgoyette printf("g\nk%d\n", i); 394 1.1 pgoyette }' >in 395 1.1 pgoyette 396 1.6 christos atf_check -o file:exp "$(prog_db)" recno in 397 1.1 pgoyette } 398 1.1 pgoyette 399 1.1 pgoyette atf_test_case alternate_recno 400 1.1 pgoyette alternate_recno_head() 401 1.1 pgoyette { 402 1.1 pgoyette atf_set "descr" "Checks recno database using alternating order entries" 403 1.1 pgoyette } 404 1.1 pgoyette alternate_recno_body() 405 1.1 pgoyette { 406 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 407 1.1 pgoyette mkdir ${TMPDIR} 408 1.1 pgoyette 409 1.1 pgoyette echo $SEVEN_SEVEN | 410 1.1 pgoyette awk ' { 411 1.1 pgoyette for (i = 1; i < 1200; i += 2) { 412 1.1 pgoyette if (i % 34) 413 1.1 pgoyette s = substr($0, 1, i % 34); 414 1.1 pgoyette else 415 1.1 pgoyette s = substr($0, 1); 416 1.1 pgoyette printf("input key %d: %s\n", i, s); 417 1.1 pgoyette } 418 1.1 pgoyette for (i = 2; i < 1200; i += 2) { 419 1.1 pgoyette if (i % 34) 420 1.1 pgoyette s = substr($0, 1, i % 34); 421 1.1 pgoyette else 422 1.1 pgoyette s = substr($0, 1); 423 1.1 pgoyette printf("input key %d: %s\n", i, s); 424 1.1 pgoyette } 425 1.1 pgoyette exit; 426 1.1 pgoyette }' >exp 427 1.1 pgoyette 428 1.1 pgoyette cat exp | 429 1.1 pgoyette awk 'BEGIN { 430 1.1 pgoyette i = 1; 431 1.1 pgoyette even = 0; 432 1.1 pgoyette } 433 1.1 pgoyette { 434 1.1 pgoyette printf("p\nk%d\nd%s\n", i, $0); 435 1.1 pgoyette i += 2; 436 1.1 pgoyette if (i >= 1200) { 437 1.1 pgoyette if (even == 1) 438 1.1 pgoyette exit; 439 1.1 pgoyette even = 1; 440 1.1 pgoyette i = 2; 441 1.1 pgoyette } 442 1.1 pgoyette } 443 1.1 pgoyette END { 444 1.1 pgoyette for (i = 1; i < 1200; ++i) 445 1.1 pgoyette printf("g\nk%d\n", i); 446 1.1 pgoyette }' >in 447 1.1 pgoyette 448 1.6 christos atf_check "$(prog_db)" -o out recno in 449 1.1 pgoyette 450 1.1 pgoyette sort -o exp exp 451 1.1 pgoyette sort -o out out 452 1.1 pgoyette 453 1.1 pgoyette cmp -s exp out || atf_fail "test failed" 454 1.1 pgoyette } 455 1.1 pgoyette 456 1.1 pgoyette h_delete() 457 1.1 pgoyette { 458 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 459 1.1 pgoyette mkdir ${TMPDIR} 460 1.1 pgoyette 461 1.1 pgoyette type=$1 462 1.1 pgoyette 463 1.1 pgoyette echo $SEVEN_SEVEN | 464 1.1 pgoyette awk '{ 465 1.1 pgoyette for (i = 1; i <= 120; ++i) 466 1.1 pgoyette printf("%05d: input key %d: %s\n", i, i, $0); 467 1.1 pgoyette }' >exp 468 1.1 pgoyette 469 1.1 pgoyette cat exp | 470 1.1 pgoyette awk '{ 471 1.1 pgoyette printf("p\nk%d\nd%s\n", ++i, $0); 472 1.1 pgoyette } 473 1.1 pgoyette END { 474 1.1 pgoyette printf("fR_NEXT\n"); 475 1.1 pgoyette for (i = 1; i <= 120; ++i) 476 1.1 pgoyette printf("s\n"); 477 1.2 pgoyette printf("fR_CURSOR\ns\nkXX\n"); 478 1.1 pgoyette printf("r\n"); 479 1.1 pgoyette printf("fR_NEXT\ns\n"); 480 1.1 pgoyette printf("fR_CURSOR\ns\nk1\n"); 481 1.1 pgoyette printf("r\n"); 482 1.1 pgoyette printf("fR_FIRST\ns\n"); 483 1.1 pgoyette }' >in 484 1.1 pgoyette 485 1.2 pgoyette # For btree, the records are ordered by the string representation 486 1.2 pgoyette # of the key value. So sort the expected output file accordingly, 487 1.2 pgoyette # and set the seek_last key to the last expected key value. 488 1.2 pgoyette 489 1.2 pgoyette if [ "$type" = "btree" ] ; then 490 1.2 pgoyette sed -e 's/kXX/k99/' < in > tmp 491 1.2 pgoyette mv tmp in 492 1.2 pgoyette sort -d -k4 < exp > tmp 493 1.2 pgoyette mv tmp exp 494 1.2 pgoyette echo $SEVEN_SEVEN | 495 1.2 pgoyette awk '{ 496 1.2 pgoyette printf("%05d: input key %d: %s\n", 99, 99, $0); 497 1.2 pgoyette printf("seq failed, no such key\n"); 498 1.2 pgoyette printf("%05d: input key %d: %s\n", 1, 1, $0); 499 1.2 pgoyette printf("%05d: input key %d: %s\n", 10, 10, $0); 500 1.2 pgoyette exit; 501 1.2 pgoyette }' >> exp 502 1.2 pgoyette else 503 1.2 pgoyette # For recno, records are ordered by numerical key value. No sort 504 1.2 pgoyette # is needed, but still need to set proper seek_last key value. 505 1.2 pgoyette sed -e 's/kXX/k120/' < in > tmp 506 1.2 pgoyette mv tmp in 507 1.2 pgoyette echo $SEVEN_SEVEN | 508 1.2 pgoyette awk '{ 509 1.2 pgoyette printf("%05d: input key %d: %s\n", 120, 120, $0); 510 1.2 pgoyette printf("seq failed, no such key\n"); 511 1.2 pgoyette printf("%05d: input key %d: %s\n", 1, 1, $0); 512 1.2 pgoyette printf("%05d: input key %d: %s\n", 2, 2, $0); 513 1.2 pgoyette exit; 514 1.2 pgoyette }' >> exp 515 1.2 pgoyette fi 516 1.2 pgoyette 517 1.6 christos atf_check "$(prog_db)" -o out $type in 518 1.1 pgoyette atf_check -o file:exp cat out 519 1.1 pgoyette } 520 1.1 pgoyette 521 1.1 pgoyette atf_test_case delete_btree 522 1.1 pgoyette delete_btree_head() 523 1.1 pgoyette { 524 1.1 pgoyette atf_set "descr" "Checks removing records in btree database" 525 1.1 pgoyette } 526 1.1 pgoyette delete_btree_body() 527 1.1 pgoyette { 528 1.1 pgoyette h_delete btree 529 1.1 pgoyette } 530 1.1 pgoyette 531 1.1 pgoyette atf_test_case delete_recno 532 1.1 pgoyette delete_recno_head() 533 1.1 pgoyette { 534 1.1 pgoyette atf_set "descr" "Checks removing records in recno database" 535 1.1 pgoyette } 536 1.1 pgoyette delete_recno_body() 537 1.1 pgoyette { 538 1.1 pgoyette h_delete recno 539 1.1 pgoyette } 540 1.1 pgoyette 541 1.1 pgoyette h_repeated() 542 1.1 pgoyette { 543 1.7 christos local type="$1" 544 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 545 1.1 pgoyette mkdir ${TMPDIR} 546 1.1 pgoyette 547 1.1 pgoyette echo "" | 548 1.1 pgoyette awk 'BEGIN { 549 1.1 pgoyette for (i = 1; i <= 10; ++i) { 550 1.1 pgoyette printf("p\nkkey1\nD/bin/sh\n"); 551 1.1 pgoyette printf("p\nkkey2\nD/bin/csh\n"); 552 1.1 pgoyette if (i % 8 == 0) { 553 1.1 pgoyette printf("c\nkkey2\nD/bin/csh\n"); 554 1.1 pgoyette printf("c\nkkey1\nD/bin/sh\n"); 555 1.1 pgoyette printf("e\t%d of 10 (comparison)\n", i); 556 1.1 pgoyette } else 557 1.1 pgoyette printf("e\t%d of 10 \n", i); 558 1.1 pgoyette printf("r\nkkey1\nr\nkkey2\n"); 559 1.1 pgoyette } 560 1.1 pgoyette }' >in 561 1.1 pgoyette 562 1.7 christos $(prog_db) $type in 563 1.1 pgoyette } 564 1.1 pgoyette 565 1.1 pgoyette atf_test_case repeated_btree 566 1.1 pgoyette repeated_btree_head() 567 1.1 pgoyette { 568 1.1 pgoyette atf_set "descr" \ 569 1.1 pgoyette "Checks btree database with repeated small keys and" \ 570 1.1 pgoyette "big data pairs. Makes sure that overflow pages are reused" 571 1.1 pgoyette } 572 1.1 pgoyette repeated_btree_body() 573 1.1 pgoyette { 574 1.1 pgoyette h_repeated btree 575 1.1 pgoyette } 576 1.1 pgoyette 577 1.1 pgoyette atf_test_case repeated_hash 578 1.1 pgoyette repeated_hash_head() 579 1.1 pgoyette { 580 1.1 pgoyette atf_set "descr" \ 581 1.1 pgoyette "Checks hash database with repeated small keys and" \ 582 1.1 pgoyette "big data pairs. Makes sure that overflow pages are reused" 583 1.1 pgoyette } 584 1.1 pgoyette repeated_hash_body() 585 1.1 pgoyette { 586 1.1 pgoyette h_repeated hash 587 1.1 pgoyette } 588 1.1 pgoyette 589 1.1 pgoyette atf_test_case duplicate_btree 590 1.1 pgoyette duplicate_btree_head() 591 1.1 pgoyette { 592 1.1 pgoyette atf_set "descr" "Checks btree database with duplicate keys" 593 1.1 pgoyette } 594 1.1 pgoyette duplicate_btree_body() 595 1.1 pgoyette { 596 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 597 1.1 pgoyette mkdir ${TMPDIR} 598 1.1 pgoyette 599 1.1 pgoyette echo $SEVEN_SEVEN | 600 1.1 pgoyette awk '{ 601 1.1 pgoyette for (i = 1; i <= 543; ++i) 602 1.1 pgoyette printf("%05d: input key %d: %s\n", i, i, $0); 603 1.1 pgoyette exit; 604 1.1 pgoyette }' >exp 605 1.1 pgoyette 606 1.1 pgoyette cat exp | 607 1.1 pgoyette awk '{ 608 1.1 pgoyette if (i++ % 2) 609 1.1 pgoyette printf("p\nkduplicatekey\nd%s\n", $0); 610 1.1 pgoyette else 611 1.1 pgoyette printf("p\nkunique%dkey\nd%s\n", i, $0); 612 1.1 pgoyette } 613 1.1 pgoyette END { 614 1.1 pgoyette printf("o\n"); 615 1.1 pgoyette }' >in 616 1.1 pgoyette 617 1.6 christos atf_check -o file:exp -x "$(prog_db) -iflags=1 btree in | sort" 618 1.1 pgoyette } 619 1.1 pgoyette 620 1.1 pgoyette h_cursor_flags() 621 1.1 pgoyette { 622 1.7 christos local type=$1 623 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 624 1.1 pgoyette mkdir ${TMPDIR} 625 1.1 pgoyette 626 1.1 pgoyette echo $SEVEN_SEVEN | 627 1.1 pgoyette awk '{ 628 1.1 pgoyette for (i = 1; i <= 20; ++i) 629 1.1 pgoyette printf("%05d: input key %d: %s\n", i, i, $0); 630 1.1 pgoyette exit; 631 1.1 pgoyette }' >exp 632 1.1 pgoyette 633 1.1 pgoyette # Test that R_CURSOR doesn't succeed before cursor initialized 634 1.1 pgoyette cat exp | 635 1.1 pgoyette awk '{ 636 1.1 pgoyette if (i == 10) 637 1.1 pgoyette exit; 638 1.1 pgoyette printf("p\nk%d\nd%s\n", ++i, $0); 639 1.1 pgoyette } 640 1.1 pgoyette END { 641 1.1 pgoyette printf("fR_CURSOR\nr\n"); 642 1.1 pgoyette printf("eR_CURSOR SHOULD HAVE FAILED\n"); 643 1.1 pgoyette }' >in 644 1.1 pgoyette 645 1.6 christos atf_check -o ignore -e ignore -s ne:0 "$(prog_db)" -o out $type in 646 1.1 pgoyette atf_check -s ne:0 test -s out 647 1.1 pgoyette 648 1.1 pgoyette cat exp | 649 1.1 pgoyette awk '{ 650 1.1 pgoyette if (i == 10) 651 1.1 pgoyette exit; 652 1.1 pgoyette printf("p\nk%d\nd%s\n", ++i, $0); 653 1.1 pgoyette } 654 1.1 pgoyette END { 655 1.1 pgoyette printf("fR_CURSOR\np\nk1\ndsome data\n"); 656 1.1 pgoyette printf("eR_CURSOR SHOULD HAVE FAILED\n"); 657 1.1 pgoyette }' >in 658 1.1 pgoyette 659 1.6 christos atf_check -o ignore -e ignore -s ne:0 "$(prog_db)" -o out $type in 660 1.1 pgoyette atf_check -s ne:0 test -s out 661 1.1 pgoyette } 662 1.1 pgoyette 663 1.1 pgoyette atf_test_case cursor_flags_btree 664 1.1 pgoyette cursor_flags_btree_head() 665 1.1 pgoyette { 666 1.1 pgoyette atf_set "descr" \ 667 1.1 pgoyette "Checks use of cursor flags without initialization in btree database" 668 1.1 pgoyette } 669 1.1 pgoyette cursor_flags_btree_body() 670 1.1 pgoyette { 671 1.1 pgoyette h_cursor_flags btree 672 1.1 pgoyette } 673 1.1 pgoyette 674 1.1 pgoyette atf_test_case cursor_flags_recno 675 1.1 pgoyette cursor_flags_recno_head() 676 1.1 pgoyette { 677 1.1 pgoyette atf_set "descr" \ 678 1.1 pgoyette "Checks use of cursor flags without initialization in recno database" 679 1.1 pgoyette } 680 1.1 pgoyette cursor_flags_recno_body() 681 1.1 pgoyette { 682 1.1 pgoyette h_cursor_flags recno 683 1.1 pgoyette } 684 1.1 pgoyette 685 1.1 pgoyette atf_test_case reverse_order_recno 686 1.1 pgoyette reverse_order_recno_head() 687 1.1 pgoyette { 688 1.1 pgoyette atf_set "descr" "Checks reverse order inserts in recno database" 689 1.1 pgoyette } 690 1.1 pgoyette reverse_order_recno_body() 691 1.1 pgoyette { 692 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 693 1.1 pgoyette mkdir ${TMPDIR} 694 1.1 pgoyette 695 1.1 pgoyette echo $SEVEN_SEVEN | 696 1.1 pgoyette awk '{ 697 1.1 pgoyette for (i = 1; i <= 779; ++i) 698 1.1 pgoyette printf("%05d: input key %d: %s\n", i, i, $0); 699 1.1 pgoyette exit; 700 1.1 pgoyette }' >exp 701 1.1 pgoyette 702 1.1 pgoyette cat exp | 703 1.1 pgoyette awk '{ 704 1.1 pgoyette if (i == 0) { 705 1.1 pgoyette i = 1; 706 1.1 pgoyette printf("p\nk1\nd%s\n", $0); 707 1.1 pgoyette printf("%s\n", "fR_IBEFORE"); 708 1.1 pgoyette } else 709 1.1 pgoyette printf("p\nk1\nd%s\n", $0); 710 1.1 pgoyette } 711 1.1 pgoyette END { 712 1.1 pgoyette printf("or\n"); 713 1.1 pgoyette }' >in 714 1.1 pgoyette 715 1.6 christos atf_check -o file:exp "$(prog_db)" recno in 716 1.1 pgoyette } 717 1.1 pgoyette 718 1.1 pgoyette atf_test_case small_page_btree 719 1.1 pgoyette small_page_btree_head() 720 1.1 pgoyette { 721 1.1 pgoyette atf_set "descr" \ 722 1.1 pgoyette "Checks btree database with lots of keys and small page" \ 723 1.1 pgoyette "size: takes the first 20000 entries in the dictionary," \ 724 1.1 pgoyette "reverses them, and gives them each a small size data" \ 725 1.1 pgoyette "entry. Uses a small page size to make sure the btree" \ 726 1.1 pgoyette "split code gets hammered." 727 1.1 pgoyette } 728 1.1 pgoyette small_page_btree_body() 729 1.1 pgoyette { 730 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 731 1.1 pgoyette mkdir ${TMPDIR} 732 1.1 pgoyette 733 1.1 pgoyette mdata=abcdefghijklmnopqrstuvwxy 734 1.1 pgoyette echo $mdata | 735 1.1 pgoyette awk '{ for (i = 1; i < 20001; ++i) print $0 }' >exp 736 1.1 pgoyette 737 1.1 pgoyette for i in `sed 20000q $(dict) | rev`; do 738 1.1 pgoyette echo p 739 1.1 pgoyette echo k$i 740 1.1 pgoyette echo d$mdata 741 1.1 pgoyette echo g 742 1.1 pgoyette echo k$i 743 1.1 pgoyette done >in 744 1.1 pgoyette 745 1.6 christos atf_check -o file:exp "$(prog_db)" -i psize=512 btree in 746 1.1 pgoyette } 747 1.1 pgoyette 748 1.1 pgoyette h_byte_orders() 749 1.1 pgoyette { 750 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 751 1.1 pgoyette mkdir ${TMPDIR} 752 1.1 pgoyette 753 1.1 pgoyette type=$1 754 1.1 pgoyette 755 1.1 pgoyette sed 50q $(dict) >exp 756 1.1 pgoyette for order in 1234 4321; do 757 1.1 pgoyette for i in `sed 50q $(dict)`; do 758 1.1 pgoyette echo p 759 1.1 pgoyette echo k$i 760 1.1 pgoyette echo d$i 761 1.7 christos echo S 762 1.1 pgoyette echo g 763 1.1 pgoyette echo k$i 764 1.1 pgoyette done >in 765 1.1 pgoyette 766 1.6 christos atf_check -o file:exp "$(prog_db)" -ilorder=$order -f byte.file $type in 767 1.1 pgoyette 768 1.1 pgoyette for i in `sed 50q $(dict)`; do 769 1.1 pgoyette echo g 770 1.1 pgoyette echo k$i 771 1.1 pgoyette done >in 772 1.1 pgoyette 773 1.6 christos atf_check -o file:exp "$(prog_db)" -s -ilorder=$order -f byte.file $type in 774 1.1 pgoyette done 775 1.1 pgoyette } 776 1.1 pgoyette 777 1.1 pgoyette atf_test_case byte_orders_btree 778 1.1 pgoyette byte_orders_btree_head() 779 1.1 pgoyette { 780 1.1 pgoyette atf_set "descr" "Checks btree database using differing byte orders" 781 1.1 pgoyette } 782 1.1 pgoyette byte_orders_btree_body() 783 1.1 pgoyette { 784 1.1 pgoyette h_byte_orders btree 785 1.1 pgoyette } 786 1.1 pgoyette 787 1.1 pgoyette atf_test_case byte_orders_hash 788 1.1 pgoyette byte_orders_hash_head() 789 1.1 pgoyette { 790 1.1 pgoyette atf_set "descr" "Checks hash database using differing byte orders" 791 1.1 pgoyette } 792 1.1 pgoyette byte_orders_hash_body() 793 1.1 pgoyette { 794 1.1 pgoyette h_byte_orders hash 795 1.1 pgoyette } 796 1.1 pgoyette 797 1.1 pgoyette h_bsize_ffactor() 798 1.1 pgoyette { 799 1.1 pgoyette bsize=$1 800 1.1 pgoyette ffactor=$2 801 1.1 pgoyette 802 1.1 pgoyette echo "bucketsize $bsize, fill factor $ffactor" 803 1.6 christos atf_check -o file:exp "$(prog_db)" "-ibsize=$bsize,\ 804 1.1 pgoyette ffactor=$ffactor,nelem=25000,cachesize=65536" hash in 805 1.1 pgoyette } 806 1.1 pgoyette 807 1.1 pgoyette atf_test_case bsize_ffactor 808 1.1 pgoyette bsize_ffactor_head() 809 1.1 pgoyette { 810 1.5 martin atf_set "timeout" "1800" 811 1.1 pgoyette atf_set "descr" "Checks hash database with various" \ 812 1.1 pgoyette "bucketsizes and fill factors" 813 1.1 pgoyette } 814 1.1 pgoyette bsize_ffactor_body() 815 1.1 pgoyette { 816 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 817 1.1 pgoyette mkdir ${TMPDIR} 818 1.1 pgoyette 819 1.1 pgoyette echo $SEVEN_SEVEN | 820 1.1 pgoyette awk '{ 821 1.1 pgoyette for (i = 1; i <= 10000; ++i) { 822 1.1 pgoyette if (i % 34) 823 1.1 pgoyette s = substr($0, 1, i % 34); 824 1.1 pgoyette else 825 1.1 pgoyette s = substr($0, 1); 826 1.1 pgoyette printf("%s\n", s); 827 1.1 pgoyette } 828 1.1 pgoyette exit; 829 1.1 pgoyette 830 1.1 pgoyette }' >exp 831 1.1 pgoyette 832 1.1 pgoyette sed 10000q $(dict) | 833 1.1 pgoyette awk 'BEGIN { 834 1.1 pgoyette ds="'$SEVEN_SEVEN'" 835 1.1 pgoyette } 836 1.1 pgoyette { 837 1.1 pgoyette if (++i % 34) 838 1.1 pgoyette s = substr(ds, 1, i % 34); 839 1.1 pgoyette else 840 1.1 pgoyette s = substr(ds, 1); 841 1.1 pgoyette printf("p\nk%s\nd%s\n", $0, s); 842 1.1 pgoyette }' >in 843 1.1 pgoyette 844 1.1 pgoyette sed 10000q $(dict) | 845 1.1 pgoyette awk '{ 846 1.1 pgoyette ++i; 847 1.1 pgoyette printf("g\nk%s\n", $0); 848 1.1 pgoyette }' >>in 849 1.1 pgoyette 850 1.1 pgoyette h_bsize_ffactor 256 11 851 1.1 pgoyette h_bsize_ffactor 256 14 852 1.1 pgoyette h_bsize_ffactor 256 21 853 1.1 pgoyette 854 1.1 pgoyette h_bsize_ffactor 512 21 855 1.1 pgoyette h_bsize_ffactor 512 28 856 1.1 pgoyette h_bsize_ffactor 512 43 857 1.1 pgoyette 858 1.1 pgoyette h_bsize_ffactor 1024 43 859 1.1 pgoyette h_bsize_ffactor 1024 57 860 1.1 pgoyette h_bsize_ffactor 1024 85 861 1.1 pgoyette 862 1.1 pgoyette h_bsize_ffactor 2048 85 863 1.1 pgoyette h_bsize_ffactor 2048 114 864 1.1 pgoyette h_bsize_ffactor 2048 171 865 1.1 pgoyette 866 1.1 pgoyette h_bsize_ffactor 4096 171 867 1.1 pgoyette h_bsize_ffactor 4096 228 868 1.1 pgoyette h_bsize_ffactor 4096 341 869 1.1 pgoyette 870 1.1 pgoyette h_bsize_ffactor 8192 341 871 1.1 pgoyette h_bsize_ffactor 8192 455 872 1.1 pgoyette h_bsize_ffactor 8192 683 873 1.6 christos 874 1.6 christos h_bsize_ffactor 16384 341 875 1.6 christos h_bsize_ffactor 16384 455 876 1.6 christos h_bsize_ffactor 16384 683 877 1.6 christos 878 1.6 christos h_bsize_ffactor 32768 341 879 1.6 christos h_bsize_ffactor 32768 455 880 1.6 christos h_bsize_ffactor 32768 683 881 1.6 christos 882 1.6 christos h_bsize_ffactor 65536 341 883 1.6 christos h_bsize_ffactor 65536 455 884 1.6 christos h_bsize_ffactor 65536 683 885 1.1 pgoyette } 886 1.1 pgoyette 887 1.6 christos # This tests 64K block size addition/removal 888 1.1 pgoyette atf_test_case four_char_hash 889 1.1 pgoyette four_char_hash_head() 890 1.1 pgoyette { 891 1.1 pgoyette atf_set "descr" \ 892 1.1 pgoyette "Checks hash database with 4 char key and" \ 893 1.1 pgoyette "value insert on a 65536 bucket size" 894 1.1 pgoyette } 895 1.1 pgoyette four_char_hash_body() 896 1.1 pgoyette { 897 1.1 pgoyette TMPDIR="$(pwd)/db_dir"; export TMPDIR 898 1.1 pgoyette mkdir ${TMPDIR} 899 1.1 pgoyette 900 1.1 pgoyette cat >in <<EOF 901 1.1 pgoyette p 902 1.1 pgoyette k1234 903 1.1 pgoyette d1234 904 1.1 pgoyette r 905 1.1 pgoyette k1234 906 1.1 pgoyette EOF 907 1.1 pgoyette 908 1.6 christos atf_check "$(prog_db)" -i bsize=65536 hash in 909 1.6 christos } 910 1.6 christos 911 1.6 christos 912 1.6 christos atf_test_case bsize_torture 913 1.6 christos bsize_torture_head() 914 1.6 christos { 915 1.6 christos atf_set "timeout" "36000" 916 1.6 christos atf_set "descr" "Checks hash database with various bucket sizes" 917 1.6 christos } 918 1.6 christos bsize_torture_body() 919 1.6 christos { 920 1.6 christos TMPDIR="$(pwd)/db_dir"; export TMPDIR 921 1.6 christos mkdir ${TMPDIR} 922 1.9 martin AVAIL=$( df -m ${TMPDIR} | awk '{if (int($4) > 0) print $4}' ) 923 1.9 martin LIST="2048 4096 8192 16384" 924 1.9 martin if [ $AVAIL -gt 30 ]; then 925 1.9 martin LIST="$LIST 32768" 926 1.9 martin fi 927 1.9 martin if [ $AVAIL -gt 60 ]; then 928 1.9 martin LIST="$LIST 65536" 929 1.9 martin fi 930 1.9 martin for i in $LIST 931 1.6 christos do 932 1.6 christos atf_check "$(prog_lfsr)" $i 933 1.6 christos done 934 1.1 pgoyette } 935 1.1 pgoyette 936 1.7 christos atf_test_case btree_weird_page_split 937 1.7 christos btree_weird_page_split_head() 938 1.7 christos { 939 1.7 christos atf_set "descr" \ 940 1.7 christos "Test for a weird page split condition where an insertion " \ 941 1.7 christos "into index 0 of a page that would cause the new item to " \ 942 1.7 christos "be the only item on the left page results in index 0 of " \ 943 1.7 christos "the right page being erroneously skipped; this only " \ 944 1.7 christos "happens with one particular key+data length for each page size." 945 1.8 martin atf_set "timeout" "900" 946 1.7 christos } 947 1.7 christos btree_weird_page_split_body() 948 1.7 christos { 949 1.7 christos for psize in 512 1024 2048 4096 8192; do 950 1.7 christos echo " page size $psize" 951 1.7 christos kdsizes=`awk 'BEGIN { 952 1.7 christos psize = '$psize'; hsize = int(psize/2); 953 1.7 christos for (kdsize = hsize-40; kdsize <= hsize; kdsize++) { 954 1.7 christos print kdsize; 955 1.7 christos } 956 1.7 christos }' /dev/null` 957 1.7 christos 958 1.7 christos # Use a series of keylen+datalen values in the right 959 1.7 christos # neighborhood to find the one that triggers the bug. 960 1.7 christos # We could compute the exact size that triggers the 961 1.7 christos # bug but this additional fuzz may be useful. 962 1.7 christos 963 1.7 christos # Insert keys in reverse order to maximize the chances 964 1.7 christos # for a split on index 0. 965 1.7 christos 966 1.7 christos for kdsize in $kdsizes; do 967 1.7 christos awk 'BEGIN { 968 1.7 christos kdsize = '$kdsize'; 969 1.7 christos for (i = 8; i-- > 0; ) { 970 1.7 christos s = sprintf("a%03d:%09d", i, kdsize); 971 1.7 christos for (j = 0; j < kdsize-20; j++) { 972 1.7 christos s = s "x"; 973 1.7 christos } 974 1.7 christos printf("p\nka%03d\nd%s\n", i, s); 975 1.7 christos } 976 1.7 christos print "o"; 977 1.7 christos }' /dev/null > in 978 1.7 christos sed -n 's/^d//p' in | sort > exp 979 1.7 christos atf_check -o file:exp \ 980 1.7 christos "$(prog_db)" -i psize=$psize btree in 981 1.7 christos done 982 1.7 christos done 983 1.7 christos } 984 1.7 christos 985 1.7 christos # Extremely tricky test attempting to replicate some unusual database 986 1.7 christos # corruption seen in the field: pieces of the database becoming 987 1.7 christos # inaccessible to random access, sequential access, or both. The 988 1.7 christos # hypothesis is that at least some of these are triggered by the bug 989 1.7 christos # in page splits on index 0 with a particular exact keylen+datalen. 990 1.7 christos # (See Test 40.) For psize=4096, this size is exactly 2024. 991 1.7 christos 992 1.7 christos # The order of operations here relies on very specific knowledge of 993 1.7 christos # the internals of the btree access method in order to place records 994 1.7 christos # at specific offsets in a page and to create certain keys on internal 995 1.7 christos # pages. The to-be-split page immediately prior to the bug-triggering 996 1.7 christos # split has the following properties: 997 1.7 christos # 998 1.7 christos # * is not the leftmost leaf page 999 1.7 christos # * key on the parent page is compares less than the key of the item 1000 1.7 christos # on index 0 1001 1.7 christos # * triggering record's key also compares greater than the key on the 1002 1.7 christos # parent page 1003 1.7 christos 1004 1.7 christos # Additionally, we prime the mpool LRU chain so that the head page on 1005 1.7 christos # the chain has the following properties: 1006 1.7 christos # 1007 1.7 christos # * record at index 0 is located where it will not get overwritten by 1008 1.7 christos # items written to the right-hand page during the split 1009 1.7 christos # * key of the record at index 0 compares less than the key of the 1010 1.7 christos # bug-triggering record 1011 1.7 christos 1012 1.7 christos # If the page-split bug exists, this test appears to create a database 1013 1.7 christos # where some records are inaccessible to a search, but still remain in 1014 1.7 christos # the file and are accessible by sequential traversal. At least one 1015 1.7 christos # record gets duplicated out of sequence. 1016 1.7 christos 1017 1.7 christos atf_test_case btree_tricky_page_split 1018 1.7 christos btree_tricky_page_split_head() 1019 1.7 christos { 1020 1.7 christos atf_set "descr" \ 1021 1.7 christos "btree: no unsearchables due to page split on index 0" 1022 1.7 christos } 1023 1.7 christos btree_tricky_page_split_body() 1024 1.7 christos { 1025 1.7 christos list=`(for i in a b c d; do 1026 1.7 christos for j in 990 998 999; do 1027 1.7 christos echo g ${i}${j} 1024 1028 1.7 christos done 1029 1.7 christos done; 1030 1.7 christos echo g y997 2014 1031 1.7 christos for i in y z; do 1032 1.7 christos for j in 998 999; do 1033 1.7 christos echo g ${i}${j} 1024 1034 1.7 christos done 1035 1.7 christos done)` 1036 1.7 christos # Exact number for trigger condition accounts for newlines 1037 1.7 christos # retained by dbtest with -ofile but not without; we use 1038 1.7 christos # -ofile, so count newlines. keylen=5,datalen=5+2014 for 1039 1.7 christos # psize=4096 here. 1040 1.7 christos (cat - <<EOF 1041 1.7 christos p z999 1024 1042 1.7 christos p z998 1024 1043 1.7 christos p y999 1024 1044 1.7 christos p y990 1024 1045 1.7 christos p d999 1024 1046 1.7 christos p d990 1024 1047 1.7 christos p c999 1024 1048 1.7 christos p c990 1024 1049 1.7 christos p b999 1024 1050 1.7 christos p b990 1024 1051 1.7 christos p a999 1024 1052 1.7 christos p a990 1024 1053 1.7 christos p y998 1024 1054 1.7 christos r y990 1055 1.7 christos p d998 1024 1056 1.7 christos p d990 1024 1057 1.7 christos p c998 1024 1058 1.7 christos p c990 1024 1059 1.7 christos p b998 1024 1060 1.7 christos p b990 1024 1061 1.7 christos p a998 1024 1062 1.7 christos p a990 1024 1063 1.7 christos p y997 2014 1064 1.7 christos S 1065 1.7 christos o 1066 1.7 christos EOF 1067 1.7 christos echo "$list") | 1068 1.7 christos # awk script input: 1069 1.7 christos # {p|g|r} key [datasize] 1070 1.7 christos awk '/^[pgr]/{ 1071 1.7 christos printf("%s\nk%s\n", $1, $2); 1072 1.7 christos } 1073 1.7 christos /^p/{ 1074 1.7 christos s = $2; 1075 1.7 christos for (i = 0; i < $3; i++) { 1076 1.7 christos s = s "x"; 1077 1.7 christos } 1078 1.7 christos printf("d%s\n", s); 1079 1.7 christos } 1080 1.7 christos !/^[pgr]/{ 1081 1.7 christos print $0; 1082 1.7 christos }' > in 1083 1.7 christos (echo "$list"; echo "$list") | awk '{ 1084 1.7 christos s = $2; 1085 1.7 christos for (i = 0; i < $3; i++) { 1086 1.7 christos s = s "x"; 1087 1.7 christos } 1088 1.7 christos print s; 1089 1.7 christos }' > exp 1090 1.7 christos atf_check -o file:exp \ 1091 1.7 christos "$(prog_db)" -i psize=4096 btree in 1092 1.7 christos } 1093 1.7 christos 1094 1.7 christos atf_test_case btree_recursive_traversal 1095 1.7 christos btree_recursive_traversal_head() 1096 1.7 christos { 1097 1.7 christos atf_set "descr" \ 1098 1.7 christos "btree: Test for recursive traversal successfully " \ 1099 1.7 christos "retrieving records that are inaccessible to normal " \ 1100 1.7 christos "sequential 'sibling-link' traversal. This works by " \ 1101 1.7 christos "unlinking a few leaf pages but leaving their parent " \ 1102 1.7 christos "links intact. To verify that the unlink actually makes " \ 1103 1.7 christos "records inaccessible, the test first uses 'o' to do a " \ 1104 1.7 christos "normal sequential traversal, followed by 'O' to do a " \ 1105 1.7 christos "recursive traversal." 1106 1.7 christos } 1107 1.7 christos btree_recursive_traversal_body() 1108 1.7 christos { 1109 1.7 christos fill="abcdefghijklmnopqrstuvwxyzy" 1110 1.7 christos script='{ 1111 1.7 christos for (i = 0; i < 20000; i++) { 1112 1.7 christos printf("p\nkAA%05d\nd%05d%s\n", i, i, $0); 1113 1.7 christos } 1114 1.7 christos print "u"; 1115 1.7 christos print "u"; 1116 1.7 christos print "u"; 1117 1.7 christos print "u"; 1118 1.7 christos }' 1119 1.7 christos (echo $fill | awk "$script"; echo o) > in1 1120 1.7 christos echo $fill | 1121 1.7 christos awk '{ 1122 1.7 christos for (i = 0; i < 20000; i++) { 1123 1.7 christos if (i >= 5 && i <= 40) 1124 1.7 christos continue; 1125 1.7 christos printf("%05d%s\n", i, $0); 1126 1.7 christos } 1127 1.7 christos }' > exp1 1128 1.7 christos atf_check -o file:exp1 \ 1129 1.7 christos "$(prog_db)" -i psize=512 btree in1 1130 1.7 christos echo $fill | 1131 1.7 christos awk '{ 1132 1.7 christos for (i = 0; i < 20000; i++) { 1133 1.7 christos printf("%05d%s\n", i, $0); 1134 1.7 christos } 1135 1.7 christos }' > exp2 1136 1.7 christos (echo $fill | awk "$script"; echo O) > in2 1137 1.7 christos atf_check -o file:exp2 \ 1138 1.7 christos "$(prog_db)" -i psize=512 btree in2 1139 1.7 christos } 1140 1.7 christos 1141 1.7 christos atf_test_case btree_byteswap_unaligned_access_bksd 1142 1.7 christos btree_byteswap_unaligned_access_bksd_head() 1143 1.7 christos { 1144 1.7 christos atf_set "descr" \ 1145 1.7 christos "btree: big key, small data, byteswap unaligned access" 1146 1.7 christos } 1147 1.7 christos btree_byteswap_unaligned_access_bksd_body() 1148 1.7 christos { 1149 1.7 christos (echo foo; echo bar) | 1150 1.7 christos awk '{ 1151 1.7 christos s = $0 1152 1.7 christos for (i = 0; i < 488; i++) { 1153 1.7 christos s = s "x"; 1154 1.7 christos } 1155 1.7 christos printf("p\nk%s\ndx\n", s); 1156 1.7 christos }' > in 1157 1.7 christos for order in 1234 4321; do 1158 1.7 christos atf_check \ 1159 1.7 christos "$(prog_db)" -o out -i psize=512,lorder=$order btree in 1160 1.7 christos done 1161 1.7 christos } 1162 1.7 christos 1163 1.7 christos atf_test_case btree_byteswap_unaligned_access_skbd 1164 1.7 christos btree_byteswap_unaligned_access_skbd_head() 1165 1.7 christos { 1166 1.7 christos atf_set "descr" \ 1167 1.7 christos "btree: small key, big data, byteswap unaligned access" 1168 1.7 christos } 1169 1.7 christos btree_byteswap_unaligned_access_skbd_body() 1170 1.7 christos { 1171 1.7 christos # 484 = 512 - 20 (header) - 7 ("foo1234") - 1 (newline) 1172 1.7 christos (echo foo1234; echo bar1234) | 1173 1.7 christos awk '{ 1174 1.7 christos s = $0 1175 1.7 christos for (i = 0; i < 484; i++) { 1176 1.7 christos s = s "x"; 1177 1.7 christos } 1178 1.7 christos printf("p\nk%s\nd%s\n", $0, s); 1179 1.7 christos }' > in 1180 1.7 christos for order in 1234 4321; do 1181 1.7 christos atf_check \ 1182 1.7 christos "$(prog_db)" -o out -i psize=512,lorder=$order btree in 1183 1.7 christos done 1184 1.7 christos } 1185 1.7 christos 1186 1.7 christos atf_test_case btree_known_byte_order 1187 1.7 christos btree_known_byte_order_head() 1188 1.7 christos { 1189 1.7 christos atf_set "descr" \ 1190 1.7 christos "btree: small key, big data, known byte order" 1191 1.7 christos } 1192 1.7 christos btree_known_byte_order_body() 1193 1.7 christos { 1194 1.7 christos local a="-i psize=512,lorder=" 1195 1.7 christos 1196 1.7 christos (echo foo1234; echo bar1234) | 1197 1.7 christos awk '{ 1198 1.7 christos s = $0 1199 1.7 christos for (i = 0; i < 484; i++) { 1200 1.7 christos s = s "x"; 1201 1.7 christos } 1202 1.7 christos printf("%s\n", s); 1203 1.7 christos }' > exp 1204 1.7 christos (echo foo1234; echo bar1234) | 1205 1.7 christos awk '{ 1206 1.7 christos s = $0 1207 1.7 christos for (i = 0; i < 484; i++) { 1208 1.7 christos s = s "x"; 1209 1.7 christos } 1210 1.7 christos printf("p\nk%s\nd%s\n", $0, s); 1211 1.7 christos }' > in1 1212 1.7 christos for order in 1234 4321; do 1213 1.7 christos atf_check \ 1214 1.7 christos "$(prog_db)" -f out.$order $a$order btree in1 1215 1.7 christos done 1216 1.7 christos (echo g; echo kfoo1234; echo g; echo kbar1234) > in2 1217 1.7 christos for order in 1234 4321; do 1218 1.7 christos atf_check -o file:exp \ 1219 1.7 christos "$(prog_db)" -s -f out.$order $a$order btree in2 1220 1.7 christos done 1221 1.7 christos } 1222 1.7 christos 1223 1.1 pgoyette atf_init_test_cases() 1224 1.1 pgoyette { 1225 1.1 pgoyette atf_add_test_case small_btree 1226 1.1 pgoyette atf_add_test_case small_hash 1227 1.1 pgoyette atf_add_test_case small_recno 1228 1.1 pgoyette atf_add_test_case medium_btree 1229 1.1 pgoyette atf_add_test_case medium_hash 1230 1.1 pgoyette atf_add_test_case medium_recno 1231 1.1 pgoyette atf_add_test_case big_btree 1232 1.1 pgoyette atf_add_test_case big_hash 1233 1.1 pgoyette atf_add_test_case big_recno 1234 1.1 pgoyette atf_add_test_case random_recno 1235 1.1 pgoyette atf_add_test_case reverse_recno 1236 1.1 pgoyette atf_add_test_case alternate_recno 1237 1.1 pgoyette atf_add_test_case delete_btree 1238 1.1 pgoyette atf_add_test_case delete_recno 1239 1.1 pgoyette atf_add_test_case repeated_btree 1240 1.1 pgoyette atf_add_test_case repeated_hash 1241 1.1 pgoyette atf_add_test_case duplicate_btree 1242 1.1 pgoyette atf_add_test_case cursor_flags_btree 1243 1.1 pgoyette atf_add_test_case cursor_flags_recno 1244 1.1 pgoyette atf_add_test_case reverse_order_recno 1245 1.1 pgoyette atf_add_test_case small_page_btree 1246 1.1 pgoyette atf_add_test_case byte_orders_btree 1247 1.1 pgoyette atf_add_test_case byte_orders_hash 1248 1.1 pgoyette atf_add_test_case bsize_ffactor 1249 1.1 pgoyette atf_add_test_case four_char_hash 1250 1.6 christos atf_add_test_case bsize_torture 1251 1.7 christos atf_add_test_case btree_weird_page_split 1252 1.7 christos atf_add_test_case btree_tricky_page_split 1253 1.7 christos atf_add_test_case btree_recursive_traversal 1254 1.7 christos atf_add_test_case btree_byteswap_unaligned_access_bksd 1255 1.7 christos atf_add_test_case btree_byteswap_unaligned_access_skbd 1256 1.7 christos atf_add_test_case btree_known_byte_order 1257 1.1 pgoyette } 1258