├── .authorspellings ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── ANNOUNCE ├── CHANGES ├── HCAR.tex ├── LICENSE ├── Makefile ├── README.md ├── Setup.hs ├── shelltestrunner.cabal ├── site ├── README ├── files │ ├── cat.test │ ├── cat2.test │ └── true.test ├── gittip.png ├── paypal.gif ├── site.css ├── site.tmpl ├── syntax.css ├── title.png ├── title.pxm └── title2.png ├── src ├── Import.hs ├── Parse.hs ├── Preprocessor.hs ├── Print.hs ├── Types.hs ├── Utils.hs ├── Utils │ └── Debug.hs └── shelltest.hs ├── stack.yaml ├── stack8.10.yaml ├── stack912.yaml ├── stack96.yaml ├── stack98.yaml └── tests ├── README ├── bash ├── dollar-quote.test └── process-substitution.test ├── examples ├── README ├── examples.test ├── format2_1.test ├── format2_2.test ├── format3_1.test └── format3_2.test ├── format1.unix ├── empty-unix.test ├── no-eol-unix.test └── unicode-unix.test ├── format1.windows └── empty-windows.test ├── format1 ├── abstract-test-with-macros ├── args.test ├── delimiters.test ├── failure-line.test ├── format1.test ├── help.test ├── indented-input.test ├── just-a-comment.test ├── large-output.test ├── large-regexp.test ├── macros.test ├── no-input.test ├── one-failing-test ├── parsing.test ├── trailing-comment-no-newline.test └── trailing-comment.test.todo ├── format2.unix ├── empty-unix.test ├── no-eol-unix.test └── unicode-unix.test ├── format2.windows └── empty-windows.test ├── format2 ├── abstract-test-with-macros ├── args.test ├── delimiters.test ├── failure-line.test ├── format2.test ├── help.test ├── ideal.test ├── indented-input.test ├── just-a-comment.test ├── large-output.test ├── macros.test ├── no-input.test ├── one-failing-test ├── parsing.test ├── regexps.test └── trailing-comment-no-newline.test ├── format3.unix ├── empty-unix.test ├── no-eol-unix.test └── unicode-unix.test ├── format3.windows └── empty-windows.test ├── format3 ├── abstract-test-with-macros ├── args.test ├── failure-line.test ├── format3.test ├── help.test ├── ideal.test ├── indented-input.test ├── just-a-comment.test ├── large-output.test ├── macros.test ├── no-input.test ├── one-failing-test ├── parsing.test ├── regexps.test └── trailing-comment-no-newline.test └── print ├── print-format1.test ├── print-format2.test └── print-format3.test /.authorspellings: -------------------------------------------------------------------------------- 1 | Bernie Pope , bjpop@unimelb.edu.au 2 | John MacFarlane 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: shelltestrunner CI 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/**' 7 | - 'stack*' 8 | - 'src/**' 9 | - 'tests/**' 10 | - '!**.md' 11 | - '!**.1' 12 | - '!**.5' 13 | - '!**.info' 14 | - '!**.txt' 15 | 16 | pull_request: 17 | paths: 18 | - '.github/workflows/**' 19 | - 'stack*' 20 | - 'src/**' 21 | - 'tests/**' 22 | - '!**.md' 23 | - '!**.1' 24 | - '!**.5' 25 | - '!**.info' 26 | - '!**.txt' 27 | 28 | # Scheduled workflows run on the latest commit on the default or base branch. (master) 29 | # schedule: 30 | # - cron: "0 07 * * 0" # sunday midnight pacific 31 | 32 | jobs: 33 | test: 34 | runs-on: ubuntu-latest 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | plan: 39 | - { ghc: "912", stack: "stack --stack-yaml=stack912.yaml --system-ghc --no-install-ghc" } 40 | # Use the preinstalled stack and ghc (3.5.1 and 9.12.2 as of 2025-04). 41 | # This risks breaking when github updates these, but avoids a lot of wasted work. 42 | 43 | steps: 44 | 45 | - name: Check out 46 | uses: actions/checkout@v4 47 | 48 | - name: Cache stack global package db 49 | id: stack-global 50 | uses: actions/cache@v4 51 | with: 52 | path: ~/.stack 53 | key: ${{ runner.os }}-stack-global-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }} 54 | restore-keys: | 55 | ${{ runner.os }}-stack-global-${{ matrix.plan.ghc }} 56 | 57 | - name: Cache stack-installed programs in ~/.local/bin 58 | id: stack-programs 59 | uses: actions/cache@v4 60 | with: 61 | path: ~/.local/bin 62 | key: ${{ runner.os }}-stack-programs-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }} 63 | restore-keys: | 64 | ${{ runner.os }}-stack-programs-${{ matrix.plan.ghc }} 65 | 66 | - name: Cache .stack-work 67 | uses: actions/cache@v4 68 | with: 69 | path: .stack-work 70 | key: ${{ runner.os }}-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }} 71 | restore-keys: | 72 | ${{ runner.os }}-stack-work-${{ matrix.plan.ghc }} 73 | 74 | # - name: Install specific stack version 75 | # run: | 76 | # mkdir -p ~/.local/bin 77 | # export PATH=~/.local/bin:$PATH 78 | # # curl -sL https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack 79 | # if [[ ! -x ~/.local/bin/stack ]]; then curl -sL https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi 80 | # stack --version 81 | # 82 | # - name: Install specific GHC version 83 | # env: 84 | # stack: ${{ matrix.plan.stack }} 85 | # run: | 86 | # $stack setup --install-ghc 87 | 88 | - name: Install haskell deps 89 | env: 90 | stack: ${{ matrix.plan.stack }} 91 | run: | 92 | $stack build --test --bench --only-dependencies 93 | 94 | - name: Build all shelltestrunner modules warning free, optimised and minimised, and run any unit/doc/bench tests 95 | env: 96 | stack: ${{ matrix.plan.stack }} 97 | run: | 98 | $stack install --test --bench --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --ghc-options=-split-sections --no-terminal 99 | 100 | - name: Run functional tests (excluding windows tests) 101 | env: 102 | stack: ${{ matrix.plan.stack }} 103 | run: | 104 | export PATH=~/.local/bin:$PATH 105 | make STACK="$stack" test 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.hi 2 | *.o 3 | TAGS 4 | ctags 5 | .obsidian 6 | .vscode 7 | _* 8 | /shelltest 9 | /shelltest.exe 10 | #/shelltest.hs.1 11 | /[a-z].* 12 | .idea/ 13 | *.iml 14 | .stack-work/ 15 | dist/ 16 | patches/ 17 | *.org 18 | .idea* 19 | t.* 20 | *.html 21 | /stack.yaml.lock 22 | /stack*.yaml.lock 23 | -------------------------------------------------------------------------------- /ANNOUNCE: -------------------------------------------------------------------------------- 1 | I'm pleased to announce shelltestrunner 1.10 ! 2 | 3 | shelltestrunner (executable: `shelltest`) is a portable, GPLv3+ 4 | command-line tool for testing command-line programs or shell commands. 5 | It reads simple test specifications defining a command to run, some 6 | input, and the expected output, stderr, and exit status. 7 | It can run tests in parallel, selectively, with a timeout, in color, etc. 8 | 9 | The last release was 1.9, in 2018. The 1.10 release has been overdue; 10 | it brings some useful improvements, notably --print mode (with which 11 | you can convert old format 1 tests to the cleaner, recommended format 3), 12 | and precise line number reporting (to quickly locate the failing test). 13 | 14 | User-visible changes in 1.10 (2023-09-12): 15 | 16 | * GHC 9.6 compatibility (Andreas Abel) 17 | * Add --print for printing tests and/or converting file format (#24, Jakob Schöttl) 18 | * Add --shell option to select shell (#17, FC Stegerman) 19 | * Fix format1's handling of angle brackets in test data (#16) 20 | * Print test line number on failure (#14, Taavi Väljaots) 21 | * Add -p short flag for --precise 22 | * -h means --help, not --hide-successes 23 | * Clarify 300 char regex limit message 24 | 25 | Other changes: 26 | 27 | * Set up CI testing (#18 FC Stegerman, Simon Michael) 28 | * Improve bash-related tests (#20, FC Stegerman, Simon Michael) 29 | * Improved tests 30 | 31 | Thanks to release contributors: 32 | Jakob Schöttl, Taavi Väljaots, Felix C. Stegerman, and Andreas Abel. 33 | 34 | Install: 35 | 36 | $ stack install shelltestrunner-1.10 37 | 38 | or: 39 | 40 | $ cabal update && cabal install shelltestrunner-1.10 41 | 42 | Home: https://github.com/simonmichael/shelltestrunner 43 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 1.11 (unreleased) 2 | 3 | * Fixed: -i1 was not selecting the test if the file contained only one test ([#37], Thomas Miedema) 4 | 5 | 1.10 (2023-09-12) 6 | 7 | User-visible changes: 8 | 9 | * GHC 9.6 compatibility (Andreas Abel) 10 | * Add --print for printing tests and/or converting file format (#24, Jakob Schöttl) 11 | * Print test line number on failure (#14, Taavi Väljaots) 12 | * Add --shell option to select shell (#17, FC Stegerman) 13 | * Fix format1's handling of angle brackets in test data (#16) 14 | * Add -p short flag for --precise 15 | * -h means --help, not --hide-successes 16 | * Clarify 300 char regex limit message 17 | 18 | Other: 19 | 20 | * Set up CI testing (#18 FC Stegerman, Simon Michael) 21 | * Improve bash-related tests (#20, FC Stegerman, Simon Michael) 22 | * Improved tests 23 | 24 | 1.9 (2018/1/14) 25 | 26 | * two new test file formats have been added, allowing input re-use and lighter syntax 27 | * new -l/--list flag lists the tests found 28 | * new -D/--defmacro option allows text substitution (Taavi Valjaots) 29 | * new --xmlout option saves test results as xml (Taavi Valjaots) 30 | * tests with Windows line endings now also work on unix (Taavi Valjaots) 31 | * shelltestrunner's tests should now pass on Windows (Taavi Valjaots) 32 | * flags formerly passed through to test-framework are now built in 33 | * >>>= with nothing after it now matches any exit status 34 | * failure messages now show the test command (John Chee) 35 | * include shelltestrunner's tests in cabal sdist archive (Iustin Pop) 36 | * build with latest deps and stackage resolvers 37 | * process dep update (Andrés Sicard-Ramírez) 38 | * shelltestrunner's code and home page have moved to github 39 | 40 | 1.3.5 (2015/3/30) 41 | 42 | * fix Applicative warning with ghc 7.10 43 | * allow utf8-string <1.1 44 | 45 | 1.3.4 (2014/5/28) 46 | 47 | * drop cabal-file-th, support GHC 7.8.2 48 | 49 | 1.3.3 (2014/5/25) 50 | 51 | * allow process 1.2, regex-tdfa-1.2 52 | * add a hackage-compatible changelog 53 | 54 | 1.3.2 (2013/11/13) 55 | 56 | * increase upper bound on Diff package 57 | 58 | 1.3.1 (2012/12/28) 59 | 60 | * fix cabal file typo breaking the build 61 | 62 | 1.3 (2012/12/28) 63 | 64 | * support latest Diff, cmdargs, test-framework; tested with GHC 7.6.1 (Magnus Therning) 65 | 66 | * fix unicode handling on GHC >= 7.2 67 | 68 | 1.2.1 (2012/3/12) 69 | 70 | * use the more up-to-date filemanip package for easier Debian packaging 71 | 72 | 1.2 (2012/2/26) 73 | 74 | * support latest cmdargs, test-framework, and GHC 7.4 75 | * more readable non-quoted failure output by default; for quoted output, use -p/--precise 76 | * the --all, --diff and --precise options now interact well 77 | 78 | 1.1 (2011/8/25) 79 | 80 | * bump process dependency to allow building with GHC 7.2.1 81 | * new -a/--all flag shows all failure output without truncating 82 | 83 | 1.0 (2011/7/23) 84 | 85 | * New home page/docs 86 | * The >>>= field is now required; you may need to add it to your existing tests 87 | * Input and expected output can now contain lines beginning with # 88 | * Multiple tests in a file may now have whitespace between them 89 | * The -i/--implicit option has been dropped 90 | * New -d/--diff option shows test failures as a unified diff when possible, including line numbers to help locate the problem 91 | * New -x/--exclude option skips certain test files (eg platform-specific ones) 92 | * Passing arguments through to test-framework is now more robust 93 | * Fixed: parsing could fail when input contained left angle brackets 94 | * Fixed: some test files generated an extra blank test at the end 95 | 96 | 0.9 (2010/9/3) 97 | 98 | * show plain non-ansi output by default, add --color option 99 | * better handling of non-ascii test data. We assume that non-ascii file 100 | paths, command-line arguments etc. are UTF-8 encoded on unix systems 101 | (cf http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html), 102 | and that GHC 6.12 or greater is used. Then: 103 | - non-ascii test file paths should render correctly, eg in failure messages 104 | - non-ascii test commands should run correctly 105 | - non-ascii expected output should match correctly 106 | - non-ascii regular expressions should match correctly. (Caveat: not 107 | thoroughly tested, this may break certain regexps, ) 108 | * use regex-tdfa instead of pcre-light for better windows compatibility 109 | To avoid a memory leak in current regex-tdfa, only regular expressions 110 | up to 300 characters in size are supported. Also, DOTALL is no longer 111 | enabled and probably fewer regexp constructs are supported. There are 112 | still issues on windows/wine but in theory this will help. 113 | * tighten up dependencies 114 | 115 | 0.8 (2010/4/9) 116 | 117 | * rename executable to shelltest. The package might also be renamed at some point. 118 | * better built-in help 119 | * shell tests now include a full command line, making them more readable 120 | and self-contained. The --with option can be used to replace the first 121 | word with something else, unless the test command line begins with a 122 | space. 123 | * we also accept directory arguments, searching for test files below 124 | them, with two new options: 125 | --execdir execute tested command in same directory as test file 126 | --extension=EXT file extension of test files (default=.test) 127 | 128 | 0.7 (2010/3/5) 129 | 130 | * more robust parsing 131 | - --debug-parse parses test files and stops 132 | - regexps now support escaped forward slash (\/) 133 | - bad regexps now fail at startup 134 | - command-line arguments are required in a test, and may be blank 135 | - a >>>= is no longer required to separate multiple tests in a file 136 | - comments can be appended to delimiter lines 137 | - comments can appear at end of file 138 | - files need not have a final newline 139 | - files containing nothing, all comments, or valid tests are allowed; anything else is rejected 140 | - somewhat better errors 141 | - allow indented input 142 | * support negative (-) and negatively-matched (!) numeric exit codes 143 | * let . in regexps match newline 144 | * warn but continue when a test file fails to parse 145 | * output cleanups, trim large output 146 | * more flexible --implicit flag 147 | * switch to the more robust and faster pcre-light regexp lib 148 | 149 | 0.6 (2009/7/15) 150 | 151 | * allow multiple tests per file, handle bad executable better 152 | 153 | 0.5 (2009/7/14) 154 | 155 | * show failure output in proper order 156 | 157 | 0.4 (2009/7/14) 158 | 159 | * run commands in a more robust way to avoid hangs 160 | This fixes hanging when a command generates large output, and hopefully 161 | all other deadlocks. The output is consumed strictly. Thanks to Ganesh 162 | Sittampalam for his help with this. 163 | * --implicit-tests flag providing implicit tests for omitted fields 164 | * --debug flag 165 | * regular expression matching 166 | * disallow interspersed foreign options which confused parseargs 167 | * change comment character to # 168 | 169 | 0.3 (2009/7/11) 170 | 171 | * misc. bugfixes/improvements 172 | 173 | 0.2 (2009/7/10) 174 | 175 | * bugfix, build with -threaded 176 | 177 | 0.1 (2009/7/10) 178 | 179 | * shelltestrunner, a generic shell command stdout/stderr/exit status tester 180 | -------------------------------------------------------------------------------- /HCAR.tex: -------------------------------------------------------------------------------- 1 | % shelltestrunner-Ss.tex 2 | \begin{hcarentry}[new]{shelltestrunner} 3 | \report{Simon Michael}%11/11 4 | \status{stable} 5 | \makeheader 6 | 7 | shelltestrunner was first released in 2009, inspired by the test suite 8 | in John Wiegley's ledger project. It is a command-line tool for doing 9 | repeatable functional testing of command-line programs or shell 10 | commands. It reads simple declarative tests specifying a command, some 11 | input, and the expected output, error output and exit status. Tests 12 | can be run selectively, in parallel, with a timeout, in color, and/or 13 | with differences highlighted. 14 | 15 | In the last six months, shelltestrunner has had three releases (1.0, 16 | 1.1, 1.2) and acquired a home page. Projects using it include hledger, 17 | yesod, berp, and eddie. shelltestrunner is free software released 18 | under GPLv3+ from Hackage or \url{http://joyful.com/shelltestrunner}. 19 | 20 | \FurtherReading 21 | \url{http://joyful.com/repos/shelltestrunner} 22 | \end{hcarentry} 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # shelltestrunner project makefile 2 | 3 | # ensure a utf8-aware locale is set, required by ghc executables 4 | export LANG = en_US.UTF-8 5 | 6 | # which stack.yaml file (& ghc version) to use, can be overridden by STACK env var 7 | STACKYAML ?= stack.yaml 8 | 9 | # the current base stack command 10 | STACK = stack --stack-yaml=$(STACKYAML) 11 | # STACK = stack --silent --stack-yaml=$(STACKYAML) 12 | 13 | # the shelltest executable built with current stack 14 | SHELLTESTEXE = $(shell $(STACK) path --local-install-root)/bin/shelltest 15 | 16 | SHELLTEST = $(SHELLTESTEXE) --exclude /_ -j16 --hide-successes 17 | 18 | # standard targets 19 | 20 | default: build 21 | 22 | build: 23 | @$(STACK) build 24 | 25 | install: 26 | @$(STACK) install 27 | 28 | ghci: 29 | @echo 30 | @echo "Warning: argumentss will be accepted in GHCI only on first run after load," 31 | @echo "probably because of using cmdargs' unsafeperformio-based easy mode." 32 | @echo 33 | $(STACK) ghci 34 | 35 | ghcid: 36 | $(STACK) exec -- ghcid 37 | 38 | test: testcross testunix testbash testexamples 39 | 40 | # tests 41 | 42 | # run cross-platform shell tests 43 | testcross: build 44 | @echo; echo "cross-platform tests should succeed:" 45 | $(SHELLTEST) -w $(SHELLTESTEXE) tests -x /bash -x /examples -x .windows -x .unix 46 | 47 | # run unix-specific shell tests 48 | testunix: build 49 | @echo; echo "on unix, unix tests should succeed:" 50 | $(SHELLTEST) -w $(SHELLTESTEXE) tests/*.unix 51 | 52 | # run windows-specific shell tests 53 | # (though if you are using make on windows, you may be able to, or may have to, use testunix) 54 | testwindows: build 55 | @echo; echo "on windows, windows tests should succeed:" 56 | @$(SHELLTEST) -w $(SHELLTESTEXE) tests/*.windows 57 | 58 | # run bash-specific shell tests 59 | testbash: build 60 | @echo; echo "when using bash, bash tests should succeed:" 61 | @$(SHELLTEST) tests/bash --shell /bin/bash 62 | 63 | # run tests of the README examples 64 | testexamples: build 65 | @echo; echo "README examples should succeed:" 66 | @$(SHELLTEST) tests/examples 67 | 68 | # misc 69 | 70 | LASTTAG=$(shell git describe --tags --abbrev=0) 71 | 72 | changes-show: $(call def-help,changes-show, show commits affecting the current directory excluding any hledger package subdirs from the last tag as org nodes newest first ) 73 | @make changes-show-from-$(LASTTAG) 74 | 75 | changes-show-from-%: #$(call def-help,changes-show-from-REV, show commits affecting the current directory excluding any hledger package subdirs from this git revision onward as org nodes newest first ) 76 | @git log --abbrev-commit --pretty=format:'ORGNODE %s (%an)%n%b%h' $*.. -- . ':!hledger' ':!hledger-*' \ 77 | | sed -e 's/^\*/-/' -e 's/^ORGNODE/*/' \ 78 | | sed -e 's/ (Simon Michael)//' 79 | 80 | loc: 81 | @echo Current lines of code including tests: 82 | @sloccount src | grep haskell: 83 | 84 | # files to tag 85 | HSFILES=src/*.hs src/Utils/*.hs 86 | TESTFILES=tests/format*/*.test 87 | 88 | tag: $(HSFILES) #$(TESTFILES) *.md Makefile 89 | hasktags -e -o TAGS $^ 90 | hasktags -c -o ctags $^ 91 | 92 | # clean: 93 | # rm -f `find . -name "*.o" -o -name "*.hi" -o -name "*~" -o -name "darcs-amend-record*" -o -name "*-darcs-backup*"` 94 | 95 | # Clean: clean 96 | # rm -f TAGS _cache #_site $(EXE) 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Easy, repeatable testing of CLI programs/commands

