1 #!/bin/bash 2 # 3 # Copyright 2008 Google Inc. 4 # Author: Lincoln Smith 5 # 6 # Licensed under the Apache License, Version 2.0 (the "License"); 7 # you may not use this file except in compliance with the License. 8 # You may obtain a copy of the License at 9 # 10 # http:#www.apache.org/licenses/LICENSE-2.0 11 # 12 # Unless required by applicable law or agreed to in writing, software 13 # distributed under the License is distributed on an "AS IS" BASIS, 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 # See the License for the specific language governing permissions and 16 # limitations under the License. 17 # 18 # This script tests the correctness of the vcdiff command-line executable. 19 # If you add a new test here, please add the same test to the Windows script 20 # vsprojects/vcdiff_test.bat. 21 # 22 # The caller should set the environment variable $srcdir to the root directory 23 # of the open-vcdiff package. ($srcdir is automatically provided by Automake 24 # when this script is run by "make check".) 25 26 # Find input files 27 VCDIFF=./vcdiff 28 # These options are only needed for the encoder; 29 # the decoder will recognize the interleaved and checksum formats 30 # without needing to specify any options. 31 VCD_OPTIONS="-interleaved -checksum" 32 DICTIONARY_FILE=$srcdir/testdata/configure.ac.v0.1 33 TARGET_FILE=$srcdir/testdata/configure.ac.v0.2 34 TEST_TMPDIR=${TMPDIR-/tmp} 35 DELTA_FILE=$TEST_TMPDIR/configure.ac.vcdiff 36 OUTPUT_TARGET_FILE=$TEST_TMPDIR/configure.ac.output 37 MALICIOUS_ENCODING=$srcdir/testdata/allocates_4gb.vcdiff 38 39 # vcdiff with no arguments shows usage information & error result 40 $VCDIFF \ 41 && { echo "vcdiff with no arguments should fail, but succeeded"; \ 42 exit 1; } 43 echo "Test 1 ok"; 44 45 # vcdiff with three arguments but without "encode" or "decode" 46 # shows usage information & error result 47 $VCDIFF $VCD_OPTIONS \ 48 -dictionary $DICTIONARY_FILE -target $TARGET_FILE -delta $DELTA_FILE \ 49 && { echo "vcdiff without operation argument should fail, but succeeded"; \ 50 exit 1; } 51 echo "Test 2 ok"; 52 53 # vcdiff with all three arguments. Verify that output file matches target file 54 $VCDIFF $VCD_OPTIONS \ 55 encode -dictionary $DICTIONARY_FILE \ 56 -target $TARGET_FILE \ 57 -delta $DELTA_FILE \ 58 || { echo "Encode with three arguments failed"; \ 59 exit 1; } 60 $VCDIFF decode -dictionary $DICTIONARY_FILE \ 61 -delta $DELTA_FILE \ 62 -target $OUTPUT_TARGET_FILE \ 63 || { echo "Decode with three arguments failed"; \ 64 exit 1; } 65 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 66 || { echo "Decoded target does not match original"; \ 67 exit 1; } 68 echo "Test 3 ok"; 69 70 rm $DELTA_FILE 71 rm $OUTPUT_TARGET_FILE 72 73 # vcdiff using stdin/stdout. Verify that output file matches target file 74 { $VCDIFF $VCD_OPTIONS \ 75 encode -dictionary $DICTIONARY_FILE \ 76 < $TARGET_FILE \ 77 > $DELTA_FILE; } \ 78 || { echo "Encode using stdin/stdout failed"; \ 79 exit 1; } 80 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 81 < $DELTA_FILE \ 82 > $OUTPUT_TARGET_FILE; } \ 83 || { echo "Decode using stdin/stdout failed"; \ 84 exit 1; } 85 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 86 || { echo "Decoded target does not match original"; \ 87 exit 1; } 88 echo "Test 4 ok"; 89 90 rm $DELTA_FILE 91 rm $OUTPUT_TARGET_FILE 92 93 # vcdiff with mixed stdin/stdout. 94 { $VCDIFF $VCD_OPTIONS \ 95 encode -dictionary $DICTIONARY_FILE \ 96 -target $TARGET_FILE \ 97 > $DELTA_FILE; } \ 98 || { echo "Encode with mixed arguments failed"; \ 99 exit 1; } 100 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 101 -delta $DELTA_FILE \ 102 > $OUTPUT_TARGET_FILE; } \ 103 || { echo "Decode with mixed arguments failed"; \ 104 exit 1; } 105 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 106 || { echo "Decoded target does not match original"; \ 107 exit 1; } 108 echo "Test 5 ok"; 109 110 rm $DELTA_FILE 111 rm $OUTPUT_TARGET_FILE 112 113 { $VCDIFF $VCD_OPTIONS \ 114 encode -dictionary $DICTIONARY_FILE \ 115 < $TARGET_FILE \ 116 -delta $DELTA_FILE; } \ 117 || { echo "Encode with mixed arguments failed"; \ 118 exit 1; } 119 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 120 < $DELTA_FILE \ 121 -target $OUTPUT_TARGET_FILE; } \ 122 || { echo "Decode with mixed arguments failed"; \ 123 exit 1; } 124 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 125 || { echo "Decoded target does not match original"; \ 126 exit 1; } 127 echo "Test 6 ok"; 128 129 rm $OUTPUT_TARGET_FILE 130 # Don't remove $DELTA_FILE; use it for the next test 131 132 # If using the wrong dictionary, and dictionary is smaller than the original 133 # dictionary, vcdiff will spot the mistake and return an error. (It can't 134 # detect the case where the wrong dictionary is larger than the right one.) 135 $VCDIFF decode -dictionary $TARGET_FILE \ 136 -delta $DELTA_FILE \ 137 -target $OUTPUT_TARGET_FILE \ 138 && { echo "Decode using larger dictionary should fail, but succeeded"; \ 139 exit 1; } 140 echo "Test 7 ok"; 141 142 rm $DELTA_FILE 143 rm $OUTPUT_TARGET_FILE 144 145 # "vcdiff test" with all three arguments. 146 $VCDIFF $VCD_OPTIONS \ 147 test -dictionary $DICTIONARY_FILE \ 148 -target $TARGET_FILE \ 149 -delta $DELTA_FILE \ 150 || { echo "vcdiff test with three arguments failed"; \ 151 exit 1; } 152 echo "Test 8 ok"; 153 154 rm $DELTA_FILE 155 156 # Dictionary file not found. 157 $VCDIFF $VCD_OPTIONS \ 158 encode -dictionary $TEST_TMPDIR/nonexistent_file \ 159 -target $TARGET_FILE \ 160 -delta $DELTA_FILE \ 161 && { echo "vcdiff with missing dictionary file should fail, but succeeded"; \ 162 exit 1; } 163 echo "Test 9 ok"; 164 165 # Target file not found. 166 $VCDIFF $VCD_OPTIONS \ 167 encode -dictionary $DICTIONARY_FILE \ 168 -target $TEST_TMPDIR/nonexistent_file \ 169 -delta $DELTA_FILE \ 170 && { echo "vcdiff with missing target file should fail, but succeeded"; \ 171 exit 1; } 172 echo "Test 10 ok"; 173 174 # Delta file not found. 175 $VCDIFF decode -dictionary $DICTIONARY_FILE \ 176 -delta $TEST_TMPDIR/nonexistent_file \ 177 -target $OUTPUT_TARGET_FILE \ 178 && { echo "vcdiff with missing delta file should fail, but succeeded"; \ 179 exit 1; } 180 echo "Test 11 ok"; 181 182 # Try traversing an infinite loop of symbolic links. 183 ln -s $TEST_TMPDIR/infinite_loop1 $TEST_TMPDIR/infinite_loop2 184 ln -s $TEST_TMPDIR/infinite_loop2 $TEST_TMPDIR/infinite_loop1 185 $VCDIFF $VCD_OPTIONS \ 186 encode -dictionary $TEST_TMPDIR/infinite_loop1 \ 187 -target $TEST_TMPDIR/infinite_loop2 \ 188 -delta $DELTA_FILE \ 189 && { echo "vcdiff with symbolic link loop should fail, but succeeded"; \ 190 exit 1; } 191 echo "Test 12 ok"; 192 193 rm $TEST_TMPDIR/infinite_loop1 $TEST_TMPDIR/infinite_loop2 194 195 # Test using -stats flag 196 $VCDIFF $VCD_OPTIONS \ 197 encode -dictionary $DICTIONARY_FILE \ 198 -target $TARGET_FILE \ 199 -delta $DELTA_FILE \ 200 -stats \ 201 || { echo "Encode with -stats failed"; \ 202 exit 1; } 203 $VCDIFF -stats \ 204 decode -dictionary $DICTIONARY_FILE \ 205 -delta $DELTA_FILE \ 206 -target $OUTPUT_TARGET_FILE \ 207 || { echo "Decode with -stats failed"; \ 208 exit 1; } 209 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 210 || { echo "Decoded target does not match original"; \ 211 exit 1; } 212 echo "Test 13 ok"; 213 214 rm $DELTA_FILE 215 rm $OUTPUT_TARGET_FILE 216 217 # Using /dev/null as dictionary should work, but (because dictionary is empty) 218 # it will not produce a small delta file. 219 $VCDIFF $VCD_OPTIONS \ 220 test -dictionary /dev/null \ 221 -target $TARGET_FILE \ 222 -delta $DELTA_FILE \ 223 -stats \ 224 || { echo "vcdiff test with /dev/null as dictionary failed"; \ 225 exit 1; } 226 echo "Test 14 ok"; 227 228 rm $DELTA_FILE 229 230 # Using /dev/kmem as dictionary or target should produce an error 231 # (permission denied, or too large, or special file type) 232 $VCDIFF $VCD_OPTIONS \ 233 encode -dictionary /dev/kmem \ 234 -target $TARGET_FILE \ 235 -delta $DELTA_FILE \ 236 && { echo "vcdiff with /dev/kmem as dictionary should fail, but succeeded"; \ 237 exit 1; } 238 echo "Test 15 ok"; 239 240 $VCDIFF $VCD_OPTIONS \ 241 encode -dictionary $DICTIONARY_FILE \ 242 -target /dev/kmem \ 243 -delta $DELTA_FILE \ 244 && { echo "vcdiff with /dev/kmem as target should fail, but succeeded"; \ 245 exit 1; } 246 echo "Test 16 ok"; 247 248 # Decode using something that isn't a delta file 249 $VCDIFF decode -dictionary $DICTIONARY_FILE \ 250 -delta /etc/fstab \ 251 -target $OUTPUT_TARGET_FILE \ 252 && { echo "vcdiff with invalid delta file should fail, but succeeded"; \ 253 exit 1; } 254 echo "Test 17 ok"; 255 256 $VCDIFF $VCD_OPTIONS \ 257 encode -target $TARGET_FILE \ 258 -delta $DELTA_FILE \ 259 -dictionary \ 260 && { echo "-dictionary option with no file name should fail, but succeeded"; \ 261 exit 1; } 262 echo "Test 18 ok"; 263 264 $VCDIFF $VCD_OPTIONS \ 265 encode -dictionary $DICTIONARY_FILE \ 266 -delta $DELTA_FILE \ 267 -target \ 268 && { echo "-target option with no file name should fail, but succeeded"; \ 269 exit 1; } 270 echo "Test 19 ok"; 271 272 $VCDIFF $VCD_OPTIONS \ 273 encode -dictionary $DICTIONARY_FILE \ 274 -target $TARGET_FILE \ 275 -delta \ 276 && { echo "-delta option with no file name should fail, but succeeded"; \ 277 exit 1; } 278 echo "Test 20 ok"; 279 280 $VCDIFF $VCD_OPTIONS \ 281 encode -dictionary $DICTIONARY_FILE \ 282 -target $TARGET_FILE \ 283 -delta $DELTA_FILE \ 284 -buffersize \ 285 && { echo "-buffersize option with no argument should fail, but succeeded"; \ 286 exit 1; } 287 echo "Test 21 ok"; 288 289 # Using -buffersize=1 should still work. 290 $VCDIFF $VCD_OPTIONS \ 291 test -dictionary $DICTIONARY_FILE \ 292 -target $TARGET_FILE \ 293 -delta $DELTA_FILE \ 294 -buffersize 1 \ 295 -stats \ 296 || { echo "vcdiff test with -buffersize=1 failed"; \ 297 exit 1; } 298 echo "Test 22 ok"; 299 300 rm $DELTA_FILE 301 302 # Using -buffersize=1 with stdin/stdout means that vcdiff 303 # will create a separate target window for each byte read. 304 { $VCDIFF encode -dictionary $DICTIONARY_FILE \ 305 -buffersize 1 \ 306 -stats \ 307 < $TARGET_FILE \ 308 > $DELTA_FILE; } \ 309 || { echo "Encode using stdin/stdout with -buffersize=1 failed"; \ 310 exit 1; } 311 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 312 -buffersize 1 \ 313 -stats \ 314 < $DELTA_FILE \ 315 > $OUTPUT_TARGET_FILE; } \ 316 || { echo "Decode using stdin/stdout with -buffersize=1 failed"; \ 317 exit 1; } 318 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 319 || { echo "Decoded target does not match original with -buffersize=1"; \ 320 exit 1; } 321 echo "Test 23 ok"; 322 323 rm $DELTA_FILE 324 rm $OUTPUT_TARGET_FILE 325 326 # Using -buffersize=0 should fail. 327 $VCDIFF $VCD_OPTIONS \ 328 test -dictionary $DICTIONARY_FILE \ 329 -target $TARGET_FILE \ 330 -delta $DELTA_FILE \ 331 -buffersize 0 \ 332 && { echo "vcdiff test with -buffersize=0 should fail, but succeeded"; \ 333 exit 1; } 334 echo "Test 24 ok"; 335 336 rm $DELTA_FILE 337 338 # Using -buffersize=128M (larger than default maximum) should still work. 339 $VCDIFF $VCD_OPTIONS \ 340 test -dictionary $DICTIONARY_FILE \ 341 -target $TARGET_FILE \ 342 -delta $DELTA_FILE \ 343 -buffersize 134217728 \ 344 -stats \ 345 || { echo "vcdiff test with -buffersize=128M failed"; \ 346 exit 1; } 347 echo "Test 25 ok"; 348 349 rm $DELTA_FILE 350 351 $VCDIFF $VCD_OPTIONS \ 352 test -dictionary $DICTIONARY_FILE \ 353 -target $TARGET_FILE \ 354 -delta $DELTA_FILE \ 355 -froobish \ 356 && { echo "vdiff test with unrecognized option should fail, but succeeded"; \ 357 exit 1; } 358 echo "Test 26 ok"; 359 360 $VCDIFF $VCD_OPTIONS \ 361 encode -target $TARGET_FILE \ 362 -delta $DELTA_FILE \ 363 && { echo "encode with no dictionary option should fail, but succeeded"; \ 364 exit 1; } 365 echo "Test 27 ok"; 366 367 $VCDIFF decode -target $TARGET_FILE \ 368 -delta $DELTA_FILE \ 369 && { echo "decode with no dictionary option should fail, but succeeded"; \ 370 exit 1; } 371 echo "Test 28 ok"; 372 373 # Remove -interleaved and -checksum options 374 { $VCDIFF encode -dictionary $DICTIONARY_FILE \ 375 < $TARGET_FILE \ 376 > $DELTA_FILE; } \ 377 || { echo "Encode without -interleaved and -checksum options failed"; \ 378 exit 1; } 379 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 380 < $DELTA_FILE \ 381 > $OUTPUT_TARGET_FILE; } \ 382 || { echo "Decode non-interleaved output failed"; \ 383 exit 1; } 384 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 385 || { echo "Decoded target does not match original with -interleaved"; \ 386 exit 1; } 387 echo "Test 29 ok"; 388 389 # -target_matches option 390 { $VCDIFF encode -dictionary $DICTIONARY_FILE \ 391 -target_matches \ 392 -stats \ 393 < $TARGET_FILE \ 394 > $DELTA_FILE; } \ 395 || { echo "Encode with -target_matches option failed"; \ 396 exit 1; } 397 # The decode operation ignores the -target_matches option. 398 { $VCDIFF decode -dictionary $DICTIONARY_FILE \ 399 < $DELTA_FILE \ 400 > $OUTPUT_TARGET_FILE; } \ 401 || { echo "Decode output failed with -target_matches"; \ 402 exit 1; } 403 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 404 || { echo "Decoded target does not match original with -target_matches"; \ 405 exit 1; } 406 echo "Test 30 ok"; 407 408 rm $DELTA_FILE 409 rm $OUTPUT_TARGET_FILE 410 411 $VCDIFF $VCD_OPTIONS \ 412 dencode -dictionary $DICTIONARY_FILE \ 413 -target $TARGET_FILE \ 414 -delta $DELTA_FILE \ 415 && { echo "vdiff with unrecognized action should fail, but succeeded"; \ 416 exit 1; } 417 echo "Test 31 ok"; 418 419 $VCDIFF $VCD_OPTIONS \ 420 test -dictionary $DICTIONARY_FILE \ 421 -target $TARGET_FILE \ 422 && { echo "vdiff test without delta option should fail, but succeeded"; \ 423 exit 1; } 424 echo "Test 32 ok"; 425 426 $VCDIFF $VCD_OPTIONS \ 427 test -dictionary $DICTIONARY_FILE \ 428 -delta $DELTA_FILE \ 429 && { echo "vdiff test without target option should fail, but succeeded"; \ 430 exit 1; } 431 echo "Test 33 ok"; 432 433 # open-vcdiff bug 8 (http://code.google.com/p/open-vcdiff/issues/detail?id=8) 434 # A malicious encoding that tries to produce a 4GB target file made up of 64 435 # windows, each window having a size of 64MB. 436 # Limit memory usage to 256MB per process, so the test doesn't take forever 437 # to run out of memory. 438 OLD_ULIMIT=$(ulimit -v) 439 echo "Old ulimit: $OLD_ULIMIT" 440 ulimit -S -v 262144 441 echo "New ulimit: $(ulimit -v)" 442 443 $VCDIFF $VCD_OPTIONS \ 444 decode -dictionary $DICTIONARY_FILE \ 445 -delta $MALICIOUS_ENCODING \ 446 -target /dev/null \ 447 -max_target_file_size=65536 \ 448 && { echo "Decoding malicious file should fail, but succeeded"; \ 449 exit 1; } 450 echo "Test 34 ok"; 451 452 $VCDIFF $VCD_OPTIONS \ 453 decode -dictionary $DICTIONARY_FILE \ 454 -delta $MALICIOUS_ENCODING \ 455 -target /dev/null \ 456 -max_target_window_size=65536 \ 457 && { echo "Decoding malicious file should fail, but succeeded"; \ 458 exit 1; } 459 echo "Test 35 ok"; 460 461 ulimit -S -v $OLD_ULIMIT 462 463 # Decoding a small target with the -max_target_file_size option should succeed. 464 $VCDIFF $VCD_OPTIONS \ 465 test -dictionary $DICTIONARY_FILE \ 466 -target $TARGET_FILE \ 467 -delta $DELTA_FILE \ 468 -max_target_file_size=65536 \ 469 || { echo "vcdiff test with -max_target_file_size failed"; \ 470 exit 1; } 471 echo "Test 36 ok"; 472 473 # Decoding a small target with -max_target_window_size option should succeed. 474 $VCDIFF $VCD_OPTIONS \ 475 test -dictionary $DICTIONARY_FILE \ 476 -target $TARGET_FILE \ 477 -delta $DELTA_FILE \ 478 -max_target_window_size=65536 \ 479 || { echo "vcdiff test with -max_target_window_size failed"; \ 480 exit 1; } 481 echo "Test 37 ok"; 482 483 rm $DELTA_FILE 484 485 # Test using -allow_vcd_target=false 486 $VCDIFF $VCD_OPTIONS \ 487 encode -dictionary $DICTIONARY_FILE \ 488 -target $TARGET_FILE \ 489 -delta $DELTA_FILE \ 490 -allow_vcd_target=false \ 491 || { echo "Encode with -allow_vcd_target=false failed"; \ 492 exit 1; } 493 $VCDIFF $VCD_OPTIONS \ 494 decode -dictionary $DICTIONARY_FILE \ 495 -delta $DELTA_FILE \ 496 -target $OUTPUT_TARGET_FILE \ 497 -allow_vcd_target=false \ 498 || { echo "Decode with -allow_vcd_target=false failed"; \ 499 exit 1; } 500 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 501 || { echo "Decoded target does not match original"; \ 502 exit 1; } 503 echo "Test 38 ok"; 504 505 rm $DELTA_FILE 506 rm $OUTPUT_TARGET_FILE 507 508 # Test using -allow_vcd_target=true 509 $VCDIFF $VCD_OPTIONS \ 510 encode -dictionary $DICTIONARY_FILE \ 511 -target $TARGET_FILE \ 512 -delta $DELTA_FILE \ 513 -allow_vcd_target=true \ 514 || { echo "Encode with -allow_vcd_target=true failed"; \ 515 exit 1; } 516 $VCDIFF $VCD_OPTIONS \ 517 decode -dictionary $DICTIONARY_FILE \ 518 -delta $DELTA_FILE \ 519 -target $OUTPUT_TARGET_FILE \ 520 -allow_vcd_target=true \ 521 || { echo "Decode with -allow_vcd_target=true failed"; \ 522 exit 1; } 523 cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 524 || { echo "Decoded target does not match original"; \ 525 exit 1; } 526 echo "Test 39 ok"; 527 528 echo "PASS" 529