URI:
       test_curses.sh - sfeed_tests - sfeed tests and RSS and Atom files
  HTML git clone git://git.codemadness.org/sfeed_tests
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       test_curses.sh (45920B)
       ---
            1 #!/bin/sh
            2 # Dependencies: printf with support for \x, stty, awk, pgrep, pkill, sha256.
            3 #
            4 # Source-code modifications:
            5 # Disable pledge and unveil in util.h
            6 # To test all coverage before _exit add the definition: void __gcov_dump(void); and __gcov_dump() to flush reports.
            7 # Build: make CC=gcc CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs"
            8 #
            9 # TODO maybe, for now manual test it:
           10 # ? resources:
           11 #        - fork resource limit ulimit? maybe non-interactive and let many process wait.
           12 #        - memory limit ulimit?
           13 # ? auto test 't' with no items.
           14 # ? page_scrollpage: pages > 0 && if ((p->pos % p->height)).
           15 # ? terminal with size 0x0.
           16 # ? read errors: using /proc/self/mem? (Linux-specific).
           17 # ? write errors: using /dev/full? (Linux-specific).
           18 # ? test reload of feeds while the feed was removed:
           19 #   - lazyload case.
           20 #   - fseek case in feeds_load.
           21 # ? try to find the same feed in the pane but it is not visible anymore.
           22 #   steps: have feed with new items, press 't' and highlight the row: reload
           23 #          feed and make sure it has old items.
           24 # ? memory allocation failures: realloc, calloc, strdup.
           25 # ? open /dev/tty, /dev/null failure.
           26 
           27 #sc="sfeed_curses"
           28 
           29 sc="$(pwd)/sfeed_curses"
           30 markread="$(pwd)/sfeed_markread read"
           31 markunread="$(pwd)/sfeed_markread unread"
           32 
           33 cmd_sha256="$(command -v sha256)" # "sha256" typically on BSD
           34 if test -n "$cmd_sha256"; then
           35 sha() {
           36         sha256 -q # -q only print hash
           37 }
           38 else
           39 sha() {
           40         sha256sum | cut -f 1 -d ' ' # first field is hash
           41 }
           42 fi
           43 
           44 # TODO: portable POSIX wrapper for pgrep.
           45 # maybe: ps -U "$USER" -o pid=,command= | grep "$1" | sed -E 's@^[ ]*|[ ]*$@@g'
           46 #if test -z "$(command -v "pgrep")"; then
           47 #pgrep(programname)
           48 #pgrep() {
           49 #        ps -C "$1"
           50 #}
           51 #fi
           52 
           53 # TODO: portable POSIX wrapper for pkill.
           54 # maybe: pgrep "$1" | cut -f 1 -d ' '
           55 #if test -z "$(command -v "pkill")"; then
           56 # pkill(signal, programname)
           57 #pkill() {
           58 #        ps -C "$2" -o pid= | xargs kill "$1"
           59 #}
           60 #fi
           61 
           62 if test -f "/usr/bin/printf"; then
           63         printf="/usr/bin/printf" # busybox printf on Void Linux is dogshit.
           64 else
           65         printf="$(command -v printf)" # a printf with support for \x.
           66 fi
           67 
           68 test_count=1
           69 test_name=""
           70 test_start() {
           71         test_name="$1"
           72         $printf '[%s] #%d Test starting %s\n' "$(date +'%H:%M:%S')" "$test_count" "$test_name" >&2
           73 }
           74 
           75 test_end() {
           76         #$printf '[%s] #%d Test success: %s %s\n' "$(date +'%H:%M:%S')" "$test_count" "$test_name" "$1" >&2
           77         test_count=$((test_count+1))
           78 }
           79 
           80 fail() {
           81         $printf '[%s] #%d Test failed: %s %s\n' "$(date +'%H:%M:%S')" "$test_count" "$test_name" "$1" >&2
           82         cleanup
           83         exit $?
           84 }
           85 
           86 emptydata() {
           87         $printf ''
           88 }
           89 
           90 fakedata() {
           91         $printf '0\t1. a\thttp://a\n'
           92         $printf '1\t2. b\thttp://b\n'
           93         $printf '2\t3. c\thttp://c\n'
           94 }
           95 
           96 fakedata2() {
           97         $printf '3\t3. d\thttp://d\n'
           98         $printf '4\t4. e\thttp://e\n'
           99         $printf '5\t5. f\thttp://f\n'
          100 }
          101 
          102 fakedata3() {
          103         $printf '6\t6. g\thttp://g\n'
          104         $printf '2124567591\t7. h\thttp://h\n' # 2037-04-28
          105         $printf '\t8. i\thttp://i\tcontent\tplain\tid\tauthor\thttp://enclosure/file.mp3\n'
          106         $printf 'NEIN\t9. j\thttp://j\tcontent\tplain\tid\tauthor\thttp://enclosure2/file.mp3\n'
          107 }
          108 
          109 fakedata4() {
          110         $printf '15\t15. x\thttp://x\n'
          111         $printf '2124567591\t16. y\thttp://y\n' # 2037-04-28
          112         $printf '17\t17. z\thttp://z\n'
          113 }
          114 
          115 sausage="$($printf '\xe3\x82\xbd\xe3\x83\xbc\xe3\x82\xbb\xe3\x83\xbc\xe3\x82\xb8')" # japanese sausage
          116 dollar="$($printf '\xef\xbc\x84\xef\xbc\x84\xef\xbc\x84\xef\xbc\x84\xef\xbc\x84')" # big dollar 2 width
          117 invaliduni="$($printf '\xc3\xc3\xc3\xc3\xc3\xc3')"
          118 ctrl="$($printf 'a\tb\rc\nd')"
          119 wcneg="$($printf '\xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe')"
          120 
          121 fakedataunicode() {
          122         $printf '10\t10. 2 width \xef\xbc\x84\xef\xbc\x84\xef\xbc\x84\xef\xbc\x84\xef\xbc\x84\n' # "big dollar" 2 width
          123         $printf '11\t11. invalid \xc3\xc3\xc3\xc3\xc3\xc3\n' # invalid
          124         $printf '12\t12. replacement char \xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n' # replacement character
          125         $printf '13\t13. wcwidth -1 \xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe\xef\xbf\xbe\n' # codepoint 0xfffe, wcwidth -1 on some systems.
          126         $printf '14\t14. \xe3\x82\xbd\xe3\x83\xbc\xe3\x82\xbb\xe3\x83\xbc\xe3\x82\xb8\thttp://jp\n' # japanese sausage
          127 }
          128 
          129 muchdata() {
          130         # very wow
          131         echo | awk 'END {
          132                 for (i = 0;i < 500; i++)
          133                         printf("%d\t%d. %d\thttp://%d\n", i, i, i, i);
          134         }'
          135 }
          136 
          137 # setup: create files
          138 # feedfiles
          139 feedfile1=$(mktemp)
          140 feedfile2=$(mktemp)
          141 feedfile3=$(mktemp)
          142 feedfile4=$(mktemp)
          143 emptyfile=$(mktemp)
          144 fakedata > "$feedfile1"
          145 fakedata2 > "$feedfile2"
          146 fakedata3 > "$feedfile3"
          147 fakedata4 > "$feedfile4"
          148 emptydata > "$emptyfile"
          149 # URL file
          150 urlfile=$(mktemp)
          151 touch "$urlfile"
          152 
          153 pipefile="$(mktemp)"
          154 yankfile="$(mktemp)"
          155 
          156 plumbfile="$(mktemp)"
          157 plumbscript="$(mktemp)"
          158 $printf '#!/bin/sh\necho "$1" >"%s"\n' "$plumbfile" > "$plumbscript"
          159 chmod +x "$plumbscript"
          160 
          161 # terminal size.
          162 size=$(stty size)
          163 rows="${size%% *}"
          164 if test "$rows" = "0"; then
          165         rows="24" # serial console
          166 fi
          167 itemrows=$((rows - 1)) # -1 for bottom bar.
          168 
          169 cleanup() {
          170         rm -f \
          171                 "$urlfile" "$yankfile" "$pipefile" "$plumbfile" "$plumbscript" \
          172                 "$feedfile1" "$feedfile2" "$feedfile3" "$feedfile4" "$emptyfile"
          173 }
          174 
          175 # manual tests
          176 manual() {
          177         echo "Manual tests:"
          178         echo "* Press ^L to redraw the terminal."
          179         echo "* Test SIGWINCH by resizing the terminal: resize also to very small sizes in all layouts"
          180         echo "* Test resizing the sidebar in all layouts and resetting it by pressing ="
          181         echo ""
          182         echo "Press RETURN to continue"
          183         read p
          184         test_start "Manual tests"
          185         "$sc" "$feedfile1" "$feedfile2" "$feedfile3" "$emptyfile"
          186         test_end
          187 
          188         sleep 1
          189         echo "Was it OK? [y]/n"
          190         read answer
          191         if test "$answer" = "n"; then
          192                 cleanup
          193                 exit 1
          194         fi
          195 
          196         echo "Unicode data with various widths. Resize the terminal to proper test truncation and decoding."
          197         echo ""
          198         echo "Press RETURN to continue"
          199         read p
          200         test_start "Unicode"
          201         fakedataunicode | "$sc"
          202         test_end
          203 
          204         echo "Was it OK? [y]/n"
          205         read answer
          206         if test "$answer" = "n"; then
          207                 cleanup
          208                 exit 1
          209         fi
          210 
          211         echo "* Test filenames with unicode and multi-column characters"
          212         echo ""
          213         echo "Press RETURN to continue"
          214         read p
          215 
          216         test_start "Test filenames with unicode"
          217         tmpfile1="/tmp/sfeed_$sausage"
          218         tmpfile2="/tmp/sfeed_$invaliduni"
          219         tmpfile3="/tmp/sfeed_$dollar"
          220         tmpfile4="/tmp/sfeed_$ctrl"
          221         tmpfile5="/tmp/sfeed_$wcneg"
          222         cp "$feedfile1" "$tmpfile1"
          223         cp "$feedfile2" "$tmpfile2"
          224         cp "$feedfile3" "$tmpfile3"
          225         cp "$feedfile4" "$tmpfile4"
          226         cp "$feedfile4" "$tmpfile5"
          227         $sc "$tmpfile1" "$tmpfile2" "$tmpfile3" "$tmpfile4" "$tmpfile5"
          228         rm -f "$tmpfile1" "$tmpfile2" "$tmpfile3" "$tmpfile4" "$tmpfile5"
          229         test_end
          230 
          231         echo "Was it OK? [y]/n"
          232         read answer
          233         if test "$answer" = "n"; then
          234                 cleanup
          235                 exit 1
          236         fi
          237 
          238         echo "* Test SIGHUP to reload feed data, after 3 seconds it reloads the feed and the counts"
          239         echo "  should be different. Afterward manually close it by pressing q."
          240         echo ""
          241         echo "Press RETURN to continue"
          242         read p
          243 
          244         test_start "Test SIGHUP to reload feed data"
          245         tmpfile="$(mktemp)"
          246         cat "$feedfile2" > "$tmpfile"
          247         (sleep 3;cp "$feedfile3" "$tmpfile"; pkill -SIGHUP sfeed_curses) &
          248         SFEED_AUTOCMD="" "$sc" "$feedfile1" "$tmpfile"
          249         rm -f "$tmpfile"
          250         test_end
          251 
          252         echo "Was it OK? [y]/n"
          253         read answer
          254         if test "$answer" = "n"; then
          255                 cleanup
          256                 exit 1
          257         fi
          258 
          259         echo "* Test R to reload feed data, after 2 seconds press R to reloads the feed and the counts"
          260         echo "  should be different. Afterward manually close it by pressing q."
          261         echo ""
          262         echo "Press RETURN to continue"
          263         read p
          264 
          265         test_start "Test R to reload feed data"
          266         tmpfile="$(mktemp)"
          267         cat "$feedfile2" > "$tmpfile"
          268         # use muchdata so the counts are changed, should resizing the sidebar.
          269         (sleep 2;muchdata > "$tmpfile") &
          270         SFEED_AUTOCMD="" "$sc" "$feedfile1" "$tmpfile"
          271         rm -f "$tmpfile"
          272         test_end
          273 
          274         echo "Was it OK? [y]/n"
          275         read answer
          276         if test "$answer" = "n"; then
          277                 cleanup
          278                 exit 1
          279         fi
          280 
          281         echo "* Test SIGHUP to reload the URLs list. After 3 seconds it reloads the feed"
          282         echo "  and the first item should be non-bold. Afterward manually close it by pressing q."
          283         echo ""
          284         echo "Press RETURN to continue"
          285         read p
          286 
          287         test_start "Change URL contents externally. Reload URLs with R with stdin input (one-time read)"
          288         rm -f "/tmp/u"
          289         touch "/tmp/u"
          290         (sleep 2; echo "http://a" > "/tmp/u"; pkill -SIGHUP sfeed_curses) &
          291         fakedata | SFEED_URL_FILE="/tmp/u" SFEED_AUTOCMD="G" $sc
          292         status=$?
          293         test $status -eq 0 || fail "Exit code must be 0, was: $status"
          294         rm -f "/tmp/u"
          295         test_end
          296 
          297         echo "Was it OK? [y]/n"
          298         read answer
          299         if test "$answer" = "n"; then
          300                 cleanup
          301                 exit 1
          302         fi
          303 
          304         echo "* Test SIGHUP while the piper program is open. After 3 seconds it sends SIGHUP."
          305         echo "  After closing the piper program after 3 seconds the signal is queued and it"
          306         echo "  should handle the reload event. The counts of the second feed should be"
          307         echo "  new / bold. Afterward manually close it by pressing q."
          308         echo ""
          309         echo "Press RETURN to continue"
          310         read p
          311 
          312         test_start "Test SIGHUP to reload feed data while piper program is open"
          313         tmpfile="$(mktemp)"
          314         cat "$feedfile2" > "$tmpfile"
          315         (sleep 3;cp "$feedfile3" "$tmpfile"; pkill -SIGHUP sfeed_curses) &
          316         SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="less" SFEED_AUTOCMD="lp" "$sc" "$feedfile1" "$tmpfile"
          317         rm -f "$tmpfile"
          318         test_end
          319 
          320         echo "Was it OK? [y]/n"
          321         read answer
          322         if test "$answer" = "n"; then
          323                 cleanup
          324                 exit 1
          325         fi
          326 
          327         echo "Test exit status of mark read program: if it returns 0 the item"
          328         echo "is marked. Press r to test it. It should mark the items as read."
          329         echo ""
          330         echo "Press RETURN to continue"
          331         read p
          332 
          333         test_start "Test exit status of mark read: exit status zero"
          334         rm -f "$urlfile"
          335         touch "$urlfile"
          336         fakedata | SFEED_URL_FILE="$urlfile" SFEED_MARK_READ="true" $sc
          337         test_end
          338 
          339         echo "Was it OK? [y]/n"
          340         read answer
          341         if test "$answer" = "n"; then
          342                 cleanup
          343                 exit 1
          344         fi
          345 
          346         echo "Test exit status of mark read program: if it returns non-zero the item"
          347         echo "is not marked. Press r to test it, it should NOT mark the items as read."
          348         echo ""
          349         echo "Press RETURN to continue"
          350         read p
          351 
          352         test_start "Test exit status of mark read: exit status non-zero"
          353         rm -f "$urlfile"
          354         touch "$urlfile"
          355         fakedata | SFEED_URL_FILE="$urlfile" SFEED_MARK_READ="false" $sc
          356         test_end
          357 
          358         echo "Was it OK? [y]/n"
          359         read answer
          360         if test "$answer" = "n"; then
          361                 cleanup
          362                 exit 1
          363         fi
          364 }
          365 
          366 # -m runs manual tests only.
          367 if test "$1" = "-m"; then
          368         manual
          369         cleanup
          370         exit
          371 fi
          372 
          373 test_start "Search feed name"
          374 n=$(basename "$feedfile2")
          375 rm -f "$yankfile"
          376 touch "$yankfile"
          377 SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="cat >$yankfile" SFEED_AUTOCMD="$($printf '/%s\r' "$n")olyq" $sc "$feedfile1" "$feedfile2" "$feedfile3" "$feedfile4"
          378 status=$?
          379 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          380 contents="$(cat "$yankfile")"
          381 test "$contents" = "http://d" || fail "Incorrect URL: $contents"
          382 test_end
          383 
          384 test_start "Forward searching and yanking an URL"
          385 rm -f "$yankfile"
          386 touch "$yankfile"
          387 # NOTE: interactive is needed, else it could spawn and close too fast.
          388 fakedata | SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="cat >$yankfile" SFEED_AUTOCMD="$($printf '/\b3\b2\nyq')" $sc
          389 status=$?
          390 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          391 contents="$(cat "$yankfile")"
          392 test "$contents" = "http://b" || fail "Incorrect URL: $contents"
          393 test_end
          394 
          395 test_start "Forward searching (unicode) and yanking an URL"
          396 rm -f "$yankfile"
          397 touch "$yankfile"
          398 # NOTE: interactive is needed, else it could spawn and close too fast.
          399 fakedataunicode | SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="cat >$yankfile" SFEED_AUTOCMD="$($printf '/%s\r' "$sausage")yq" $sc
          400 status=$?
          401 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          402 contents="$(cat "$yankfile")"
          403 test "$contents" = "http://jp" || fail "Incorrect URL: $contents"
          404 test_end
          405 
          406 test_start "Monocle layout: toggle between panes with TAB."
          407 rm -f "$plumbfile"
          408 touch "$plumbfile"
          409 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="l3        jooq" $sc "$feedfile1" "$feedfile2" "$feedfile3"
          410 status=$?
          411 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          412 contents="$(cat "$plumbfile")"
          413 test "$contents" = "http://d" || fail "Incorrect URL: $contents"
          414 test_end
          415 
          416 test_start "Pipe: nonexistant command"
          417 rm -f "$pipefile"
          418 touch "$pipefile"
          419 fakedata | SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="/nonexist" SFEED_AUTOCMD="pq" $sc
          420 status=$?
          421 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          422 contents="$(cat "$pipefile")"
          423 line1=""
          424 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
          425 test_end
          426 
          427 test_start "Plumb: nonexistant command"
          428 rm -f "$plumbfile"
          429 touch "$plumbfile"
          430 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="/nonexist" SFEED_AUTOCMD="oq" $sc
          431 status=$?
          432 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          433 contents="$(cat "$plumbfile")"
          434 test "$contents" = "" || fail "Incorrect URL: $contents"
          435 test_end
          436 
          437 test_start "Yank: nonexistant command"
          438 rm -f "$yankfile"
          439 touch "$yankfile"
          440 # NOTE: interactive is needed, else it could spawn and close too fast.
          441 fakedata | SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="/nonexist" SFEED_AUTOCMD="$($printf '/\b3\b2\nyq')" $sc
          442 status=$?
          443 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          444 contents="$(cat "$yankfile")"
          445 test "$contents" = "" || fail "Incorrect URL: $contents"
          446 test_end
          447 
          448 # empty command should not exec and do nothing.
          449 test_start "Pipe: empty command"
          450 rm -f "$pipefile"
          451 touch "$pipefile"
          452 fakedata | SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="" SFEED_AUTOCMD="pq" $sc
          453 status=$?
          454 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          455 contents="$(cat "$pipefile")"
          456 line1=""
          457 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
          458 test_end
          459 
          460 # empty command should not exec and do nothing.
          461 test_start "Plumb: empty command"
          462 rm -f "$plumbfile"
          463 touch "$plumbfile"
          464 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="" SFEED_AUTOCMD="oq" $sc
          465 status=$?
          466 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          467 contents="$(cat "$plumbfile")"
          468 test "$contents" = "" || fail "Incorrect URL: $contents"
          469 test_end
          470 
          471 # empty command should not exec and do nothing.
          472 test_start "Yank: empty command"
          473 rm -f "$yankfile"
          474 touch "$yankfile"
          475 fakedata | SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="" SFEED_AUTOCMD="$($printf '/\b3\b2\nyq')" $sc
          476 status=$?
          477 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          478 contents="$(cat "$yankfile")"
          479 test "$contents" = "" || fail "Incorrect URL: $contents"
          480 test_end
          481 
          482 test_start "Test \$SFEED_FEED_PATH"
          483 rm -f "$yankfile"
          484 touch "$yankfile"
          485 SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="echo \$SFEED_FEED_PATH >$yankfile" SFEED_AUTOCMD="lyq" $sc "$feedfile1"
          486 status=$?
          487 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          488 contents="$(cat "$yankfile")"
          489 test "$contents" = "$feedfile1" || fail "Incorrect content: $contents"
          490 test_end
          491 
          492 test_start "Test \$SFEED_FEED_PATH for stdin"
          493 rm -f "$yankfile"
          494 touch "$yankfile"
          495 fakedata | SFEED_YANKER_INTERACTIVE="1" SFEED_YANKER="echo a\$SFEED_FEED_PATH >$yankfile" SFEED_AUTOCMD="yq" $sc
          496 status=$?
          497 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          498 contents="$(cat "$yankfile")"
          499 test "$contents" = "a" || fail "Incorrect content: $contents"
          500 test_end
          501 
          502 # Switch to monocle layout: navigation:
          503 # select second feed and open it (opens items pane). Switch to feed pane with left key and
          504 # go one row down and open the next feed. Switch left and right and open the first item.
          505 test_start "Monocle layout: test navigation"
          506 rm -f "$plumbfile"
          507 touch "$plumbfile"
          508 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3johjo$($printf '\x1b[D')loq" $sc "$feedfile1" "$feedfile2" "$feedfile3"
          509 status=$?
          510 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          511 contents="$(cat "$plumbfile")"
          512 test "$contents" = "http://g" || fail "Incorrect URL: $contents"
          513 test_end
          514 
          515 test_start "Navigation keys: up arrow"
          516 expectedurl="http://h"
          517 rm -f "$plumbfile"
          518 touch "$plumbfile"
          519 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="G$($printf '\x1b[A\x1bOA')oq" $sc
          520 status=$?
          521 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          522 contents="$(cat "$plumbfile")"
          523 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          524 test_end
          525 
          526 test_start "Navigation keys: up"
          527 expectedurl="http://h"
          528 rm -f "$plumbfile"
          529 touch "$plumbfile"
          530 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1bOF')kkoq" $sc
          531 status=$?
          532 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          533 contents="$(cat "$plumbfile")"
          534 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          535 test_end
          536 
          537 test_start "Navigation keys: home"
          538 expectedurl="http://g"
          539 rm -f "$plumbfile"
          540 touch "$plumbfile"
          541 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="G$($printf '\x1b[H')oq" $sc
          542 status=$?
          543 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          544 contents="$(cat "$plumbfile")"
          545 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          546 test_end
          547 
          548 test_start "Navigation keys 2: home"
          549 expectedurl="http://g"
          550 rm -f "$plumbfile"
          551 touch "$plumbfile"
          552 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="G$($printf '\x1b[1~')oq" $sc
          553 status=$?
          554 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          555 contents="$(cat "$plumbfile")"
          556 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          557 test_end
          558 
          559 test_start "Navigation keys: home key (urxvt)"
          560 expectedurl="http://g"
          561 rm -f "$plumbfile"
          562 touch "$plumbfile"
          563 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="G$($printf '\x1b[7~')oq" $sc
          564 status=$?
          565 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          566 contents="$(cat "$plumbfile")"
          567 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          568 test_end
          569 
          570 test_start "Navigation keys: end key (urxvt)"
          571 expectedurl="http://j"
          572 rm -f "$plumbfile"
          573 touch "$plumbfile"
          574 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[8~')oq" $sc
          575 status=$?
          576 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          577 contents="$(cat "$plumbfile")"
          578 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          579 test_end
          580 
          581 test_start "Navigation keys: home key (SUN)"
          582 expectedurl="http://g"
          583 rm -f "$plumbfile"
          584 touch "$plumbfile"
          585 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="G$($printf '\x1b[214z')oq" $sc
          586 status=$?
          587 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          588 contents="$(cat "$plumbfile")"
          589 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          590 test_end
          591 
          592 test_start "Navigation keys: end key (SUN)"
          593 expectedurl="http://j"
          594 rm -f "$plumbfile"
          595 touch "$plumbfile"
          596 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[220z')oq" $sc
          597 status=$?
          598 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          599 contents="$(cat "$plumbfile")"
          600 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          601 test_end
          602 
          603 test_start "Navigation keys: unsupported DEC application key INSERT"
          604 fakedata3 | SFEED_AUTOCMD="$($printf '\x1b[2~')q" $sc
          605 status=$?
          606 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          607 test_end
          608 
          609 test_start "Navigation keys: unsupported DEC application key F13"
          610 fakedata3 | SFEED_AUTOCMD="$($printf '\x1b[25~')q" $sc
          611 status=$?
          612 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          613 test_end
          614 
          615 test_start "Navigation keys: unsupported DEC application key, unclosed ~"
          616 fakedata3 | SFEED_AUTOCMD="$($printf '\x1b[2')qq" $sc # NOTE: qq to force-close it since sequence must end with non-digit.
          617 status=$?
          618 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          619 test_end
          620 
          621 test_start "Run it with empty data"
          622 emptydata | SFEED_AUTOCMD="q" $sc
          623 status=$?
          624 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          625 test_end
          626 
          627 test_start "Run with empty data and an URL file"
          628 rm -f "$urlfile"
          629 touch "$urlfile"
          630 emptydata | SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="q" $sc
          631 status=$?
          632 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          633 test_end
          634 
          635 test_start "Run with empty data and an URL file which does not exist"
          636 emptydata | SFEED_URL_FILE="/tmp/notexist" SFEED_AUTOCMD="q" $sc
          637 status=$?
          638 test $status -eq 1 || fail "Exit code must be 1, was: $status"
          639 test_end
          640 
          641 test_start "Mark URL as read. Mark first 2 entries as read"
          642 rm -f "$urlfile"
          643 touch "$urlfile"
          644 fakedata | SFEED_MARK_READ="$markread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="rrq" $sc
          645 status=$?
          646 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          647 expect="997864e8cb6fd5ab981f7d64e9817fd80871dd1172dbd04849db6fefa9dd0208"
          648 result=$(sha < "$urlfile")
          649 test "$result" = "$expect" || fail "Invalid result"
          650 test_end
          651 
          652 test_start "Mark URL as read. Mark first 2 entries as read. Mark already read items as read"
          653 rm -f "$urlfile"
          654 touch "$urlfile"
          655 fakedata | SFEED_MARK_READ="$markread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="rrgjrq" $sc
          656 status=$?
          657 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          658 expect="997864e8cb6fd5ab981f7d64e9817fd80871dd1172dbd04849db6fefa9dd0208"
          659 result=$(sha < "$urlfile")
          660 test "$result" = "$expect" || fail "Invalid result"
          661 test_end
          662 
          663 test_start "Mark URL as read. Select second entry and mark as unread"
          664 fakedata | SFEED_MARK_UNREAD="$markunread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="juq" $sc
          665 status=$?
          666 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          667 result=$(cat "$urlfile")
          668 expect="http://a"
          669 test "$result" = "$expect" || fail "Invalid result"
          670 test_end
          671 
          672 test_start "Mark all URLs of a feed as read"
          673 rm -f "$urlfile"
          674 touch "$urlfile"
          675 fakedata | SFEED_MARK_READ="$markread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="fq" $sc  "$feedfile1" "$feedfile2"
          676 status=$?
          677 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          678 expect="da4a1d3a7c80beb04e451c6c02a7a321a69e87abcee2178e7411f6b5d8e3960d"
          679 result=$(sha < "$urlfile")
          680 test "$result" = "$expect" || fail "Invalid result"
          681 test_end
          682 
          683 test_start "Mark first 2 feeds read, then mark URLs of first feed as unread"
          684 rm -f "$urlfile"
          685 touch "$urlfile"
          686 SFEED_MARK_READ="$markread" SFEED_MARK_UNREAD="$markunread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="fjofgFq" $sc "$feedfile1" "$feedfile2"
          687 status=$?
          688 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          689 expect="da4a1d3a7c80beb04e451c6c02a7a321a69e87abcee2178e7411f6b5d8e3960d"
          690 result=$(sha < "$urlfile")
          691 test "$result" = "$expect" || fail "Invalid result"
          692 test_end
          693 
          694 test_start "Mark all items of the first 2 feeds as read"
          695 rm -f "$urlfile"
          696 touch "$urlfile"
          697 fakedata | SFEED_MARK_READ="$markread" SFEED_URL_FILE="$urlfile" SFEED_AUTOCMD="fjofq" $sc "$feedfile1" "$feedfile2"
          698 status=$?
          699 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          700 expect="9228e2265258aa0c4afe33a129b4484f9b1d01e10ad30333a2139beb6bb0881d"
          701 result=$(sha < "$urlfile")
          702 test "$result" = "$expect" || fail "Invalid result"
          703 test_end
          704 
          705 test_start "Backward search and plumb script"
          706 rm -f "$plumbfile"
          707 touch "$plumbfile"
          708 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="llG$($printf '?2\noq')" $sc "$feedfile1" "$feedfile2"
          709 status=$?
          710 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          711 contents="$(cat "$plumbfile")"
          712 test "$contents" = "http://b" || fail "Incorrect URL: $contents"
          713 test_end
          714 
          715 test_start "Pipe contents of item to a pipe script"
          716 rm -f "$pipefile"
          717 touch "$pipefile"
          718 fakedata | SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="cat >$pipefile" SFEED_AUTOCMD="pq" $sc
          719 status=$?
          720 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          721 contents="$(cat "$pipefile")"
          722 line1="$($printf '0\t1. a\thttp://a\t\t\t\t\t\t\n')"
          723 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
          724 test_end
          725 
          726 test_start "Plumb script"
          727 rm -f "$plumbfile"
          728 touch "$plumbfile"
          729 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="oq" $sc
          730 status=$?
          731 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          732 contents="$(cat "$plumbfile")"
          733 test "$contents" = "http://a" || fail "Incorrect URL: $contents"
          734 test_end
          735 
          736 test_start "Plumb script and lazyload"
          737 rm -f "$plumbfile"
          738 touch "$plumbfile"
          739 SFEED_LAZYLOAD="1" SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="loq" $sc "$feedfile1" "$feedfile2"
          740 status=$?
          741 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          742 contents="$(cat "$plumbfile")"
          743 test "$contents" = "http://a" || fail "Incorrect URL: $contents"
          744 test_end
          745 
          746 test_start "Toggle new feeds in sidebar, but there are none"
          747 rm -f "$plumbfile"
          748 touch "$plumbfile"
          749 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="toloq" $sc "$emptyfile"
          750 status=$?
          751 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          752 contents="$(cat "$plumbfile")"
          753 test "$contents" = "" || fail "Incorrect URL: $contents"
          754 test_end
          755 
          756 test_start "Toggle new feeds in sidebar (horizontal mode), but there are none"
          757 rm -f "$plumbfile"
          758 touch "$plumbfile"
          759 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="2toloq" $sc "$emptyfile"
          760 status=$?
          761 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          762 contents="$(cat "$plumbfile")"
          763 test "$contents" = "" || fail "Incorrect URL: $contents"
          764 test_end
          765 
          766 test_start "Select a new feed in the sidebar, toggle new feeds: make sure it selects the same item"
          767 rm -f "$plumbfile"
          768 touch "$plumbfile"
          769 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="Gktoloq" $sc "$feedfile1" "$feedfile3" "$feedfile4" "$feedfile2"
          770 status=$?
          771 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          772 contents="$(cat "$plumbfile")"
          773 test "$contents" = "http://x" || fail "Incorrect URL: $contents"
          774 test_end
          775 
          776 test_start "Jump to next bold item"
          777 rm -f "$plumbfile"
          778 touch "$plumbfile"
          779 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="JolJoq" $sc "$feedfile1" "$feedfile2" "$feedfile3" "$feedfile4"
          780 status=$?
          781 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          782 expect="http://h"
          783 contents="$(cat "$plumbfile")"
          784 test "$contents" = "$expect" || fail "Incorrect URL: $contents"
          785 test_end
          786 
          787 test_start "Jump to previous bold item"
          788 rm -f "$plumbfile"
          789 touch "$plumbfile"
          790 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="GKolGKoq" $sc "$feedfile1" "$feedfile2" "$feedfile3" "$feedfile4"
          791 status=$?
          792 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          793 expect="http://h"
          794 contents="$(cat "$plumbfile")"
          795 test "$contents" = "$expect" || fail "Incorrect URL: $contents"
          796 test_end
          797 
          798 test_start "Jump to next or previous bold item but there are none"
          799 rm -f "$plumbfile"
          800 touch "$plumbfile"
          801 emptydata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="JJKKoq" $sc
          802 status=$?
          803 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          804 expect=""
          805 contents="$(cat "$plumbfile")"
          806 test "$contents" = "$expect" || fail "Incorrect URL: $contents"
          807 test_end
          808 
          809 test_start "Plumb script (enclosure)"
          810 rm -f "$plumbfile"
          811 touch "$plumbfile"
          812 fakedata3 | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="jjeq" $sc
          813 status=$?
          814 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          815 contents="$(cat "$plumbfile")"
          816 test "$contents" = "http://enclosure/file.mp3" || fail "Incorrect URL: $contents"
          817 test_end
          818 
          819 # monocle layout: open second feed (switches pane to item in monocle mode),
          820 # open second item.
          821 test_start "Monocle layout: open second feed (switches pane to item in monocle mode)"
          822 rm -f "$plumbfile"
          823 touch "$plumbfile"
          824 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3jojoq" $sc "$feedfile1" "$feedfile2"
          825 status=$?
          826 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          827 contents="$(cat "$plumbfile")"
          828 test "$contents" = "http://e" || fail "Incorrect URL: $contents"
          829 test_end
          830 
          831 test_start "Load first and second feed, switch to item and open it"
          832 rm -f "$plumbfile"
          833 touch "$plumbfile"
          834 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="]]l$($printf '\x1b[C')joq" $sc "$feedfile1" "$feedfile2"
          835 status=$?
          836 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          837 contents="$(cat "$plumbfile")"
          838 test "$contents" = "http://e" || fail "Incorrect URL: $contents"
          839 test_end
          840 
          841 # arrow key navigation.
          842 # monocle layout: arrow down, open second feed (switches pane to item in monocle mode),
          843 # page down, open item.
          844 test_start "Monocle layout: arrow keys: open second feed (switches pane to item in monocle mode)"
          845 rm -f "$plumbfile"
          846 touch "$plumbfile"
          847 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3hh$($printf '\x1b[B')o$($printf '\x1b[6~')oq" $sc "$feedfile1" "$feedfile2"
          848 status=$?
          849 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          850 contents="$(cat "$plumbfile")"
          851 test "$contents" = "http://f" || fail "Incorrect URL: $contents"
          852 test_end
          853 
          854 # arrow key navigation.
          855 # monocle layout: arrow down, open second feed (switches pane to item in monocle mode),
          856 # page down, open item.
          857 test_start "Monocle layout: arrow keys 2: open second feed (switches pane to item in monocle mode)"
          858 rm -f "$plumbfile"
          859 touch "$plumbfile"
          860 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3$($printf '\x1bOB')o$($printf '\x1b[6~')oq" $sc "$feedfile1" "$feedfile2"
          861 status=$?
          862 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          863 contents="$(cat "$plumbfile")"
          864 test "$contents" = "http://f" || fail "Incorrect URL: $contents"
          865 test_end
          866 
          867 test_start "Scroll 3 pages down and one up (selecting the last item of that page)"
          868 expectedurl="http://$((itemrows * 3 - 1))"
          869 rm -f "$plumbfile"
          870 touch "$plumbfile"
          871 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="   $($printf '\x1b[5~')oq" $sc
          872 status=$?
          873 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          874 contents="$(cat "$plumbfile")"
          875 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          876 test_end
          877 
          878 test_start "SUN keys: scroll 3 pages down and one up (selecting the last item of that page)"
          879 expectedurl="http://$((itemrows * 3 - 1))"
          880 rm -f "$plumbfile"
          881 touch "$plumbfile"
          882 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[222z\x1b[222z\x1b[222z\x1b[216z')oq" $sc
          883 status=$?
          884 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          885 contents="$(cat "$plumbfile")"
          886 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          887 test_end
          888 
          889 test_start "SCO keys: scroll 3 pages down and one up (selecting the last item of that page)"
          890 expectedurl="http://$((itemrows * 3 - 1))"
          891 rm -f "$plumbfile"
          892 touch "$plumbfile"
          893 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[G\x1b[G\x1b[G\x1b[I')oq" $sc
          894 status=$?
          895 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          896 contents="$(cat "$plumbfile")"
          897 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          898 test_end
          899 
          900 test_start "End key: go to last item"
          901 expectedurl="http://499"
          902 rm -f "$plumbfile"
          903 touch "$plumbfile"
          904 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[4~')oq" $sc
          905 status=$?
          906 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          907 contents="$(cat "$plumbfile")"
          908 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
          909 test_end
          910 
          911 # toggle to monocle
          912 # monocle layout: open second feed (switches pane to item in monocle mode),
          913 # open second item.
          914 test_start "Toggle to monocle layout: open second feed (switches pane to item in monocle mode)"
          915 rm -f "$plumbfile"
          916 touch "$plumbfile"
          917 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="sjojoq" $sc "$feedfile1" "$feedfile2"
          918 status=$?
          919 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          920 contents="$(cat "$plumbfile")"
          921 test "$contents" = "http://e" || fail "Incorrect URL: $contents"
          922 test_end
          923 
          924 # Test mouse, reference:
          925 #
          926 # mouse button encoding:
          927 # 0 is left button
          928 # 1 is middle button
          929 # 2 is right button
          930 # 64 scroll up
          931 # 65 scroll down
          932 # 128 side button, button 7 backward
          933 # 129 side button, button 8 forward
          934 #
          935 # SGR:
          936 # m is press, M is release
          937 #
          938 # SGR mouse:
          939 
          940 test_start "Mouse SGR: left button, press column (x, y) = (1, 2) which is the second row, double-click"
          941 rm -f "$plumbfile"
          942 touch "$plumbfile"
          943 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[<0;1;2M\x1b[<0;1;2m\x1b[<0;1;2M\x1b[<0;1;2m')q" "$sc"
          944 status=$?
          945 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          946 contents="$(cat "$plumbfile")"
          947 test "$contents" = "http://b" || fail "Incorrect content: $contents"
          948 test_end
          949 
          950 test_start "Mouse SGR: left button, press column (x, y) = (1, 2) which loads the second feed"
          951 rm -f "$plumbfile"
          952 touch "$plumbfile"
          953 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[<0;1;2M\x1b[<0;1;2m')loq" "$sc" "$feedfile1" "$feedfile2"
          954 status=$?
          955 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          956 contents="$(cat "$plumbfile")"
          957 test "$contents" = "http://d" || fail "Incorrect content: $contents"
          958 test_end
          959 
          960 test_start "Mouse SGR: right button, pipe contents of item to a pipe script"
          961 rm -f "$pipefile"
          962 touch "$pipefile"
          963 fakedata | SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="cat >$pipefile" SFEED_AUTOCMD="$($printf '\x1b[<2;1;2M\x1b[<2;1;2m')q" $sc
          964 status=$?
          965 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          966 contents="$(cat "$pipefile")"
          967 line1="$($printf '1\t2. b\thttp://b\t\t\t\t\t\t\n')"
          968 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
          969 test_end
          970 
          971 test_start "Mouse SGR: side button 7"
          972 rm -f "$plumbfile"
          973 touch "$plumbfile"
          974 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3o$($printf '\x1b[<128;1;2M\x1b[<128;1;2m\x1b[<128;1;2M\x1b[<128;1;2m')jooq" "$sc" "$feedfile1" "$feedfile2"
          975 status=$?
          976 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          977 contents="$(cat "$plumbfile")"
          978 test "$contents" = "http://d" || fail "Incorrect content: $contents"
          979 test_end
          980 
          981 test_start "Mouse SGR: side button 8"
          982 rm -f "$plumbfile"
          983 touch "$plumbfile"
          984 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3joh$($printf '\x1b[<129;1;2M\x1b[<129;1;2m\x1b[<129;1;2M\x1b[<129;1;2m')oq" "$sc" "$feedfile1" "$feedfile2"
          985 status=$?
          986 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          987 contents="$(cat "$plumbfile")"
          988 test "$contents" = "http://d" || fail "Incorrect content: $contents"
          989 test_end
          990 
          991 test_start "Mouse SGR: scroll 3 pages down and one up (selecting the last item of that page)"
          992 expectedurl="http://$((itemrows * 3 - 1))"
          993 rm -f "$plumbfile"
          994 touch "$plumbfile"
          995 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[<65;1;1M\x1b[<65;1;1M\x1b[<65;1;1M\x1b[<64;1;1M')oq" $sc
          996 status=$?
          997 test $status -eq 0 || fail "Exit code must be 0, was: $status"
          998 contents="$(cat "$plumbfile")"
          999 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
         1000 test_end
         1001 
         1002 test_start "Mouse X10: left button, press column (x, y) = (1, 2) which is the second row, double-click"
         1003 rm -f "$plumbfile"
         1004 touch "$plumbfile"
         1005 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[M !"\x1b[M#!"\x1b[M !"\x1b[M#!"')q" "$sc"
         1006 status=$?
         1007 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1008 contents="$(cat "$plumbfile")"
         1009 test "$contents" = "http://b" || fail "Incorrect URL: $contents"
         1010 test_end
         1011 
         1012 test_start "Mouse X10: right button, pipe contents of item to a pipe script"
         1013 rm -f "$pipefile"
         1014 touch "$pipefile"
         1015 fakedata | SFEED_PIPER_INTERACTIVE="1" SFEED_PIPER="cat >$pipefile" SFEED_AUTOCMD="$($printf '\x1b[M"!"\x1b[M#!"')q" $sc
         1016 status=$?
         1017 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1018 contents="$(cat "$pipefile")"
         1019 line1="$($printf '1\t2. b\thttp://b\t\t\t\t\t\t\n')"
         1020 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
         1021 test_end
         1022 
         1023 test_start "Mouse X10: scroll 3 pages down and one up (selecting the last item of that page)"
         1024 expectedurl="http://$((itemrows * 3 - 1))"
         1025 rm -f "$plumbfile"
         1026 touch "$plumbfile"
         1027 muchdata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="$($printf '\x1b[Ma!!\x1b[Ma!!\x1b[Ma!!\x1b[M`!!')oq" $sc
         1028 status=$?
         1029 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1030 contents="$(cat "$plumbfile")"
         1031 test "$contents" = "$expectedurl" || fail "Incorrect URL: $contents"
         1032 test_end
         1033 
         1034 test_start "Mouse X10: side button 7"
         1035 rm -f "$plumbfile"
         1036 touch "$plumbfile"
         1037 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3o$($printf '\x1b[M\xa0!!\x1b[M#!!')jooq" "$sc" "$feedfile1" "$feedfile2"
         1038 status=$?
         1039 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1040 contents="$(cat "$plumbfile")"
         1041 test "$contents" = "http://d" || fail "Incorrect content: $contents"
         1042 test_end
         1043 
         1044 test_start "Mouse X10: side button 8"
         1045 rm -f "$plumbfile"
         1046 touch "$plumbfile"
         1047 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3joh$($printf '\x1b[M\xa1!!\x1b[M#!!')oq" "$sc" "$feedfile1" "$feedfile2"
         1048 status=$?
         1049 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1050 contents="$(cat "$plumbfile")"
         1051 test "$contents" = "http://d" || fail "Incorrect content: $contents"
         1052 test_end
         1053 
         1054 # monocle layout: arrow down, open second feed (switches pane to item in monocle mode),
         1055 # scroll down, open item.
         1056 test_start "Monocle layout: mouse scroll down, open second feed (switches pane to item in monocle mode)"
         1057 rm -f "$plumbfile"
         1058 touch "$plumbfile"
         1059 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="3$($printf '\x1b[B')o$($printf '\x1b[<65;1;2M\x1b[<65;1;2m')oq" $sc "$feedfile1" "$feedfile2"
         1060 status=$?
         1061 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1062 contents="$(cat "$plumbfile")"
         1063 test "$contents" = "http://f" || fail "Incorrect URL: $contents"
         1064 test_end
         1065 
         1066 # Select pane items with keybind, then mouse side button 7 backward, go one item down,
         1067 # open it, switch to items pane with TAB, open item.
         1068 test_start "Mouse: side button 7, switches to feeds pane. Then open the item"
         1069 rm -f "$plumbfile"
         1070 touch "$plumbfile"
         1071 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="l$($printf '\x1b[<128;1;2M\x1b[<128;1;2m')jo        joq" "$sc" "$feedfile1" "$feedfile2"
         1072 status=$?
         1073 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1074 contents="$(cat "$plumbfile")"
         1075 test "$contents" = "http://e" || fail "Incorrect URL: $contents"
         1076 test_end
         1077 
         1078 # mouse disabled (toggle off), left button, press column (x, y) = (1, 2)
         1079 # which is the second row, double-click. So this should not do anything.
         1080 test_start "Mouse disabled (toggle off), left button, press column (x, y) = (1, 2)"
         1081 rm -f "$plumbfile"
         1082 touch "$plumbfile"
         1083 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="m$($printf '\x1b[<0;1;2M\x1b[<0;1;2m\x1b[<0;1;2M\x1b[<0;1;2m')q" "$sc"
         1084 status=$?
         1085 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1086 contents="$(cat "$plumbfile")"
         1087 test "$contents" = "" || fail "Incorrect URL: $contents"
         1088 test_end
         1089 
         1090 # Horizontal layout, resize 4 down, 2 up, doubleclick cell (1, 8). (3 feeds + line separator + items).
         1091 test_start "Resize sidebar"
         1092 rm -f "$plumbfile"
         1093 touch "$plumbfile"
         1094 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="2>>>><<$($printf '\x1b[<0;1;8M\x1b[<0;1;8m\x1b[<0;1;8M\x1b[<0;1;8m')q" "$sc" "$feedfile1" "$feedfile2" "$feedfile3"
         1095 status=$?
         1096 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1097 contents="$(cat "$plumbfile")"
         1098 test "$contents" = "http://b" || fail "Incorrect content: $contents"
         1099 test_end
         1100 
         1101 # file does not exist.
         1102 test_start "Test opening a file via argv that does not exist"
         1103 SFEED_AUTOCMD="q" "$sc" "$feedfile1" "$feedfile2" "/tmp/noexist"
         1104 status=$?
         1105 test $status -eq 1 || fail "Exit code must be 1, was: $status"
         1106 test_end
         1107 
         1108 # file access denied.
         1109 test_start "Test opening a file via argv with no permission to it"
         1110 SFEED_AUTOCMD="q" "$sc" "$feedfile1" "$feedfile2" "/root/denied"
         1111 status=$?
         1112 test $status -eq 1 || fail "Exit code must be 1, was: $status"
         1113 test_end
         1114 
         1115 # setupterm: terminfo database or entry for $TERM not found
         1116 # NOTE: if using minicurses this does not error.
         1117 test_start 'Test bogus $TERM'
         1118 emptydata | TERM=noexist "$sc"
         1119 status=$?
         1120 test $status -eq 1 || fail "Exit code must be 1, was: $status"
         1121 test_end
         1122 
         1123 # $TERM: test tparm() returning NULL. Assuming TERM=dumb exists and returns NULL.
         1124 test_start 'Test tparm() returning NULL for a capability'
         1125 fakedata | TERM=dumb SFEED_AUTOCMD="jjkkq" "$sc"
         1126 status=$?
         1127 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1128 test_end
         1129 
         1130 test_start "Mark read: nonexistant command: child in popen returns status non-zero"
         1131 rm -f "$urlfile"
         1132 echo -n "test" > "$urlfile"
         1133 (sleep 1; pkill -SIGTERM sfeed_curses) &
         1134 fakedata | SFEED_URL_FILE="$urlfile" SFEED_MARK_READ="/tmp/nonexist" SFEED_AUTOCMD="r" $sc
         1135 status=$?
         1136 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1137 expect="test"
         1138 result=$(cat "$urlfile")
         1139 test "$result" = "$expect" || fail "Invalid result"
         1140 test_end
         1141 
         1142 test_start "Check if sfeed_curses is killed by SIGTERM while an interactive child program is running"
         1143 rm -f /tmp/sfeed_curses_sigterm # state file.
         1144 plumbscript2="$(mktemp)"
         1145 $printf '#!/bin/sh\ncat\n' > "$plumbscript2"
         1146 chmod +x "$plumbscript2"
         1147 
         1148 (sleep 1; pkill -SIGTERM sfeed_curses;
         1149 sleep 1; pgrep sfeed_curses >/dev/null && touch /tmp/sfeed_curses_sigterm) &
         1150 
         1151 (sleep 3; pkill -SIGKILL sfeed_curses) & # watchdog: make sure it is killed eventually.
         1152 
         1153 fakedata | SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript2" SFEED_AUTOCMD="o" $sc
         1154 status=$?
         1155 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1156 wait
         1157 
         1158 rm -f "$plumbscript2"
         1159 if test -f /tmp/sfeed_curses_sigterm; then
         1160         rm -f /tmp/sfeed_curses_sigterm
         1161         fail "sfeed_curses was not killed by SIGTERM while the program was running"
         1162 fi
         1163 rm -f /tmp/sfeed_curses_sigterm
         1164 test_end
         1165 
         1166 test_start "Test non-interactive mode for yanking a link"
         1167 rm -f "$pipefile"
         1168 touch "$pipefile"
         1169 (sleep 1;pkill -SIGTERM sfeed_curses) &
         1170 SFEED_YANKER_INTERACTIVE="0" SFEED_YANKER="cat >$pipefile" SFEED_AUTOCMD="ly" $sc "$feedfile1" "$feedfile2" "$feedfile3"
         1171 status=$?
         1172 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1173 contents="$(cat "$pipefile")"
         1174 line1="$($printf 'http://a')"
         1175 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
         1176 test_end
         1177 
         1178 test_start "Test non-interactive mode for piping content"
         1179 rm -f "$pipefile"
         1180 touch "$pipefile"
         1181 (sleep 1;pkill -SIGTERM sfeed_curses) &
         1182 SFEED_PIPER_INTERACTIVE="0" SFEED_PIPER="cat >$pipefile" SFEED_AUTOCMD="lp" $sc "$feedfile1" "$feedfile2" "$feedfile3"
         1183 status=$?
         1184 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1185 contents="$(cat "$pipefile")"
         1186 line1="$($printf '0\t1. a\thttp://a\t\t\t\t\t\t\n')"
         1187 test "$contents" = "$line1" || fail "Incorrect content: $contents, expected: $line1"
         1188 test_end
         1189 
         1190 test_start "Test non-interactive mode for plumbing a link"
         1191 rm -f "$plumbfile"
         1192 touch "$plumbfile"
         1193 (sleep 1;pkill -SIGTERM sfeed_curses) &
         1194 SFEED_PLUMBER_INTERACTIVE="0" SFEED_PLUMBER="$plumbscript" SFEED_AUTOCMD="lo" $sc "$feedfile1" "$feedfile2" "$feedfile3"
         1195 status=$?
         1196 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1197 contents="$(cat "$plumbfile")"
         1198 test "$contents" = "http://a" || fail "Incorrect URL: $contents"
         1199 test_end
         1200 
         1201 # SIGTERM while search is open.
         1202 test_start "test SIGTERM while search is open: should exit"
         1203 (sleep 1;pkill -SIGTERM sfeed_curses) &
         1204 SFEED_AUTOCMD="/abc" "$sc" "$feedfile1" "$feedfile2"
         1205 status=$?
         1206 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1207 test_end
         1208 
         1209 test_start "test SIGINT and exit status"
         1210 (sleep 1;pkill -SIGINT sfeed_curses) &
         1211 SFEED_AUTOCMD="jo" "$sc" "$feedfile1" "$feedfile2"
         1212 status=$?
         1213 test $status -eq 130 || fail "Exit code must be 130, was: $status"
         1214 test_end
         1215 
         1216 test_start "test SIGINT, interrupting the search prompt"
         1217 rm -f /tmp/sfeed_tests.tmp
         1218 (sleep 1
         1219 pkill -SIGINT sfeed_curses
         1220 sleep 1
         1221 c=$(pgrep sfeed_curses | wc -l)
         1222 echo "$c" > /tmp/sfeed_tests.tmp
         1223 pkill -SIGTERM sfeed_curses # make sure it stops.
         1224 ) &
         1225 SFEED_AUTOCMD="$($printf '/abc')" "$sc" "$feedfile1" "$feedfile2"
         1226 status=$?
         1227 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1228 c="$(cat /tmp/sfeed_tests.tmp)"
         1229 c=$((c+0)) # convert int
         1230 test $c -gt 0 || fail "The process was interrupted instead of the prompt"
         1231 rm -f /tmp/sfeed_tests.tmp
         1232 test_end
         1233 
         1234 test_start "Check reaping zombies (SIGCHLD)"
         1235 rm -f /tmp/sfeed_zombies
         1236 touch /tmp/sfeed_zombies
         1237 (sleep 3
         1238 # check for any zombies
         1239 ps -o 'state=' | grep Z > "/tmp/sfeed_zombies"
         1240 pkill -SIGTERM sfeed_curses
         1241 ) &
         1242 fakedata | \
         1243 SFEED_YANKER_INTERACTIVE="0" SFEED_YANKER="sleep 1" \
         1244 SFEED_AUTOCMD="yjy" \
         1245 $sc
         1246 status=$?
         1247 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1248 count=$(wc -l < "/tmp/sfeed_zombies")
         1249 count=$((count + 0))
         1250 rm -f /tmp/sfeed_zombies
         1251 test $count -eq 0 || fail "Failed to handle SIGCHLD and reap zombies"
         1252 test_end
         1253 
         1254 test_start "Check reaping zombies (SIGCHLD) while line editor is open"
         1255 rm -f /tmp/sfeed_zombies
         1256 touch /tmp/sfeed_zombies
         1257 (sleep 3
         1258 # check for any zombies
         1259 ps -o 'state=' | grep Z > "/tmp/sfeed_zombies"
         1260 pkill -SIGTERM sfeed_curses
         1261 ) &
         1262 fakedata | \
         1263 SFEED_YANKER_INTERACTIVE="0" SFEED_YANKER="sleep 1" \
         1264 SFEED_AUTOCMD="yjy/abc" \
         1265 $sc
         1266 status=$?
         1267 test $status -eq 143 || fail "Exit code must be 143, was: $status"
         1268 count=$(wc -l < "/tmp/sfeed_zombies")
         1269 count=$((count + 0))
         1270 rm -f /tmp/sfeed_zombies
         1271 test $count -eq 0 || fail "Failed to handle SIGCHLD and reap zombies"
         1272 test_end
         1273 
         1274 test_start "Check if \$SFEED_FEED_PATH variable is properly set for plumbing"
         1275 rm -f /tmp/sfeed_curses_path # value of $SFEED_FEED_PATH
         1276 plumbscript2="$(mktemp)"
         1277 $printf '#!/bin/sh\necho "$SFEED_FEED_PATH" > /tmp/sfeed_curses_path\n' > "$plumbscript2"
         1278 chmod +x "$plumbscript2"
         1279 SFEED_PLUMBER_INTERACTIVE="1" SFEED_PLUMBER="$plumbscript2" SFEED_AUTOCMD="loq" $sc "$feedfile1"
         1280 status=$?
         1281 test $status -eq 0 || fail "Exit code must be 0, was: $status"
         1282 rm -f "$plumbscript2"
         1283 content=$(cat '/tmp/sfeed_curses_path')
         1284 if ! test "$content" = "$feedfile1"; then
         1285         rm -f /tmp/sfeed_curses_path
         1286         fail 'Value of $SFEED_FEED_PATH is incorrect'
         1287 fi
         1288 rm -f /tmp/sfeed_curses_path
         1289 test_end
         1290 
         1291 # -a runs automated tests only.
         1292 test "$1" = "-a" || manual
         1293 
         1294 cleanup
         1295 echo "OK, all tests (${test_count}) passed \o/"