| #!/bin/bash |
| # |
| # Copyright 2008 Google Inc. |
| # Author: Lincoln Smith |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http:#www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # This script tests the correctness of the vcdiff command-line executable. |
| # If you add a new test here, please add the same test to the Windows script |
| # vsprojects/vcdiff_test.bat. |
| # |
| # The caller should set the environment variable $srcdir to the root directory |
| # of the open-vcdiff package. ($srcdir is automatically provided by Automake |
| # when this script is run by "make check".) |
| |
| # Find input files |
| VCDIFF=./vcdiff |
| # These options are only needed for the encoder; |
| # the decoder will recognize the interleaved and checksum formats |
| # without needing to specify any options. |
| VCD_OPTIONS="-interleaved -checksum" |
| DICTIONARY_FILE=$srcdir/testdata/configure.ac.v0.1 |
| TARGET_FILE=$srcdir/testdata/configure.ac.v0.2 |
| TEST_TMPDIR=${TMPDIR-/tmp} |
| DELTA_FILE=$TEST_TMPDIR/configure.ac.vcdiff |
| OUTPUT_TARGET_FILE=$TEST_TMPDIR/configure.ac.output |
| MALICIOUS_ENCODING=$srcdir/testdata/allocates_4gb.vcdiff |
| |
| # vcdiff with no arguments shows usage information & error result |
| $VCDIFF \ |
| && { echo "vcdiff with no arguments should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 1 ok"; |
| |
| # vcdiff with three arguments but without "encode" or "decode" |
| # shows usage information & error result |
| $VCDIFF $VCD_OPTIONS \ |
| -dictionary $DICTIONARY_FILE -target $TARGET_FILE -delta $DELTA_FILE \ |
| && { echo "vcdiff without operation argument should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 2 ok"; |
| |
| # vcdiff with all three arguments. Verify that output file matches target file |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| || { echo "Encode with three arguments failed"; \ |
| exit 1; } |
| $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE \ |
| || { echo "Decode with three arguments failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 3 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # vcdiff using stdin/stdout. Verify that output file matches target file |
| { $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| < $TARGET_FILE \ |
| > $DELTA_FILE; } \ |
| || { echo "Encode using stdin/stdout failed"; \ |
| exit 1; } |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| < $DELTA_FILE \ |
| > $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode using stdin/stdout failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 4 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # vcdiff with mixed stdin/stdout. |
| { $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| > $DELTA_FILE; } \ |
| || { echo "Encode with mixed arguments failed"; \ |
| exit 1; } |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| > $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode with mixed arguments failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 5 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| { $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| < $TARGET_FILE \ |
| -delta $DELTA_FILE; } \ |
| || { echo "Encode with mixed arguments failed"; \ |
| exit 1; } |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| < $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode with mixed arguments failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 6 ok"; |
| |
| rm $OUTPUT_TARGET_FILE |
| # Don't remove $DELTA_FILE; use it for the next test |
| |
| # If using the wrong dictionary, and dictionary is smaller than the original |
| # dictionary, vcdiff will spot the mistake and return an error. (It can't |
| # detect the case where the wrong dictionary is larger than the right one.) |
| $VCDIFF decode -dictionary $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE \ |
| && { echo "Decode using larger dictionary should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 7 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # "vcdiff test" with all three arguments. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| || { echo "vcdiff test with three arguments failed"; \ |
| exit 1; } |
| echo "Test 8 ok"; |
| |
| rm $DELTA_FILE |
| |
| # Dictionary file not found. |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $TEST_TMPDIR/nonexistent_file \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "vcdiff with missing dictionary file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 9 ok"; |
| |
| # Target file not found. |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TEST_TMPDIR/nonexistent_file \ |
| -delta $DELTA_FILE \ |
| && { echo "vcdiff with missing target file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 10 ok"; |
| |
| # Delta file not found. |
| $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| -delta $TEST_TMPDIR/nonexistent_file \ |
| -target $OUTPUT_TARGET_FILE \ |
| && { echo "vcdiff with missing delta file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 11 ok"; |
| |
| # Try traversing an infinite loop of symbolic links. |
| ln -s $TEST_TMPDIR/infinite_loop1 $TEST_TMPDIR/infinite_loop2 |
| ln -s $TEST_TMPDIR/infinite_loop2 $TEST_TMPDIR/infinite_loop1 |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $TEST_TMPDIR/infinite_loop1 \ |
| -target $TEST_TMPDIR/infinite_loop2 \ |
| -delta $DELTA_FILE \ |
| && { echo "vcdiff with symbolic link loop should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 12 ok"; |
| |
| rm $TEST_TMPDIR/infinite_loop1 $TEST_TMPDIR/infinite_loop2 |
| |
| # Test using -stats flag |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -stats \ |
| || { echo "Encode with -stats failed"; \ |
| exit 1; } |
| $VCDIFF -stats \ |
| decode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE \ |
| || { echo "Decode with -stats failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 13 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # Using /dev/null as dictionary should work, but (because dictionary is empty) |
| # it will not produce a small delta file. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary /dev/null \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -stats \ |
| || { echo "vcdiff test with /dev/null as dictionary failed"; \ |
| exit 1; } |
| echo "Test 14 ok"; |
| |
| rm $DELTA_FILE |
| |
| # Using /dev/kmem as dictionary or target should produce an error |
| # (permission denied, or too large, or special file type) |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary /dev/kmem \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "vcdiff with /dev/kmem as dictionary should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 15 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target /dev/kmem \ |
| -delta $DELTA_FILE \ |
| && { echo "vcdiff with /dev/kmem as target should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 16 ok"; |
| |
| # Decode using something that isn't a delta file |
| $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| -delta /etc/fstab \ |
| -target $OUTPUT_TARGET_FILE \ |
| && { echo "vcdiff with invalid delta file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 17 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -dictionary \ |
| && { echo "-dictionary option with no file name should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 18 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| -target \ |
| && { echo "-target option with no file name should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 19 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta \ |
| && { echo "-delta option with no file name should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 20 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -buffersize \ |
| && { echo "-buffersize option with no argument should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 21 ok"; |
| |
| # Using -buffersize=1 should still work. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -buffersize 1 \ |
| -stats \ |
| || { echo "vcdiff test with -buffersize=1 failed"; \ |
| exit 1; } |
| echo "Test 22 ok"; |
| |
| rm $DELTA_FILE |
| |
| # Using -buffersize=1 with stdin/stdout means that vcdiff |
| # will create a separate target window for each byte read. |
| { $VCDIFF encode -dictionary $DICTIONARY_FILE \ |
| -buffersize 1 \ |
| -stats \ |
| < $TARGET_FILE \ |
| > $DELTA_FILE; } \ |
| || { echo "Encode using stdin/stdout with -buffersize=1 failed"; \ |
| exit 1; } |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| -buffersize 1 \ |
| -stats \ |
| < $DELTA_FILE \ |
| > $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode using stdin/stdout with -buffersize=1 failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original with -buffersize=1"; \ |
| exit 1; } |
| echo "Test 23 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # Using -buffersize=0 should fail. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -buffersize 0 \ |
| && { echo "vcdiff test with -buffersize=0 should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 24 ok"; |
| |
| rm $DELTA_FILE |
| |
| # Using -buffersize=128M (larger than default maximum) should still work. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -buffersize 134217728 \ |
| -stats \ |
| || { echo "vcdiff test with -buffersize=128M failed"; \ |
| exit 1; } |
| echo "Test 25 ok"; |
| |
| rm $DELTA_FILE |
| |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -froobish \ |
| && { echo "vdiff test with unrecognized option should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 26 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| encode -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "encode with no dictionary option should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 27 ok"; |
| |
| $VCDIFF decode -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "decode with no dictionary option should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 28 ok"; |
| |
| # Remove -interleaved and -checksum options |
| { $VCDIFF encode -dictionary $DICTIONARY_FILE \ |
| < $TARGET_FILE \ |
| > $DELTA_FILE; } \ |
| || { echo "Encode without -interleaved and -checksum options failed"; \ |
| exit 1; } |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| < $DELTA_FILE \ |
| > $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode non-interleaved output failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original with -interleaved"; \ |
| exit 1; } |
| echo "Test 29 ok"; |
| |
| # -target_matches option |
| { $VCDIFF encode -dictionary $DICTIONARY_FILE \ |
| -target_matches \ |
| -stats \ |
| < $TARGET_FILE \ |
| > $DELTA_FILE; } \ |
| || { echo "Encode with -target_matches option failed"; \ |
| exit 1; } |
| # The decode operation ignores the -target_matches option. |
| { $VCDIFF decode -dictionary $DICTIONARY_FILE \ |
| < $DELTA_FILE \ |
| > $OUTPUT_TARGET_FILE; } \ |
| || { echo "Decode output failed with -target_matches"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original with -target_matches"; \ |
| exit 1; } |
| echo "Test 30 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| $VCDIFF $VCD_OPTIONS \ |
| dencode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "vdiff with unrecognized action should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 31 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| && { echo "vdiff test without delta option should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 32 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| && { echo "vdiff test without target option should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 33 ok"; |
| |
| # open-vcdiff bug 8 (http://code.google.com/p/open-vcdiff/issues/detail?id=8) |
| # A malicious encoding that tries to produce a 4GB target file made up of 64 |
| # windows, each window having a size of 64MB. |
| # Limit memory usage to 256MB per process, so the test doesn't take forever |
| # to run out of memory. |
| OLD_ULIMIT=$(ulimit -v) |
| echo "Old ulimit: $OLD_ULIMIT" |
| ulimit -S -v 262144 |
| echo "New ulimit: $(ulimit -v)" |
| |
| $VCDIFF $VCD_OPTIONS \ |
| decode -dictionary $DICTIONARY_FILE \ |
| -delta $MALICIOUS_ENCODING \ |
| -target /dev/null \ |
| -max_target_file_size=65536 \ |
| && { echo "Decoding malicious file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 34 ok"; |
| |
| $VCDIFF $VCD_OPTIONS \ |
| decode -dictionary $DICTIONARY_FILE \ |
| -delta $MALICIOUS_ENCODING \ |
| -target /dev/null \ |
| -max_target_window_size=65536 \ |
| && { echo "Decoding malicious file should fail, but succeeded"; \ |
| exit 1; } |
| echo "Test 35 ok"; |
| |
| ulimit -S -v $OLD_ULIMIT |
| |
| # Decoding a small target with the -max_target_file_size option should succeed. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -max_target_file_size=65536 \ |
| || { echo "vcdiff test with -max_target_file_size failed"; \ |
| exit 1; } |
| echo "Test 36 ok"; |
| |
| # Decoding a small target with -max_target_window_size option should succeed. |
| $VCDIFF $VCD_OPTIONS \ |
| test -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -max_target_window_size=65536 \ |
| || { echo "vcdiff test with -max_target_window_size failed"; \ |
| exit 1; } |
| echo "Test 37 ok"; |
| |
| rm $DELTA_FILE |
| |
| # Test using -allow_vcd_target=false |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -allow_vcd_target=false \ |
| || { echo "Encode with -allow_vcd_target=false failed"; \ |
| exit 1; } |
| $VCDIFF $VCD_OPTIONS \ |
| decode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE \ |
| -allow_vcd_target=false \ |
| || { echo "Decode with -allow_vcd_target=false failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 38 ok"; |
| |
| rm $DELTA_FILE |
| rm $OUTPUT_TARGET_FILE |
| |
| # Test using -allow_vcd_target=true |
| $VCDIFF $VCD_OPTIONS \ |
| encode -dictionary $DICTIONARY_FILE \ |
| -target $TARGET_FILE \ |
| -delta $DELTA_FILE \ |
| -allow_vcd_target=true \ |
| || { echo "Encode with -allow_vcd_target=true failed"; \ |
| exit 1; } |
| $VCDIFF $VCD_OPTIONS \ |
| decode -dictionary $DICTIONARY_FILE \ |
| -delta $DELTA_FILE \ |
| -target $OUTPUT_TARGET_FILE \ |
| -allow_vcd_target=true \ |
| || { echo "Decode with -allow_vcd_target=true failed"; \ |
| exit 1; } |
| cmp $TARGET_FILE $OUTPUT_TARGET_FILE \ |
| || { echo "Decoded target does not match original"; \ |
| exit 1; } |
| echo "Test 39 ok"; |
| |
| echo "PASS" |