Home | History | Annotate | Download | only in src
      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