1#!/usr/bin/env bash 2test_description="\"notmuch dump\" and \"notmuch restore\"" 3. $(dirname "$0")/test-lib.sh || exit 1 4 5NOTMUCH_NEW > /dev/null 6test_begin_subtest "dump header" 7cat <<EOF > EXPECTED 8#notmuch-dump batch-tag:3 config,properties,tags 9EOF 10notmuch dump > OUTPUT 11test_expect_equal_file EXPECTED OUTPUT 12add_email_corpus 13 14test_begin_subtest "Dumping all tags" 15test_expect_success 'generate_message && notmuch new && notmuch dump > dump.expected' 16 17# The use of from:cworth is rather arbitrary: it matches some of the 18# email corpus' messages, but not all of them. 19 20test_begin_subtest "Dumping all tags II" 21test_expect_success \ 22 'notmuch tag +ABC +DEF -- from:cworth && 23 notmuch dump > dump-ABC_DEF.expected && 24 ! cmp dump.expected dump-ABC_DEF.expected' 25 26test_begin_subtest "Clearing all tags" 27test_expect_success \ 28 'sed -e "s/(\([^(]*\))$/()/" < dump.expected > clear.expected && 29 notmuch restore --input=clear.expected && 30 notmuch dump > clear.actual && 31 test_cmp clear.expected clear.actual' 32 33test_begin_subtest "Clearing all tags" 34test_expect_success \ 35 'notmuch tag +ABC +DEF -- from:cworth && 36 notmuch restore --accumulate < dump.expected && 37 notmuch dump > dump.actual && 38 test_cmp dump-ABC_DEF.expected dump.actual' 39 40test_begin_subtest "Restoring original tags" 41test_expect_success \ 42 'notmuch restore --input=dump.expected && 43 notmuch dump > dump.actual && 44 test_cmp dump.expected dump.actual' 45 46test_begin_subtest "Restore with nothing to do" 47test_expect_success \ 48 'notmuch restore < dump.expected && 49 notmuch dump > dump.actual && 50 test_cmp dump.expected dump.actual' 51 52test_begin_subtest "Accumulate with existing tags" 53test_expect_success \ 54 'notmuch restore --accumulate --input=dump.expected && 55 notmuch dump > dump.actual && 56 test_cmp dump.expected dump.actual' 57 58test_begin_subtest "Accumulate with no tags" 59test_expect_success \ 60 'notmuch restore --accumulate < clear.expected && 61 notmuch dump > dump.actual && 62 test_cmp dump.expected dump.actual' 63 64test_begin_subtest "Accumulate with new tags" 65test_expect_success \ 66 'notmuch restore --input=dump.expected && 67 notmuch restore --accumulate --input=dump-ABC_DEF.expected && 68 notmuch dump > OUTPUT.$test_count && 69 notmuch restore --input=dump.expected && 70 test_cmp dump-ABC_DEF.expected OUTPUT.$test_count' 71 72# notmuch restore currently only considers the first argument. 73test_begin_subtest "Invalid restore invocation" 74test_expect_success \ 75 'test_must_fail notmuch restore --input=dump.expected another_one' 76 77test_begin_subtest "dump --output=outfile" 78notmuch dump --output=dump-outfile.actual 79test_expect_equal_file dump.expected dump-outfile.actual 80 81test_begin_subtest "dump --output=outfile --" 82notmuch dump --output=dump-1-arg-dash.actual -- 83test_expect_equal_file dump.expected dump-1-arg-dash.actual 84 85# gzipped output 86 87test_begin_subtest "dump --gzip" 88notmuch dump --gzip > dump-gzip.gz 89gunzip dump-gzip.gz 90test_expect_equal_file dump.expected dump-gzip 91 92test_begin_subtest "dump --gzip --output=outfile" 93notmuch dump --gzip --output=dump-gzip-outfile.gz 94gunzip dump-gzip-outfile.gz 95test_expect_equal_file dump.expected dump-gzip-outfile 96 97test_begin_subtest "restoring gzipped stdin" 98notmuch dump --gzip --output=backup.gz 99notmuch tag +new_tag '*' 100notmuch restore < backup.gz 101notmuch dump --output=dump.actual 102test_expect_equal_file dump.expected dump.actual 103 104test_begin_subtest "restoring gzipped file" 105notmuch dump --gzip --output=backup.gz 106notmuch tag +new_tag '*' 107notmuch restore --input=backup.gz 108notmuch dump --output=dump.actual 109test_expect_equal_file dump.expected dump.actual 110 111# Note, we assume all messages from cworth have a message-id 112# containing cworth.org 113 114{ head -1 dump.expected ; grep 'cworth[.]org' dump.expected; } > dump-cworth.expected 115 116test_begin_subtest "dump -- from:cworth" 117notmuch dump -- from:cworth > dump-dash-cworth.actual 118test_expect_equal_file dump-cworth.expected dump-dash-cworth.actual 119 120 121if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then 122 123 test_begin_subtest "dump --query=sexp -- '(from cworth)'" 124 notmuch dump --query=sexp -- '(from cworth)' > dump-dash-cworth.actual2 125 test_expect_equal_file_nonempty dump-cworth.expected dump-dash-cworth.actual2 126 127 test_begin_subtest "dump --query=sexp --output=outfile '(from cworth)'" 128 notmuch dump --output=dump-outfile-cworth.actual2 --query=sexp '(from cworth)' 129 test_expect_equal_file dump-cworth.expected dump-outfile-cworth.actual2 130 131fi 132 133test_begin_subtest "dump --output=outfile from:cworth" 134notmuch dump --output=dump-outfile-cworth.actual from:cworth 135test_expect_equal_file dump-cworth.expected dump-outfile-cworth.actual 136 137test_begin_subtest "dump --output=outfile -- from:cworth" 138notmuch dump --output=dump-outfile-dash-inbox.actual -- from:cworth 139test_expect_equal_file dump-cworth.expected dump-outfile-dash-inbox.actual 140 141test_begin_subtest "Check for a safe set of message-ids" 142notmuch search --output=messages from:cworth | sed s/^id:// > EXPECTED 143notmuch search --output=messages from:cworth | sed s/^id:// |\ 144 $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT 145test_expect_equal_file EXPECTED OUTPUT 146 147test_begin_subtest "format=batch-tag, dump sanity check." 148NOTMUCH_DUMP_TAGS --format=sup from:cworth | cut -f1 -d' ' | \ 149 sort > EXPECTED.$test_count 150NOTMUCH_DUMP_TAGS --format=batch-tag from:cworth | sed 's/^.*-- id://' | \ 151 sort > OUTPUT.$test_count 152test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 153 154test_begin_subtest "format=batch-tag, missing newline" 155printf "+a_tag_without_newline -- id:20091117232137.GA7669@griffis1.net" > IN 156notmuch restore --accumulate < IN 157NOTMUCH_DUMP_TAGS id:20091117232137.GA7669@griffis1.net > OUT 158cat <<EOF > EXPECTED 159+a_tag_without_newline +inbox +unread -- id:20091117232137.GA7669@griffis1.net 160EOF 161test_expect_equal_file EXPECTED OUT 162 163test_begin_subtest "format=batch-tag, # round-trip" 164notmuch dump --format=sup | sort > EXPECTED.$test_count 165notmuch dump --format=batch-tag > DUMPFILE 166notmuch restore --format=batch-tag < DUMPFILE 167notmuch dump --format=sup | sort > OUTPUT.$test_count 168test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 169 170test_begin_subtest "format=batch-tag, # blank lines and comments" 171notmuch dump --format=batch-tag| sort > EXPECTED.$test_count 172notmuch restore <<EOF 173# this line is a comment; the next has only white space 174 175 176# the previous line is empty 177EOF 178notmuch dump --format=batch-tag | sort > OUTPUT.$test_count 179test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 180 181test_begin_subtest "format=batch-tag, # reverse-round-trip empty tag" 182cat <<EOF >EXPECTED.$test_count 183+ -- id:20091117232137.GA7669@griffis1.net 184EOF 185notmuch restore --format=batch-tag < EXPECTED.$test_count 186NOTMUCH_DUMP_TAGS --format=batch-tag id:20091117232137.GA7669@griffis1.net > OUTPUT.$test_count 187test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 188 189tag1='comic_swear=$&^%$^%\\//-+$^%$' 190enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1") 191 192tag2=$(printf 'this\n tag\t has\n spaces') 193enc2=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag2") 194 195enc3='%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' 196tag3=$($TEST_DIRECTORY/hex-xcode --direction=decode $enc3) 197 198notmuch dump --format=batch-tag > BACKUP 199 200notmuch tag +"$tag1" +"$tag2" +"$tag3" -inbox -unread "*" 201 202# initial segment of file used for several tests below. 203cat <<EOF > comments-and-blanks 204# this is a comment 205 206# next line has leading whitespace 207 208 209EOF 210 211test_begin_subtest 'restoring empty file is not an error' 212notmuch restore < /dev/null 2>OUTPUT.$test_count 213cp /dev/null EXPECTED 214test_expect_equal_file EXPECTED OUTPUT.$test_count 215 216test_begin_subtest 'file of comments and blank lines is not an error' 217notmuch restore --input=comments-and-blanks 218ret_val=$? 219test_expect_equal "$ret_val" "0" 220 221cp comments-and-blanks leading-comments-blanks-batch-tag 222echo "+some_tag -- id:yun1vjwegii.fsf@aiko.keithp.com" \ 223 >> leading-comments-blanks-batch-tag 224 225test_begin_subtest 'detect format=batch-tag with leading comments and blanks' 226notmuch restore --input=leading-comments-blanks-batch-tag 227notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count 228echo "some_tag" > EXPECTED 229test_expect_equal_file EXPECTED OUTPUT.$test_count 230 231cp comments-and-blanks leading-comments-blanks-sup 232echo "yun1vjwegii.fsf@aiko.keithp.com (another_tag)" \ 233 >> leading-comments-blanks-sup 234 235test_begin_subtest 'detect format=sup with leading comments and blanks' 236notmuch restore --input=leading-comments-blanks-sup 237notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count 238echo "another_tag" > EXPECTED 239test_expect_equal_file EXPECTED OUTPUT.$test_count 240 241test_begin_subtest 'format=batch-tag, round trip with strange tags' 242notmuch dump --format=batch-tag > EXPECTED.$test_count 243notmuch dump --format=batch-tag > DUMPFILE 244notmuch restore --format=batch-tag < DUMPFILE 245notmuch dump --format=batch-tag > OUTPUT.$test_count 246test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 247 248test_begin_subtest 'format=batch-tag, checking encoded output' 249NOTMUCH_DUMP_TAGS --format=batch-tag -- from:cworth |\ 250 awk "{ print \"+$enc1 +$enc2 +$enc3 -- \" \$5 }" > EXPECTED.$test_count 251NOTMUCH_DUMP_TAGS --format=batch-tag -- from:cworth > OUTPUT.$test_count 252test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 253 254test_begin_subtest 'restoring sane tags' 255notmuch restore --format=batch-tag < BACKUP 256notmuch dump --format=batch-tag > OUTPUT.$test_count 257test_expect_equal_file BACKUP OUTPUT.$test_count 258 259test_begin_subtest 'format=batch-tag, restore=auto' 260notmuch dump --format=batch-tag > EXPECTED.$test_count 261notmuch tag -inbox -unread "*" 262notmuch restore --format=auto < EXPECTED.$test_count 263notmuch dump --format=batch-tag > OUTPUT.$test_count 264test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 265 266test_begin_subtest 'format=sup, restore=auto' 267notmuch dump --format=sup > EXPECTED.$test_count 268notmuch tag -inbox -unread "*" 269notmuch restore --format=auto < EXPECTED.$test_count 270notmuch dump --format=sup > OUTPUT.$test_count 271test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 272 273test_begin_subtest 'format=batch-tag, restore=default' 274notmuch dump --format=batch-tag > EXPECTED.$test_count 275notmuch tag -inbox -unread "*" 276notmuch restore < EXPECTED.$test_count 277notmuch dump --format=batch-tag > OUTPUT.$test_count 278test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 279 280test_begin_subtest 'format=sup, restore=default' 281notmuch dump --format=sup > EXPECTED.$test_count 282notmuch tag -inbox -unread "*" 283notmuch restore < EXPECTED.$test_count 284notmuch dump --format=sup > OUTPUT.$test_count 285test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 286 287test_begin_subtest 'restore: checking error messages' 288notmuch restore <<EOF 2>OUTPUT 289# the next line has a space 290 291a 292+0 293+a +b 294# trailing whitespace 295+a +b 296+c +d -- 297# this is a harmless comment, do not yell about it. 298 299# the previous line was blank; also no yelling please 300+%zz -- id:whatever 301+e +f id:" 302+e +f tag:abc 303# the next non-comment line should report an an empty tag error for 304# batch tagging, but not for restore 305+ +e -- id:20091117232137.GA7669@griffis1.net 306# valid id, but warning about missing message 307+e id:missing_message_id 308# exercise parser 309+e -- id:some)stuff 310+e -- id:some stuff 311+e -- id:some"stuff 312+e -- id:"a_message_id_with""_a_quote" 313+e -- id:"a message id with spaces" 314+e -- id:an_id_with_leading_and_trailing_ws \ 315 316EOF 317 318cat <<EOF > EXPECTED 319Warning: cannot parse query: a (skipping) 320Warning: no query string [+0] 321Warning: no query string [+a +b] 322Warning: missing query string [+a +b ] 323Warning: no query string after -- [+c +d --] 324Warning: hex decoding of tag %zz failed [+%zz -- id:whatever] 325Warning: cannot parse query: id:" (skipping) 326Warning: not an id query: tag:abc (skipping) 327Warning: cannot apply tags to missing message: missing_message_id 328Warning: cannot parse query: id:some)stuff (skipping) 329Warning: cannot parse query: id:some stuff (skipping) 330Warning: cannot apply tags to missing message: some"stuff 331Warning: cannot apply tags to missing message: a_message_id_with"_a_quote 332Warning: cannot apply tags to missing message: a message id with spaces 333Warning: cannot apply tags to missing message: an_id_with_leading_and_trailing_ws 334EOF 335 336test_expect_equal_file EXPECTED OUTPUT 337 338backup_database 339test_begin_subtest 'roundtripping random message-ids and tags' 340 341 ${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \ 342 --num-messages=100 343 344 notmuch dump --format=batch-tag| \ 345 sort > EXPECTED.$test_count 346 347 notmuch tag +this_tag_is_very_unlikely_to_be_random '*' 348 349 notmuch restore --format=batch-tag < EXPECTED.$test_count 350 351 notmuch dump --format=batch-tag| \ 352 sort > OUTPUT.$test_count 353 354test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count 355restore_database 356 357test_done 358 359