3 | 4 | 5 | [Install](#install) 6 | | [Usage](#usage) 7 | | [Options](#options) 8 | | [Test formats](#test-formats) 9 | | [Support/Contribute](#supportcontribute) 10 | | [Credits](#credits) 11 |
12 | 13 | **shelltestrunner** (executable: `shelltest`) is a portable 14 | command-line tool for testing command-line programs, or general shell 15 | commands, released under GPLv3+. It reads simple test specifications 16 | defining a command to run, some input, and the expected output, 17 | stderr, and exit status. It can run tests in parallel, selectively, 18 | with a timeout, in color, etc. 19 | 20 | ## Install 21 | 22 | There may be a new-enough 23 | [packaged version](https://repology.org/metapackage/shelltestrunner/badges) 24 | on your platform. Eg: 25 | 26 | ||| 27 | |----------------|--------------------------------------- 28 | | Debian/Ubuntu: | **`apt install shelltestrunner`** 29 | | Gentoo: | **`emerge shelltestrunner`** 30 | 31 | Or, build the latest release on any major platform: 32 | 33 | ||| 34 | |----------------|--------------------------------------- 35 | | stack: | **[get stack](https://docs.haskellstack.org)**, **`stack install shelltestrunner-1.10`** 36 | | cabal: | **`cabal update; cabal install shelltestrunner-1.10`** 37 | 38 | ## Usage 39 | 40 | Here's a test file containing three simple tests. 41 | They're called "shell tests" because any shell command line can be tested. 42 | A test contains: 43 | 44 | - `<` and one or more lines of input to be provided on stdin (optional) 45 | - `$` and the command line to test (required) 46 | - zero or more lines of expected stdout output, or a regexp (optional) 47 | - `>2` and zero or more lines of expected stderr output, or a regexp (optional) 48 | - `>=` and an expected exit code, or a regexp (optional) 49 | 50 | 51 | ``` 52 | # 1. Test that the "echo" command (a shell builtin, usually) 53 | # prints its argument on stdout, prints nothing on stderr, 54 | # and exits with a zero exit code. 55 | 56 | $ echo a 57 | a 58 | 59 | # 2. Test that echo with no arguments prints a blank line, 60 | # no stderr output, and exits with zero. 61 | # Since the output ends with whitespace, this time we must write 62 | # the exit code test (>=) explicitly, to act as a delimiter. 63 | 64 | $ echo 65 | 66 | >= 67 | 68 | # 3. Test that cat with a bad flag prints nothing on stdout, 69 | # an error containing "unrecognized option" or "illegal option" on stderr, 70 | # and exits with non-zero status. 71 | 72 | $ cat --no-such-flag 73 | >2 /(unrecognized|illegal) option/ 74 | >= !0 75 | 76 | ``` 77 | 78 | To run these tests: 79 | 80 | ``` 81 | $ shelltest examples.test 82 | :examples.test:1: [OK] 83 | :examples.test:2: [OK] 84 | :examples.test:3: [OK] 85 | 86 | Test Cases Total 87 | Passed 3 3 88 | Failed 0 0 89 | Total 3 3 90 | ``` 91 | 92 | That's the basics! 93 | There are also some alternate test formats you'll read about below. 94 | 95 | ## Options 96 | 97 | 98 | ``` 99 | shelltest 1.10 100 | 101 | shelltest [OPTIONS] [TESTFILES|TESTDIRS] 102 | 103 | Common flags: 104 | -l --list List the names of all tests found 105 | -i --include=PAT Include tests whose name contains this glob pattern 106 | (eg: -i1 -i{4,5,6}) 107 | -x --exclude=STR Exclude test files whose path contains STR 108 | -a --all Show all output without truncating, even if large 109 | -c --color Show colored output if your terminal supports it 110 | -d --diff Show differences between expected/actual output 111 | -p --precise Show expected/actual output precisely, with quoting 112 | --hide-successes Show only test failures 113 | -f --fail-fast Only hspec: stop tests on first failure 114 | --xmlout=FILE Save test results to FILE in XML format. 115 | -D --defmacro=D=DEF Define a macro D to be replaced by DEF while parsing 116 | test files. 117 | --execdir Run tests from within each test file's directory 118 | --extension=EXT File suffix of test files (default: .test) 119 | -w --with=EXE Replace the first word of test commands with EXE 120 | (unindented commands only) 121 | -o --timeout=SECS Number of seconds a test may run (default: no limit) 122 | -j --threads=N Number of threads for running tests (default: 1) 123 | --shell=EXE The shell program to use (must accept -c CMD; 124 | default: /bin/sh on POSIX, cmd.exe on Windows) 125 | --debug Show debug info while running 126 | --debug-parse Show test file parsing results and stop 127 | Print test file: 128 | --print[=FORMAT] Print test files in specified format (default: v3). 129 | --hspec Use hspec to run tests. 130 | -h --help Display help message 131 | -V --version Print version information 132 | --numeric-version Print just the version number 133 | 134 | ``` 135 | 136 | `shelltest` accepts one or more test file or directory arguments. 137 | A directory means all files below it named `*.test` (customisable with `--extension`). 138 | 139 | By default, test commands are run with `/bin/sh` on POSIX systems 140 | and with `CMD` on Windows; you can change this with the `--shell` option. 141 | 142 | By default, tests run in the directory in which you ran `shelltest`; 143 | with `--execdir` they will run in each test file's directory instead. 144 | 145 | `--include` selects only tests whose name (file name plus intra-file sequence number) matches a 146 | [.gitignore-style pattern](https://batterseapower.github.io/test-framework#the-console-test-runner), 147 | while `--exclude` skips tests based on their file path. 148 | These can be used eg to focus on a particular test, or to skip tests intended for a different platform. 149 | 150 | `-D/--defmacro` defines a macro that is replaced by preprocessor before any tests are parsed and run. 151 | 152 | `-w/--with` replaces the first word of all test commands with something 153 | else, which can be useful for testing alternate versions of a 154 | program. Commands which have been prefixed by an extra space will 155 | not be affected by this option. 156 | 157 | `--hide-successes` gives quieter output, reporting only failed tests. 158 | 159 | Long flags can be abbreviated to a unique prefix. 160 | 161 | 162 | For example, the command: 163 | 164 | $ shelltest tests -i args -c -j8 -o1 -DCONF_FILE=test/myconf.cfq --hide 165 | 166 | - runs the tests defined in any `*.test` file in or below the `tests/` directory 167 | - whose names contain "`args`" 168 | - in colour if possible 169 | - with up to 8 tests running in parallel 170 | - allowing no more than 1 second for each test 171 | - replacing the text "`CONF_FILE`" in all tests with "`test/myconf.cfq`" 172 | - reporting only the failures. 173 | 174 | ## Test formats 175 | 176 | shelltestrunner supports three test file formats: 177 | 178 | | Format name | Description | Delimiters, in order | 179 | |-----------------------|---------------------------------------------------------------|----------------------------| 180 | | format 1 (deprecated) | command is first; exit status is required | `(none) <<< >>> >>>2 >>>=` | 181 | | format 2 (verbose) | input is first, can be reused; all but command can be omitted | `<<< $$$ >>> >>>2 >>>=` | 182 | | format 3 (preferred) | same as format 2 but with short delimiters | `< $ > >2 >=` | 183 | 184 | To read each file, shelltestrunner tries the formats in this order: format 2, then format 3, then format 1. 185 | Within a file, all tests should use the same format. 186 | 187 | Here are the formats in detail, from oldest to newest. 188 | You should use format 3; or if that clashes with your data, then format 2. 189 | 190 | ### Format 1 191 | 192 | This old format is included for backward compatibility with old tests. 193 | 194 | Test files contain one or more individual tests, each consisting of a 195 | one-line shell command, optional input, expected standard output 196 | and/or error output, and a (required) exit status. 197 | 198 | # COMMENTS OR BLANK LINES 199 | COMMAND LINE 200 | <<< 201 | INPUT 202 | >>> 203 | EXPECTED OUTPUT (OR >>> /REGEXP/) 204 | >>>2 205 | EXPECTED STDERR (OR >>>2 /REGEXP/) 206 | >>>= EXPECTED EXIT STATUS (OR >>>= /REGEXP/) 207 | 208 | When not specified, stdout/stderr are ignored. 209 | A space before the command protects it from -w/--with. 210 | 211 | Examples: 212 | [shelltestrunner](https://github.com/simonmichael/shelltestrunner/tree/master/tests/format1), 213 | [Agda](https://github.com/agda/agda/tree/master/src/size-solver/test), 214 | [berp](https://github.com/bjpop/berp/tree/master/test/regression), 215 | [cblrepo](https://github.com/magthe/cblrepo/tree/master/tests). 216 | 217 | ### Format 2 218 | 219 | This is supported by shelltestrunner 1.9+. 220 | It improves on format 1 in two ways: it allows tests to reuse the same input, 221 | and it allows delimiters/test clauses to be omitted, with more useful defaults. 222 | 223 | Test files contain one or more test groups. 224 | A test group consists of some optional standard input and one or more tests. 225 | Each test is a one-line shell command followed by optional expected standard output, 226 | error output and/or numeric exit status, separated by delimiters. 227 | 228 | # COMMENTS OR BLANK LINES 229 | <<< 230 | INPUT 231 | $$$ COMMAND LINE 232 | >>> 233 | EXPECTED OUTPUT (OR >>> /REGEX/) 234 | >>>2 235 | EXPECTED STDERR (OR >>>2 /REGEX/) 236 | >>>= EXPECTED EXIT STATUS (OR >>>= /REGEX/ OR >>>=) 237 | # COMMENTS OR BLANK LINES 238 | ADDITIONAL TESTS FOR THIS INPUT 239 | ADDITIONAL TEST GROUPS WITH DIFFERENT INPUT 240 | 241 | All test parts are optional except the command line. 242 | If not specified, stdout and stderr are expected to be empty 243 | and exit status is expected to be zero. 244 | 245 | Two spaces between `$$$` and the command protects it from -w/--with. 246 | 247 | The `<<<` delimiter is optional for the first input in a file. 248 | Without it, input begins at the first non-blank/comment line. 249 | Input ends at the `$$$` delimiter. You can't put a comment before the first `$$$`. 250 | 251 | The `>>>` delimiter is optional except when matching via regex. 252 | Expected output/stderr extends to the next `>>>2` or `>>>=` if present, 253 | or to the last non-blank/comment line before the next `<<<` or `$$$` or file end. 254 | `/REGEX/` regular expression patterns may be used instead of 255 | specifying the expected output in full. The regex syntax is 256 | [regex-tdfa](https://hackage.haskell.org/package/regex-tdfa)'s, plus 257 | you can put `!` before `/REGEX/` to negate the match. 258 | 259 | The [exit status](https://en.wikipedia.org/wiki/Exit_status) is a 260 | number, normally 0 for a successful exit. This too can be prefixed 261 | with `!` to negate the match, or you can use a `/REGEX/` pattern. 262 | A `>>>=` with nothing after it ignores the exit status. 263 | 264 | Examples: 265 | 266 | All delimiters explicit: 267 | 268 | # cat copies its input to stdout 269 | <<< 270 | foo 271 | $$$ cat 272 | >>> 273 | foo 274 | 275 | # or, given a bad flag, prints a platform-specific error and exits with non-zero status 276 | $$$ cat --no-such-flag 277 | >>>2 /(unrecognized|illegal) option/ 278 | >>>= !0 279 | 280 | # echo ignores the input and prints a newline. 281 | # We need the >>>= (or a >>>2) to delimit the whitespace which 282 | # would otherwise be ignored. 283 | $$$ echo 284 | >>> 285 | 286 | >>>= 287 | 288 | Non-required `<<<` and `>>>` delimiters omitted: 289 | 290 | foo 291 | $$$ cat 292 | foo 293 | 294 | $$$ cat --no-such-flag 295 | >>>2 /(unrecognized|illegal) option/ 296 | >>>= !0 297 | 298 | $$$ echo 299 | 300 | >>>= 301 | 302 | ### Format 3 303 | 304 | This is supported by shelltestrunner 1.9+. 305 | It is the preferred format - like format 2 but with more convenient short delimiters: 306 | 307 | # COMMENTS OR BLANK LINES 308 | < 309 | INPUT 310 | $ COMMAND LINE 311 | > 312 | EXPECTED OUTPUT (OR > /REGEX/) 313 | >2 314 | EXPECTED STDERR (OR >2 /REGEX/) 315 | >= EXPECTED EXIT STATUS (OR >= /REGEX/ OR >=) 316 | # COMMENTS OR BLANK LINES 317 | ADDITIONAL TESTS FOR THIS INPUT 318 | ADDITIONAL TEST GROUPS WITH DIFFERENT INPUT 319 | 320 | Examples: 321 | 322 | All delimiters explicit: 323 | 324 | # cat copies its input to stdout 325 | < 326 | foo 327 | $ cat 328 | > 329 | foo 330 | 331 | # or, given a bad flag, prints a platform-specific error and exits with non-zero status 332 | $ cat --no-such-flag 333 | >2 /(unrecognized|illegal) option/ 334 | >= !0 335 | 336 | # echo ignores the input and prints a newline. 337 | # We use an explicit >= (or >2) to delimit the whitespace which 338 | # would otherwise be ignored. 339 | $ echo 340 | > 341 | 342 | >= 343 | 344 | Non-required `<` and `>` delimiters omitted: 345 | 346 | foo 347 | $ cat 348 | foo 349 | 350 | $ cat --no-such-flag 351 | >2 /(unrecognized|illegal) option/ 352 | >= !0 353 | 354 | $ echo 355 | 356 | >2 357 | 358 | Also: 359 | [above](#usage), 360 | [shelltestrunner](https://github.com/simonmichael/shelltestrunner/tree/master/tests/format3), 361 | [hledger](https://github.com/simonmichael/hledger/tree/master/hledger/test). 362 | 363 | ## Printing tests 364 | 365 | The `--print` option prints tests to stdout. 366 | This can be used to convert between test formats. 367 | Format 1, 2, and 3 are supported. 368 | 369 | Here are some issues to be aware of when converting between formats: 370 | 371 | - Printing v1 as v2/v3 372 | - A `>>>= 0` often gets converted to a `>>>2 //` or `>2 //`, when `>=` or nothing would be preferred. 373 | This is semantically accurate, because v1 ignores out/err by default, and v2/v3 check for zero exit by default, 374 | and therefore the safest conversion; but it's annoying 375 | - Printing v3 as v3 376 | - loses comments at the top of the file, even above an explicit < delimiter 377 | - may lose other data 378 | - A missing newline at EOF will not be preserved. 379 | - v2/v3 allow shared input, but v1 does not 380 | - A file containing only comments may be emptied 381 | 382 | In general, always review the result of a conversion yourself before committing it. 383 | 384 | ## Support/Contribute 385 | 386 | ||| 387 | |----------------------|--------------------------------------------------| 388 | | Released version: | https://hackage.haskell.org/package/shelltestrunner 389 | | Changelog: | https://hackage.haskell.org/package/shelltestrunner/changelog 390 | | Code | https://github.com/simonmichael/shelltestrunner 391 | | Issues | https://github.com/simonmichael/shelltestrunner/issues 392 | | Chat | Contact sm in the #hledger:matrix.org room on matrix or the #hledger channel on libera.chat 393 | 394 | 395 | [2012 user survey](https://docs.google.com/spreadsheet/pub?key=0Au47MrJax8HpdGpZSzdhWHlCUkJpR2hjX1MwMWFoUEE&single=true&gid=3&output=html). 396 | 397 | Feedback, testing, code, documentation, packaging, blogging, and funding are most welcome. 398 | 399 | 402 | 403 | ## Credits 404 | 405 | [Simon Michael](https://joyful.com) wrote shelltestrunner, 406 | inspired by John Wiegley's tests for Ledger. 407 | 408 | Code contributors: 409 | Andreas Abel, 410 | Andrés Sicard-Ramírez, 411 | Bernie Pope, 412 | Felix C. Stegerman, 413 | Iustin Pop, 414 | Jakob Schöttl 415 | John Chee. 416 | John Macfarlane, 417 | Sergei Trofimovich, 418 | Taavi Väljaots, 419 | Trygve Laugstøl, 420 | 421 | shelltestrunner depends on several fine libraries, 422 | in particular Max Bolingbroke's test-framework, 423 | and of course on the Glorious Haskell Compiler. 424 | 425 | The Blade Runner font is by Phil Steinschneider. 426 | 427 | 428 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env runhaskell 2 | import Distribution.Simple 3 | 4 | main = defaultMain 5 | -------------------------------------------------------------------------------- /shelltestrunner.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 3.0 2 | name: shelltestrunner 3 | -- keep synced: shelltest.hs 4 | version: 1.10.99 5 | synopsis: Easy, repeatable testing of CLI programs/commands 6 | description: 7 | shelltestrunner (executable: shelltest) is a portable 8 | command-line tool for testing command-line programs, or general shell 9 | commands, released under GPLv3+. It reads simple test specifications 10 | defining a command to run, some input, and the expected output, 11 | stderr, and exit status. It can run tests in parallel, selectively, 12 | with a timeout, in color, etc. 13 | category: Testing 14 | stability: stable 15 | homepage: https://github.com/simonmichael/shelltestrunner 16 | bug-reports: https://github.com/simonmichael/shelltestrunner/issues 17 | author: Simon Michael 18 | maintainer: Simon Michael 19 | copyright: Copyright: (c) 2009-2025 Simon Michael and contributors 20 | license: GPL-3.0-or-later 21 | license-file: LICENSE 22 | build-type: Simple 23 | tested-with: ghc==9.6, ghc==9.8, ghc==9.10, ghc==9.12 24 | 25 | extra-source-files: 26 | ANNOUNCE 27 | Makefile 28 | README.md 29 | stack96.yaml 30 | stack98.yaml 31 | stack.yaml 32 | stack912.yaml 33 | tests/README 34 | tests/bash/*.test 35 | tests/examples/*.test 36 | tests/examples/README 37 | tests/format1.unix/*.test 38 | tests/format1.windows/*.test 39 | tests/format1/*.test 40 | tests/format1/abstract-test-with-macros 41 | tests/format1/one-failing-test 42 | tests/format2.unix/*.test 43 | tests/format2.windows/*.test 44 | tests/format2/*.test 45 | tests/format2/abstract-test-with-macros 46 | tests/format2/one-failing-test 47 | tests/format3.unix/*.test 48 | tests/format3.windows/*.test 49 | tests/format3/*.test 50 | tests/format3/abstract-test-with-macros 51 | tests/format3/one-failing-test 52 | 53 | -- These are also copied to haddock docs. 54 | extra-doc-files: 55 | CHANGES 56 | 57 | source-repository head 58 | type: git 59 | location: https://github.com/simonmichael/shelltestrunner 60 | 61 | executable shelltest 62 | hs-source-dirs: src 63 | main-is: shelltest.hs 64 | default-language: Haskell2010 65 | ghc-options: -threaded -W -fwarn-tabs 66 | other-modules: 67 | Import 68 | Parse 69 | Preprocessor 70 | Print 71 | Types 72 | Utils 73 | Utils.Debug 74 | 75 | build-depends: 76 | base >= 4 && < 5 77 | , Diff >= 0.2.0 78 | , filemanip >= 0.3 79 | , HUnit 80 | , cmdargs >= 0.7 81 | , directory >= 1.0 82 | , filepath >= 1.0 83 | , parsec 84 | , pretty-show >= 1.6.5 85 | , process 86 | , regex-tdfa >= 1.1 87 | , safe 88 | , test-framework >= 0.3.2 89 | , test-framework-hunit >= 0.2 90 | , utf8-string >= 0.3.5 91 | , hspec >=2.9.0 92 | , hspec-core >=2.9.0 93 | , hspec-contrib >=0.5.1.1 94 | -------------------------------------------------------------------------------- /site/README: -------------------------------------------------------------------------------- 1 | Source files for the project web site/page. -------------------------------------------------------------------------------- /site/files/cat.test: -------------------------------------------------------------------------------- 1 | # cat copies its input to stdout 2 | <<< 3 | foo 4 | $$$ cat 5 | >>> 6 | foo 7 | 8 | # or, given a bad flag, prints a platform-specific error and exits with non-zero status 9 | $$$ cat --no-such-flag 10 | >>>2 /(unrecognized|illegal) option/ 11 | >>>= !0 12 | 13 | # echo ignores the input and prints a newline. 14 | # We use an explicit >>>2 (or >>>=) to delimit the whitespace which 15 | # would otherwise be ignored. 16 | $$$ echo 17 | >>> 18 | 19 | >>>2 20 | -------------------------------------------------------------------------------- /site/files/cat2.test: -------------------------------------------------------------------------------- 1 | foo 2 | $$$ cat 3 | foo 4 | 5 | $$$ cat --no-such-flag 6 | >>>2 /(unrecognized|illegal) option/ 7 | >>>= !0 8 | 9 | $$$ echo 10 | >>> 11 | 12 | >>>2 13 | -------------------------------------------------------------------------------- /site/files/true.test: -------------------------------------------------------------------------------- 1 | # true, given no input, prints nothing on stdout or stderr and 2 | # terminates with exit status 0. 3 | $$$ true 4 | 5 | # false gives exit status 1. 6 | $$$ false 7 | >>>= 1 8 | -------------------------------------------------------------------------------- /site/gittip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmichael/shelltestrunner/e2c204be2e3a7a0a33968270c0ad23d28d4b28ed/site/gittip.png -------------------------------------------------------------------------------- /site/paypal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmichael/shelltestrunner/e2c204be2e3a7a0a33968270c0ad23d28d4b28ed/site/paypal.gif -------------------------------------------------------------------------------- /site/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding:0 10%; 3 | background-color:white; 4 | color:black; 5 | font-family: 'Droid Sans', Helvetica, sans-serif; 6 | max-width:50em; 7 | margin:0 auto 2em; 8 | } 9 | 10 | h1, h2, h3 { 11 | position:relative; 12 | left:-0.5em; 13 | margin-top:2em; 14 | font-style:italic; 15 | } 16 | 17 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { 18 | color:black; 19 | text-decoration:none; 20 | } 21 | 22 | #title { 23 | text-align:center; 24 | margin-top:6em; 25 | margin-bottom:4em; 26 | } 27 | 28 | #toc { 29 | /* font-size:small; */ 30 | /* float:right; */ 31 | /* margin:0 0 1em 1em; */ 32 | /* border:thin solid #ddd; */ 33 | /* background-color:#f0f0f0; */ 34 | /* border-radius:4px; */ 35 | } 36 | 37 | /* #toc ul { */ 38 | /* list-style-type: none; */ 39 | /* padding:0 1em 0 1em; */ 40 | /* } */ 41 | 42 | code { 43 | font-family: Inconsolata, 'Lucida Console', Monaco, monospace; 44 | font-size:medium; 45 | } 46 | 47 | pre { 48 | background-color:#e0e0e0; 49 | border-radius:4px; 50 | font-weight:bold; 51 | padding:.5em; 52 | margin-left:.5em; 53 | /* display:inline-block; */ 54 | /* max-width:60em; */ 55 | /* overflow:scroll; */ 56 | max-width: intrinsic; /* Safari/WebKit */ 57 | max-width: -moz-max-content; /* Firefox/Gecko */ 58 | } 59 | 60 | 61 | /* from https://github.com/blaenk/blaenk.github.io/blob/source/provider/scss/_article.scss */ 62 | #toc.right-toc { 63 | float: right; 64 | /* margin-left: 15px; */ 65 | margin-left:2em; 66 | margin-bottom: 15px; 67 | margin-top: 0; 68 | padding: 0; 69 | @media screen and (max-width: 600px) { 70 | float: none; 71 | padding: 0; 72 | margin-left: 0; 73 | margin-top: 10px; 74 | } 75 | } 76 | #toc { 77 | margin-top: 10px; 78 | p { 79 | font-weight: bold; 80 | margin-top: 0; 81 | } 82 | & > ol { 83 | margin-left: 0; 84 | margin-top: 5px; 85 | font-size: 14px; 86 | @media screen and (max-width: 600px) { 87 | font-size: 13px; 88 | } 89 | } 90 | ol { 91 | counter-reset: item; 92 | } 93 | li { 94 | margin-top: 0; 95 | display: block; 96 | @media screen and (max-width: 600px) { 97 | line-height: 1.69; 98 | } 99 | &:before { 100 | content: counters(item, ".") ". "; 101 | counter-increment: item; 102 | } 103 | } 104 | &:after { 105 | clear: both; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /site/site.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | $title$ - Joyful Systems 8 | 9 | 10 | 11 | 12 | 13 | $body$ 14 | 15 | 16 | -------------------------------------------------------------------------------- /site/syntax.css: -------------------------------------------------------------------------------- 1 | /* Generated with pandoc --highlight-style=X */ 2 | 3 | /* pygments */ 4 | 5 | /* 6 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre 7 | { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; } 8 | td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; } 9 | td.sourceCode { padding-left: 5px; } 10 | pre.sourceCode span.kw { color: #007020; font-weight: bold; } 11 | pre.sourceCode span.dt { color: #902000; } 12 | pre.sourceCode span.dv { color: #40a070; } 13 | pre.sourceCode span.bn { color: #40a070; } 14 | pre.sourceCode span.fl { color: #40a070; } 15 | pre.sourceCode span.ch { color: #4070a0; } 16 | pre.sourceCode span.st { color: #4070a0; } 17 | pre.sourceCode span.co { color: #60a0b0; font-style: italic; } 18 | pre.sourceCode span.ot { color: #007020; } 19 | pre.sourceCode span.al { color: red; font-weight: bold; } 20 | pre.sourceCode span.fu { color: #06287e; } 21 | pre.sourceCode span.re { } 22 | pre.sourceCode span.er { color: red; font-weight: bold; } 23 | */ 24 | 25 | /* kate */ 26 | 27 | /* 28 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 29 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 30 | table.sourceCode { width: 100%; line-height: 100%; } 31 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; background-color: #dddddd; } 32 | td.sourceCode { padding-left: 5px; } 33 | code > span.kw { font-weight: bold; } 34 | code > span.dt { color: #800000; } 35 | code > span.dv { color: #0000ff; } 36 | code > span.bn { color: #0000ff; } 37 | code > span.fl { color: #800080; } 38 | code > span.ch { color: #ff00ff; } 39 | code > span.st { color: #dd0000; } 40 | code > span.co { color: #808080; font-style: italic; } 41 | code > span.al { color: #00ff00; font-weight: bold; } 42 | code > span.fu { color: #000080; } 43 | code > span.er { color: #ff0000; font-weight: bold; } 44 | */ 45 | 46 | /* monochrome */ 47 | /* 48 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 49 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 50 | table.sourceCode { width: 100%; line-height: 100%; } 51 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; } 52 | td.sourceCode { padding-left: 5px; } 53 | code > span.kw { font-weight: bold; } 54 | code > span.dt { text-decoration: underline; } 55 | code > span.co { font-style: italic; } 56 | code > span.al { font-weight: bold; } 57 | code > span.er { font-weight: bold; } 58 | */ 59 | 60 | /* espresso */ 61 | /* 62 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 63 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 64 | table.sourceCode { width: 100%; line-height: 100%; background-color: #2a211c; color: #bdae9d; } 65 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; background-color: #2a211c; color: #bdae9d; border-right: 1px solid #bdae9d; } 66 | td.sourceCode { padding-left: 5px; } 67 | pre, code { color: #bdae9d; background-color: #2a211c; } 68 | code > span.kw { color: #43a8ed; font-weight: bold; } 69 | code > span.dt { text-decoration: underline; } 70 | code > span.dv { color: #44aa43; } 71 | code > span.bn { color: #44aa43; } 72 | code > span.fl { color: #44aa43; } 73 | code > span.ch { color: #049b0a; } 74 | code > span.st { color: #049b0a; } 75 | code > span.co { color: #0066ff; font-style: italic; } 76 | code > span.al { color: #ffff00; } 77 | code > span.fu { color: #ff9358; font-weight: bold; } 78 | code > span.er { font-weight: bold; } 79 | */ 80 | 81 | /* zenburn */ 82 | /* 83 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 84 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 85 | table.sourceCode { width: 100%; line-height: 100%; background-color: #303030; color: #cccccc; } 86 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; } 87 | td.sourceCode { padding-left: 5px; } 88 | pre, code { color: #cccccc; background-color: #303030; } 89 | code > span.kw { color: #f0dfaf; } 90 | code > span.dt { color: #dfdfbf; } 91 | code > span.dv { color: #dcdccc; } 92 | code > span.bn { color: #dca3a3; } 93 | code > span.fl { color: #c0bed1; } 94 | code > span.ch { color: #dca3a3; } 95 | code > span.st { color: #cc9393; } 96 | code > span.co { color: #7f9f7f; } 97 | code > span.ot { color: #efef8f; } 98 | code > span.al { color: #ffcfaf; } 99 | code > span.fu { color: #efef8f; } 100 | code > span.er { color: #c3bf9f; } 101 | */ 102 | 103 | /* haddock */ 104 | /* 105 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 106 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 107 | table.sourceCode { width: 100%; line-height: 100%; } 108 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; } 109 | td.sourceCode { padding-left: 5px; } 110 | code > span.kw { color: #0000ff; } 111 | code > span.ch { color: #008080; } 112 | code > span.st { color: #008080; } 113 | code > span.co { color: #008000; } 114 | code > span.ot { color: #ff4000; } 115 | code > span.al { color: #ff0000; } 116 | code > span.er { font-weight: bold; } 117 | */ 118 | 119 | /* tango */ 120 | 121 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 122 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 123 | table.sourceCode { width: 100%; line-height: 100%; background-color: #f8f8f8; } 124 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; } 125 | td.sourceCode { padding-left: 5px; } 126 | pre, code { background-color: #f8f8f8; } 127 | code > span.kw { color: #204a87; font-weight: bold; } 128 | code > span.dt { color: #204a87; } 129 | code > span.dv { color: #0000cf; } 130 | code > span.bn { color: #0000cf; } 131 | code > span.fl { color: #0000cf; } 132 | code > span.ch { color: #4e9a06; } 133 | code > span.st { color: #4e9a06; } 134 | code > span.co { color: #8f5902; font-style: italic; } 135 | code > span.ot { color: #8f5902; } 136 | code > span.al { color: #ef2929; } 137 | code > span.fu { color: #000000; } 138 | code > span.er { font-weight: bold; } 139 | */ 140 | -------------------------------------------------------------------------------- /site/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmichael/shelltestrunner/e2c204be2e3a7a0a33968270c0ad23d28d4b28ed/site/title.png -------------------------------------------------------------------------------- /site/title.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmichael/shelltestrunner/e2c204be2e3a7a0a33968270c0ad23d28d4b28ed/site/title.pxm -------------------------------------------------------------------------------- /site/title2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmichael/shelltestrunner/e2c204be2e3a7a0a33968270c0ad23d28d4b28ed/site/title2.png -------------------------------------------------------------------------------- /src/Import.hs: -------------------------------------------------------------------------------- 1 | -- our local prelude, imports common to all modules 2 | 3 | module Import 4 | ( module Control.Applicative 5 | , module Control.Monad 6 | , module Data.List 7 | , module Data.Maybe 8 | , module System.Exit 9 | , module Text.Printf 10 | ) where 11 | 12 | import Control.Applicative ((<$>), (<*), (*>)) 13 | import Control.Monad (liftM, when, unless) 14 | import Data.List 15 | import Data.Maybe 16 | import System.Exit 17 | import Text.Printf (printf) 18 | -- import Text.Regex.TDFA ((=~)) 19 | -------------------------------------------------------------------------------- /src/Parse.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Parse 3 | ( parseShellTestFile 4 | ) 5 | where 6 | 7 | import Text.Parsec 8 | import Text.Parsec.String 9 | 10 | import Import 11 | import Types 12 | import Utils hiding (dbg, ptrace) 13 | import qualified Utils 14 | import Preprocessor 15 | import System.IO hiding (stdin) 16 | 17 | 18 | parseFromFileWithPreprocessor :: Parser [ShellTest] -> PreProcessor -> FilePath -> IO (Either ParseError [ShellTest]) 19 | parseFromFileWithPreprocessor p preproc fname = 20 | do 21 | h <- openFile fname ReadMode 22 | hSetNewlineMode h universalNewlineMode 23 | input <- hGetContents h 24 | let processed = preprocess preproc input 25 | case processed of Right text -> return (runParser p () fname text) 26 | (Left err) -> return (Left err) -- To make haskell happy. 27 | 28 | 29 | -- | Parse this shell test file, optionally logging debug output. 30 | parseShellTestFile :: Bool -> PreProcessor -> FilePath -> IO (Either ParseError [ShellTest]) 31 | parseShellTestFile debug preProcessor f = do 32 | p <- parseFromFileWithPreprocessor shelltestfile preProcessor f 33 | case p of 34 | Right ts -> do 35 | let ts' = [t{testname=testname t++":"++show n} | (n,t) <- zip ([1..]::[Int]) ts] 36 | when (debug) $ do 37 | printf "parsed %s:\n" f 38 | mapM_ (putStrLn.(' ':).ppShow) ts' 39 | return $ Right ts' 40 | Left _ -> do 41 | when (debug) $ printf "failed to parse any tests in %s\n" f 42 | return p 43 | 44 | 45 | -- parsers 46 | 47 | -- show lots of parsing debug output if enabled. 48 | -- NB not connected to the --debug-parse flag 49 | showParserDebugOutput = debugLevel >= 2 50 | 51 | ptrace_ s | showParserDebugOutput = Utils.ptrace s 52 | | otherwise = return () 53 | ptrace s a | showParserDebugOutput = Utils.ptrace $ s ++ ": " ++ show a 54 | | otherwise = return () 55 | 56 | shelltestfile :: Parser [ShellTest] 57 | shelltestfile = do 58 | ptrace_ "shelltestfile 0" 59 | ts <- try (do first <- try (format2testgroup False) 60 | rest <- many $ try (format2testgroup True) 61 | return $ concat $ first : rest 62 | ) 63 | <|> 64 | (do first <- try (format3testgroup False) 65 | rest <- many $ try (format3testgroup True) 66 | return $ concat $ first : rest 67 | ) 68 | <|> 69 | (many $ try format1test) 70 | ptrace_ "shelltestfile 1" 71 | trailingComments <- many whitespaceorcommentline 72 | ptrace_ "shelltestfile 2" 73 | eof 74 | let ts' = appendTrailingComments trailingComments ts 75 | ptrace "shelltestfile ." ts' 76 | return ts' 77 | 78 | 79 | ---------------------------------------------------------------------- 80 | -- format 1 (shelltestrunner 1.x) 81 | -- each test specifies its input; missing test parts are not checked 82 | 83 | format1test = do 84 | ptrace_ " format1test 0" 85 | comments <- many whitespaceorcommentline 86 | ptrace_ " format1test 1" 87 | ln <- sourceLine <$> getPosition 88 | c <- command1 "command line" 89 | ptrace " format1test c" c 90 | i <- optionMaybe input1 "input" 91 | ptrace " format1test i" i 92 | o <- optionMaybe expectedoutput1 "expected output" 93 | ptrace " format1test o" o 94 | e <- optionMaybe expectederror1 "expected error output" 95 | ptrace " format1test e" e 96 | x <- expectedexitcode1 "expected exit status" 97 | ptrace " format1test x" x 98 | when (null (show c) && (isNothing i) && (null $ catMaybes [o,e]) && null (show x)) $ fail "" 99 | f <- sourceName . statePos <$> getParserState 100 | let t = ShellTest{testname=f,command=c,stdin=i,stdoutExpected=o,stderrExpected=e,exitCodeExpected=x,lineNumber=ln,comments=comments,trailingComments=[]} 101 | ptrace " format1test ." t 102 | return t 103 | 104 | command1 :: Parser TestCommand 105 | command1 = fixedcommand <|> replaceablecommand 106 | 107 | input1 :: Parser String 108 | input1 = try $ string "<<<" >> whitespaceorcommentline >> unlines <$> (line `manyTill` (lookAhead (try delimiter))) 109 | 110 | expectedoutput1 :: Parser Matcher 111 | expectedoutput1 = (try $ do 112 | string ">>>" 113 | whitespace 114 | choice [regexmatcher, negativeregexmatcher, whitespaceorcommentlineoreof >> linesmatcher1] 115 | ) "expected output" 116 | 117 | expectederror1 :: Parser Matcher 118 | expectederror1 = (try $ do 119 | string ">>>2" 120 | whitespace 121 | choice [regexmatcher, negativeregexmatcher, (whitespaceorcommentlineoreof >> linesmatcher1)] 122 | ) "expected error output" 123 | 124 | expectedexitcode1 :: Parser Matcher 125 | expectedexitcode1 = (try $ do 126 | string ">>>=" 127 | whitespace 128 | fromMaybe anyMatcher <$> (optionMaybe $ choice [regexmatcher, try negativeregexmatcher, numericmatcher, negativenumericmatcher]) 129 | ) "expected exit status" 130 | 131 | ---------------------------------------------------------------------- 132 | -- format 2 133 | -- input first, then tests; missing test parts are implicitly checked 134 | 135 | -- A format 2 test group, optionally with the initial <<< delimiter 136 | -- being optional. 137 | format2testgroup :: Bool -> Parser [ShellTest] 138 | format2testgroup inputRequiresDelimiter = do 139 | ptrace " format2testgroup 0" inputRequiresDelimiter 140 | skipMany whitespaceorcommentline 141 | ptrace_ " format2testgroup 1" 142 | let startdelims | inputRequiresDelimiter = ["<<<"] 143 | | otherwise = ["<<<", ""] 144 | enddelims = ["$$$","<<<"] 145 | i <- optionMaybe (linesBetween startdelims enddelims) "input" 146 | ptrace " format2testgroup i" i 147 | ts <- many1 $ try (format2test i) 148 | ptrace " format2testgroup ." ts 149 | return ts 150 | 151 | format2test :: Maybe String -> Parser ShellTest 152 | format2test i = do 153 | ptrace_ " format2test 0" 154 | comments <- many whitespaceorcommentline 155 | ptrace_ " format2test 1" 156 | ln <- sourceLine <$> getPosition 157 | c <- command2 "command line" 158 | ptrace " format2test c" c 159 | nullstdout <- nullLinesMatcher . sourceLine <$> getPosition 160 | o <- maybe (Just nullstdout) Just <$> optionMaybe expectedoutput2 "expected output" 161 | ptrace " format2test o" o 162 | nullstderr <- nullLinesMatcher . sourceLine <$> getPosition 163 | e <- maybe (Just $ nullstderr) Just <$> optionMaybe expectederror2 "expected error output" 164 | ptrace " format2test e" e 165 | x <- fromMaybe nullStatusMatcher <$> optionMaybe expectedexitcode2 "expected exit status" 166 | ptrace " format2test x" x 167 | when (null (show c) && (isNothing i) && (null $ catMaybes [o,e]) && null (show x)) $ fail "" 168 | f <- sourceName . statePos <$> getParserState 169 | let t = ShellTest{testname=f,command=c,stdin=i,stdoutExpected=o,stderrExpected=e,exitCodeExpected=x,lineNumber=ln,comments=comments,trailingComments=[]} 170 | ptrace " format2test ." t 171 | return t 172 | 173 | nullLinesMatcher n = Lines n "" 174 | 175 | nullStatusMatcher = Numeric "0" 176 | 177 | anyMatcher = PositiveRegex "" 178 | 179 | command2 :: Parser TestCommand 180 | command2 = string "$$$" >> optional (char ' ') >> (fixedcommand <|> replaceablecommand) 181 | 182 | -- In format 2, >>> is used only with /REGEX/, also don't consume the 183 | -- whitespace/comments immediately preceding a following test. 184 | expectedoutput2 :: Parser Matcher 185 | expectedoutput2 = (try $ do 186 | try (string ">>>" >> whitespace >> (regexmatcher <|> negativeregexmatcher)) 187 | <|> (optional (string ">>>" >> whitespaceline) >> linesmatcher2 "expected output") 188 | ) 189 | 190 | -- Don't consume the whitespace/comments immediately preceding a 191 | -- following test. 192 | expectederror2 :: Parser Matcher 193 | expectederror2 = (try $ do 194 | ptrace_ " expectederror2 0" 195 | string ">>>2" >> whitespace 196 | ptrace_ " expectederror2 1" 197 | m <- (regexmatcher <|> negativeregexmatcher) 198 | <|> 199 | (newline >> linesmatcher2 "expected error output") 200 | ptrace " expectederror2 ." m 201 | return m 202 | ) 203 | 204 | expectedexitcode2 :: Parser Matcher 205 | expectedexitcode2 = expectedexitcode1 206 | 207 | -- The format 2 lines matcher consumes lines until one of these: 208 | -- 1. another section delimiter in this test (>>>, >>>2, >>>=) 209 | -- 2. the next test's start delimiter (<<<, $$$), or the start of blank/comment lines preceding it 210 | -- 3. end of file, or the start of blank/comment lines preceding it 211 | linesmatcher2 :: Parser Matcher 212 | linesmatcher2 = do 213 | ptrace_ " linesmatcher2 0" 214 | ln <- sourceLine <$> getPosition 215 | ls <- unlines <$> 216 | line `manyTill` lookAhead (choice' [delimiterNotNewTest 217 | ,many whitespaceorcommentline >> delimiterNewTest 218 | ,many whitespaceorcommentline >> eofasstr]) 219 | "lines of output" 220 | ptrace " linesmatcher2 ." ls 221 | return $ Lines ln ls 222 | 223 | delimiterNewTest = do 224 | -- ptrace_ " delimiterNewTest 0" 225 | choice [string "$$$", string "<<<"] 226 | 227 | delimiterNotNewTest = do 228 | -- ptrace_ " delimiterNotNewTest 0" 229 | choice [try (string ">>>2"), try (string ">>>="), string ">>>"] 230 | 231 | ---------------------------------------------------------------------- 232 | -- format 3 233 | -- Like format 2 but with short delimiters. 234 | -- XXX duplication 235 | format3testgroup :: Bool -> Parser [ShellTest] 236 | format3testgroup inputRequiresDelimiter = do 237 | ptrace " format3testgroup 0" inputRequiresDelimiter 238 | skipMany whitespaceorcommentline 239 | ptrace_ " format3testgroup 1" 240 | let startdelims | inputRequiresDelimiter = ["<"] 241 | | otherwise = ["<", ""] 242 | enddelims = ["$","<"] 243 | i <- optionMaybe (linesBetween startdelims enddelims) "input" 244 | ptrace " format3testgroup i" i 245 | ts <- many1 $ try (format3test i) 246 | ptrace " format3testgroup ." ts 247 | return ts 248 | 249 | format3test :: Maybe String -> Parser ShellTest 250 | format3test i = do 251 | ptrace_ " format3test 0" 252 | comments <- many whitespaceorcommentline 253 | ptrace_ " format3test 1" 254 | ln <- sourceLine <$> getPosition 255 | c <- command3 "command line" 256 | ptrace " format3test c" c 257 | nullstdout <- nullLinesMatcher . sourceLine <$> getPosition 258 | o <- maybe (Just nullstdout) Just <$> optionMaybe expectedoutput3 "expected output" 259 | ptrace " format3test o" o 260 | nullstderr <- nullLinesMatcher . sourceLine <$> getPosition 261 | e <- maybe (Just $ nullstderr) Just <$> optionMaybe expectederror3 "expected error output" 262 | ptrace " format3test e" e 263 | x <- fromMaybe nullStatusMatcher <$> optionMaybe expectedexitcode3 "expected exit status" 264 | ptrace " format3test x" x 265 | when (null (show c) && (isNothing i) && (null $ catMaybes [o,e]) && null (show x)) $ fail "" 266 | f <- sourceName . statePos <$> getParserState 267 | let t = ShellTest{testname=f,command=c,stdin=i,stdoutExpected=o,stderrExpected=e,exitCodeExpected=x,lineNumber=ln,comments=comments,trailingComments=[]} 268 | ptrace " format3test ." t 269 | return t 270 | 271 | command3 :: Parser TestCommand 272 | command3 = string "$" >> optional (char ' ') >> (fixedcommand <|> replaceablecommand) 273 | 274 | -- In format 3, >>> is used only with /REGEX/, also don't consume the 275 | -- whitespace/comments immediately preceding a following test. 276 | expectedoutput3 :: Parser Matcher 277 | expectedoutput3 = (try $ do 278 | try (string ">" >> whitespace >> (regexmatcher <|> negativeregexmatcher)) 279 | <|> (optional (string ">" >> whitespaceline) >> linesmatcher3 "expected output") 280 | ) 281 | 282 | -- Don't consume the whitespace/comments immediately preceding a 283 | -- following test. 284 | expectederror3 :: Parser Matcher 285 | expectederror3 = (try $ do 286 | ptrace_ " expectederror3 0" 287 | string ">2" >> whitespace 288 | ptrace_ " expectederror3 1" 289 | m <- (regexmatcher <|> negativeregexmatcher) 290 | <|> 291 | (newline >> linesmatcher3 "expected error output") 292 | ptrace " expectederror3 ." m 293 | return m 294 | ) 295 | 296 | expectedexitcode3 :: Parser Matcher 297 | expectedexitcode3 = (try $ do 298 | string ">=" 299 | whitespace 300 | fromMaybe anyMatcher <$> (optionMaybe $ choice [regexmatcher, try negativeregexmatcher, numericmatcher, negativenumericmatcher]) 301 | ) "expected exit status" 302 | 303 | -- The format 3 lines matcher consumes lines until one of these: 304 | -- 1. another section delimiter in this test (>, >2, >=) 305 | -- 2. the next test's start delimiter (<, $), or the start of blank/comment lines preceding it 306 | -- 3. end of file, or the start of blank/comment lines preceding it 307 | linesmatcher3 :: Parser Matcher 308 | linesmatcher3 = do 309 | ptrace_ " linesmatcher3 0" 310 | ln <- sourceLine <$> getPosition 311 | ls <- unlines <$> 312 | line `manyTill` lookAhead (choice' [delimiterNotNewTest3 313 | ,many whitespaceorcommentline >> delimiterNewTest3 314 | ,many whitespaceorcommentline >> eofasstr]) 315 | "lines of output" 316 | ptrace " linesmatcher3 ." ls 317 | return $ Lines ln ls 318 | 319 | delimiterNewTest3 = do 320 | -- ptrace_ " delimiterNewTest 0" 321 | choice [string "$", string "<"] 322 | 323 | delimiterNotNewTest3 = do 324 | -- ptrace_ " delimiterNotNewTest 0" 325 | choice [try (string ">2"), try (string ">="), string ">"] 326 | 327 | ---------------------------------------------------------------------- 328 | -- common 329 | 330 | appendTrailingComments :: [String] -> [ShellTest] -> [ShellTest] 331 | appendTrailingComments _ [] = [] -- in this case, trailing comment are discarded 332 | appendTrailingComments cs ts = 333 | init ts ++ [(last ts) { trailingComments = cs }] 334 | 335 | linesBetween :: [String] -> [String] -> Parser String 336 | linesBetween startdelims enddelims = do 337 | let delimp "" = string "" 338 | delimp s = string s <* whitespace <* newline 339 | Utils.choice' $ map delimp startdelims 340 | let end = choice $ (map (try . string) enddelims) ++ [eofasstr] 341 | unlines <$> line `manyTill` lookAhead end 342 | 343 | fixedcommand,replaceablecommand :: Parser TestCommand 344 | fixedcommand = many1 whitespacechar >> line >>= return . FixedCommand 345 | replaceablecommand = line >>= return . ReplaceableCommand 346 | 347 | regexmatcher :: Parser Matcher 348 | regexmatcher = (do 349 | char '/' 350 | r <- (try escapedslash <|> noneOf "/") `manyTill` (char '/') 351 | whitespaceorcommentlineoreof 352 | return $ PositiveRegex $ MR r) "regex pattern" 353 | 354 | escapedslash :: Parser Char 355 | escapedslash = char '\\' >> char '/' 356 | 357 | negativeregexmatcher :: Parser Matcher 358 | negativeregexmatcher = (do 359 | char '!' 360 | PositiveRegex r <- regexmatcher 361 | return $ NegativeRegex r) "negative regex pattern" 362 | 363 | numericmatcher :: Parser Matcher 364 | numericmatcher = (do 365 | s <- many1 $ oneOf "0123456789" 366 | whitespaceorcommentlineoreof 367 | return $ Numeric s 368 | ) "number match" 369 | 370 | negativenumericmatcher :: Parser Matcher 371 | negativenumericmatcher = (do 372 | char '!' 373 | Numeric s <- numericmatcher 374 | return $ NegativeNumeric s 375 | ) "negative number match" 376 | 377 | linesmatcher1 :: Parser Matcher 378 | linesmatcher1 = do 379 | ln <- sourceLine <$> getPosition 380 | (Lines ln . unlines <$>) (line `manyTill` (lookAhead delimiter)) "lines of output" 381 | 382 | delimiter = choice' [string "$$$", string "<<<", string ">>>2", string ">>>=", string ">>>", eofasstr] 383 | 384 | -- longdelims = ["<<<", "$$$", ">>>2", ">>>=", ">>>"] 385 | -- shortdelims = ["<", "$", ">2", ">=", ">"] 386 | 387 | -- newlineoreof, whitespacechar :: Parser Char 388 | -- line,lineoreof,whitespace,whitespaceline,commentline,whitespaceorcommentline,whitespaceorcommentlineoreof,delimiter,input :: Parser String 389 | 390 | -- lineoreof = (anyChar `manyTill` newlineoreof) 391 | -- XXX shouldn't it be: 392 | lineoreof = (noneOf "\n" `manyTill` newlineoreof) 393 | newlineoreof = newline <|> (eof >> return '\n') "newline or end of file" 394 | line = (anyChar `manyTill` newline) "rest of line" 395 | whitespacechar = oneOf " \t" 396 | whitespace = many whitespacechar 397 | whitespaceline = try (newline >> return "") <|> try (whitespacechar >> whitespacechar `manyTill` newlineoreof) 398 | 399 | -- a line beginning with optional whitespace and # 400 | commentline = try (do 401 | prefix <- whitespace >> many1 (char '#') 402 | rest <- lineoreof 403 | return $ prefix ++ rest 404 | ) "comments" 405 | 406 | whitespaceorcommentline = commentline <|> whitespaceline 407 | whitespaceorcommentlineoreof = choice [eofasstr, commentline, whitespaceline] 408 | eofasstr = eof >> return "" 409 | -------------------------------------------------------------------------------- /src/Preprocessor.hs: -------------------------------------------------------------------------------- 1 | module Preprocessor 2 | ( preprocess, 3 | createMacroPreProcessor, 4 | getMacros 5 | ) 6 | where 7 | 8 | import Text.Parsec 9 | import Data.List 10 | import Types 11 | 12 | 13 | {- Apply preprocessor functions in sequence to change a string. -} 14 | preprocess :: PreProcessor -> String -> Either ParseError String 15 | preprocess NoPreprocess [] = Right [] 16 | preprocess NoPreprocess str = Right str 17 | preprocess (PreProcessor flist) str = foldl (\ac f -> case ac of Right a -> f a 18 | err -> err) (Right str) flist 19 | {- Creates a macro [(macro,value)] preprocessor that replaces all substrings with macro values. -} 20 | createMacroPreProcessor :: [Macro] -> PreProcessor 21 | createMacroPreProcessor [] = NoPreprocess 22 | createMacroPreProcessor macro = PreProcessor [\s -> Right (replaceMacros macro s)] 23 | 24 | {- substring -> replacement -> input -} 25 | replace :: String -> String -> String -> String 26 | replace _ _ [] = [] 27 | replace [] _ str = str 28 | replace _ [] str = str 29 | replace sub rep str = let compareLen = length sub 30 | subtoken = take compareLen str 31 | afterSubtoken = drop compareLen str 32 | (s:xs) = str 33 | in case sub == subtoken of False -> s:(replace sub rep xs) 34 | True -> rep ++(replace sub rep afterSubtoken) 35 | 36 | {- macros -> replacement -> input -} 37 | replaceMacros :: [Macro] -> String -> String 38 | replaceMacros [] str = str 39 | replaceMacros macro str = Prelude.foldl (\ac m -> let 40 | (key, replacment) = m 41 | in replace key replacment ac) str macro 42 | {- Read macro from string =. -} 43 | readMacro :: String -> Maybe Macro 44 | readMacro str = do 45 | i <- elemIndex '=' str 46 | return (take i str, drop (i + 1) str) 47 | 48 | {- Get macros from input parameters. -} 49 | getMacros :: [String] -> [Macro] 50 | getMacros str = let m = map readMacro str 51 | tmp = filter (\a -> case a of Nothing -> False 52 | _ -> True) m 53 | in map (\a -> let Just x = a in x) tmp 54 | -------------------------------------------------------------------------------- /src/Print.hs: -------------------------------------------------------------------------------- 1 | -- Print tests in any of the supported formats. 2 | -- Useful for debugging and for migrating between formats. 3 | -- Issues: 4 | -- converting v1 -> v2/v3 5 | -- a >>>= 0 often gets converted to a >>>2 // or >2 //, when >= or nothing would be preferred (but semantically less accurate, therefore risky to choose automatically) 6 | -- converting v3 -> v3 7 | -- loses comments at the top of the file, even above an explicit < delimiter 8 | -- may lose other data 9 | 10 | module Print 11 | where 12 | 13 | import Safe (lastMay) 14 | import Import 15 | import Types 16 | 17 | -- | Print a shell test. See CLI documentation for details. 18 | -- For v3 (the preferred, lightweight format), avoid printing most unnecessary things 19 | -- (stdout delimiter, 0 exit status value). 20 | printShellTest 21 | :: String -- ^ Shelltest format. Value of option @--print[=FORMAT]@. 22 | -> ShellTest -- ^ Test to print 23 | -> IO () 24 | printShellTest format ShellTest{command=c,stdin=i,comments=comments,trailingComments=trailingComments, 25 | stdoutExpected=o_expected,stderrExpected=e_expected,exitCodeExpected=x_expected} 26 | = do 27 | case format of 28 | "v1" -> do 29 | printComments comments 30 | printCommand "" c 31 | printStdin "<<<" i 32 | printStdouterr False ">>>" o_expected 33 | printStdouterr False ">>>2" e_expected 34 | printExitStatus True True ">>>=" x_expected 35 | printComments trailingComments 36 | "v2" -> do 37 | printComments comments 38 | printStdin "<<<" i 39 | printCommand "$$$ " c 40 | printStdouterr True ">>>" o_expected 41 | printStdouterr True ">>>2" e_expected 42 | printExitStatus trailingblanklines True ">>>=" x_expected 43 | printComments trailingComments 44 | "v3" -> do 45 | printComments comments 46 | printStdin "<" i 47 | printCommand "$ " c 48 | printStdouterr True ">" o_expected 49 | printStdouterr True ">2" e_expected 50 | printExitStatus trailingblanklines False ">=" x_expected 51 | printComments trailingComments 52 | _ -> fail $ "Unsupported --print format: " ++ format 53 | where 54 | trailingblanklines = case (o_expected, e_expected) of 55 | (Just (Lines _ o), Just (Lines _ e)) -> hasblanks $ if null e then o else e 56 | _ -> False 57 | where hasblanks s = maybe False null $ lastMay $ lines s 58 | 59 | printComments :: [String] -> IO () 60 | printComments = mapM_ putStrLn 61 | 62 | printStdin :: String -> Maybe String -> IO () 63 | printStdin _ (Just "") = return () 64 | printStdin _ Nothing = return () 65 | printStdin prefix (Just s) = printf "%s\n%s" prefix s 66 | 67 | printCommand :: String -> TestCommand -> IO () 68 | printCommand prefix (ReplaceableCommand s) = printf "%s%s\n" prefix s 69 | printCommand prefix (FixedCommand s) = printf "%s %s\n" prefix s 70 | 71 | -- Print an expected stdout or stderr test, prefixed with the given delimiter. 72 | -- If no expected value is specified, print nothing if first argument is true 73 | -- (for format 1, which ignores unspecified out/err), otherwise print a dummy test. 74 | printStdouterr :: Bool -> String -> Maybe Matcher -> IO () 75 | printStdouterr alwaystest prefix Nothing = when alwaystest $ printf "%s //\n" prefix 76 | printStdouterr _ _ (Just (Lines _ "")) = return () 77 | printStdouterr _ _ (Just (Numeric _)) = fail "FATAL: Cannot handle Matcher (Numeric) for stdout/stderr." 78 | printStdouterr _ _ (Just (NegativeNumeric _)) = fail "FATAL: Cannot handle Matcher (NegativeNumeric) for stdout/stderr." 79 | printStdouterr _ prefix (Just (Lines _ s)) | prefix==">" = printf "%s" s -- omit v3's > delimiter, really no need for it 80 | printStdouterr _ prefix (Just (Lines _ s)) = printf "%s\n%s" prefix s 81 | printStdouterr _ prefix (Just regex) = printf "%s %s\n" prefix (show regex) 82 | 83 | -- | Print an expected exit status clause, prefixed with the given delimiter. 84 | -- If zero is expected: 85 | -- if the first argument is not true, nothing will be printed; 86 | -- otherwise if the second argument is not true, only the delimiter will be printed. 87 | printExitStatus :: Bool -> Bool -> String -> Matcher -> IO () 88 | printExitStatus _ _ _ (Lines _ _) = fail "FATAL: Cannot handle Matcher (Lines) for exit status." 89 | printExitStatus always showzero prefix (Numeric "0") = when always $ printf "%s %s\n" prefix (if showzero then "0" else "") 90 | printExitStatus _ _ prefix s = printf "%s %s\n" prefix (show s) 91 | -------------------------------------------------------------------------------- /src/Types.hs: -------------------------------------------------------------------------------- 1 | module Types 2 | where 3 | 4 | import Import 5 | import Utils 6 | import Text.Parsec 7 | import Data.String (IsString(..)) 8 | 9 | data ShellTest = ShellTest { 10 | comments :: [String] -- # COMMENTS OR BLANK LINES before test 11 | ,trailingComments :: [String] -- # COMMENTS OR BLANK LINES after the last test 12 | ,command :: TestCommand 13 | ,stdin :: Maybe String 14 | ,stdoutExpected :: Maybe Matcher 15 | ,stderrExpected :: Maybe Matcher 16 | ,exitCodeExpected :: Matcher 17 | ,testname :: String 18 | ,lineNumber :: Int 19 | } 20 | 21 | instance Show ShellTest where 22 | show ShellTest{testname=n,command=c,lineNumber=ln,stdin=i,stdoutExpected=o,stderrExpected=e,exitCodeExpected=x} = 23 | printf "ShellTest {command = %s, stdin = %s, stdoutExpected = %s, stderrExpected = %s, exitCodeExpected = %s, testname = %s, lineNumber = %s}" 24 | (show c) 25 | (maybe "Nothing" (show.trim) i) 26 | (show $ show <$> o) 27 | (show $ show <$> e) 28 | (show x) 29 | (show $ trim n) 30 | (show ln) 31 | 32 | data TestCommand = ReplaceableCommand String 33 | | FixedCommand String 34 | deriving Show 35 | 36 | newtype MatcherRegex = MR String 37 | instance IsString MatcherRegex where fromString = MR 38 | instance Show MatcherRegex where show (MR r) = "/" ++ escapeMatcherRegex r ++ "/" 39 | -- Do some minimal escaping to avoid showing unparseable regex matchers: 40 | -- backslash-escape forward slashes. 41 | -- XXX not super efficient 42 | escapeMatcherRegex (c:r) = (if c == '/' then "\\/" else [c]) ++ escapeMatcherRegex r 43 | escapeMatcherRegex r = r 44 | 45 | data Matcher = Lines Int String -- ^ 0 or more lines of text, also the starting line number ? 46 | | Numeric String -- ^ numeric exit code as a string 47 | | NegativeNumeric String -- ^ numeric exit code as a string, matched negatively 48 | | PositiveRegex MatcherRegex -- ^ regular expression 49 | | NegativeRegex MatcherRegex -- ^ regular expression, matched negatively 50 | 51 | instance Show Matcher where show = showMatcherTrimmed 52 | 53 | showMatcherTrimmed :: Matcher -> String 54 | showMatcherTrimmed (PositiveRegex (MR r)) = show $ MR $ trim r 55 | showMatcherTrimmed (NegativeRegex mr) = "!" ++ showMatcherTrimmed (PositiveRegex mr) 56 | showMatcherTrimmed (Numeric s) = trim s 57 | showMatcherTrimmed (NegativeNumeric s) = "!"++ trim s 58 | showMatcherTrimmed (Lines _ s) = trim s 59 | 60 | showMatcher :: Matcher -> String 61 | showMatcher mr@(PositiveRegex _) = show mr 62 | showMatcher (NegativeRegex r) = "!" ++ showMatcher (PositiveRegex r) 63 | showMatcher (Numeric s) = s 64 | showMatcher (NegativeNumeric s) = "!"++ s 65 | showMatcher (Lines _ s) = s 66 | 67 | type Macro = (String, String) 68 | 69 | data PreProcessor = NoPreprocess | 70 | PreProcessor [(String -> Either ParseError String)] 71 | -------------------------------------------------------------------------------- /src/Utils.hs: -------------------------------------------------------------------------------- 1 | module Utils 2 | ( module Utils.Debug 3 | , module Utils 4 | ) 5 | where 6 | 7 | import Text.Parsec (choice, try) 8 | import Text.Parsec.String (GenParser) 9 | import Text.Regex.TDFA ((=~)) 10 | 11 | import Import 12 | import Utils.Debug 13 | 14 | 15 | -- strings 16 | 17 | trim :: String -> String 18 | trim s | l <= limit = s 19 | | otherwise = take limit s ++ suffix 20 | where 21 | limit = 500 22 | l = length s 23 | suffix = printf "...(%d more)" (l-limit) 24 | 25 | strip,lstrip,rstrip,dropws :: String -> String 26 | strip = lstrip . rstrip 27 | lstrip = dropws 28 | rstrip = reverse . dropws . reverse 29 | dropws = dropWhile (`elem` " \t") 30 | 31 | -- | Test if a string contains a regular expression. A malformed regexp 32 | -- (or a regexp larger than 300 characters, to avoid a regex-tdfa memory leak) 33 | -- will cause a runtime error. This version uses regex-tdfa and no regexp 34 | -- options. 35 | containsRegex :: String -> String -> Bool 36 | containsRegex s "" = containsRegex s "^" 37 | containsRegex s r 38 | | length r <= 300 = s =~ r 39 | | otherwise = error "please avoid regexps larger than 300 characters, they trigger a memory leak in regex-tdfa" 40 | 41 | -- parsing 42 | 43 | choice' :: [GenParser tok st a] -> GenParser tok st a 44 | choice' = choice . map try 45 | 46 | -- system 47 | 48 | -- toExitCode :: Int -> ExitCode 49 | -- toExitCode 0 = ExitSuccess 50 | -- toExitCode n = ExitFailure n 51 | 52 | fromExitCode :: ExitCode -> Int 53 | fromExitCode ExitSuccess = 0 54 | fromExitCode (ExitFailure n) = n 55 | 56 | -- misc 57 | 58 | -- | Replace occurrences of old list with new list within a larger list. 59 | replace::(Eq a) => [a] -> [a] -> [a] -> [a] 60 | replace [] _ = id 61 | replace old new = replace' 62 | where 63 | replace' [] = [] 64 | replace' l@(h:ts) = if old `isPrefixOf` l 65 | then new ++ replace' (drop len l) 66 | else h : replace' ts 67 | len = length old 68 | 69 | -- | Show a message, usage string, and terminate with exit status 1. 70 | warn :: String -> IO () 71 | warn s = putStrLn s >> exitWith (ExitFailure 1) 72 | -------------------------------------------------------------------------------- /src/Utils/Debug.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Utils.Debug 3 | ( module Debug.Trace 4 | , traceWith 5 | , strace 6 | , ltrace 7 | , mtrace 8 | , ptrace 9 | , ppShow 10 | , debugLevel 11 | , dbg 12 | , dbg0 13 | , dbg1 14 | , dbg2 15 | , dbg3 16 | , dbg4 17 | , dbg5 18 | , dbg6 19 | , dbg7 20 | , dbg8 21 | , dbg9 22 | , dbgAt 23 | , dbgAtIO 24 | -- , dbgAtM 25 | -- , dbgtrace 26 | -- , dbgshow 27 | -- , dbgppshow 28 | , dbgExit 29 | , pdbg 30 | ) 31 | where 32 | 33 | import Debug.Trace (trace) 34 | import Control.Monad (when) 35 | import Data.List 36 | import Safe (readDef) 37 | import System.Environment (getArgs) 38 | import System.Exit 39 | import System.IO.Unsafe (unsafePerformIO) 40 | import Text.Parsec (getPosition, getInput, sourceLine, sourceColumn) 41 | import Text.Parsec.String (GenParser) 42 | import Text.Printf 43 | 44 | -- ppShow is good at prettyifying many type's default show format 45 | #if __GLASGOW_HASKELL__ >= 704 46 | -- a good version of it requires GHC 7.4+ 47 | import Text.Show.Pretty (ppShow) 48 | #else 49 | -- otherwise just use show 50 | ppShow :: Show a => a -> String 51 | ppShow = show 52 | #endif 53 | 54 | -- | Trace a value using some string-producing function. 55 | traceWith :: (a -> String) -> a -> a 56 | traceWith f e = trace (f e) e 57 | 58 | -- | Trace a showable value by showing it. 59 | strace :: Show a => a -> a 60 | strace = traceWith show 61 | 62 | -- | Labelled trace - like strace, with a label prepended. 63 | ltrace :: Show a => String -> a -> a 64 | ltrace l a = trace (l ++ ": " ++ show a) a 65 | 66 | -- | Monadic trace - like strace, but works as a standalone line in a monad. 67 | mtrace :: (Monad m, Show a) => a -> m a 68 | mtrace a = strace a `seq` return a 69 | 70 | -- | Parsec trace - show the current parsec position and next input, 71 | -- and the provided label if it's non-null. 72 | ptrace :: String -> GenParser Char st () 73 | ptrace msg = do 74 | pos <- getPosition 75 | next <- take peeklength `fmap` getInput 76 | let (l,c) = (sourceLine pos, sourceColumn pos) 77 | s = printf "at line %2d col %2d: %s" l c (show next) :: String 78 | s' = printf ("%-"++show (peeklength+30)++"s") s ++ " " ++ msg 79 | trace s' $ return () 80 | where 81 | peeklength = 30 82 | 83 | -- | Global debug level, which controls the verbosity of debug output 84 | -- on the console. The default is 0 meaning no debug output. The 85 | -- @--debug@ command line flag sets it to 1, or @--debug=N@ sets it to 86 | -- a higher value (note: not @--debug N@ for some reason). This uses 87 | -- unsafePerformIO and can be accessed from anywhere and before normal 88 | -- command-line processing. After command-line processing, it is also 89 | -- available as the @debug_@ field of 'Hledger.Cli.Options.CliOpts'. 90 | debugLevel :: Int 91 | debugLevel = case snd $ break (=="--debug") args of 92 | "--debug":[] -> 1 93 | "--debug":n:_ -> readDef 1 n 94 | _ -> 95 | case take 1 $ filter ("--debug" `isPrefixOf`) args of 96 | ['-':'-':'d':'e':'b':'u':'g':'=':v] -> readDef 1 v 97 | _ -> 0 98 | 99 | where 100 | args = unsafePerformIO getArgs 101 | 102 | -- | Print a message and a showable value to the console if the global 103 | -- debug level is non-zero. Uses unsafePerformIO. 104 | dbg :: Show a => String -> a -> a 105 | dbg = dbg1 106 | 107 | -- always prints 108 | dbg0 :: Show a => String -> a -> a 109 | dbg0 = dbgAt 0 110 | 111 | dbg1 :: Show a => String -> a -> a 112 | dbg1 = dbgAt 1 113 | 114 | dbg2 :: Show a => String -> a -> a 115 | dbg2 = dbgAt 2 116 | 117 | dbg3 :: Show a => String -> a -> a 118 | dbg3 = dbgAt 3 119 | 120 | dbg4 :: Show a => String -> a -> a 121 | dbg4 = dbgAt 4 122 | 123 | dbg5 :: Show a => String -> a -> a 124 | dbg5 = dbgAt 5 125 | 126 | dbg6 :: Show a => String -> a -> a 127 | dbg6 = dbgAt 6 128 | 129 | dbg7 :: Show a => String -> a -> a 130 | dbg7 = dbgAt 7 131 | 132 | dbg8 :: Show a => String -> a -> a 133 | dbg8 = dbgAt 8 134 | 135 | dbg9 :: Show a => String -> a -> a 136 | dbg9 = dbgAt 9 137 | 138 | -- | Print a message and a showable value to the console if the global 139 | -- debug level is at or above the specified level. Uses unsafePerformIO. 140 | dbgAt :: Show a => Int -> String -> a -> a 141 | dbgAt lvl = dbgppshow lvl 142 | 143 | -- Could not deduce (a ~ ()) 144 | -- from the context (Show a) 145 | -- bound by the type signature for 146 | -- dbgM :: Show a => String -> a -> IO () 147 | -- at hledger/Hledger/Cli/Main.hs:200:13-42 148 | -- ‘a’ is a rigid type variable bound by 149 | -- the type signature for dbgM :: Show a => String -> a -> IO () 150 | -- at hledger/Hledger/Cli/Main.hs:200:13 151 | -- Expected type: String -> a -> IO () 152 | -- Actual type: String -> a -> IO a 153 | -- -- dbgAtM :: (Monad m, Show a) => Int -> String -> a -> m a 154 | -- -- dbgAtM lvl lbl x = dbgAt lvl lbl x `seq` return x 155 | -- -- XXX temporary: 156 | -- dbgAtM :: Show a => Int -> String -> a -> IO () 157 | -- dbgAtM = dbgAtIO 158 | 159 | dbgAtIO :: Show a => Int -> String -> a -> IO () 160 | dbgAtIO lvl lbl x = dbgAt lvl lbl x `seq` return () 161 | 162 | -- -- | print this string to the console before evaluating the expression, 163 | -- -- if the global debug level is non-zero. Uses unsafePerformIO. 164 | -- dbgtrace :: String -> a -> a 165 | -- dbgtrace 166 | -- | debugLevel > 0 = trace 167 | -- | otherwise = flip const 168 | 169 | -- -- | Print a showable value to the console, with a message, if the 170 | -- -- debug level is at or above the specified level (uses 171 | -- -- unsafePerformIO). 172 | -- -- Values are displayed with show, all on one line, which is hard to read. 173 | -- dbgshow :: Show a => Int -> String -> a -> a 174 | -- dbgshow level 175 | -- | debugLevel >= level = ltrace 176 | -- | otherwise = flip const 177 | 178 | -- | Print a showable value to the console, with a message, if the 179 | -- debug level is at or above the specified level (uses 180 | -- unsafePerformIO). 181 | -- Values are displayed with ppShow, each field/constructor on its own line. 182 | dbgppshow :: Show a => Int -> String -> a -> a 183 | dbgppshow level 184 | | debugLevel < level = flip const 185 | | otherwise = \s a -> let p = ppShow a 186 | ls = lines p 187 | nlorspace | length ls > 1 = "\n" 188 | | otherwise = " " ++ take (10 - length s) (repeat ' ') 189 | ls' | length ls > 1 = map (" "++) ls 190 | | otherwise = ls 191 | in trace (s++":"++nlorspace++intercalate "\n" ls') a 192 | 193 | -- -- | Print a showable value to the console, with a message, if the 194 | -- -- debug level is at or above the specified level (uses 195 | -- -- unsafePerformIO). 196 | -- -- Values are displayed with pprint. Field names are not shown, but the 197 | -- -- output is compact with smart line wrapping, long data elided, 198 | -- -- and slow calculations timed out. 199 | -- dbgpprint :: Data a => Int -> String -> a -> a 200 | -- dbgpprint level msg a 201 | -- | debugLevel >= level = unsafePerformIO $ do 202 | -- pprint a >>= putStrLn . ((msg++": \n") ++) . show 203 | -- return a 204 | -- | otherwise = a 205 | 206 | 207 | -- | Like dbg, then exit the program. Uses unsafePerformIO. 208 | dbgExit :: Show a => String -> a -> a 209 | dbgExit msg = const (unsafePerformIO exitFailure) . dbg msg 210 | 211 | -- | Print a message and parsec debug info (parse position and next 212 | -- input) to the console when the debug level is at or above 213 | -- this level. Uses unsafePerformIO. 214 | -- pdbgAt :: GenParser m => Float -> String -> m () 215 | pdbg level msg = when (level <= debugLevel) $ ptrace msg 216 | 217 | -------------------------------------------------------------------------------- /src/shelltest.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DeriveDataTypeable, CPP, DoAndIfThenElse #-} 2 | {- | 3 | 4 | shelltest - for testing command-line programs. See shelltestrunner.cabal. 5 | (c) Simon Michael & contributors 2009-2023, released under GNU GPLv3 or later. 6 | 7 | -} 8 | 9 | module Main 10 | where 11 | 12 | import Control.Concurrent (forkIO) 13 | import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) 14 | import Control.Monad (void) 15 | import Data.Algorithm.Diff 16 | import System.Console.CmdArgs 17 | import System.Directory (doesDirectoryExist) 18 | import System.FilePath (takeDirectory) 19 | import System.FilePath.Find (findWithHandler, (==?), always) 20 | import qualified System.FilePath.Find as Find (extension) 21 | import System.IO (Handle, hGetContents, hPutStr) 22 | import System.Process (StdStream (CreatePipe), shell, proc, createProcess, CreateProcess (..), waitForProcess, ProcessHandle) 23 | import Test.Framework (defaultMainWithArgs) 24 | import Test.Framework.Providers.HUnit (hUnitTestToTests) 25 | import Test.HUnit 26 | import Text.Parsec 27 | import Test.Hspec.Core.Runner (defaultConfig, runSpec, Config (..)) 28 | import Test.Hspec.Contrib.HUnit (fromHUnitTest) 29 | 30 | import Import 31 | import Utils 32 | import Types 33 | import Parse 34 | import Print 35 | import Preprocessor 36 | 37 | 38 | progname, progversion :: String 39 | progname = "shelltest" 40 | progversion = progname ++ " " ++ "1.10" 41 | proghelpsuffix :: [String] 42 | proghelpsuffix = [ 43 | "shelltest file formats, tried in this order:" 44 | ,"" 45 | ,"Description Delimiters, in order" 46 | ,"------------------------------------------------------ ------------------------" 47 | ,"v2 input then multiple tests; some delimiters optional <<< $$$ >>> >>>2 >>>=" 48 | ,"v3 same as v2, but with short delimiters < $ > >2 >=" 49 | ,"v1 command first; exit status is required (none) <<< >>> >>>2 >>>=" 50 | ,"" 51 | ] 52 | 53 | data Args = Args { 54 | list :: Bool 55 | ,include :: [String] 56 | ,exclude :: [String] 57 | ,all_ :: Bool 58 | ,color :: Bool 59 | ,diff :: Bool 60 | ,precise :: Bool 61 | ,hide_successes :: Bool 62 | ,fail_fast :: Bool 63 | ,xmlout :: String 64 | ,defmacro :: [String] 65 | ,execdir :: Bool 66 | ,extension :: String 67 | ,with :: String 68 | ,timeout :: Int 69 | ,threads :: Int 70 | ,shell_cmd :: Maybe FilePath 71 | ,debug :: Bool 72 | ,debug_parse :: Bool 73 | ,testpaths :: [FilePath] 74 | ,print_ :: Maybe String 75 | ,hspec_ :: Bool 76 | } deriving (Show, Data, Typeable) 77 | 78 | argdefs = Args { 79 | list = def &= help "List the names of all tests found" 80 | ,include = def &= name "i" &= typ "PAT" &= help "Include tests whose name contains this glob pattern (eg: -i1 -i{4,5,6})" 81 | ,exclude = def &= name "x" &= typ "STR" &= help "Exclude test files whose path contains STR" 82 | ,all_ = def &= help "Show all output without truncating, even if large" 83 | ,color = def &= help "Show colored output if your terminal supports it" 84 | ,diff = def &= name "d" &= help "Show differences between expected/actual output" 85 | ,precise = def &= name "p" &= help "Show expected/actual output precisely, with quoting" 86 | ,hide_successes = def &= explicit &= name "hide-successes" &= help "Show only test failures" 87 | ,fail_fast = def &= explicit &= name "fail-fast" &= help "Only hspec: stop tests on first failure" 88 | ,xmlout = def &= typ "FILE" &= help "Save test results to FILE in XML format." 89 | ,defmacro = def &= name "D" &= typ "D=DEF" &= help "Define a macro D to be replaced by DEF while parsing test files." 90 | ,execdir = def &= help "Run tests from within each test file's directory" 91 | ,extension = ".test" &= typ "EXT" &= help "File suffix of test files (default: .test)" 92 | ,with = def &= typ "EXE" &= help "Replace the first word of test commands with EXE (unindented commands only)" 93 | ,timeout = def &= name "o" &= typ "SECS" &= help "Number of seconds a test may run (default: no limit)" 94 | ,threads = def &= name "j" &= typ "N" &= help "Number of threads for running tests (default: 1)" 95 | ,shell_cmd = def &= explicit &= name "shell" &= typ "EXE" &= help "The shell program to use (must accept -c CMD; default: /bin/sh on POSIX, cmd.exe on Windows)" 96 | ,debug = def &= help "Show debug info while running" 97 | ,debug_parse = def &= help "Show test file parsing results and stop" 98 | ,testpaths = def &= args &= typ "TESTFILES|TESTDIRS" 99 | ,print_ = def &= typ "FORMAT" &= opt "v3" &= groupname "Print test file" &= help "Print test files in specified format (default: v3)." 100 | ,hspec_ = def &= name"hspec" &= help "Use hspec to run tests." 101 | } 102 | &= helpArg [explicit, name "help", name "h"] 103 | &= program progname 104 | &= summary progversion 105 | &= details proghelpsuffix 106 | 107 | main :: IO () 108 | main = do 109 | -- parse args 110 | args' <- cmdArgs argdefs >>= checkArgs 111 | -- some of the cmdargs-parsed "arguments" may be test-framework options following --, 112 | -- separate those out 113 | let (tfopts', realargs) = partition ("-" `isPrefixOf`) $ testpaths args' 114 | args = args'{testpaths=realargs} 115 | tfopts = tfopts' 116 | ++ (if list args then ["--list"] else []) 117 | ++ (if color args then [] else ["--plain"]) 118 | ++ (if hide_successes args then ["--hide-successes"] else []) 119 | ++ (["--select-tests="++s | s <- include args]) 120 | ++ (if timeout args > 0 then ["--timeout=" ++ show (timeout args)] else []) 121 | ++ (if threads args > 0 then ["--threads=" ++ show (threads args)] else []) 122 | ++ (if not (xmlout args == []) then ["--jxml=" ++ (xmlout args)] else []) 123 | hspecconf = defaultConfig 124 | {configConcurrentJobs = Just (threads args) 125 | ,configFailFast = fail_fast args 126 | -- TODO add other options; compare shelltest -h and http://hspec.github.io/options.html 127 | -- https://hackage.haskell.org/package/hspec-core-2.7.2/docs/Test-Hspec-Core-Runner.html#g:2 128 | } 129 | 130 | 131 | when (debug args) $ printf "%s\n" progversion >> printf "args: %s\n" (ppShow args) 132 | 133 | -- gather test files 134 | testfiles' <- nub . concat <$> mapM 135 | (\p -> do 136 | isdir <- doesDirectoryExist p 137 | if isdir 138 | then findWithHandler (\_ e->fail (show e)) always (Find.extension ==? extension args) p 139 | else return [p]) 140 | (testpaths args) 141 | let testfiles = filter (not . \p -> any (`isInfixOf` p) (exclude args)) testfiles' 142 | excluded = length testfiles' - length testfiles 143 | macros = (getMacros (defmacro args)) 144 | preprocessor = createMacroPreProcessor macros 145 | when (excluded > 0) $ printf "Excluding %d test files\n" excluded 146 | 147 | -- parse test files 148 | when (debug args) $ printf "processing %d test files: %s\n" (length testfiles) (intercalate ", " testfiles) 149 | shelltests <- mapM (parseShellTestFile (debug args || debug_parse args) preprocessor) testfiles 150 | 151 | -- exit after --debug-parse output 152 | if debug_parse args then exitSuccess 153 | -- or print tests 154 | else if isJust $ print_ args then mapM_ (printShellTestsWithResults args) shelltests 155 | -- or run tests 156 | else do 157 | when (debug args) $ printf "running tests:\n" 158 | if hspec_ args 159 | then runWithHspec args hspecconf shelltests 160 | else runWithTestFramework args tfopts shelltests 161 | 162 | runWithTestFramework :: Args -> [String] -> [Either ParseError [ShellTest]] -> IO () 163 | runWithTestFramework args tfopts shelltests = defaultMainWithArgs hunittests tfopts 164 | where hunittests = concatMap (hUnitTestToTests . testFileParseToHUnitTest args) shelltests 165 | 166 | runWithHspec :: Args -> Config -> [Either ParseError [ShellTest]] -> IO () 167 | runWithHspec args hsconf shelltests = void $ runSpec spec hsconf 168 | where 169 | spec = fromHUnitTest $ TestLabel "All shelltests" $ TestList hunittests 170 | hunittests = map (testFileParseToHUnitTest args) shelltests 171 | 172 | printShellTestsWithResults :: Args -> Either ParseError [ShellTest] -> IO () 173 | printShellTestsWithResults args (Right ts) = mapM_ (prepareShellTest args) ts 174 | printShellTestsWithResults _ (Left e) = putStrLn $ "*** parse error in " ++ (sourceName $ errorPos e) 175 | 176 | -- | Additional argument checking. 177 | checkArgs :: Args -> IO Args 178 | checkArgs args = do 179 | when (null $ testpaths args) $ 180 | warn $ printf "Please specify at least one test file or directory, eg: %s tests" progname 181 | return args 182 | 183 | -- running tests 184 | 185 | testFileParseToHUnitTest :: Args -> Either ParseError [ShellTest] -> Test.HUnit.Test 186 | testFileParseToHUnitTest args (Right ts) = TestList $ map (\t -> testname t ~: prepareShellTest args t) ts 187 | testFileParseToHUnitTest _ (Left e) = ("parse error in " ++ (sourceName $ errorPos e)) ~: (assertFailure :: (String -> IO ())) $ show e 188 | 189 | -- | Convert this test to an IO action that either runs the test or prints it 190 | -- to stdout, depending on the arguments. 191 | prepareShellTest :: Args -> ShellTest -> IO () 192 | prepareShellTest args st@ShellTest{testname=n,command=c,stdin=i,stdoutExpected=o_expected, 193 | stderrExpected=e_expected,exitCodeExpected=x_expected,lineNumber=ln} = 194 | do 195 | let e = with args 196 | cmd = case (e,c) of (_:_, ReplaceableCommand s) -> e ++ " " ++ dropWhile (/=' ') s 197 | (_, ReplaceableCommand s) -> s 198 | (_, FixedCommand s) -> s 199 | dir = if execdir args then Just $ takeDirectory n else Nothing 200 | trim' = if all_ args then id else trim 201 | when (debug args) $ do 202 | printf "actual command was: %s\n" (show cmd) 203 | (o_actual, e_actual, x_actual) <- runCommandWithInput (shell_cmd args) dir cmd i 204 | when (debug args) $ do 205 | printf "actual stdout was : %s\n" (show $ trim' o_actual) 206 | printf "actual stderr was : %s\n" (show $ trim' e_actual) 207 | printf "actual exit was : %s\n" (trim' $ show x_actual) 208 | let outputMatch = maybe True (o_actual `matches`) o_expected 209 | let errorMatch = maybe True (e_actual `matches`) e_expected 210 | let exitCodeMatch = show x_actual `matches` x_expected 211 | case print_ args of 212 | Just format -> printShellTest format st 213 | Nothing -> if (x_actual == 127) -- catch bad executable - should work on posix systems at least 214 | then ioError $ userError $ unwords $ filter (not . null) [e_actual, printf "Command: '%s' Exit code: %i" cmd x_actual] -- XXX still a test failure; should be an error 215 | else assertString $ concat $ filter (not . null) [ 216 | if any not [outputMatch, errorMatch, exitCodeMatch] 217 | then printf "Command (at line %s):\n%s\n" (show ln) cmd 218 | else "" 219 | ,if outputMatch 220 | then "" 221 | else showExpectedActual args "stdout" (fromJust o_expected) o_actual 222 | ,if errorMatch 223 | then "" 224 | else showExpectedActual args "stderr" (fromJust e_expected) e_actual 225 | ,if exitCodeMatch 226 | then "" 227 | else showExpectedActual args{diff=False} "exit code" x_expected (show x_actual) 228 | ] 229 | 230 | -- | Run a shell command line, passing it standard input if provided, 231 | -- and return the standard output, standard error output and exit code. 232 | -- Note on unix, at least with ghc 6.12, command (and filepath) are assumed to be utf8-encoded. 233 | runCommandWithInput :: Maybe FilePath -> Maybe FilePath -> String -> Maybe String -> IO (String, String, Int) 234 | runCommandWithInput sh wd cmd input = do 235 | -- this has to be done carefully 236 | (ih,oh,eh,ph) <- runInteractiveCommandInDir sh wd cmd 237 | when (isJust input) $ forkIO (hPutStr ih $ fromJust input) >> return () 238 | o <- newEmptyMVar 239 | e <- newEmptyMVar 240 | forkIO $ oh `hGetContentsStrictlyAnd` putMVar o 241 | forkIO $ eh `hGetContentsStrictlyAnd` putMVar e 242 | x_actual <- waitForProcess ph >>= return.fromExitCode 243 | o_actual <- takeMVar o 244 | e_actual <- takeMVar e 245 | return (o_actual, e_actual, x_actual) 246 | 247 | runInteractiveCommandInDir :: Maybe FilePath -> Maybe FilePath -> String -> IO (Handle, Handle, Handle, ProcessHandle) 248 | runInteractiveCommandInDir sh wd cmd = do 249 | (mb_in, mb_out, mb_err, p) <- 250 | createProcess $ 251 | run { cwd = wd 252 | , std_in = CreatePipe 253 | , std_out = CreatePipe 254 | , std_err = CreatePipe } 255 | -- these should all be Just since we used CreatePipe 256 | return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p) 257 | where 258 | run = maybe (shell cmd) (\shcmd -> proc shcmd ["-c", cmd]) sh 259 | 260 | hGetContentsStrictlyAnd :: Handle -> (String -> IO b) -> IO b 261 | hGetContentsStrictlyAnd h f = hGetContents h >>= \s -> length s `seq` f s 262 | 263 | matches :: String -> Matcher -> Bool 264 | matches s (PositiveRegex (MR r)) = s `containsRegex` r 265 | matches s (NegativeRegex (MR r)) = not $ s `containsRegex` r 266 | matches s (Numeric p) = s == p 267 | matches s (NegativeNumeric p) = not $ s == p 268 | matches s (Lines _ p) = s == p 269 | 270 | showExpectedActual :: Args -> String -> Matcher -> String -> String 271 | showExpectedActual args@Args{diff=True} _ (Lines ln e) a = 272 | printf "--- Expected\n+++ Got\n" ++ showDiff args(1,ln) (getDiff (lines a) (lines e)) 273 | showExpectedActual Args{all_=all_,precise=precise} field e a = 274 | printf "Expected %s: %s\nGot %s: %s" field (show' $ showm e) field (show' $ trim' a) 275 | where 276 | show' = if precise then show else ("\n"++) 277 | showm = if all_ then showMatcher else showMatcherTrimmed 278 | trim' = if all_ then id else trim 279 | 280 | showDiff :: Args -> (Int,Int) -> [(Diff String)] -> String 281 | showDiff _ _ [] = "" 282 | showDiff args@Args{all_=all_,precise=precise} (l,r) ((First ln) : ds) = 283 | printf "+%4d " l ++ ln' ++ "\n" ++ showDiff args (l+1,r) ds 284 | where 285 | ln' = trim' $ show' ln 286 | trim' = if all_ then id else trim 287 | show' = if precise then show else id 288 | showDiff args@Args{all_=all_,precise=precise} (l,r) ((Second ln) : ds) = 289 | printf "-%4d " r ++ ln' ++ "\n" ++ showDiff args (l,r+1) ds 290 | where 291 | ln' = trim' $ show' ln 292 | trim' = if all_ then id else trim 293 | show' = if precise then show else id 294 | showDiff args (l,r) ((Both _ _) : ds) = showDiff args (l+1,r+1) ds 295 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | snapshot: nightly-2025-04-01 4 | -------------------------------------------------------------------------------- /stack8.10.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-18.28 2 | packages: 3 | 4 | extra-deps: 5 | - hspec-2.10.8 6 | - hspec-core-2.10.8 7 | - hspec-discover-2.10.8 8 | - hspec-contrib-0.5.1.1 9 | -------------------------------------------------------------------------------- /stack912.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | snapshot: ghc-9.12.2 4 | extra-deps: 5 | - ansi-terminal-1.1.2 6 | - ansi-terminal-types-1.1 7 | - ansi-wl-pprint-1.0.2 8 | - call-stack-0.4.0 9 | - cmdargs-0.10.22 10 | - colour-2.3.6 11 | - Diff-1.0.2 12 | - extensible-exceptions-0.1.1.4 13 | - filemanip-0.3.6.3 14 | - happy-2.1.5 15 | - happy-lib-2.1.5 16 | - haskell-lexer-1.2.1 17 | - hostname-1.0 18 | - hspec-2.11.12 19 | - hspec-contrib-0.5.2 20 | - hspec-core-2.11.12 21 | - hspec-discover-2.11.12 22 | - hspec-expectations-0.8.4 23 | - HUnit-1.6.2.0 24 | - old-locale-1.0.0.7 25 | - pretty-show-1.10 26 | - prettyprinter-1.7.1 27 | - prettyprinter-ansi-terminal-1.1.3 28 | - prettyprinter-compat-ansi-wl-pprint-1.0.2 29 | - primitive-0.9.1.0 30 | - QuickCheck-2.15.0.1 31 | - quickcheck-io-0.2.0 32 | - random-1.3.0 33 | - regex-base-0.94.0.3 34 | - regex-posix-0.96.0.2 35 | - regex-tdfa-1.3.2.3 36 | - safe-0.3.21 37 | - splitmix-0.1.1 38 | - test-framework-0.8.2.1 39 | - test-framework-hunit-0.3.0.2 40 | - tf-random-0.5 41 | - unix-compat-0.7.4 42 | - utf8-string-1.0.2 43 | - xml-1.3.14 44 | 45 | notify-if-cabal-untested: false 46 | notify-if-ghc-untested: false 47 | -------------------------------------------------------------------------------- /stack96.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | snapshot: lts-22.43 4 | -------------------------------------------------------------------------------- /stack98.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | snapshot: lts-23.17 4 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | Functional tests for shelltest itself. 2 | 3 | The test files (*.test) are grouped in directories by format. 4 | Platform-specific tests also have their own directories. The files 5 | and tests should be kept in sync across formats, differing only in 6 | format. 7 | -------------------------------------------------------------------------------- /tests/bash/dollar-quote.test: -------------------------------------------------------------------------------- 1 | # Test bash-only $'...' syntax. 2 | # This only works when run with --shell /bin/bash 3 | # See also: https://github.com/simonmichael/shelltestrunner/issues/15 4 | echo $'\'o\' `elem` p' 5 | >>> 6 | 'o' `elem` p 7 | >>>= 0 8 | -------------------------------------------------------------------------------- /tests/bash/process-substitution.test: -------------------------------------------------------------------------------- 1 | # Test bash-only <( ... ) syntax. 2 | # This only works when run with --shell /bin/bash 3 | diff <( echo foo ) <( echo bar ) 4 | >>> 5 | 1c1 6 | < foo 7 | --- 8 | > bar 9 | >>>= 1 10 | -------------------------------------------------------------------------------- /tests/examples/README: -------------------------------------------------------------------------------- 1 | The examples from the project README as shelltests. 2 | Copy/pasted by hand for now, should be kept in sync. 3 | 4 | To watch for errors: 5 | 6 | $ watchexec -- make test 7 | -------------------------------------------------------------------------------- /tests/examples/examples.test: -------------------------------------------------------------------------------- 1 | # 1. Test that the "echo" command (a shell builtin, usually) 2 | # prints its argument on stdout, prints nothing on stderr, 3 | # and exits with a zero exit code. 4 | 5 | $ echo a 6 | a 7 | 8 | # 2. Test that echo with no arguments prints a blank line, 9 | # no stderr output, and exits with zero. 10 | # Since the output ends with whitespace, this time we must write 11 | # the exit code test (>=) explicitly, to act as a delimiter. 12 | 13 | $ echo 14 | 15 | >= 16 | 17 | # 3. Test that cat with a bad flag prints nothing on stdout, 18 | # an error containing "unrecognized option" or "illegal option" on stderr, 19 | # and exits with non-zero status. 20 | 21 | $ cat --no-such-flag 22 | >2 /(unrecognized|illegal) option/ 23 | >= !0 24 | -------------------------------------------------------------------------------- /tests/examples/format2_1.test: -------------------------------------------------------------------------------- 1 | # cat copies its input to stdout 2 | <<< 3 | foo 4 | $$$ cat 5 | >>> 6 | foo 7 | 8 | # or, given a bad flag, prints a platform-specific error and exits with non-zero status 9 | $$$ cat --no-such-flag 10 | >>>2 /(unrecognized|illegal) option/ 11 | >>>= !0 12 | 13 | # echo ignores the input and prints a newline. 14 | # We need the >>>= (or a >>>2) to delimit the whitespace which 15 | # would otherwise be ignored. 16 | $$$ echo 17 | >>> 18 | 19 | >>>2 20 | -------------------------------------------------------------------------------- /tests/examples/format2_2.test: -------------------------------------------------------------------------------- 1 | foo 2 | $$$ cat 3 | foo 4 | 5 | $$$ cat --no-such-flag 6 | >>>2 /(unrecognized|illegal) option/ 7 | >>>= !0 8 | 9 | $$$ echo 10 | 11 | >>>= 12 | -------------------------------------------------------------------------------- /tests/examples/format3_1.test: -------------------------------------------------------------------------------- 1 | # cat copies its input to stdout 2 | < 3 | foo 4 | $ cat 5 | > 6 | foo 7 | 8 | # or, given a bad flag, prints a platform-specific error and exits with non-zero status 9 | $ cat --no-such-flag 10 | >2 /(unrecognized|illegal) option/ 11 | >= !0 12 | 13 | # echo ignores the input and prints a newline. 14 | # We use an explicit >2 (or >=) to delimit the whitespace which 15 | # would otherwise be ignored. 16 | $ echo 17 | > 18 | 19 | >2 20 | -------------------------------------------------------------------------------- /tests/examples/format3_2.test: -------------------------------------------------------------------------------- 1 | foo 2 | $ cat 3 | foo 4 | 5 | $ cat --no-such-flag 6 | >2 /(unrecognized|illegal) option/ 7 | >= !0 8 | 9 | $ echo 10 | > 11 | 12 | >= 13 | -------------------------------------------------------------------------------- /tests/format1.unix/empty-unix.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | shelltest /dev/null 3 | >>> /Total +0/ 4 | >>>= 0 5 | -------------------------------------------------------------------------------- /tests/format1.unix/no-eol-unix.test: -------------------------------------------------------------------------------- 1 | # test output which does not end with a newline 2 | cat 3 | <<< 4 | >>> /^$/ 5 | >>>= 0 6 | -------------------------------------------------------------------------------- /tests/format1.unix/unicode-unix.test: -------------------------------------------------------------------------------- 1 | # 0. utf8-encoded unicode in filename should be fine 2 | # XXX file renamed from unicode-ß-unix.test to appease hackage (non-utf8-encoded ?) 3 | # 4 | # 1. in command field: 5 | echo проверка 6 | >>>= 0 7 | # 2. in output field: 8 | echo проверка 9 | >>> 10 | проверка 11 | >>>= 0 12 | # 3. in regexp: 13 | echo проверка 14 | >>> /проверка/ 15 | >>>= 0 16 | -------------------------------------------------------------------------------- /tests/format1.windows/empty-windows.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | shelltest NUL: 3 | >>> /Total +0/ 4 | >>>= 0 5 | -------------------------------------------------------------------------------- /tests/format1/abstract-test-with-macros: -------------------------------------------------------------------------------- 1 | # 1 Abstract test with unresolved macros. Test is run by macros.test. 2 | {exe} {in} 3 | >>> /{out}/ 4 | >>>= 0 5 | 6 | -------------------------------------------------------------------------------- /tests/format1/args.test: -------------------------------------------------------------------------------- 1 | # test with various arguments 2 | # 3 | # 1. with no args, should run all tests below current dir 4 | # shelltest 5 | # >>> /Not enough non-flag arguments/ 6 | # >>>= !0 7 | # 8 | # 2. a bad executable with no testfiles is accepted 9 | # XXX should really error 10 | #shelltest nosuchexe 11 | #>>> /Total +0/ 12 | # 13 | # 3. a bad executable with testfiles should fail 14 | shelltest --with nosuchexe tests/format1/args.test 15 | >>> /user error/ 16 | >>>= 1 17 | # 18 | # 4. a bad testfile should fail 19 | shelltest --with cat nosuchtestfile 20 | >>>2 /No such file/ 21 | >>>= 1 22 | # a final comment -------------------------------------------------------------------------------- /tests/format1/delimiters.test: -------------------------------------------------------------------------------- 1 | # test content beginning with delimiter characters 2 | 3 | echo "<" 4 | >>> 5 | < 6 | >>>2 7 | >>>= 0 8 | 9 | echo ">" 10 | >>> 11 | > 12 | >>>2 13 | >>>= 0 14 | 15 | echo "$" 16 | >>> 17 | $ 18 | >>>2 19 | >>>= 0 20 | -------------------------------------------------------------------------------- /tests/format1/failure-line.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest tests/format1/one-failing-test 3 | >>> /.*Command [(]at line 8[)].* 4 | .*plahh.* 5 | .*Expected stdout.* 6 | .*slahh.* 7 | .*Got stdout.* 8 | .*plahh.*/ 9 | >>>= 1 10 | -------------------------------------------------------------------------------- /tests/format1/format1.test: -------------------------------------------------------------------------------- 1 | # Test file format 1 - one or more tests, each specifying its input. 2 | # 3 | # OPTIONAL WHITESPACE/#COMMENT 4 | # COMMAND LINE 5 | # OPTIONAL <<< INPUT 6 | # OPTIONAL >>> OUTPUT/REGEX 7 | # OPTIONAL >>>2 STDERR/REGEX 8 | # >>>= STATUS/REGEX 9 | # 0 OR MORE ADDITIONAL TESTS 10 | # 11 | # The command line and exit status check are required. 12 | # stdout/stderr are not checked implicitly. 13 | # Comment & whitespace lines before and after tests are ignored. 14 | 15 | cat 16 | <<< 17 | A 18 | >>> 19 | A 20 | >>>2 21 | >>>= 0 22 | 23 | cat 24 | <<< 25 | A 26 | >>> 27 | A 28 | >>>2 29 | >>>= 0 30 | 31 | # 32 | -------------------------------------------------------------------------------- /tests/format1/help.test: -------------------------------------------------------------------------------- 1 | # with --help, output should contain usage 2 | # and exit code should be 0 3 | shelltest --help 4 | >>> /Common flags:/ 5 | >>>=0 6 | -------------------------------------------------------------------------------- /tests/format1/indented-input.test: -------------------------------------------------------------------------------- 1 | # indented input should not break the parser 2 | cat 3 | <<< 4 | x 5 | >>>= 0 6 | -------------------------------------------------------------------------------- /tests/format1/just-a-comment.test: -------------------------------------------------------------------------------- 1 | # just a comment 2 | -------------------------------------------------------------------------------- /tests/format1/large-regexp.test: -------------------------------------------------------------------------------- 1 | # pcre-light handles regexps up to about 32764 chars, any larger gives a runtime error 2 | #>>> /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 3 | # regex-tdfa memory usage blows up.. I fear to use anything more than 250 chars 4 | ghc -e "putStr $ replicate 33000 'a'" 5 | >>> /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 6 | >>>= 0 7 | -------------------------------------------------------------------------------- /tests/format1/macros.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest -D{exe}=echo "-D{in}=My message" "-D{out}=My message" -D{doNotExist}=null tests/format1/abstract-test-with-macros 3 | >>>= 0 4 | -------------------------------------------------------------------------------- /tests/format1/no-input.test: -------------------------------------------------------------------------------- 1 | # test "mac will hang if input is specified and stdin is not read" fix 2 | echo 3 | <<< 4 | dummy input 5 | >>>= 0 6 | -------------------------------------------------------------------------------- /tests/format1/one-failing-test: -------------------------------------------------------------------------------- 1 | # Note that this file is called from 'failure-line.test' 2 | # This should be fine. 3 | echo "plahh" 4 | >>> /plahh/ 5 | >>>= 0 6 | 7 | # This should be broken. 8 | echo "plahh" 9 | >>> /slahh/ 10 | >>>= 0 11 | 12 | # This should be fine. 13 | echo "plahh" 14 | >>> /plahh/ 15 | >>>= 0 -------------------------------------------------------------------------------- /tests/format1/parsing.test: -------------------------------------------------------------------------------- 1 | # misc. testfile parsing tests 2 | # 1. can we regexp-match a forward slash ? 3 | echo / 4 | >>> /\// 5 | >>>= 0 6 | 7 | # 2. can we handle an empty regexp ? 8 | echo 9 | >>> // 10 | >>>= 0 11 | 12 | # 3. or a regexp followed by a comment ? 13 | echo 14 | >>> // # comment 15 | >>>= 0 16 | -------------------------------------------------------------------------------- /tests/format1/trailing-comment-no-newline.test: -------------------------------------------------------------------------------- 1 | echo 2 | >>>= 0 3 | # comment -------------------------------------------------------------------------------- /tests/format1/trailing-comment.test.todo: -------------------------------------------------------------------------------- 1 | echo 2 | # comment 3 | -------------------------------------------------------------------------------- /tests/format2.unix/empty-unix.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | $$$ shelltest /dev/null 3 | >>> /Total +0/ 4 | 5 | -------------------------------------------------------------------------------- /tests/format2.unix/no-eol-unix.test: -------------------------------------------------------------------------------- 1 | # test output which does not end with a newline 2 | <<< 3 | $$$ cat 4 | >>> /^$/ 5 | -------------------------------------------------------------------------------- /tests/format2.unix/unicode-unix.test: -------------------------------------------------------------------------------- 1 | # 0. utf8-encoded unicode in filename should be fine 2 | # XXX file renamed from unicode-ß-unix.test to appease hackage (non-utf8-encoded ?) 3 | # 4 | # 1. in command field: 5 | $$$ echo проверка 6 | >>> // 7 | 8 | # 2. in output field: 9 | $$$ echo проверка 10 | проверка 11 | 12 | # 3. in regexp: 13 | $$$ echo проверка 14 | >>> /проверка/ 15 | 16 | -------------------------------------------------------------------------------- /tests/format2.windows/empty-windows.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | $$$ shelltest NUL: 3 | >>> /Total +0/ 4 | -------------------------------------------------------------------------------- /tests/format2/abstract-test-with-macros: -------------------------------------------------------------------------------- 1 | # 1 Abstract test with unresolved macros. Test is run by macros.test. 2 | $$$ {exe} {in} 3 | >>> /{out}/ 4 | >>>= 0 5 | 6 | -------------------------------------------------------------------------------- /tests/format2/args.test: -------------------------------------------------------------------------------- 1 | # test with various arguments 2 | 3 | # 1. with no args, should run all tests below current dir 4 | $$$ shelltest 5 | >>> /Please specify at least one test file or directory/ 6 | >>>= !0 7 | 8 | # 2. XXX a bad executable should error without running tests 9 | #$$$ shelltest --with nosuchexe 10 | #>>> /Total +0/ 11 | 12 | # 3. a bad executable with testfiles should fail 13 | $$$ shelltest --with nosuchexe tests/format2/args.test 14 | >>> /user error/ 15 | >>>= 1 16 | 17 | # 4. a bad testfile should fail 18 | $$$ shelltest --with cat nosuchtestfile 19 | >>>2 /No such file/ 20 | >>>= 1 21 | 22 | # a final comment -------------------------------------------------------------------------------- /tests/format2/delimiters.test: -------------------------------------------------------------------------------- 1 | # test content beginning with delimiter characters 2 | 3 | < 4 | $ 5 | $$$ cat 6 | < 7 | $ 8 | 9 | $$$ echo ">" 10 | >>> 11 | > 12 | >>>2 13 | >>>= 0 14 | -------------------------------------------------------------------------------- /tests/format2/failure-line.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest tests/format1/one-failing-test 3 | >>> /.*Command [(]at line 8[)].* 4 | .*plahh.* 5 | .*Expected stdout.* 6 | .*slahh.* 7 | .*Got stdout.* 8 | .*plahh.*/ 9 | >>>= 1 10 | -------------------------------------------------------------------------------- /tests/format2/format2.test: -------------------------------------------------------------------------------- 1 | # Test file format 2 - one or more test groups, which are input followed by one or more tests/ 2 | # 3 | # See --help-format/shelltest.hs. Last copied 2015/3/16: 4 | # "--------------------------------------" 5 | # ,"shelltestrunner test file format:" 6 | # ,"" 7 | # ,"# COMMENTS OR BLANK LINES" 8 | # ,"<<<" 9 | # ,"INPUT" 10 | # ,"$$$ COMMAND LINE" 11 | # ,">>>" 12 | # ,"EXPECTED OUTPUT (OR >>> /REGEX/)" 13 | # ,">>>2" 14 | # ,"EXPECTED STDERR (OR >>>2 /REGEX/)" 15 | # ,">>>= EXPECTED EXIT STATUS (OR >>>= /REGEX/)" 16 | # ,"# COMMENTS OR BLANK LINES" 17 | # ,"ADDITIONAL TESTS FOR THIS INPUT" 18 | # ,"ADDITIONAL TEST GROUPS WITH DIFFERENT INPUT" 19 | # ,"" 20 | # ,"All parts are optional except the command line." 21 | # ,"When unspecified, stdout/stderr/exit status are tested for emptiness." 22 | # ,"" 23 | # ,"The <<< delimiter is optional for the first input in a file." 24 | # ,"Without it, input begins at the first non-blank/comment line." 25 | # ,"Input ends at the $$$ delimiter. You can't put a comment before the first $$$." 26 | # ,"" 27 | # ,"The >>> delimiter is optional except when matching via regex." 28 | # ,"Expected output/stderr extends to the next >>>2 or >>>= if present," 29 | # ,"or to the last non-blank/comment line before the next <<< or $$$ or file end." 30 | # ,"" 31 | # ,"Two spaces between $$$ and the command protects it from -w/--with." 32 | # ,"!/REGEX/ negates a regular expression match." 33 | # ,"" 34 | # ,"--------------------------------------" 35 | 36 | 37 | AA 38 | $$$ cat 39 | AA 40 | 41 | # test 2 42 | $$$ cat 43 | >>> /A/ 44 | >>>2 45 | >>>= 0 46 | 47 | # test 3 48 | <<< 49 | A 50 | $$$ cat 51 | >>> /A/ 52 | >>>2 53 | >>>= 54 | 55 | # 56 | -------------------------------------------------------------------------------- /tests/format2/help.test: -------------------------------------------------------------------------------- 1 | # with --help, output should contain usage 2 | # and exit code should be 0 3 | $$$ shelltest --help 4 | >>> /Common flags:/ 5 | 6 | -------------------------------------------------------------------------------- /tests/format2/ideal.test: -------------------------------------------------------------------------------- 1 | $$$ false 2 | >>>= 1 3 | 4 | # no comment at begin of file because they are currently not parsed because of shared input 5 | 6 | $$$ echo foo 7 | >>> 8 | foo 9 | 10 | $$$ cat --unknown-option 11 | >>>2 /option/ 12 | >>>= 1 13 | 14 | # comment at end of file 15 | -------------------------------------------------------------------------------- /tests/format2/indented-input.test: -------------------------------------------------------------------------------- 1 | # indented input should not break the parser 2 | x 3 | $$$ cat 4 | >>> // -------------------------------------------------------------------------------- /tests/format2/just-a-comment.test: -------------------------------------------------------------------------------- 1 | # just a comment 2 | -------------------------------------------------------------------------------- /tests/format2/macros.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest -D{exe}=echo "-D{in}=My message" "-D{out}=My message" -D{doNotExist}=null tests/format2/abstract-test-with-macros 3 | >>>= 0 4 | -------------------------------------------------------------------------------- /tests/format2/no-input.test: -------------------------------------------------------------------------------- 1 | # test "mac will hang if input is specified and stdin is not read" fix 2 | dummy input 3 | $$$ echo 4 | >>> /( 5 | )|(.*ECHO is on.*)/ 6 | >>>= 0 7 | -------------------------------------------------------------------------------- /tests/format2/one-failing-test: -------------------------------------------------------------------------------- 1 | # Note that this file is called from 'failure-line.test' 2 | # This should be fine. 3 | $$$ echo "plahh" 4 | >>> /plahh/ 5 | >>>= 0 6 | 7 | # This should be broken. 8 | $$$ echo "plahh" 9 | >>> /slahh/ 10 | >>>= 0 11 | 12 | # This should be fine. 13 | $$$ echo "plahh" 14 | >>> /plahh/ 15 | >>>= 0 -------------------------------------------------------------------------------- /tests/format2/parsing.test: -------------------------------------------------------------------------------- 1 | # misc. testfile parsing tests 2 | # 1. can we regexp-match a forward slash ? 3 | $$$ echo / 4 | >>> /\// 5 | 6 | # 2. can we handle an empty regexp ? 7 | $$$ echo 8 | >>> // 9 | 10 | # 3. or a regexp followed by a comment ? 11 | $$$ echo 12 | >>> // # comment 13 | -------------------------------------------------------------------------------- /tests/format2/regexps.test: -------------------------------------------------------------------------------- 1 | # simple regexp 2 | $$$ echo test 3 | >>> /^test$/ 4 | 5 | # negative regexp 6 | $$$ echo test 7 | >>> !/toast/ 8 | 9 | # large regexp 10 | # pcre-light handles regexps up to about 32764 chars, any larger gives a runtime error 11 | #>>> /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 12 | # regex-tdfa memory usage blows up.. I fear to use anything more than 250 chars 13 | $$$ ghc -ignore-dot-ghci -e "putStr $ replicate 33000 'a'" 14 | >>> /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 15 | 16 | # regexp containing quoted / 17 | $$$ echo 2015/1/1 18 | >>> /2015\/1\/1/ 19 | -------------------------------------------------------------------------------- /tests/format2/trailing-comment-no-newline.test: -------------------------------------------------------------------------------- 1 | $$$ echo 2 | >>> /( 3 | )|(.*ECHO is on.*)/ 4 | >>>= 0 5 | # comment -------------------------------------------------------------------------------- /tests/format3.unix/empty-unix.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | $ shelltest /dev/null 3 | > /Total +0/ 4 | 5 | -------------------------------------------------------------------------------- /tests/format3.unix/no-eol-unix.test: -------------------------------------------------------------------------------- 1 | # test output which does not end with a newline 2 | < 3 | $ cat 4 | > /^$/ 5 | -------------------------------------------------------------------------------- /tests/format3.unix/unicode-unix.test: -------------------------------------------------------------------------------- 1 | # 0. utf8-encoded unicode in filename should be fine 2 | # XXX file renamed from unicode-ß-unix.test to appease hackage (non-utf8-encoded ?) 3 | # 4 | # 1. in command field: 5 | $ echo проверка 6 | > // 7 | 8 | # 2. in output field: 9 | $ echo проверка 10 | проверка 11 | 12 | # 3. in regexp: 13 | $ echo проверка 14 | > /проверка/ 15 | 16 | -------------------------------------------------------------------------------- /tests/format3.windows/empty-windows.test: -------------------------------------------------------------------------------- 1 | # handle a totally empty test file 2 | $ shelltest NUL: 3 | > /Total +0/ 4 | -------------------------------------------------------------------------------- /tests/format3/abstract-test-with-macros: -------------------------------------------------------------------------------- 1 | # 1 Abstract test with unresolved macros. Test is run by macros.test. 2 | $ {exe} {in} 3 | > /{out}/ 4 | >= 0 5 | 6 | -------------------------------------------------------------------------------- /tests/format3/args.test: -------------------------------------------------------------------------------- 1 | # test with various arguments 2 | 3 | # 1. with no args, should run all tests below current dir 4 | $ shelltest 5 | > /Please specify at least one test file or directory/ 6 | >= !0 7 | 8 | # 2. XXX a bad executable should error without running tests 9 | #$ shelltest --with nosuchexe 10 | #> /Total +0/ 11 | 12 | # 3. a bad executable with testfiles should fail 13 | $ shelltest --with nosuchexe tests/format2/args.test 14 | > /user error/ 15 | >= 1 16 | 17 | # 4. a bad testfile should fail 18 | $ shelltest --with cat nosuchtestfile 19 | >2 /No such file/ 20 | >= 1 21 | 22 | # a final comment -------------------------------------------------------------------------------- /tests/format3/failure-line.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest tests/format1/one-failing-test 3 | >>> /.*Command [(]at line 8[)].* 4 | .*plahh.* 5 | .*Expected stdout.* 6 | .*slahh.* 7 | .*Got stdout.* 8 | .*plahh.*/ 9 | >>>= 1 10 | -------------------------------------------------------------------------------- /tests/format3/format3.test: -------------------------------------------------------------------------------- 1 | # File format 2b - same as format 2, but with short delimiters. 2 | 3 | AA 4 | $ cat 5 | AA 6 | 7 | # test 2 8 | $ cat 9 | > /A/ 10 | >2 11 | >= 0 12 | 13 | # test 3 14 | < 15 | A 16 | $ cat 17 | > /A/ 18 | >2 19 | >= 20 | 21 | # 22 | -------------------------------------------------------------------------------- /tests/format3/help.test: -------------------------------------------------------------------------------- 1 | # with --help, output should contain usage 2 | # and exit code should be 0 3 | $ shelltest --help 4 | > /Common flags:/ 5 | 6 | -------------------------------------------------------------------------------- /tests/format3/ideal.test: -------------------------------------------------------------------------------- 1 | $ false 2 | >= 1 3 | 4 | # no comment is allowed at start of file, because of the first input's < delimiter being optional. 5 | 6 | $ echo foo 7 | foo 8 | 9 | $ cat --unknown-option 10 | >2 /option/ 11 | >= 1 12 | 13 | # slashes in a regexp matcher must be backslash-escaped 14 | $ echo 2000/1/2 15 | > /2000\/1\/2/ 16 | 17 | # comment at end of file 18 | -------------------------------------------------------------------------------- /tests/format3/indented-input.test: -------------------------------------------------------------------------------- 1 | # indented input should not break the parser 2 | x 3 | $ cat 4 | > // -------------------------------------------------------------------------------- /tests/format3/just-a-comment.test: -------------------------------------------------------------------------------- 1 | # just a comment 2 | -------------------------------------------------------------------------------- /tests/format3/macros.test: -------------------------------------------------------------------------------- 1 | # 1. Test if macros are replaced and tests are successful. 2 | shelltest -D{exe}=echo "-D{in}=My message" "-D{out}=My message" -D{doNotExist}=null tests/format3/abstract-test-with-macros 3 | >>>= 0 4 | -------------------------------------------------------------------------------- /tests/format3/no-input.test: -------------------------------------------------------------------------------- 1 | # test "mac will hang if input is specified and stdin is not read" fix 2 | dummy input 3 | $ echo 4 | > /( 5 | )|(.*ECHO is on.*)/ 6 | >= 0 7 | -------------------------------------------------------------------------------- /tests/format3/one-failing-test: -------------------------------------------------------------------------------- 1 | # Note that this file is called from 'failure-line.test' 2 | # This should be fine. 3 | $ echo "plahh" 4 | > /plahh/ 5 | >= 0 6 | 7 | # This should be broken. 8 | $ echo "plahh" 9 | > /slahh/ 10 | >= 0 11 | 12 | # This should be fine. 13 | $ echo "plahh" 14 | > /plahh/ 15 | >= 0 -------------------------------------------------------------------------------- /tests/format3/parsing.test: -------------------------------------------------------------------------------- 1 | # misc. testfile parsing tests 2 | # 1. can we regexp-match a forward slash ? 3 | $ echo / 4 | > /\// 5 | 6 | # 2. can we handle an empty regexp ? 7 | $ echo 8 | > // 9 | 10 | # 3. or a regexp followed by a comment ? 11 | $ echo 12 | > // # comment 13 | -------------------------------------------------------------------------------- /tests/format3/regexps.test: -------------------------------------------------------------------------------- 1 | # simple regexp 2 | $ echo test 3 | > /^test$/ 4 | 5 | # negative regexp 6 | $ echo test 7 | > !/toast/ 8 | 9 | # large regexp 10 | # pcre-light handles regexps up to about 32764 chars, any larger gives a runtime error 11 | #> /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 12 | # regex-tdfa memory usage blows up.. I fear to use anything more than 250 chars 13 | $ ghc -ignore-dot-ghci -e "putStr $ replicate 33000 'a'" 14 | > /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/ 15 | 16 | # regexp containing quoted / 17 | $ echo 2015/1/1 18 | > /2015\/1\/1/ 19 | -------------------------------------------------------------------------------- /tests/format3/trailing-comment-no-newline.test: -------------------------------------------------------------------------------- 1 | $ echo 2 | > /( 3 | )|(.*ECHO is on.*)/ 4 | >= 0 5 | # comment -------------------------------------------------------------------------------- /tests/print/print-format1.test: -------------------------------------------------------------------------------- 1 | 2 | $ shelltest --print=v1 tests/format1/abstract-test-with-macros | diff -u - tests/format1/abstract-test-with-macros 3 | -------------------------------------------------------------------------------- /tests/print/print-format2.test: -------------------------------------------------------------------------------- 1 | 2 | $ shelltest --print=v2 tests/format2/ideal.test | diff -u - tests/format2/ideal.test 3 | -------------------------------------------------------------------------------- /tests/print/print-format3.test: -------------------------------------------------------------------------------- 1 | 2 | $ shelltest --print=v3 tests/format3/ideal.test | diff -u - tests/format3/ideal.test 3 | 4 | $ shelltest --print tests/format3/ideal.test | diff -u - tests/format3/ideal.test 5 | --------------------------------------------------------------------------------