usage_spec.sh (62956B)
1 # pashage - age-backed POSIX password manager 2 # Copyright (C) 2024 Natasha Kerensikova 3 # 4 # This program is free software; you can redistribute it and/or 5 # modify it under the terms of the GNU General Public License 6 # as published by the Free Software Foundation; either version 2 7 # of the License, or (at your option) any later version. 8 # 9 # This program is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with this program; if not, write to the Free Software 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 18 # This test file fully covers all command functions in isolation, 19 # using mocks for all action and helper functions. 20 # It mostly tests command-line parsing and environment transmission to actions. 21 22 Describe 'Command-Line Parsing' 23 Include src/pashage.sh 24 if [ "${SHELLSPEC_SHELL_TYPE}" = sh ]; then 25 Set 'errexit:on' 'nounset:on' 26 else 27 Set 'errexit:on' 'nounset:on' 'pipefail:on' 28 fi 29 30 PREFIX=/prefix 31 PROGRAM=prg 32 33 CHARACTER_SET='[:punct:][:alnum:]' 34 CHARACTER_SET_NO_SYMBOLS='[:alnum:]' 35 36 # mocks 37 platform_tmpdir() { 38 SECURE_TMPDIR=/tmp/secure 39 } 40 41 check_sneaky_path() { mocklog check_sneaky_path "$@"; } 42 git() { mocklog git "$@"; } 43 scm_add() { mocklog scm_add "$@"; } 44 scm_begin() { mocklog scm_begin "$@"; } 45 scm_commit() { mocklog scm_commit "$@"; } 46 47 do_copy_move() { 48 mocklog do_copy_move "$@" 49 %text:expand >&2 50 #|ACTION=${ACTION} 51 #|DECISION=${DECISION} 52 #|OVERWRITE=${OVERWRITE} 53 #|SCM_ACTION=${SCM_ACTION} 54 } 55 do_decrypt() { 56 mocklog do_decrypt "$@" 57 } 58 do_decrypt_gpg() { 59 mocklog do_decrypt_gpg "$@" 60 } 61 do_deinit() { 62 mocklog do_deinit "$@" 63 %text:expand >&2 64 #|DECISION=${DECISION} 65 } 66 do_delete() { 67 mocklog do_delete "$@" 68 %text:expand >&2 69 #|DECISION=${DECISION} 70 #|RECURSIVE=${RECURSIVE} 71 } 72 do_edit() { 73 mocklog do_edit "$@" 74 %text:expand >&2 75 #|EDITOR=${EDITOR} 76 #|SECURE_TMPDIR=${SECURE_TMPDIR} 77 #|TERM=${TERM} 78 #|VISUAL=${VISUAL} 79 } 80 do_encrypt() { 81 mocklog do_encrypt "$@" 82 %text:expand >&2 83 #|IDENTITIES_FILE=${IDENTITIES_FILE} 84 #|LOCAL_RECIPIENT_FILE=${LOCAL_RECIPIENT_FILE} 85 #|PASHAGE_RECIPIENTS=${PASHAGE_RECIPIENTS} 86 #|PASHAGE_RECIPIENTS_FILE=${PASHAGE_RECIPIENTS_FILE} 87 #|PASSAGE_RECIPIENTS=${PASSAGE_RECIPIENTS} 88 #|PASSAGE_RECIPIENTS_FILE=${PASSAGE_RECIPIENTS_FILE} 89 } 90 do_generate() { 91 mocklog do_generate "$@" 92 %text:expand >&2 93 #|DECISION=${DECISION} 94 #|MULTILINE=${MULTILINE} 95 #|OVERWRITE=${OVERWRITE} 96 #|SELECTED_LINE=${SELECTED_LINE} 97 #|SHOW=${SHOW} 98 } 99 do_grep() { 100 mocklog do_grep "$@" 101 } 102 do_init() { 103 mocklog do_init "$@" 104 %text:expand >&2 105 #|DECISION=${DECISION} 106 #|OVERWRITE=${OVERWRITE} 107 } 108 do_insert() { 109 mocklog do_insert "$@" 110 %text:expand >&2 111 #|ECHO=${ECHO} 112 #|MULTILINE=${MULTILINE} 113 #|OVERWRITE=${OVERWRITE} 114 } 115 do_list_or_show() { 116 mocklog do_list_or_show "$@" 117 %text:expand >&2 118 #|SELECTED_LINE=${SELECTED_LINE} 119 #|SHOW=${SHOW} 120 } 121 do_reencrypt() { 122 mocklog do_reencrypt "$@" 123 %text:expand >&2 124 #|DECISION=${DECISION} 125 } 126 do_reencrypt_dir() { 127 mocklog do_reencrypt_dir "$@" 128 %text:expand >&2 129 #|DECISION=${DECISION} 130 } 131 do_reencrypt_file() { 132 mocklog do_reencrypt_file "$@" 133 %text:expand >&2 134 #|DECISION=${DECISION} 135 } 136 do_show() { 137 mocklog do_show "$@" 138 %text:expand >&2 139 #|SELECTED_LINE=${SELECTED_LINE} 140 #|SHOW=${SHOW} 141 } 142 do_tree() { 143 mocklog do_tree "$@" 144 } 145 146 Describe 'cmd_copy' 147 COMMAND=copy 148 149 It 'copies multiple files' 150 result() { 151 %text 152 #|$ check_sneaky_path src1 153 #|$ check_sneaky_path src2 154 #|$ check_sneaky_path src3 155 #|$ check_sneaky_path dest 156 #|$ do_copy_move src1 dest/ 157 #|ACTION=Copy 158 #|DECISION=default 159 #|OVERWRITE=no 160 #|SCM_ACTION=scm_cp 161 #|$ do_copy_move src2 dest/ 162 #|ACTION=Copy 163 #|DECISION=default 164 #|OVERWRITE=no 165 #|SCM_ACTION=scm_cp 166 #|$ do_copy_move src3 dest/ 167 #|ACTION=Copy 168 #|DECISION=default 169 #|OVERWRITE=no 170 #|SCM_ACTION=scm_cp 171 } 172 When call cmd_copy src1 src2 src3 dest 173 The status should be success 174 The output should be blank 175 The error should equal "$(result)" 176 End 177 178 It 'copies forcefully with a long option' 179 result() { 180 %text 181 #|$ check_sneaky_path src 182 #|$ check_sneaky_path dest 183 #|$ do_copy_move src dest 184 #|ACTION=Copy 185 #|DECISION=default 186 #|OVERWRITE=yes 187 #|SCM_ACTION=scm_cp 188 } 189 When call cmd_copy --force src dest 190 The status should be success 191 The output should be blank 192 The error should equal "$(result)" 193 End 194 195 It 'copies forcefully with a short option' 196 result() { 197 %text 198 #|$ check_sneaky_path src 199 #|$ check_sneaky_path dest 200 #|$ do_copy_move src dest 201 #|ACTION=Copy 202 #|DECISION=default 203 #|OVERWRITE=yes 204 #|SCM_ACTION=scm_cp 205 } 206 When call cmd_copy -f src dest 207 The status should be success 208 The output should be blank 209 The error should equal "$(result)" 210 End 211 212 It 'always reencrypts with a long option' 213 result() { 214 %text 215 #|$ check_sneaky_path src 216 #|$ check_sneaky_path dest 217 #|$ do_copy_move src dest 218 #|ACTION=Copy 219 #|DECISION=force 220 #|OVERWRITE=no 221 #|SCM_ACTION=scm_cp 222 } 223 When call cmd_copy --reencrypt src dest 224 The status should be success 225 The output should be blank 226 The error should equal "$(result)" 227 End 228 229 It 'always reencrypts with a short option' 230 result() { 231 %text 232 #|$ check_sneaky_path src 233 #|$ check_sneaky_path dest 234 #|$ do_copy_move src dest 235 #|ACTION=Copy 236 #|DECISION=force 237 #|OVERWRITE=no 238 #|SCM_ACTION=scm_cp 239 } 240 When call cmd_copy -e src dest 241 The status should be success 242 The output should be blank 243 The error should equal "$(result)" 244 End 245 246 It 'interactively reencrypts with a long option' 247 result() { 248 %text 249 #|$ check_sneaky_path src 250 #|$ check_sneaky_path dest 251 #|$ do_copy_move src dest 252 #|ACTION=Copy 253 #|DECISION=interactive 254 #|OVERWRITE=no 255 #|SCM_ACTION=scm_cp 256 } 257 When call cmd_copy --interactive src dest 258 The status should be success 259 The output should be blank 260 The error should equal "$(result)" 261 End 262 263 It 'interactively reencrypts with a short option' 264 result() { 265 %text 266 #|$ check_sneaky_path src 267 #|$ check_sneaky_path dest 268 #|$ do_copy_move src dest 269 #|ACTION=Copy 270 #|DECISION=interactive 271 #|OVERWRITE=no 272 #|SCM_ACTION=scm_cp 273 } 274 When call cmd_copy -i src dest 275 The status should be success 276 The output should be blank 277 The error should equal "$(result)" 278 End 279 280 It 'never reencrypts with a long option' 281 result() { 282 %text 283 #|$ check_sneaky_path src 284 #|$ check_sneaky_path dest 285 #|$ do_copy_move src dest 286 #|ACTION=Copy 287 #|DECISION=keep 288 #|OVERWRITE=no 289 #|SCM_ACTION=scm_cp 290 } 291 When call cmd_copy --keep src dest 292 The status should be success 293 The output should be blank 294 The error should equal "$(result)" 295 End 296 297 It 'never reencrypts with a short option' 298 result() { 299 %text 300 #|$ check_sneaky_path src 301 #|$ check_sneaky_path dest 302 #|$ do_copy_move src dest 303 #|ACTION=Copy 304 #|DECISION=keep 305 #|OVERWRITE=no 306 #|SCM_ACTION=scm_cp 307 } 308 When call cmd_copy -k src dest 309 The status should be success 310 The output should be blank 311 The error should equal "$(result)" 312 End 313 314 It 'copies a file named like a flag' 315 result() { 316 %text 317 #|$ check_sneaky_path -s 318 #|$ check_sneaky_path dest 319 #|$ do_copy_move -s dest 320 #|ACTION=Copy 321 #|DECISION=default 322 #|OVERWRITE=no 323 #|SCM_ACTION=scm_cp 324 } 325 When call cmd_copy -- -s dest 326 The status should be success 327 The output should be blank 328 The error should equal "$(result)" 329 End 330 331 usage_text() { %text 332 #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ] 333 #| [--force,-f] old-path new-path 334 } 335 336 It 'reports a bad option' 337 cat() { @cat; } 338 When run cmd_copy -s arg 339 The output should be blank 340 The error should equal "$(usage_text)" 341 The status should equal 1 342 End 343 344 It 'reports incompatible re-encryption options (-e and -i)' 345 cat() { @cat; } 346 When run cmd_copy -ei src dest 347 The output should be blank 348 The error should equal "$(usage_text)" 349 The status should equal 1 350 End 351 352 It 'reports incompatible re-encryption options (-i and -k)' 353 cat() { @cat; } 354 When run cmd_copy -ik src dest 355 The output should be blank 356 The error should equal "$(usage_text)" 357 The status should equal 1 358 End 359 360 It 'reports incompatible re-encryption options (-k and -e)' 361 cat() { @cat; } 362 When run cmd_copy -ke src dest 363 The output should be blank 364 The error should equal "$(usage_text)" 365 The status should equal 1 366 End 367 368 It 'reports a lack of argument' 369 cat() { @cat; } 370 When run cmd_copy src 371 The output should be blank 372 The error should equal "$(usage_text)" 373 The status should equal 1 374 End 375 End 376 377 Describe 'cmd_copy_move' 378 COMMAND=wrong 379 380 It 'reports both commands when confused' 381 cat() { @cat; } 382 result() { %text 383 #|Usage: prg copy [--reencrypt,-e | --interactive,-i | --keep,-k ] 384 #| [--force,-f] old-path new-path 385 #| prg move [--reencrypt,-e | --interactive,-i | --keep,-k ] 386 #| [--force,-f] old-path new-path 387 } 388 When run cmd_copy src 389 The output should be blank 390 The error should equal "$(result)" 391 The status should equal 1 392 End 393 End 394 395 Describe 'cmd_delete' 396 COMMAND=delete 397 398 It 'removes a file forcefully with a long option' 399 result() { 400 %text 401 #|$ check_sneaky_path arg1 402 #|$ do_delete arg1 403 #|DECISION=force 404 #|RECURSIVE=no 405 } 406 When call cmd_delete --force arg1 407 The status should be success 408 The output should be blank 409 The error should equal "$(result)" 410 End 411 412 It 'removes a file forcefully with a short option' 413 result() { 414 %text 415 #|$ check_sneaky_path arg1 416 #|$ do_delete arg1 417 #|DECISION=force 418 #|RECURSIVE=no 419 } 420 When call cmd_delete -f arg1 421 The status should be success 422 The output should be blank 423 The error should equal "$(result)" 424 End 425 426 It 'removes a directory recursively with a long option' 427 result() { 428 %text 429 #|$ check_sneaky_path arg1 430 #|$ do_delete arg1 431 #|DECISION=default 432 #|RECURSIVE=yes 433 } 434 When call cmd_delete --recursive arg1 435 The status should be success 436 The output should be blank 437 The error should equal "$(result)" 438 End 439 440 It 'removes a directory recursively with a short option' 441 result() { 442 %text 443 #|$ check_sneaky_path arg1 444 #|$ do_delete arg1 445 #|DECISION=default 446 #|RECURSIVE=yes 447 } 448 When call cmd_delete -r arg1 449 The status should be success 450 The output should be blank 451 The error should equal "$(result)" 452 End 453 454 It 'removes a directory recursively and forcefully with long options' 455 result() { 456 %text 457 #|$ check_sneaky_path arg1 458 #|$ do_delete arg1 459 #|DECISION=force 460 #|RECURSIVE=yes 461 } 462 When call cmd_delete --recursive --force arg1 463 The status should be success 464 The output should be blank 465 The error should equal "$(result)" 466 End 467 468 It 'removes a directory recursively and forcefully with short options' 469 result() { 470 %text 471 #|$ check_sneaky_path arg1 472 #|$ do_delete arg1 473 #|DECISION=force 474 #|RECURSIVE=yes 475 } 476 When call cmd_delete -rf arg1 477 The status should be success 478 The output should be blank 479 The error should equal "$(result)" 480 End 481 482 It 'removes a directory forcefully and recursively with short options' 483 result() { 484 %text 485 #|$ check_sneaky_path arg1 486 #|$ do_delete arg1 487 #|DECISION=force 488 #|RECURSIVE=yes 489 } 490 When call cmd_delete -fr arg1 491 The status should be success 492 The output should be blank 493 The error should equal "$(result)" 494 End 495 496 It 'removes multiple files' 497 result() { 498 %text 499 #|$ check_sneaky_path arg1 500 #|$ check_sneaky_path arg2 501 #|$ check_sneaky_path arg3 502 #|$ do_delete arg1 503 #|DECISION=default 504 #|RECURSIVE=no 505 #|$ do_delete arg2 506 #|DECISION=default 507 #|RECURSIVE=no 508 #|$ do_delete arg3 509 #|DECISION=default 510 #|RECURSIVE=no 511 } 512 When call cmd_delete arg1 arg2 arg3 513 The status should be success 514 The output should be blank 515 The error should equal "$(result)" 516 End 517 518 It 'removes a file named like a flag' 519 result() { 520 %text 521 #|$ check_sneaky_path -f 522 #|$ check_sneaky_path arg2 523 #|$ do_delete -f 524 #|DECISION=default 525 #|RECURSIVE=no 526 #|$ do_delete arg2 527 #|DECISION=default 528 #|RECURSIVE=no 529 } 530 When call cmd_delete -- -f arg2 531 The status should be success 532 The output should be blank 533 The error should equal "$(result)" 534 End 535 536 It 'reports a bad option' 537 cat() { @cat; } 538 When run cmd_delete -u arg 539 The output should be blank 540 The error should equal \ 541 'Usage: prg delete [--recursive,-r] [--force,-f] pass-name' 542 The status should equal 1 543 End 544 545 It 'reports a lack of argument' 546 cat() { @cat; } 547 When run cmd_delete 548 The output should be blank 549 The error should equal \ 550 'Usage: prg delete [--recursive,-r] [--force,-f] pass-name' 551 The status should equal 1 552 End 553 End 554 555 Describe 'cmd_edit' 556 COMMAND=edit 557 EDITOR=ed 558 TERM=dumb 559 VISUAL=vi 560 561 It 'edits multiple files succesively' 562 result() { 563 %text 564 #|$ check_sneaky_path arg1 565 #|$ check_sneaky_path arg2 566 #|$ check_sneaky_path arg3 567 #|$ do_edit arg1 568 #|EDITOR=ed 569 #|SECURE_TMPDIR=/tmp/secure 570 #|TERM=dumb 571 #|VISUAL=vi 572 #|$ do_edit arg2 573 #|EDITOR=ed 574 #|SECURE_TMPDIR=/tmp/secure 575 #|TERM=dumb 576 #|VISUAL=vi 577 #|$ do_edit arg3 578 #|EDITOR=ed 579 #|SECURE_TMPDIR=/tmp/secure 580 #|TERM=dumb 581 #|VISUAL=vi 582 } 583 When call cmd_edit arg1 arg2 arg3 584 The status should be success 585 The output should be blank 586 The error should equal "$(result)" 587 End 588 589 It 'reports a lack of argument' 590 cat() { @cat; } 591 When run cmd_edit 592 The output should be blank 593 The error should equal 'Usage: prg edit pass-name' 594 The status should equal 1 595 End 596 End 597 598 Describe 'cmd_find' 599 COMMAND=find 600 601 It 'uses the argument list directly' 602 When call cmd_find -i pattern 603 The status should be success 604 The output should equal 'Search pattern: -i pattern' 605 The error should equal '$ do_tree /prefix -i pattern' 606 End 607 608 It 'reports a lack of argument' 609 cat() { @cat; } 610 When run cmd_find 611 The output should be blank 612 The error should equal 'Usage: prg find [GREP_OPTIONS] regex' 613 The status should equal 1 614 End 615 End 616 617 Describe 'cmd_generate' 618 COMMAND=generate 619 GENERATED_LENGTH=25 620 621 usage_text() { %text 622 #|Usage: prg generate [--no-symbols,-n] [--clip,-c | --qrcode,-q] 623 #| [--in-place,-i | --force,-f] [--multiline,-m] 624 #| [--try,-t] pass-name [pass-length [character-set]] 625 } 626 627 It 'generates a new entry with default length' 628 result() { 629 %text 630 #|$ check_sneaky_path secret 631 #|$ do_generate secret 25 [:punct:][:alnum:] 632 #|DECISION=default 633 #|MULTILINE=no 634 #|OVERWRITE=no 635 #|SELECTED_LINE=1 636 #|SHOW=text 637 } 638 When call cmd_generate secret 639 The status should be success 640 The output should be blank 641 The error should equal "$(result)" 642 End 643 644 It 'generates a new entry with explicit length' 645 result() { 646 %text 647 #|$ check_sneaky_path secret 648 #|$ do_generate secret 12 [:punct:][:alnum:] 649 #|DECISION=default 650 #|MULTILINE=no 651 #|OVERWRITE=no 652 #|SELECTED_LINE=1 653 #|SHOW=text 654 } 655 When call cmd_generate secret 12 656 The status should be success 657 The output should be blank 658 The error should equal "$(result)" 659 End 660 661 It 'generates a new entry with explicit length and character set' 662 result() { 663 %text 664 #|$ check_sneaky_path secret 665 #|$ do_generate secret 12 [A-Z] 666 #|DECISION=default 667 #|MULTILINE=no 668 #|OVERWRITE=no 669 #|SELECTED_LINE=1 670 #|SHOW=text 671 } 672 When call cmd_generate secret 12 '[A-Z]' 673 The status should be success 674 The output should be blank 675 The error should equal "$(result)" 676 End 677 678 It 'generates a new flag-like entry' 679 result() { 680 %text 681 #|$ check_sneaky_path -f 682 #|$ do_generate -f 25 [:punct:][:alnum:] 683 #|DECISION=default 684 #|MULTILINE=no 685 #|OVERWRITE=no 686 #|SELECTED_LINE=1 687 #|SHOW=text 688 } 689 When call cmd_generate -- -f 690 The status should be success 691 The output should be blank 692 The error should equal "$(result)" 693 End 694 695 It 'generates a new entry and copies it into the clipboard (long)' 696 result() { 697 %text 698 #|$ check_sneaky_path secret 699 #|$ do_generate secret 25 [:punct:][:alnum:] 700 #|DECISION=default 701 #|MULTILINE=no 702 #|OVERWRITE=no 703 #|SELECTED_LINE=1 704 #|SHOW=clip 705 } 706 When call cmd_generate --clip secret 707 The status should be success 708 The output should be blank 709 The error should equal "$(result)" 710 End 711 712 It 'generates a new entry and copies it into the clipboard (short)' 713 result() { 714 %text 715 #|$ check_sneaky_path secret 716 #|$ do_generate secret 25 [:punct:][:alnum:] 717 #|DECISION=default 718 #|MULTILINE=no 719 #|OVERWRITE=no 720 #|SELECTED_LINE=1 721 #|SHOW=clip 722 } 723 When call cmd_generate -c secret 724 The status should be success 725 The output should be blank 726 The error should equal "$(result)" 727 End 728 729 It 'generates a new entry and shows it as a QR-code (long)' 730 result() { 731 %text 732 #|$ check_sneaky_path secret 733 #|$ do_generate secret 25 [:punct:][:alnum:] 734 #|DECISION=default 735 #|MULTILINE=no 736 #|OVERWRITE=no 737 #|SELECTED_LINE=1 738 #|SHOW=qrcode 739 } 740 When call cmd_generate --qrcode secret 741 The status should be success 742 The output should be blank 743 The error should equal "$(result)" 744 End 745 746 It 'generates a new entry and shows it as a QR-code (short)' 747 result() { 748 %text 749 #|$ check_sneaky_path secret 750 #|$ do_generate secret 25 [:punct:][:alnum:] 751 #|DECISION=default 752 #|MULTILINE=no 753 #|OVERWRITE=no 754 #|SELECTED_LINE=1 755 #|SHOW=qrcode 756 } 757 When call cmd_generate -q secret 758 The status should be success 759 The output should be blank 760 The error should equal "$(result)" 761 End 762 763 It 'generates a new alphanumeric entry and copies it into the clipboard (long)' 764 result() { 765 %text 766 #|$ check_sneaky_path secret 767 #|$ do_generate secret 25 [:alnum:] 768 #|DECISION=default 769 #|MULTILINE=no 770 #|OVERWRITE=no 771 #|SELECTED_LINE=1 772 #|SHOW=clip 773 } 774 When call cmd_generate --clip --no-symbols secret 775 The status should be success 776 The output should be blank 777 The error should equal "$(result)" 778 End 779 780 It 'generates a new alphanumeric entry and copies it into the clipboard (short)' 781 result() { 782 %text 783 #|$ check_sneaky_path secret 784 #|$ do_generate secret 25 [:alnum:] 785 #|DECISION=default 786 #|MULTILINE=no 787 #|OVERWRITE=no 788 #|SELECTED_LINE=1 789 #|SHOW=clip 790 } 791 When call cmd_generate -cn secret 792 The status should be success 793 The output should be blank 794 The error should equal "$(result)" 795 End 796 797 It 'generates a new alphanumeric entry and shows it as a QR-code (long)' 798 result() { 799 %text 800 #|$ check_sneaky_path secret 801 #|$ do_generate secret 25 [:alnum:] 802 #|DECISION=default 803 #|MULTILINE=no 804 #|OVERWRITE=no 805 #|SELECTED_LINE=1 806 #|SHOW=qrcode 807 } 808 When call cmd_generate --no-symbols --qrcode secret 809 The status should be success 810 The output should be blank 811 The error should equal "$(result)" 812 End 813 814 It 'generates a new alphanumeric entry and shows it as a QR-code (short)' 815 result() { 816 %text 817 #|$ check_sneaky_path secret 818 #|$ do_generate secret 25 [:alnum:] 819 #|DECISION=default 820 #|MULTILINE=no 821 #|OVERWRITE=no 822 #|SELECTED_LINE=1 823 #|SHOW=qrcode 824 } 825 When call cmd_generate -nq secret 826 The status should be success 827 The output should be blank 828 The error should equal "$(result)" 829 End 830 831 It 'generates a new entry in place (long)' 832 result() { 833 %text 834 #|$ check_sneaky_path secret 835 #|$ do_generate secret 25 [:punct:][:alnum:] 836 #|DECISION=default 837 #|MULTILINE=no 838 #|OVERWRITE=reuse 839 #|SELECTED_LINE=1 840 #|SHOW=text 841 } 842 When call cmd_generate --in-place secret 843 The status should be success 844 The output should be blank 845 The error should equal "$(result)" 846 End 847 848 It 'generates a new entry in place (short)' 849 result() { 850 %text 851 #|$ check_sneaky_path secret 852 #|$ do_generate secret 25 [:punct:][:alnum:] 853 #|DECISION=default 854 #|MULTILINE=no 855 #|OVERWRITE=reuse 856 #|SELECTED_LINE=1 857 #|SHOW=text 858 } 859 When call cmd_generate -i secret 860 The status should be success 861 The output should be blank 862 The error should equal "$(result)" 863 End 864 865 It 'overwrites an existing entry (long)' 866 result() { 867 %text 868 #|$ check_sneaky_path secret 869 #|$ do_generate secret 25 [:punct:][:alnum:] 870 #|DECISION=default 871 #|MULTILINE=no 872 #|OVERWRITE=yes 873 #|SELECTED_LINE=1 874 #|SHOW=text 875 } 876 When call cmd_generate --force secret 877 The status should be success 878 The output should be blank 879 The error should equal "$(result)" 880 End 881 882 It 'overwrites an existing entry (short)' 883 result() { 884 %text 885 #|$ check_sneaky_path secret 886 #|$ do_generate secret 25 [:punct:][:alnum:] 887 #|DECISION=default 888 #|MULTILINE=no 889 #|OVERWRITE=yes 890 #|SELECTED_LINE=1 891 #|SHOW=text 892 } 893 When call cmd_generate -f secret 894 The status should be success 895 The output should be blank 896 The error should equal "$(result)" 897 End 898 899 It 'asks for confirmation before saving the generated password (long)' 900 result() { 901 %text 902 #|$ check_sneaky_path secret 903 #|$ do_generate secret 25 [:punct:][:alnum:] 904 #|DECISION=interactive 905 #|MULTILINE=no 906 #|OVERWRITE=no 907 #|SELECTED_LINE=1 908 #|SHOW=text 909 } 910 When call cmd_generate --try secret 911 The status should be success 912 The output should be blank 913 The error should equal "$(result)" 914 End 915 916 It 'asks for confirmation before saving the generated password (short)' 917 result() { 918 %text 919 #|$ check_sneaky_path secret 920 #|$ do_generate secret 25 [:punct:][:alnum:] 921 #|DECISION=interactive 922 #|MULTILINE=no 923 #|OVERWRITE=no 924 #|SELECTED_LINE=1 925 #|SHOW=text 926 } 927 When call cmd_generate -t secret 928 The status should be success 929 The output should be blank 930 The error should equal "$(result)" 931 End 932 933 It 'accepts extra lines after the generated secret (long)' 934 result() { 935 %text 936 #|$ check_sneaky_path secret 937 #|$ do_generate secret 25 [:punct:][:alnum:] 938 #|DECISION=default 939 #|MULTILINE=yes 940 #|OVERWRITE=no 941 #|SELECTED_LINE=1 942 #|SHOW=text 943 } 944 When call cmd_generate --multiline secret 945 The status should be success 946 The output should be blank 947 The error should equal "$(result)" 948 End 949 950 It 'accepts extra lines after the generated secret (short)' 951 result() { 952 %text 953 #|$ check_sneaky_path secret 954 #|$ do_generate secret 25 [:punct:][:alnum:] 955 #|DECISION=default 956 #|MULTILINE=yes 957 #|OVERWRITE=no 958 #|SELECTED_LINE=1 959 #|SHOW=text 960 } 961 When call cmd_generate -m secret 962 The status should be success 963 The output should be blank 964 The error should equal "$(result)" 965 End 966 967 It 'reports incompatible generation long options' 968 cat() { @cat; } 969 When run cmd_generate --in-place --force secret 970 The output should be blank 971 The error should equal "$(usage_text)" 972 The status should equal 1 973 End 974 975 It 'reports incompatible generation short options' 976 cat() { @cat; } 977 When run cmd_generate -fi secret 978 The output should be blank 979 The error should equal "$(usage_text)" 980 The status should equal 1 981 End 982 983 It 'reports incompatible show long options' 984 cat() { @cat; } 985 When run cmd_generate --qrcode --clip secret 986 The output should be blank 987 The error should equal "$(usage_text)" 988 The status should equal 1 989 End 990 991 It 'reports incompatible show short options' 992 cat() { @cat; } 993 When run cmd_generate -cq secret 994 The output should be blank 995 The error should equal "$(usage_text)" 996 The status should equal 1 997 End 998 999 It 'reports a bad option' 1000 cat() { @cat; } 1001 When run cmd_generate --bad secret 1002 The output should be blank 1003 The error should equal "$(usage_text)" 1004 The status should equal 1 1005 End 1006 1007 It 'reports a lack of argument' 1008 cat() { @cat; } 1009 When run cmd_generate 1010 The output should be blank 1011 The error should equal "$(usage_text)" 1012 The status should equal 1 1013 End 1014 End 1015 1016 Describe 'cmd_git' 1017 COMMAND=git 1018 1019 cmd_gitconfig() { mocklog cmd_gitconfig "$@"; } 1020 mkdir() { mocklog mkdir "$@"; @mkdir "$@"; } 1021 1022 setup() { 1023 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/.git" 1024 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub" 1025 } 1026 1027 cleanup() { 1028 @rm -rf "${SHELLSPEC_WORKDIR}/repo" 1029 } 1030 1031 BeforeEach setup 1032 AfterEach cleanup 1033 1034 It 'initializes a new repository' 1035 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1036 result() { 1037 %text:expand 1038 #|$ mkdir -p -- ${PREFIX} 1039 #|$ git -C ${PREFIX} init 1040 #|$ scm_add . 1041 #|$ scm_commit Add current contents of password store. 1042 #|$ cmd_gitconfig 1043 } 1044 When call cmd_git init 1045 The status should be success 1046 The output should be blank 1047 The error should equal "$(result)" 1048 End 1049 1050 It 'clones a new repository' 1051 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1052 result() { 1053 %text:expand 1054 #|$ git clone origin ${PREFIX} 1055 #|$ cmd_gitconfig 1056 } 1057 When call cmd_git clone origin 1058 The status should be success 1059 The output should be blank 1060 The error should equal "$(result)" 1061 End 1062 1063 It 'runs the git command into the store' 1064 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1065 When call cmd_git log --oneline 1066 The status should be success 1067 The output should be blank 1068 The error should equal "$ git -C ${PREFIX} log --oneline" 1069 End 1070 1071 It 'transmits an empty argument list to git' 1072 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1073 When run cmd_git 1074 The status should be success 1075 The output should be blank 1076 The error should equal "$ git -C ${PREFIX}" 1077 End 1078 1079 It 'aborts without a git repository' 1080 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub" 1081 When run cmd_git log 1082 The output should be blank 1083 The error should equal 'Error: the password store is not a git repository. Try "prg git init".' 1084 The status should equal 1 1085 End 1086 End 1087 1088 Describe 'cmd_gitconfig' 1089 COMMAND=gitconfig 1090 AGE=age 1091 IDENTITIES_FILE=id 1092 1093 grep() { @grep "$@"; } 1094 1095 setup() { 1096 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/.git" 1097 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub-1/.git" 1098 %putsn data >"${SHELLSPEC_WORKDIR}/repo/sub-1/.gitattributes" 1099 @mkdir -p "${SHELLSPEC_WORKDIR}/repo/sub-2/.git" 1100 %putsn '*.age diff=age' >"${SHELLSPEC_WORKDIR}/repo/sub-2/.gitattributes" 1101 } 1102 1103 cleanup() { 1104 @rm -rf "${SHELLSPEC_WORKDIR}/repo" 1105 } 1106 1107 BeforeEach setup 1108 AfterEach cleanup 1109 1110 It 'configures a new repository' 1111 PREFIX="${SHELLSPEC_WORKDIR}/repo" 1112 result() { 1113 %text:expand 1114 #|$ scm_begin 1115 #|$ scm_add .gitattributes 1116 #|$ scm_commit Configure git repository for age file diff. 1117 #|$ git -C ${PREFIX} config --local diff.age.binary true 1118 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1119 } 1120 When call cmd_gitconfig 1121 The status should be success 1122 The output should be blank 1123 The error should equal "$(result)" 1124 The contents of file "${PREFIX}/.gitattributes" should equal '*.age diff=age' 1125 End 1126 1127 It 'expands an existing .gitattributes' 1128 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub-1" 1129 result() { 1130 %text:expand 1131 #|$ scm_begin 1132 #|$ scm_add .gitattributes 1133 #|$ scm_commit Configure git repository for age file diff. 1134 #|$ git -C ${PREFIX} config --local diff.age.binary true 1135 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1136 } 1137 attrs() { 1138 %text 1139 #|data 1140 #|*.age diff=age 1141 } 1142 When call cmd_gitconfig 1143 The status should be success 1144 The output should be blank 1145 The error should equal "$(result)" 1146 The contents of file "${PREFIX}/.gitattributes" should equal "$(attrs)" 1147 End 1148 1149 It 'configures a repository with a valid .gitattributes' 1150 PREFIX="${SHELLSPEC_WORKDIR}/repo/sub-2" 1151 result() { 1152 %text:expand 1153 #|$ git -C ${PREFIX} config --local diff.age.binary true 1154 #|$ git -C ${PREFIX} config --local diff.age.textconv age -d -i id 1155 } 1156 When call cmd_gitconfig 1157 The status should be success 1158 The output should be blank 1159 The error should equal "$(result)" 1160 The contents of file "${PREFIX}/.gitattributes" should equal '*.age diff=age' 1161 End 1162 1163 It 'aborts without a git repository' 1164 PREFIX="${SHELLSPEC_WORKDIR}/repo/prefix" 1165 When run cmd_gitconfig 1166 The output should be blank 1167 The error should equal 'The store is not a git repository.' 1168 The status should equal 1 1169 End 1170 End 1171 1172 Describe 'cmd_grep' 1173 COMMAND=grep 1174 PREFIX="${SHELLSPEC_WORKDIR}" 1175 1176 It 'uses the argument list directly' 1177 When call cmd_grep -i pattern 1178 The status should be success 1179 The output should be blank 1180 The error should equal '$ do_grep -i pattern' 1181 End 1182 1183 It 'reports a lack of argument' 1184 cat() { @cat; } 1185 When run cmd_grep 1186 The output should be blank 1187 The error should equal 'Usage: prg grep [GREP_OPTIONS] search-regex' 1188 The status should equal 1 1189 End 1190 End 1191 1192 Describe 'cmd_help' 1193 COMMAND=help 1194 1195 It 'displays version and usage' 1196 cmd_usage() { mocklog cmd_usage "$@"; } 1197 cmd_version() { mocklog cmd_version "$@"; } 1198 result() { 1199 %text | @sed 's/\$$//' 1200 #|$ cmd_version 1201 #|$ cmd_usage $ 1202 } 1203 When call cmd_help 1204 The status should be success 1205 The output should be blank 1206 The error should equal "$(result)" 1207 End 1208 End 1209 1210 Describe 'cmd_init' 1211 COMMAND=init 1212 1213 It 'initializes the whole store' 1214 result() { 1215 %text | @sed 's/\$$//' 1216 #|$ check_sneaky_path $ 1217 #|$ do_init recipient-1 recipient-2 1218 #|DECISION=default 1219 #|OVERWRITE=yes 1220 } 1221 When call cmd_init recipient-1 recipient-2 1222 The status should be success 1223 The output should be blank 1224 The error should equal "$(result)" 1225 End 1226 1227 It 'initializes the whole store conservatively with a long option' 1228 result() { 1229 %text | @sed 's/\$$//' 1230 #|$ check_sneaky_path $ 1231 #|$ do_init recipient-1 recipient-2 1232 #|DECISION=keep 1233 #|OVERWRITE=yes 1234 } 1235 When call cmd_init --keep recipient-1 recipient-2 1236 The status should be success 1237 The output should be blank 1238 The error should equal "$(result)" 1239 End 1240 1241 It 'initializes the whole store conservatively with a short option' 1242 result() { 1243 %text | @sed 's/\$$//' 1244 #|$ check_sneaky_path $ 1245 #|$ do_init recipient-1 recipient-2 1246 #|DECISION=keep 1247 #|OVERWRITE=yes 1248 } 1249 When call cmd_init -k recipient-1 recipient-2 1250 The status should be success 1251 The output should be blank 1252 The error should equal "$(result)" 1253 End 1254 1255 It 'initializes the whole store interactively with a long option' 1256 result() { 1257 %text | @sed 's/\$$//' 1258 #|$ check_sneaky_path $ 1259 #|$ do_init recipient-1 recipient-2 1260 #|DECISION=interactive 1261 #|OVERWRITE=yes 1262 } 1263 When call cmd_init --interactive recipient-1 recipient-2 1264 The status should be success 1265 The output should be blank 1266 The error should equal "$(result)" 1267 End 1268 1269 It 'initializes the whole store interactively with a short option' 1270 result() { 1271 %text | @sed 's/\$$//' 1272 #|$ check_sneaky_path $ 1273 #|$ do_init recipient-1 recipient-2 1274 #|DECISION=interactive 1275 #|OVERWRITE=yes 1276 } 1277 When call cmd_init -i recipient-1 recipient-2 1278 The status should be success 1279 The output should be blank 1280 The error should equal "$(result)" 1281 End 1282 1283 It 'initializes a subdirectory with a collapsed long option' 1284 result() { 1285 %text 1286 #|$ check_sneaky_path sub 1287 #|$ do_init sub recipient 1288 #|DECISION=default 1289 #|OVERWRITE=yes 1290 } 1291 When call cmd_init --path=sub recipient 1292 The status should be success 1293 The output should be blank 1294 The error should equal "$(result)" 1295 End 1296 1297 It 'initializes a subdirectory with an expanded long option' 1298 result() { 1299 %text 1300 #|$ check_sneaky_path sub 1301 #|$ do_init sub recipient 1302 #|DECISION=default 1303 #|OVERWRITE=yes 1304 } 1305 When call cmd_init --path sub recipient 1306 The status should be success 1307 The output should be blank 1308 The error should equal "$(result)" 1309 End 1310 1311 It 'initializes a subdirectory with a collapsed short option' 1312 result() { 1313 %text 1314 #|$ check_sneaky_path sub 1315 #|$ do_init sub recipient 1316 #|DECISION=default 1317 #|OVERWRITE=yes 1318 } 1319 When call cmd_init -psub recipient 1320 The status should be success 1321 The output should be blank 1322 The error should equal "$(result)" 1323 End 1324 1325 It 'initializes a subdirectory with an expanded short option' 1326 result() { 1327 %text 1328 #|$ check_sneaky_path sub 1329 #|$ do_init sub recipient 1330 #|DECISION=default 1331 #|OVERWRITE=yes 1332 } 1333 When call cmd_init -p sub recipient 1334 The status should be success 1335 The output should be blank 1336 The error should equal "$(result)" 1337 End 1338 1339 It 'interactively initializes a directory with collapsed short options' 1340 result() { 1341 %text 1342 #|$ check_sneaky_path sub 1343 #|$ do_init sub recipient 1344 #|DECISION=interactive 1345 #|OVERWRITE=yes 1346 } 1347 When call cmd_init -ipsub recipient 1348 The status should be success 1349 The output should be blank 1350 The error should equal "$(result)" 1351 End 1352 1353 It 'conservatively initializes a directory with long options' 1354 result() { 1355 %text 1356 #|$ check_sneaky_path sub 1357 #|$ do_init sub recipient 1358 #|DECISION=keep 1359 #|OVERWRITE=yes 1360 } 1361 When call cmd_init --path sub --keep recipient 1362 The status should be success 1363 The output should be blank 1364 The error should equal "$(result)" 1365 End 1366 1367 It 'de-initializes a subdirectory' 1368 result() { 1369 %text 1370 #|$ check_sneaky_path sub 1371 #|$ do_deinit sub 1372 #|DECISION=default 1373 } 1374 When call cmd_init -p sub '' 1375 The status should be success 1376 The output should be blank 1377 The error should equal "$(result)" 1378 End 1379 1380 It 'supports recipients starting with dash' 1381 result() { 1382 %text | @sed 's/\$$//' 1383 #|$ check_sneaky_path $ 1384 #|$ do_init -recipient 1385 #|DECISION=default 1386 #|OVERWRITE=yes 1387 } 1388 When call cmd_init -- -recipient 1389 The status should be success 1390 The output should be blank 1391 The error should equal "$(result)" 1392 End 1393 1394 usage_text() { %text 1395 #|Usage: prg init [--interactive,-i | --keep,-k ] 1396 #| [--path=subfolder,-p subfolder] age-recipient ... 1397 } 1398 1399 It 'reports a bad option' 1400 cat() { @cat; } 1401 When run cmd_init -q arg 1402 The output should be blank 1403 The error should equal "$(usage_text)" 1404 The status should equal 1 1405 End 1406 1407 It 'reports conflicting options (`-i` then `-k`)' 1408 cat() { @cat; } 1409 When run cmd_init -ik arg 1410 The output should be blank 1411 The error should equal "$(usage_text)" 1412 The status should equal 1 1413 End 1414 1415 It 'reports conflicting options (`-k` then `-i`)' 1416 cat() { @cat; } 1417 When run cmd_init --keep --interactive arg 1418 The output should be blank 1419 The error should equal "$(usage_text)" 1420 The status should equal 1 1421 End 1422 1423 It 'reports a missing recipient' 1424 cat() { @cat; } 1425 When run cmd_init -p sub 1426 The output should be blank 1427 The error should equal "$(usage_text)" 1428 The status should equal 1 1429 End 1430 1431 It 'reports a missing path' 1432 cat() { @cat; } 1433 When run cmd_init -p 1434 The output should be blank 1435 The error should equal "$(usage_text)" 1436 The status should equal 1 1437 End 1438 1439 It 'reports a lack of argument' 1440 cat() { @cat; } 1441 When run cmd_init 1442 The output should be blank 1443 The error should equal "$(usage_text)" 1444 The status should equal 1 1445 End 1446 End 1447 1448 Describe 'cmd_insert' 1449 COMMAND=insert 1450 1451 It 'inserts a few new entries' 1452 result() { 1453 %text 1454 #|$ check_sneaky_path secret1 1455 #|$ check_sneaky_path secret2 1456 #|$ do_insert secret1 1457 #|ECHO=no 1458 #|MULTILINE=no 1459 #|OVERWRITE=no 1460 #|$ do_insert secret2 1461 #|ECHO=no 1462 #|MULTILINE=no 1463 #|OVERWRITE=no 1464 } 1465 When call cmd_insert secret1 secret2 1466 The status should be success 1467 The output should be blank 1468 The error should equal "$(result)" 1469 End 1470 1471 It 'inserts a new flag-like entry' 1472 result() { 1473 %text 1474 #|$ check_sneaky_path -c 1475 #|$ do_insert -c 1476 #|ECHO=no 1477 #|MULTILINE=no 1478 #|OVERWRITE=no 1479 } 1480 When call cmd_insert -- -c 1481 The status should be success 1482 The output should be blank 1483 The error should equal "$(result)" 1484 End 1485 1486 It 'inserts a new entry with echo (short option)' 1487 result() { 1488 %text 1489 #|$ check_sneaky_path secret 1490 #|$ do_insert secret 1491 #|ECHO=yes 1492 #|MULTILINE=no 1493 #|OVERWRITE=no 1494 } 1495 When call cmd_insert -e secret 1496 The status should be success 1497 The output should be blank 1498 The error should equal "$(result)" 1499 End 1500 1501 It 'inserts a new entry with echo (long option)' 1502 result() { 1503 %text 1504 #|$ check_sneaky_path secret 1505 #|$ do_insert secret 1506 #|ECHO=yes 1507 #|MULTILINE=no 1508 #|OVERWRITE=no 1509 } 1510 When call cmd_insert --echo secret 1511 The status should be success 1512 The output should be blank 1513 The error should equal "$(result)" 1514 End 1515 1516 It 'forcefully inserts a new entry with echo (short option)' 1517 result() { 1518 %text 1519 #|$ check_sneaky_path secret 1520 #|$ do_insert secret 1521 #|ECHO=yes 1522 #|MULTILINE=no 1523 #|OVERWRITE=yes 1524 } 1525 When call cmd_insert -fe secret 1526 The status should be success 1527 The output should be blank 1528 The error should equal "$(result)" 1529 End 1530 1531 It 'forcefully inserts a new entry with echo (short options)' 1532 result() { 1533 %text 1534 #|$ check_sneaky_path secret 1535 #|$ do_insert secret 1536 #|ECHO=yes 1537 #|MULTILINE=no 1538 #|OVERWRITE=yes 1539 } 1540 When call cmd_insert -e -f secret 1541 The status should be success 1542 The output should be blank 1543 The error should equal "$(result)" 1544 End 1545 1546 It 'forcefully inserts a new entry with echo (long option)' 1547 result() { 1548 %text 1549 #|$ check_sneaky_path secret 1550 #|$ do_insert secret 1551 #|ECHO=yes 1552 #|MULTILINE=no 1553 #|OVERWRITE=yes 1554 } 1555 When call cmd_insert --force --echo secret 1556 The status should be success 1557 The output should be blank 1558 The error should equal "$(result)" 1559 End 1560 1561 It 'inserts a new multiline entry (short option)' 1562 result() { 1563 %text 1564 #|$ check_sneaky_path secret 1565 #|$ do_insert secret 1566 #|ECHO=no 1567 #|MULTILINE=yes 1568 #|OVERWRITE=no 1569 } 1570 When call cmd_insert -m secret 1571 The status should be success 1572 The output should be blank 1573 The error should equal "$(result)" 1574 End 1575 1576 It 'inserts a new multiline entry (long option)' 1577 result() { 1578 %text 1579 #|$ check_sneaky_path secret 1580 #|$ do_insert secret 1581 #|ECHO=no 1582 #|MULTILINE=yes 1583 #|OVERWRITE=no 1584 } 1585 When call cmd_insert --multiline secret 1586 The status should be success 1587 The output should be blank 1588 The error should equal "$(result)" 1589 End 1590 1591 It 'forcefully inserts a new multiline entry (short option)' 1592 result() { 1593 %text 1594 #|$ check_sneaky_path secret 1595 #|$ do_insert secret 1596 #|ECHO=no 1597 #|MULTILINE=yes 1598 #|OVERWRITE=yes 1599 } 1600 When call cmd_insert -mf secret 1601 The status should be success 1602 The output should be blank 1603 The error should equal "$(result)" 1604 End 1605 1606 It 'forcefully inserts a new multiline entry (short options)' 1607 result() { 1608 %text 1609 #|$ check_sneaky_path secret 1610 #|$ do_insert secret 1611 #|ECHO=no 1612 #|MULTILINE=yes 1613 #|OVERWRITE=yes 1614 } 1615 When call cmd_insert -m -f secret 1616 The status should be success 1617 The output should be blank 1618 The error should equal "$(result)" 1619 End 1620 1621 It 'forcefully inserts a new multiline entry (long option)' 1622 result() { 1623 %text 1624 #|$ check_sneaky_path secret 1625 #|$ do_insert secret 1626 #|ECHO=no 1627 #|MULTILINE=yes 1628 #|OVERWRITE=yes 1629 } 1630 When call cmd_insert --force --multiline secret 1631 The status should be success 1632 The output should be blank 1633 The error should equal "$(result)" 1634 End 1635 1636 It 'reports a bad option' 1637 cat() { @cat; } 1638 When run cmd_insert -u secret 1639 The output should be blank 1640 The error should equal \ 1641 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1642 The status should equal 1 1643 End 1644 1645 It 'reports incompatible long options' 1646 cat() { @cat; } 1647 When run cmd_insert --multiline --echo secret 1648 The output should be blank 1649 The error should equal \ 1650 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1651 The status should equal 1 1652 End 1653 1654 It 'reports incompatible short options' 1655 cat() { @cat; } 1656 When run cmd_insert -em secret 1657 The output should be blank 1658 The error should equal \ 1659 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1660 The status should equal 1 1661 End 1662 1663 It 'reports a lack of argument' 1664 cat() { @cat; } 1665 When run cmd_insert 1666 The output should be blank 1667 The error should equal \ 1668 'Usage: prg insert [--echo,-e | --multiline,-m] [--force,-f] pass-name' 1669 The status should equal 1 1670 End 1671 End 1672 1673 Describe 'cmd_list_or_show' 1674 COMMAND= 1675 1676 It 'lists the whole store' 1677 result() { 1678 %text | @sed 's/\$$//' 1679 #|$ do_list_or_show $ 1680 #|SELECTED_LINE=1 1681 #|SHOW=text 1682 } 1683 When call cmd_list_or_show 1684 The status should be success 1685 The output should be blank 1686 The error should equal "$(result)" 1687 End 1688 1689 It 'shows multiple entries' 1690 result() { 1691 %text 1692 #|$ check_sneaky_path arg1 1693 #|$ check_sneaky_path arg2 1694 #|$ check_sneaky_path arg3 1695 #|$ do_list_or_show arg1 1696 #|SELECTED_LINE=1 1697 #|SHOW=text 1698 #|$ do_list_or_show arg2 1699 #|SELECTED_LINE=1 1700 #|SHOW=text 1701 #|$ do_list_or_show arg3 1702 #|SELECTED_LINE=1 1703 #|SHOW=text 1704 } 1705 When call cmd_list_or_show arg1 arg2 arg3 1706 The status should be success 1707 The output should be blank 1708 The error should equal "$(result)" 1709 End 1710 1711 It 'shows a flag-like entry' 1712 result() { 1713 %text 1714 #|$ check_sneaky_path -c 1715 #|$ do_list_or_show -c 1716 #|SELECTED_LINE=1 1717 #|SHOW=text 1718 } 1719 When call cmd_list_or_show -- -c 1720 The status should be success 1721 The output should be blank 1722 The error should equal "$(result)" 1723 End 1724 1725 It 'copies an entry into the clipboard (short option)' 1726 result() { 1727 %text 1728 #|$ check_sneaky_path arg 1729 #|$ do_list_or_show arg 1730 #|SELECTED_LINE=1 1731 #|SHOW=clip 1732 } 1733 When call cmd_list_or_show -c arg 1734 The status should be success 1735 The output should be blank 1736 The error should equal "$(result)" 1737 End 1738 1739 It 'copies an entry into the clipboard (long option)' 1740 result() { 1741 %text 1742 #|$ check_sneaky_path arg 1743 #|$ do_list_or_show arg 1744 #|SELECTED_LINE=1 1745 #|SHOW=clip 1746 } 1747 When call cmd_list_or_show --clip arg 1748 The status should be success 1749 The output should be blank 1750 The error should equal "$(result)" 1751 End 1752 1753 It 'copies a line of an entry into the clipboard (short option)' 1754 result() { 1755 %text 1756 #|$ check_sneaky_path arg 1757 #|$ do_list_or_show arg 1758 #|SELECTED_LINE=2 1759 #|SHOW=clip 1760 } 1761 When call cmd_list_or_show -c2 arg 1762 The status should be success 1763 The output should be blank 1764 The error should equal "$(result)" 1765 End 1766 1767 It 'copies a line of an entry into the clipboard (short option)' 1768 result() { 1769 %text 1770 #|$ check_sneaky_path arg 1771 #|$ do_list_or_show arg 1772 #|SELECTED_LINE=2 1773 #|SHOW=clip 1774 } 1775 When call cmd_list_or_show --clip=2 arg 1776 The status should be success 1777 The output should be blank 1778 The error should equal "$(result)" 1779 End 1780 1781 It 'shows an entry as a QR-code (short option)' 1782 result() { 1783 %text 1784 #|$ check_sneaky_path arg 1785 #|$ do_list_or_show arg 1786 #|SELECTED_LINE=1 1787 #|SHOW=qrcode 1788 } 1789 When call cmd_list_or_show -q arg 1790 The status should be success 1791 The output should be blank 1792 The error should equal "$(result)" 1793 End 1794 1795 It 'shows an entry as a QR-code (long option)' 1796 result() { 1797 %text 1798 #|$ check_sneaky_path arg 1799 #|$ do_list_or_show arg 1800 #|SELECTED_LINE=1 1801 #|SHOW=qrcode 1802 } 1803 When call cmd_list_or_show --qrcode arg 1804 The status should be success 1805 The output should be blank 1806 The error should equal "$(result)" 1807 End 1808 1809 It 'shows the line of an entry as a QR-code (short option)' 1810 result() { 1811 %text 1812 #|$ check_sneaky_path arg 1813 #|$ do_list_or_show arg 1814 #|SELECTED_LINE=3 1815 #|SHOW=qrcode 1816 } 1817 When call cmd_list_or_show -q3 arg 1818 The status should be success 1819 The output should be blank 1820 The error should equal "$(result)" 1821 End 1822 1823 It 'shows the line of an entry as a QR-code (long option)' 1824 result() { 1825 %text 1826 #|$ check_sneaky_path arg 1827 #|$ do_list_or_show arg 1828 #|SELECTED_LINE=3 1829 #|SHOW=qrcode 1830 } 1831 When call cmd_list_or_show --qrcode=3 arg 1832 The status should be success 1833 The output should be blank 1834 The error should equal "$(result)" 1835 End 1836 1837 It 'reports incompatible show options' 1838 cat() { @cat; } 1839 result() { %text 1840 #|Usage: prg [list] [subfolder] 1841 #| prg [show] [--clip[=line-number],-c[line-number] | 1842 #| --qrcode[=line-number],-q[line-number]] pass-name 1843 } 1844 When run cmd_list_or_show -q -c arg 1845 The output should be blank 1846 The error should equal "$(result)" 1847 The status should equal 1 1848 End 1849 1850 It 'reports a bad option for both commands' 1851 cat() { @cat; } 1852 result() { %text 1853 #|Usage: prg [list] [subfolder] 1854 #| prg [show] [--clip[=line-number],-c[line-number] | 1855 #| --qrcode[=line-number],-q[line-number]] pass-name 1856 } 1857 When run cmd_list_or_show -f arg 1858 The output should be blank 1859 The error should equal "$(result)" 1860 The status should equal 1 1861 End 1862 1863 It 'reports a bad option for list command' 1864 COMMAND=list 1865 cat() { @cat; } 1866 result() { %text 1867 #|Usage: prg [list] [subfolder] 1868 } 1869 When run cmd_list_or_show -f arg 1870 The output should be blank 1871 The error should equal "$(result)" 1872 The status should equal 1 1873 End 1874 1875 It 'reports a bad option for show command' 1876 COMMAND=show 1877 cat() { @cat; } 1878 result() { %text 1879 #|Usage: prg [show] [--clip[=line-number],-c[line-number] | 1880 #| --qrcode[=line-number],-q[line-number]] pass-name 1881 } 1882 When run cmd_list_or_show -f arg 1883 The output should be blank 1884 The error should equal "$(result)" 1885 The status should equal 1 1886 End 1887 End 1888 1889 Describe 'cmd_move' 1890 COMMAND=move 1891 1892 It 'moves multiple files' 1893 result() { 1894 %text 1895 #|$ check_sneaky_path src1 1896 #|$ check_sneaky_path src2 1897 #|$ check_sneaky_path src3 1898 #|$ check_sneaky_path dest 1899 #|$ do_copy_move src1 dest/ 1900 #|ACTION=Move 1901 #|DECISION=default 1902 #|OVERWRITE=no 1903 #|SCM_ACTION=scm_mv 1904 #|$ do_copy_move src2 dest/ 1905 #|ACTION=Move 1906 #|DECISION=default 1907 #|OVERWRITE=no 1908 #|SCM_ACTION=scm_mv 1909 #|$ do_copy_move src3 dest/ 1910 #|ACTION=Move 1911 #|DECISION=default 1912 #|OVERWRITE=no 1913 #|SCM_ACTION=scm_mv 1914 } 1915 When call cmd_move src1 src2 src3 dest 1916 The status should be success 1917 The output should be blank 1918 The error should equal "$(result)" 1919 End 1920 1921 It 'moves forcefully with a long option' 1922 result() { 1923 %text 1924 #|$ check_sneaky_path src 1925 #|$ check_sneaky_path dest 1926 #|$ do_copy_move src dest 1927 #|ACTION=Move 1928 #|DECISION=default 1929 #|OVERWRITE=yes 1930 #|SCM_ACTION=scm_mv 1931 } 1932 When call cmd_move --force src dest 1933 The status should be success 1934 The output should be blank 1935 The error should equal "$(result)" 1936 End 1937 1938 It 'moves forcefully with a short option' 1939 result() { 1940 %text 1941 #|$ check_sneaky_path src 1942 #|$ check_sneaky_path dest 1943 #|$ do_copy_move src dest 1944 #|ACTION=Move 1945 #|DECISION=default 1946 #|OVERWRITE=yes 1947 #|SCM_ACTION=scm_mv 1948 } 1949 When call cmd_move -f src dest 1950 The status should be success 1951 The output should be blank 1952 The error should equal "$(result)" 1953 End 1954 1955 It 'always reencrypts with a long option' 1956 result() { 1957 %text 1958 #|$ check_sneaky_path src 1959 #|$ check_sneaky_path dest 1960 #|$ do_copy_move src dest 1961 #|ACTION=Move 1962 #|DECISION=force 1963 #|OVERWRITE=no 1964 #|SCM_ACTION=scm_mv 1965 } 1966 When call cmd_move --reencrypt src dest 1967 The status should be success 1968 The output should be blank 1969 The error should equal "$(result)" 1970 End 1971 1972 It 'always reencrypts with a short option' 1973 result() { 1974 %text 1975 #|$ check_sneaky_path src 1976 #|$ check_sneaky_path dest 1977 #|$ do_copy_move src dest 1978 #|ACTION=Move 1979 #|DECISION=force 1980 #|OVERWRITE=no 1981 #|SCM_ACTION=scm_mv 1982 } 1983 When call cmd_move -e src dest 1984 The status should be success 1985 The output should be blank 1986 The error should equal "$(result)" 1987 End 1988 1989 It 'interactively reencrypts with a long option' 1990 result() { 1991 %text 1992 #|$ check_sneaky_path src 1993 #|$ check_sneaky_path dest 1994 #|$ do_copy_move src dest 1995 #|ACTION=Move 1996 #|DECISION=interactive 1997 #|OVERWRITE=no 1998 #|SCM_ACTION=scm_mv 1999 } 2000 When call cmd_move --interactive src dest 2001 The status should be success 2002 The output should be blank 2003 The error should equal "$(result)" 2004 End 2005 2006 It 'interactively reencrypts with a short option' 2007 result() { 2008 %text 2009 #|$ check_sneaky_path src 2010 #|$ check_sneaky_path dest 2011 #|$ do_copy_move src dest 2012 #|ACTION=Move 2013 #|DECISION=interactive 2014 #|OVERWRITE=no 2015 #|SCM_ACTION=scm_mv 2016 } 2017 When call cmd_move -i src dest 2018 The status should be success 2019 The output should be blank 2020 The error should equal "$(result)" 2021 End 2022 2023 It 'never reencrypts with a long option' 2024 result() { 2025 %text 2026 #|$ check_sneaky_path src 2027 #|$ check_sneaky_path dest 2028 #|$ do_copy_move src dest 2029 #|ACTION=Move 2030 #|DECISION=keep 2031 #|OVERWRITE=no 2032 #|SCM_ACTION=scm_mv 2033 } 2034 When call cmd_move --keep src dest 2035 The status should be success 2036 The output should be blank 2037 The error should equal "$(result)" 2038 End 2039 2040 It 'never reencrypts with a short option' 2041 result() { 2042 %text 2043 #|$ check_sneaky_path src 2044 #|$ check_sneaky_path dest 2045 #|$ do_copy_move src dest 2046 #|ACTION=Move 2047 #|DECISION=keep 2048 #|OVERWRITE=no 2049 #|SCM_ACTION=scm_mv 2050 } 2051 When call cmd_move -k src dest 2052 The status should be success 2053 The output should be blank 2054 The error should equal "$(result)" 2055 End 2056 2057 It 'moves a file named like a flag' 2058 result() { 2059 %text 2060 #|$ check_sneaky_path -s 2061 #|$ check_sneaky_path dest 2062 #|$ do_copy_move -s dest 2063 #|ACTION=Move 2064 #|DECISION=default 2065 #|OVERWRITE=no 2066 #|SCM_ACTION=scm_mv 2067 } 2068 When call cmd_move -- -s dest 2069 The status should be success 2070 The output should be blank 2071 The error should equal "$(result)" 2072 End 2073 2074 usage_text() { %text 2075 #|Usage: prg move [--reencrypt,-e | --interactive,-i | --keep,-k ] 2076 #| [--force,-f] old-path new-path 2077 } 2078 2079 It 'reports a bad option' 2080 cat() { @cat; } 2081 When run cmd_move -s arg 2082 The output should be blank 2083 The error should equal "$(usage_text)" 2084 The status should equal 1 2085 End 2086 2087 It 'reports incompatible re-encryption options (-e and -i)' 2088 cat() { @cat; } 2089 When run cmd_move -ei src dest 2090 The output should be blank 2091 The error should equal "$(usage_text)" 2092 The status should equal 1 2093 End 2094 2095 It 'reports incompatible re-encryption options (-i and -k)' 2096 cat() { @cat; } 2097 When run cmd_move -ik src dest 2098 The output should be blank 2099 The error should equal "$(usage_text)" 2100 The status should equal 1 2101 End 2102 2103 It 'reports incompatible re-encryption options (-k and -e)' 2104 cat() { @cat; } 2105 When run cmd_move -ke src dest 2106 The output should be blank 2107 The error should equal "$(usage_text)" 2108 The status should equal 1 2109 End 2110 2111 It 'reports a lack of argument' 2112 cat() { @cat; } 2113 When run cmd_move src 2114 The output should be blank 2115 The error should equal "$(usage_text)" 2116 The status should equal 1 2117 End 2118 End 2119 2120 Describe 'cmd_random' 2121 COMMAND=generate 2122 GENERATED_LENGTH=25 2123 2124 random_chars() { mocklog random_chars "$@"; } 2125 2126 It 'generates random characters with default parameters' 2127 When run cmd_random 2128 The status should be success 2129 The error should equal \ 2130 "$ random_chars ${GENERATED_LENGTH} ${CHARACTER_SET}" 2131 End 2132 2133 It 'generates random characters with default character set' 2134 When run cmd_random 8 2135 The status should be success 2136 The error should equal "$ random_chars 8 ${CHARACTER_SET}" 2137 End 2138 2139 It 'generates random characters with the given arguments' 2140 When run cmd_random 8 a-z 2141 The status should be success 2142 The error should equal "$ random_chars 8 a-z" 2143 End 2144 2145 It 'reports too many arguments' 2146 cat() { @cat; } 2147 When run cmd_random 1 2 3 2148 The output should be blank 2149 The error should equal 'Usage: prg random [pass-length [character-set]]' 2150 The status should equal 1 2151 End 2152 End 2153 2154 Describe 'cmd_reencrypt' 2155 COMMAND=reencrypt 2156 2157 It 're-encrypts multiple files and directories' 2158 result() { 2159 %text 2160 #|$ check_sneaky_path file-1 2161 #|$ check_sneaky_path dir/ 2162 #|$ check_sneaky_path sub/file-2 2163 #|$ do_reencrypt file-1 2164 #|DECISION=default 2165 #|$ do_reencrypt dir/ 2166 #|DECISION=default 2167 #|$ do_reencrypt sub/file-2 2168 #|DECISION=default 2169 } 2170 When call cmd_reencrypt file-1 dir/ sub/file-2 2171 The status should be success 2172 The output should be blank 2173 The error should equal "$(result)" 2174 End 2175 2176 It 'interactively re-encrypts with a long option' 2177 result() { 2178 %text 2179 #|$ check_sneaky_path arg 2180 #|$ do_reencrypt arg 2181 #|DECISION=interactive 2182 } 2183 When call cmd_reencrypt --interactive arg 2184 The status should be success 2185 The output should be blank 2186 The error should equal "$(result)" 2187 End 2188 2189 It 'interactively re-encrypts with a short option' 2190 result() { 2191 %text 2192 #|$ check_sneaky_path arg 2193 #|$ do_reencrypt arg 2194 #|DECISION=interactive 2195 } 2196 When call cmd_reencrypt -i arg 2197 The status should be success 2198 The output should be blank 2199 The error should equal "$(result)" 2200 End 2201 2202 It 're-encrypts a file named like a flag' 2203 result() { 2204 %text 2205 #|$ check_sneaky_path -s 2206 #|$ do_reencrypt -s 2207 #|DECISION=default 2208 } 2209 When call cmd_reencrypt -- -s 2210 The status should be success 2211 The output should be blank 2212 The error should equal "$(result)" 2213 End 2214 2215 usage_text() { %text 2216 #|Usage: prg reencrypt [--interactive,-i] pass-name|subfolder ... 2217 } 2218 2219 It 'reports a bad option' 2220 cat() { @cat; } 2221 When run cmd_reencrypt -s arg 2222 The status should equal 1 2223 The output should be blank 2224 The error should equal "$(usage_text)" 2225 End 2226 2227 It 'reports a lack of argument' 2228 cat() { @cat; } 2229 When run cmd_reencrypt 2230 The status should equal 1 2231 The output should be blank 2232 The error should equal "$(usage_text)" 2233 End 2234 End 2235 2236 Describe 'cmd_usage' 2237 COMMAND=usage 2238 CLIP_TIME='$CLIP_TIME' 2239 GENERATED_LENGTH='$GENERATED_LENGTH' 2240 cat() { @cat; } 2241 2242 It 'displays a human-reable usage string' 2243 When call cmd_usage 2244 The status should be success 2245 The first line of output should equal 'Usage:' 2246 The error should be blank 2247 End 2248 2249 It 'includes help about all commands' 2250 When call cmd_usage 2251 The status should be success 2252 The output should include 'prg copy' 2253 The output should include 'prg delete' 2254 The output should include 'prg edit' 2255 The output should include 'prg find' 2256 The output should include 'prg generate' 2257 The output should include 'prg git' 2258 The output should include 'prg gitconfig' 2259 The output should include 'prg grep' 2260 The output should include 'prg help' 2261 The output should include 'prg init' 2262 The output should include 'prg insert' 2263 The output should include 'prg [list]' 2264 The output should include 'prg move' 2265 The output should include 'prg random' 2266 The output should include 'prg reencrypt' 2267 The output should include 'prg [show]' 2268 The output should include 'prg version' 2269 End 2270 2271 It 'rejects unknown commands' 2272 When run cmd_usage '> ' foo 2273 The output should be blank 2274 The error should equal 'cmd_usage: unknown command "foo"' 2275 The status should equal 1 2276 End 2277 End 2278 2279 Describe 'cmd_version' 2280 COMMAND=version 2281 2282 It 'shows the version box' 2283 cat() { @cat; } 2284 result() { 2285 %text 2286 #|============================================== 2287 #|= pashage: age-backed POSIX password manager = 2288 #|= = 2289 #|= v* 2290 #|= = 2291 #|= Natasha Kerensikova = 2292 #|= = 2293 #|= Based on: = 2294 #|= password-store by Jason A. Donenfeld = 2295 #|= passage by Filippo Valsorda = 2296 #|= pash by Dylan Araps = 2297 #|============================================== 2298 } 2299 When call cmd_version 2300 The status should be success 2301 The output should match pattern "$(result)" 2302 End 2303 End 2304 End