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 27VCDIFF=./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. 31VCD_OPTIONS="-interleaved -checksum" 32DICTIONARY_FILE=$srcdir/testdata/configure.ac.v0.1 33TARGET_FILE=$srcdir/testdata/configure.ac.v0.2 34TEST_TMPDIR=${TMPDIR-/tmp} 35DELTA_FILE=$TEST_TMPDIR/configure.ac.vcdiff 36OUTPUT_TARGET_FILE=$TEST_TMPDIR/configure.ac.output 37MALICIOUS_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; } 43echo "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; } 51echo "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; } 65cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 66|| { echo "Decoded target does not match original"; \ 67 exit 1; } 68echo "Test 3 ok"; 69 70rm $DELTA_FILE 71rm $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; } 85cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 86|| { echo "Decoded target does not match original"; \ 87 exit 1; } 88echo "Test 4 ok"; 89 90rm $DELTA_FILE 91rm $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; } 105cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 106|| { echo "Decoded target does not match original"; \ 107 exit 1; } 108echo "Test 5 ok"; 109 110rm $DELTA_FILE 111rm $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; } 124cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 125|| { echo "Decoded target does not match original"; \ 126 exit 1; } 127echo "Test 6 ok"; 128 129rm $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; } 140echo "Test 7 ok"; 141 142rm $DELTA_FILE 143rm $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; } 152echo "Test 8 ok"; 153 154rm $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; } 163echo "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; } 172echo "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; } 180echo "Test 11 ok"; 181 182# Try traversing an infinite loop of symbolic links. 183ln -s $TEST_TMPDIR/infinite_loop1 $TEST_TMPDIR/infinite_loop2 184ln -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; } 191echo "Test 12 ok"; 192 193rm $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; } 209cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 210|| { echo "Decoded target does not match original"; \ 211 exit 1; } 212echo "Test 13 ok"; 213 214rm $DELTA_FILE 215rm $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; } 226echo "Test 14 ok"; 227 228rm $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; } 238echo "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; } 246echo "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; } 254echo "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; } 262echo "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; } 270echo "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; } 278echo "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; } 287echo "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; } 298echo "Test 22 ok"; 299 300rm $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; } 318cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 319|| { echo "Decoded target does not match original with -buffersize=1"; \ 320 exit 1; } 321echo "Test 23 ok"; 322 323rm $DELTA_FILE 324rm $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; } 334echo "Test 24 ok"; 335 336rm $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; } 347echo "Test 25 ok"; 348 349rm $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; } 358echo "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; } 365echo "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; } 371echo "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; } 384cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 385|| { echo "Decoded target does not match original with -interleaved"; \ 386 exit 1; } 387echo "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; } 403cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 404|| { echo "Decoded target does not match original with -target_matches"; \ 405 exit 1; } 406echo "Test 30 ok"; 407 408rm $DELTA_FILE 409rm $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; } 417echo "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; } 424echo "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; } 431echo "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. 438OLD_ULIMIT=$(ulimit -v) 439echo "Old ulimit: $OLD_ULIMIT" 440ulimit -S -v 262144 441echo "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; } 450echo "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; } 459echo "Test 35 ok"; 460 461ulimit -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; } 471echo "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; } 481echo "Test 37 ok"; 482 483rm $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; } 500cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 501|| { echo "Decoded target does not match original"; \ 502 exit 1; } 503echo "Test 38 ok"; 504 505rm $DELTA_FILE 506rm $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; } 523cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ 524|| { echo "Decoded target does not match original"; \ 525 exit 1; } 526echo "Test 39 ok"; 527 528echo "PASS" 529