1#!/usr/bin/env bash 2test_description='"notmuch tag"' 3. $(dirname "$0")/test-lib.sh || exit 1 4 5test_query_syntax () { 6 # use a tag with a space to stress the query string munging code. 7 local new_tag="${RANDOM} ${RANDOM}" 8 test_begin_subtest "sexpr query: $1" 9 backup_database 10 notmuch tag --query=sexp "+${new_tag}" -- "$1" 11 notmuch dump > OUTPUT 12 restore_database 13 backup_database 14 notmuch tag "+${new_tag}" -- "$2" 15 notmuch dump > EXPECTED 16 restore_database 17 test_expect_equal_file_nonempty EXPECTED OUTPUT 18} 19 20add_message '[subject]=One' 21add_message '[subject]=Two' 22 23test_begin_subtest "Adding tags" 24notmuch tag +tag1 +tag2 +tag3 \* 25output=$(notmuch search \* | notmuch_search_sanitize) 26test_expect_equal "$output" "\ 27thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 tag2 tag3 unread) 28thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 tag3 unread)" 29 30test_begin_subtest "Removing tags" 31notmuch tag -tag1 -tag2 \* 32output=$(notmuch search \* | notmuch_search_sanitize) 33test_expect_equal "$output" "\ 34thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag3 unread) 35thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag3 unread)" 36 37test_begin_subtest "No tag operations" 38test_expect_code 1 'notmuch tag One' 39 40test_begin_subtest "No query" 41test_expect_code 1 'notmuch tag +tag2' 42 43test_begin_subtest "Redundant tagging" 44notmuch tag +tag1 -tag3 One 45notmuch tag +tag1 -tag3 \* 46output=$(notmuch search \* | notmuch_search_sanitize) 47test_expect_equal "$output" "\ 48thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread) 49thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)" 50 51test_begin_subtest "Remove all" 52notmuch tag --remove-all One 53notmuch tag --remove-all +tag5 +tag6 +unread Two 54output=$(notmuch search \* | notmuch_search_sanitize) 55test_expect_equal "$output" "\ 56thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One () 57thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (tag5 tag6 unread)" 58 59test_begin_subtest "Remove all with batch" 60notmuch tag +tag1 One 61notmuch tag --remove-all --batch <<EOF 62-- One 63+tag3 +tag4 +inbox -- Two 64EOF 65output=$(notmuch search \* | notmuch_search_sanitize) 66test_expect_equal "$output" "\ 67thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One () 68thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag3 tag4)" 69 70test_begin_subtest "Remove all with a no-op" 71notmuch tag +inbox +tag1 +unread One 72notmuch tag --remove-all +foo +inbox +tag1 -foo +unread Two 73output=$(notmuch search \* | notmuch_search_sanitize) 74test_expect_equal "$output" "\ 75thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread) 76thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)" 77 78test_begin_subtest "Special characters in tags" 79notmuch tag +':" ' \* 80notmuch tag -':" ' Two 81output=$(notmuch search \* | notmuch_search_sanitize) 82test_expect_equal "$output" "\ 83thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread) 84thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)" 85 86test_begin_subtest "Tagging order" 87notmuch tag +tag4 -tag4 One 88notmuch tag -tag4 +tag4 Two 89output=$(notmuch search \* | notmuch_search_sanitize) 90test_expect_equal "$output" "\ 91thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread) 92thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)" 93 94test_begin_subtest "--batch" 95notmuch tag --batch <<EOF 96# %20 is a space in tag 97-:"%20 -tag1 +tag5 +tag6 -- One 98+tag1 -tag1 -tag4 +tag4 -- Two 99-tag6 One 100+tag5 Two 101EOF 102output=$(notmuch search \* | notmuch_search_sanitize) 103test_expect_equal "$output" "\ 104thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag5 unread) 105thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag5 unread)" 106 107# generate a common input file for the next several tests. 108cat > batch.in <<EOF 109# %40 is an @ in tag 110+%40 -tag5 +tag6 -- One 111+tag1 -tag1 -tag4 +tag4 -- Two 112-tag5 +tag6 Two 113EOF 114 115cat > batch.expected <<EOF 116thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (@ inbox tag6 unread) 117thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag6 unread) 118EOF 119 120test_begin_subtest "--input" 121notmuch dump --format=batch-tag > backup.tags 122notmuch tag --input=batch.in 123notmuch search \* | notmuch_search_sanitize > OUTPUT 124notmuch restore --format=batch-tag < backup.tags 125test_expect_equal_file batch.expected OUTPUT 126 127test_begin_subtest "--batch --input" 128notmuch dump --format=batch-tag > backup.tags 129notmuch tag --batch --input=batch.in 130notmuch search \* | notmuch_search_sanitize > OUTPUT 131notmuch restore --format=batch-tag < backup.tags 132test_expect_equal_file batch.expected OUTPUT 133 134test_begin_subtest "--batch --input --remove-all" 135notmuch dump --format=batch-tag > backup.tags 136notmuch tag +foo +bar -- One 137notmuch tag +tag7 -- Two 138notmuch tag --batch --input=batch.in --remove-all 139notmuch search \* | notmuch_search_sanitize > OUTPUT 140notmuch restore --format=batch-tag < backup.tags 141cat > batch_removeall.expected <<EOF 142thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (@ tag6) 143thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (tag6) 144EOF 145test_expect_equal_file batch_removeall.expected OUTPUT 146rm batch_removeall.expected 147 148test_begin_subtest "--batch, dependence on previous line" 149notmuch dump --format=batch-tag > backup.tags 150notmuch tag --batch<<EOF 151+trigger -- One 152+second_tag -- tag:trigger 153EOF 154NOTMUCH_DUMP_TAGS tag:second_tag > OUTPUT 155notmuch restore --format=batch-tag < backup.tags 156cat <<EOF >EXPECTED 157+inbox +second_tag +tag5 +trigger +unread -- id:msg-001@notmuch-test-suite 158EOF 159test_expect_equal_file EXPECTED OUTPUT 160 161test_begin_subtest "--batch, blank lines and comments" 162notmuch dump | sort > EXPECTED 163notmuch tag --batch <<EOF 164# this line is a comment; the next has only white space 165 166 167# the previous line is empty 168EOF 169notmuch dump | sort > OUTPUT 170test_expect_equal_file EXPECTED OUTPUT 171 172test_begin_subtest '--batch: checking error messages' 173notmuch dump --format=batch-tag > BACKUP 174notmuch tag --batch <<EOF 2>OUTPUT 175# the next line has a space 176 177# this line has no tag operations, but this is permitted in batch format. 178a 179+0 180+a +b 181# trailing whitespace 182+a +b 183+c +d -- 184# this is a harmless comment, do not yell about it. 185 186# the previous line was blank; also no yelling please 187+%zz -- id:whatever 188# the next non-comment line should report an an empty tag error for 189# batch tagging, but not for restore 190+ +e -- id:foo 191+- -- id:foo 192EOF 193 194cat <<EOF > EXPECTED 195Warning: no query string [+0] 196Warning: no query string [+a +b] 197Warning: missing query string [+a +b ] 198Warning: no query string after -- [+c +d --] 199Warning: hex decoding of tag %zz failed [+%zz -- id:whatever] 200Warning: empty tag forbidden [+ +e -- id:foo] 201Warning: tag starting with '-' forbidden [+- -- id:foo] 202EOF 203 204notmuch restore --format=batch-tag < BACKUP 205test_expect_equal_file EXPECTED OUTPUT 206 207test_begin_subtest '--batch: tags with quotes' 208notmuch dump --format=batch-tag > BACKUP 209 210notmuch tag --batch <<EOF 211+%22%27%22%27%22%22%27%27 -- One 212-%22%27%22%27%22%22%27%27 -- One 213+%22%27%22%22%22%27 -- One 214+%22%27%22%27%22%22%27%27 -- Two 215EOF 216 217cat <<EOF > EXPECTED 218+%22%27%22%22%22%27 +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite 219+%22%27%22%27%22%22%27%27 +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite 220EOF 221 222NOTMUCH_DUMP_TAGS > OUTPUT 223notmuch restore --format=batch-tag < BACKUP 224test_expect_equal_file EXPECTED OUTPUT 225 226test_begin_subtest '--batch: tags with punctuation and space' 227notmuch dump --format=batch-tag > BACKUP 228 229notmuch tag --batch <<EOF 230+%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One 231-%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One 232+%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two 233-%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two 234+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One 235+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- Two 236EOF 237 238cat <<EOF > EXPECTED 239+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite 240+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite 241EOF 242 243NOTMUCH_DUMP_TAGS > OUTPUT 244notmuch restore --format=batch-tag < BACKUP 245test_expect_equal_file EXPECTED OUTPUT 246 247test_begin_subtest '--batch: unicode tags' 248notmuch dump --format=batch-tag > BACKUP 249 250notmuch tag --batch <<EOF 251+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 -- One 252+=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d -- One 253+A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 -- One 254+R -- One 255+%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 -- One 256+%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- One 257+L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 -- One 258+P%c4%98%2f -- One 259+%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d -- One 260+%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- One 261+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +R +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- Two 262EOF 263 264cat <<EOF > EXPECTED 265+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag4 +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-002@notmuch-test-suite 266+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-001@notmuch-test-suite 267EOF 268 269NOTMUCH_DUMP_TAGS > OUTPUT 270notmuch restore --format=batch-tag < BACKUP 271test_expect_equal_file EXPECTED OUTPUT 272 273test_begin_subtest "--batch: only space and % needs to be encoded." 274notmuch dump --format=batch-tag > BACKUP 275 276notmuch tag --batch <<EOF 277+winner * 278+foo::bar%25 -- (One and Two) or (One and tag:winner) 279+found::it -- tag:foo::bar% 280# ignore this line and the next 281 282+space%20in%20tags -- Two 283# add tag '(tags)', among other stunts. 284+crazy{ +(tags) +&are +#possible\ -- tag:"space in tags" 285+match*crazy -- tag:crazy{ 286+some_tag -- id:"this is ""nauty)""" 287EOF 288 289cat <<EOF > EXPECTED 290+%23possible%5c +%26are +%28tags%29 +crazy%7b +inbox +match%2acrazy +space%20in%20tags +tag4 +tag5 +unread +winner -- id:msg-002@notmuch-test-suite 291+foo%3a%3abar%25 +found%3a%3ait +inbox +tag5 +unread +winner -- id:msg-001@notmuch-test-suite 292EOF 293 294NOTMUCH_DUMP_TAGS > OUTPUT 295notmuch restore --format=batch-tag < BACKUP 296test_expect_equal_file EXPECTED OUTPUT 297 298test_begin_subtest '--batch: unicode message-ids' 299 300${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \ 301 --num-messages=100 302 303notmuch dump --format=batch-tag | sed 's/^.* -- /+common_tag -- /' | \ 304 sort > EXPECTED 305 306notmuch dump --format=batch-tag | sed 's/^.* -- / -- /' > INTERMEDIATE_STEP 307notmuch restore --format=batch-tag < INTERMEDIATE_STEP 308 309notmuch tag --batch < EXPECTED 310 311notmuch dump --format=batch-tag| \ 312 sort > OUTPUT 313 314test_expect_equal_file EXPECTED OUTPUT 315 316test_begin_subtest "Empty tag names" 317test_expect_code 1 'notmuch tag + One' 318 319test_begin_subtest "Tag name beginning with -" 320test_expect_code 1 'notmuch tag +- One' 321 322test_begin_subtest "Xapian exception: read only files" 323chmod u-w ${MAIL_DIR}/.notmuch/xapian/*.* 324output=$(notmuch tag +something '*' 2>&1 | sed 's/: .*$//' ) 325chmod u+w ${MAIL_DIR}/.notmuch/xapian/*.* 326test_expect_equal "$output" "A Xapian exception occurred opening database" 327 328add_email_corpus 329 330if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then 331 332 test_query_syntax '(and "wonderful" "wizard")' 'wonderful and wizard' 333 test_query_syntax '(or "php" "wizard")' 'php or wizard' 334 test_query_syntax 'wizard' 'wizard' 335 test_query_syntax 'Wizard' 'Wizard' 336 test_query_syntax '(attachment notmuch-help.patch)' 'attachment:notmuch-help.patch' 337 test_query_syntax '(mimetype text/html)' 'mimetype:text/html' 338 339 test_begin_subtest "--batch --query=sexp" 340 notmuch dump --format=batch-tag > backup.tags 341 notmuch tag --batch --query=sexp <<EOF 342 +all -- (or One Two) 343 +none -- (and One Two) 344 EOF 345 notmuch dump > OUTPUT 346 cat <<EOF > EXPECTED 347 #notmuch-dump batch-tag:3 config,properties,tags 348 +all +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite 349 +all +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite 350EOF 351 notmuch restore --format=batch-tag < backup.tags 352 test_expect_equal_file EXPECTED OUTPUT 353 354fi 355 356test_done 357