trackler 2.2.1.40 → 2.2.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/dot-dsl/metadata.yml +1 -0
- data/problem-specifications/exercises/etl/metadata.yml +1 -0
- data/problem-specifications/exercises/isogram/canonical-data.json +3 -3
- data/problem-specifications/exercises/ocr-numbers/metadata.yml +1 -0
- data/problem-specifications/exercises/pascals-triangle/metadata.yml +1 -0
- data/problem-specifications/exercises/pov/metadata.yml +1 -0
- data/problem-specifications/exercises/rna-transcription/metadata.yml +1 -0
- data/problem-specifications/exercises/sgf-parsing/metadata.yml +1 -0
- data/tracks/c/exercises/all-your-base/src/example.c +14 -14
- data/tracks/c/exercises/all-your-base/src/example.h +2 -2
- data/tracks/ceylon/exercises/hamming/source/hamming/HammingTest.ceylon +1 -1
- data/tracks/ceylon/exercises/rna-transcription/source/rnatranscription/{RNAtest.ceylon → RNATest.ceylon} +0 -0
- data/tracks/cfml/.git +1 -0
- data/tracks/cfml/.gitignore +5 -0
- data/tracks/cfml/.travis.yml +18 -0
- data/tracks/cfml/CONTRIBUTING.md +10 -0
- data/tracks/cfml/LICENSE +21 -0
- data/tracks/cfml/README.md +92 -0
- data/tracks/cfml/bin/fetch-configlet +32 -0
- data/tracks/cfml/config/exercise_readme.go.tmpl +16 -0
- data/tracks/cfml/config/maintainers.json +13 -0
- data/tracks/cfml/config.json +223 -0
- data/tracks/cfml/docs/ABOUT.md +10 -0
- data/tracks/cfml/docs/EXERCISE_README_INSERT.md +15 -0
- data/tracks/cfml/docs/INSTALLATION.md +35 -0
- data/tracks/cfml/docs/LEARNING.md +37 -0
- data/tracks/cfml/docs/RESOURCES.md +29 -0
- data/tracks/cfml/docs/SNIPPET.txt +8 -0
- data/tracks/cfml/docs/TESTS.md +13 -0
- data/tracks/cfml/exercises/acronym/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/acronym/Acronym.cfc +13 -0
- data/tracks/cfml/exercises/acronym/AcronymTest.cfc +43 -0
- data/tracks/cfml/exercises/acronym/Solution.cfc +22 -0
- data/tracks/cfml/exercises/acronym/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/acronym/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/acronym/box.json +8 -0
- data/tracks/cfml/exercises/acronym/index.cfm +37 -0
- data/tracks/cfml/exercises/atbash-cipher/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/atbash-cipher/AtbashCipher.cfc +14 -0
- data/tracks/cfml/exercises/atbash-cipher/AtbashCipherTest.cfc +71 -0
- data/tracks/cfml/exercises/atbash-cipher/Solution.cfc +56 -0
- data/tracks/cfml/exercises/atbash-cipher/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/atbash-cipher/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/atbash-cipher/box.json +8 -0
- data/tracks/cfml/exercises/atbash-cipher/index.cfm +37 -0
- data/tracks/cfml/exercises/bob/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/bob/Bob.cfc +13 -0
- data/tracks/cfml/exercises/bob/BobTest.cfc +115 -0
- data/tracks/cfml/exercises/bob/Solution.cfc +27 -0
- data/tracks/cfml/exercises/bob/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/bob/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/bob/box.json +8 -0
- data/tracks/cfml/exercises/bob/index.cfm +37 -0
- data/tracks/cfml/exercises/diamond/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/diamond/Diamond.cfc +13 -0
- data/tracks/cfml/exercises/diamond/DiamondTest.cfc +35 -0
- data/tracks/cfml/exercises/diamond/Solution.cfc +35 -0
- data/tracks/cfml/exercises/diamond/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/diamond/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/diamond/box.json +8 -0
- data/tracks/cfml/exercises/diamond/index.cfm +37 -0
- data/tracks/cfml/exercises/difference-of-squares/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquares.cfc +18 -0
- data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquaresTest.cfc +63 -0
- data/tracks/cfml/exercises/difference-of-squares/Solution.cfc +28 -0
- data/tracks/cfml/exercises/difference-of-squares/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/difference-of-squares/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/difference-of-squares/box.json +8 -0
- data/tracks/cfml/exercises/difference-of-squares/index.cfm +37 -0
- data/tracks/cfml/exercises/flatten-array/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/flatten-array/FlattenArray.cfc +13 -0
- data/tracks/cfml/exercises/flatten-array/FlattenArrayTest.cfc +42 -0
- data/tracks/cfml/exercises/flatten-array/Solution.cfc +26 -0
- data/tracks/cfml/exercises/flatten-array/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/flatten-array/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/flatten-array/box.json +8 -0
- data/tracks/cfml/exercises/flatten-array/index.cfm +37 -0
- data/tracks/cfml/exercises/gigasecond/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/gigasecond/Gigasecond.cfc +13 -0
- data/tracks/cfml/exercises/gigasecond/GigasecondTest.cfc +39 -0
- data/tracks/cfml/exercises/gigasecond/Solution.cfc +16 -0
- data/tracks/cfml/exercises/gigasecond/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/gigasecond/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/gigasecond/box.json +8 -0
- data/tracks/cfml/exercises/gigasecond/index.cfm +37 -0
- data/tracks/cfml/exercises/grains/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/grains/Grains.cfc +14 -0
- data/tracks/cfml/exercises/grains/GrainsTest.cfc +63 -0
- data/tracks/cfml/exercises/grains/Solution.cfc +22 -0
- data/tracks/cfml/exercises/grains/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/grains/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/grains/box.json +8 -0
- data/tracks/cfml/exercises/grains/index.cfm +37 -0
- data/tracks/cfml/exercises/hamming/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/hamming/Hamming.cfc +13 -0
- data/tracks/cfml/exercises/hamming/HammingTest.cfc +75 -0
- data/tracks/cfml/exercises/hamming/Solution.cfc +25 -0
- data/tracks/cfml/exercises/hamming/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/hamming/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/hamming/box.json +8 -0
- data/tracks/cfml/exercises/hamming/index.cfm +37 -0
- data/tracks/cfml/exercises/hello-world/HelloWorld.cfc +13 -0
- data/tracks/cfml/exercises/hello-world/HelloWorldTest.cfc +18 -0
- data/tracks/cfml/exercises/hello-world/Solution.cfc +13 -0
- data/tracks/cfml/exercises/hello-world/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/hello-world/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/hello-world/box.json +8 -0
- data/tracks/cfml/exercises/hello-world/index.cfm +37 -0
- data/tracks/cfml/exercises/isogram/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/isogram/Isogram.cfc +13 -0
- data/tracks/cfml/exercises/isogram/IsogramTest.cfc +55 -0
- data/tracks/cfml/exercises/isogram/Solution.cfc +23 -0
- data/tracks/cfml/exercises/isogram/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/isogram/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/isogram/box.json +8 -0
- data/tracks/cfml/exercises/isogram/index.cfm +37 -0
- data/tracks/cfml/exercises/largest-series-product/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/largest-series-product/LargestSeriesProduct.cfc +13 -0
- data/tracks/cfml/exercises/largest-series-product/LargestSeriesProductTest.cfc +75 -0
- data/tracks/cfml/exercises/largest-series-product/Solution.cfc +41 -0
- data/tracks/cfml/exercises/largest-series-product/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/largest-series-product/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/largest-series-product/box.json +8 -0
- data/tracks/cfml/exercises/largest-series-product/index.cfm +37 -0
- data/tracks/cfml/exercises/leap/Leap.cfc +15 -0
- data/tracks/cfml/exercises/leap/LeapTest.cfc +39 -0
- data/tracks/cfml/exercises/leap/README.md +33 -0
- data/tracks/cfml/exercises/leap/Solution.cfc +19 -0
- data/tracks/cfml/exercises/leap/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/leap/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/leap/box.json +8 -0
- data/tracks/cfml/exercises/leap/index.cfm +37 -0
- data/tracks/cfml/exercises/luhn/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/luhn/Luhn.cfc +13 -0
- data/tracks/cfml/exercises/luhn/LuhnTest.cfc +67 -0
- data/tracks/cfml/exercises/luhn/Solution.cfc +38 -0
- data/tracks/cfml/exercises/luhn/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/luhn/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/luhn/box.json +8 -0
- data/tracks/cfml/exercises/luhn/index.cfm +37 -0
- data/tracks/cfml/exercises/nth-prime/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/nth-prime/NthPrime.cfc +13 -0
- data/tracks/cfml/exercises/nth-prime/NthPrimeTest.cfc +35 -0
- data/tracks/cfml/exercises/nth-prime/Solution.cfc +33 -0
- data/tracks/cfml/exercises/nth-prime/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/nth-prime/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/nth-prime/box.json +8 -0
- data/tracks/cfml/exercises/nth-prime/index.cfm +37 -0
- data/tracks/cfml/exercises/pangram/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/pangram/Pangram.cfc +13 -0
- data/tracks/cfml/exercises/pangram/PangramTest.cfc +55 -0
- data/tracks/cfml/exercises/pangram/Solution.cfc +21 -0
- data/tracks/cfml/exercises/pangram/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/pangram/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/pangram/box.json +8 -0
- data/tracks/cfml/exercises/pangram/index.cfm +37 -0
- data/tracks/cfml/exercises/pig-latin/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/pig-latin/PigLatin.cfc +13 -0
- data/tracks/cfml/exercises/pig-latin/PigLatinTest.cfc +115 -0
- data/tracks/cfml/exercises/pig-latin/Solution.cfc +30 -0
- data/tracks/cfml/exercises/pig-latin/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/pig-latin/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/pig-latin/box.json +8 -0
- data/tracks/cfml/exercises/pig-latin/index.cfm +37 -0
- data/tracks/cfml/exercises/raindrops/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/raindrops/Raindrops.cfc +13 -0
- data/tracks/cfml/exercises/raindrops/RaindropsTest.cfc +87 -0
- data/tracks/cfml/exercises/raindrops/Solution.cfc +33 -0
- data/tracks/cfml/exercises/raindrops/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/raindrops/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/raindrops/box.json +8 -0
- data/tracks/cfml/exercises/raindrops/index.cfm +37 -0
- data/tracks/cfml/exercises/rna-transcription/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/rna-transcription/RnaTranscription.cfc +13 -0
- data/tracks/cfml/exercises/rna-transcription/RnaTranscriptionTest.cfc +47 -0
- data/tracks/cfml/exercises/rna-transcription/Solution.cfc +35 -0
- data/tracks/cfml/exercises/rna-transcription/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/rna-transcription/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/rna-transcription/box.json +8 -0
- data/tracks/cfml/exercises/rna-transcription/index.cfm +37 -0
- data/tracks/cfml/exercises/saddle-points/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/saddle-points/SaddlePoints.cfc +13 -0
- data/tracks/cfml/exercises/saddle-points/SaddlePointsTest.cfc +35 -0
- data/tracks/cfml/exercises/saddle-points/Solution.cfc +59 -0
- data/tracks/cfml/exercises/saddle-points/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/saddle-points/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/saddle-points/box.json +8 -0
- data/tracks/cfml/exercises/saddle-points/index.cfm +37 -0
- data/tracks/cfml/exercises/scrabble-score/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/scrabble-score/ScrabbleScore.cfc +13 -0
- data/tracks/cfml/exercises/scrabble-score/ScrabbleScoreTest.cfc +59 -0
- data/tracks/cfml/exercises/scrabble-score/Solution.cfc +50 -0
- data/tracks/cfml/exercises/scrabble-score/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/scrabble-score/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/scrabble-score/box.json +8 -0
- data/tracks/cfml/exercises/scrabble-score/index.cfm +37 -0
- data/tracks/cfml/exercises/secret-handshake/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/secret-handshake/SecretHandshake.cfc +13 -0
- data/tracks/cfml/exercises/secret-handshake/SecretHandshakeTest.cfc +63 -0
- data/tracks/cfml/exercises/secret-handshake/Solution.cfc +31 -0
- data/tracks/cfml/exercises/secret-handshake/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/secret-handshake/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/secret-handshake/box.json +8 -0
- data/tracks/cfml/exercises/secret-handshake/index.cfm +37 -0
- data/tracks/cfml/exercises/space-age/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/space-age/Solution.cfc +28 -0
- data/tracks/cfml/exercises/space-age/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/space-age/SpaceAge.cfc +13 -0
- data/tracks/cfml/exercises/space-age/SpaceAgeTest.cfc +47 -0
- data/tracks/cfml/exercises/space-age/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/space-age/box.json +8 -0
- data/tracks/cfml/exercises/space-age/index.cfm +37 -0
- data/tracks/cfml/exercises/sum-of-multiples/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/sum-of-multiples/Solution.cfc +27 -0
- data/tracks/cfml/exercises/sum-of-multiples/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiples.cfc +13 -0
- data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiplesTest.cfc +63 -0
- data/tracks/cfml/exercises/sum-of-multiples/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/sum-of-multiples/box.json +8 -0
- data/tracks/cfml/exercises/sum-of-multiples/index.cfm +37 -0
- data/tracks/cfml/exercises/triangle/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/triangle/Solution.cfc +53 -0
- data/tracks/cfml/exercises/triangle/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/triangle/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/triangle/Triangle.cfc +18 -0
- data/tracks/cfml/exercises/triangle/TriangleTest.cfc +95 -0
- data/tracks/cfml/exercises/triangle/box.json +8 -0
- data/tracks/cfml/exercises/triangle/index.cfm +37 -0
- data/tracks/cfml/exercises/word-count/.meta/HINTS.md +0 -0
- data/tracks/cfml/exercises/word-count/Solution.cfc +22 -0
- data/tracks/cfml/exercises/word-count/SolutionTest.cfc +7 -0
- data/tracks/cfml/exercises/word-count/TestRunner.cfc +103 -0
- data/tracks/cfml/exercises/word-count/WordCount.cfc +13 -0
- data/tracks/cfml/exercises/word-count/WordCountTest.cfc +55 -0
- data/tracks/cfml/exercises/word-count/box.json +8 -0
- data/tracks/cfml/exercises/word-count/index.cfm +37 -0
- data/tracks/cfml/img/icon.png +0 -0
- data/tracks/cfml/tasks/GenerateTests.cfc +179 -0
- data/tracks/cfml/tasks/ScaffoldExercise.cfc +85 -0
- data/tracks/cfml/tasks/TestAllSolutions.cfc +24 -0
- data/tracks/cfml/tasks/exercise_template/.meta/HINTS.md +0 -0
- data/tracks/cfml/tasks/exercise_template/@@name@@.cfc +13 -0
- data/tracks/cfml/tasks/exercise_template/@@name@@Test.cfc +15 -0
- data/tracks/cfml/tasks/exercise_template/Solution.cfc +6 -0
- data/tracks/cfml/tasks/exercise_template/SolutionTest.cfc +7 -0
- data/tracks/cfml/tasks/exercise_template/TestRunner.cfc +103 -0
- data/tracks/cfml/tasks/exercise_template/box.json +8 -0
- data/tracks/cfml/tasks/exercise_template/index.cfm +37 -0
- data/tracks/coldfusion/docs/ABOUT.md +8 -6
- data/tracks/csharp/docs/GENERATORS.md +7 -0
- data/tracks/csharp/exercises/clock/ClockTest.cs +15 -15
- data/tracks/csharp/exercises/nucleotide-count/Example.cs +10 -11
- data/tracks/csharp/exercises/nucleotide-count/NucleotideCount.cs +2 -7
- data/tracks/csharp/exercises/nucleotide-count/NucleotideCountTest.cs +37 -47
- data/tracks/csharp/exercises/pig-latin/Example.cs +1 -1
- data/tracks/csharp/exercises/pig-latin/PigLatinTest.cs +19 -7
- data/tracks/csharp/exercises/sum-of-multiples/SumOfMultiplesTest.cs +7 -1
- data/tracks/csharp/exercises/tournament/Example.cs +1 -1
- data/tracks/csharp/exercises/tournament/TournamentTest.cs +151 -68
- data/tracks/csharp/exercises/triangle/Example.cs +26 -8
- data/tracks/csharp/exercises/triangle/Triangle.cs +16 -1
- data/tracks/csharp/exercises/triangle/TriangleTest.cs +44 -30
- data/tracks/csharp/generators/Exercise.cs +6 -1
- data/tracks/csharp/generators/Exercises/Clock.cs +17 -1
- data/tracks/csharp/generators/Exercises/NucleotideCount.cs +61 -0
- data/tracks/csharp/generators/Exercises/Tournament.cs +66 -0
- data/tracks/csharp/generators/Exercises/Triangle.cs +36 -0
- data/tracks/dart/config.json +15 -2
- data/tracks/dart/exercises/raindrops/lib/example.dart +23 -0
- data/tracks/dart/exercises/raindrops/lib/raindrops.dart +3 -0
- data/tracks/dart/exercises/raindrops/pubspec.lock +281 -0
- data/tracks/dart/exercises/raindrops/pubspec.yaml +3 -0
- data/tracks/dart/exercises/raindrops/test/raindrops_test.dart +94 -0
- data/tracks/delphi/exercises/pig-latin/uPigLatinExample.pas +1 -25
- data/tracks/haskell/config.json +9 -0
- data/tracks/haskell/exercises/acronym/README.md +0 -1
- data/tracks/haskell/exercises/all-your-base/README.md +1 -1
- data/tracks/haskell/exercises/allergies/README.md +0 -1
- data/tracks/haskell/exercises/alphametics/README.md +2 -2
- data/tracks/haskell/exercises/atbash-cipher/README.md +2 -1
- data/tracks/haskell/exercises/beer-song/README.md +1 -1
- data/tracks/haskell/exercises/binary/README.md +2 -0
- data/tracks/haskell/exercises/bowling/README.md +20 -6
- data/tracks/haskell/exercises/collatz-conjecture/README.md +1 -1
- data/tracks/haskell/exercises/connect/README.md +1 -1
- data/tracks/haskell/exercises/crypto-square/README.md +4 -4
- data/tracks/haskell/exercises/diamond/README.md +113 -0
- data/tracks/haskell/exercises/diamond/examples/success-standard/package.yaml +16 -0
- data/tracks/haskell/exercises/diamond/examples/success-standard/src/Diamond.hs +16 -0
- data/tracks/haskell/exercises/diamond/package.yaml +20 -0
- data/tracks/haskell/exercises/diamond/src/Diamond.hs +4 -0
- data/tracks/haskell/exercises/diamond/stack.yaml +1 -0
- data/tracks/haskell/exercises/diamond/test/Tests.hs +109 -0
- data/tracks/haskell/exercises/etl/README.md +3 -1
- data/tracks/haskell/exercises/food-chain/README.md +1 -1
- data/tracks/haskell/exercises/go-counting/README.md +1 -1
- data/tracks/haskell/exercises/grade-school/README.md +0 -1
- data/tracks/haskell/exercises/grains/README.md +0 -1
- data/tracks/haskell/exercises/house/README.md +1 -2
- data/tracks/haskell/exercises/isogram/README.md +2 -1
- data/tracks/haskell/exercises/kindergarten-garden/README.md +3 -3
- data/tracks/haskell/exercises/leap/README.md +1 -1
- data/tracks/haskell/exercises/linked-list/README.md +10 -10
- data/tracks/haskell/exercises/luhn/README.md +7 -7
- data/tracks/haskell/exercises/matrix/README.md +6 -4
- data/tracks/haskell/exercises/meetup/README.md +1 -2
- data/tracks/haskell/exercises/nucleotide-count/README.md +8 -22
- data/tracks/haskell/exercises/ocr-numbers/README.md +6 -6
- data/tracks/haskell/exercises/octal/README.md +6 -2
- data/tracks/haskell/exercises/palindrome-products/README.md +12 -6
- data/tracks/haskell/exercises/pangram/README.md +1 -1
- data/tracks/haskell/exercises/pascals-triangle/README.md +2 -2
- data/tracks/haskell/exercises/phone-number/README.md +3 -2
- data/tracks/haskell/exercises/pov/README.md +3 -3
- data/tracks/haskell/exercises/pythagorean-triplet/README.md +3 -3
- data/tracks/haskell/exercises/queen-attack/README.md +1 -1
- data/tracks/haskell/exercises/rna-transcription/README.md +1 -1
- data/tracks/haskell/exercises/roman-numerals/README.md +1 -1
- data/tracks/haskell/exercises/run-length-encoding/README.md +4 -4
- data/tracks/haskell/exercises/saddle-points/README.md +1 -1
- data/tracks/haskell/exercises/scrabble-score/README.md +3 -1
- data/tracks/haskell/exercises/secret-handshake/README.md +1 -1
- data/tracks/haskell/exercises/sgf-parsing/README.md +4 -4
- data/tracks/haskell/exercises/simple-cipher/README.md +1 -1
- data/tracks/haskell/exercises/spiral-matrix/README.md +2 -2
- data/tracks/haskell/exercises/triangle/README.md +9 -6
- data/tracks/haskell/exercises/trinary/README.md +1 -1
- data/tracks/haskell/exercises/word-count/README.md +1 -2
- data/tracks/haskell/exercises/wordy/README.md +0 -5
- data/tracks/java/config.json +56 -9
- data/tracks/java/exercises/binary-search-tree/src/test/java/BSTTest.java +4 -4
- data/tracks/javascript/exercises/two-bucket/example.js +66 -69
- data/tracks/javascript/exercises/two-bucket/two-bucket.spec.js +18 -18
- data/tracks/julia/config.json +1 -0
- data/tracks/julia/docs/ABOUT.md +3 -8
- data/tracks/prolog/README.md +1 -1
- data/tracks/purescript/.travis.yml +1 -0
- data/tracks/purescript/README.md +9 -0
- data/tracks/purescript/bin/check-bower.sh +42 -0
- data/tracks/purescript/bin/test-separate.sh +46 -0
- data/tracks/python/README.md +2 -2
- data/tracks/python/exercises/all-your-base/all_your_base.py +2 -0
- data/tracks/python/exercises/atbash-cipher/atbash_cipher.py +2 -2
- data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +2 -2
- data/tracks/python/exercises/complex-numbers/example.py +2 -2
- data/tracks/python/exercises/gigasecond/gigasecond.py +1 -1
- data/tracks/python/exercises/hamming/hamming.py +1 -1
- data/tracks/python/exercises/hexadecimal/hexadecimal.py +1 -1
- data/tracks/python/exercises/leap/leap.py +1 -1
- data/tracks/python/exercises/meetup/meetup.py +1 -1
- data/tracks/python/exercises/phone-number/example.py +4 -2
- data/tracks/python/exercises/phone-number/phone_number_test.py +47 -16
- data/tracks/python/exercises/pig-latin/pig_latin.py +1 -1
- data/tracks/python/exercises/scrabble-score/scrabble_score.py +1 -1
- data/tracks/python/exercises/wordy/wordy.py +1 -1
- data/tracks/scala/exercises/meetup/example.scala +29 -10
- data/tracks/scala/exercises/meetup/src/main/scala/Meetup.scala +23 -0
- data/tracks/scala/exercises/meetup/src/test/scala/MeetupTest.scala +273 -183
- data/tracks/sml/config.json +13 -0
- data/tracks/sml/exercises/anagram/README.md +21 -5
- data/tracks/sml/exercises/anagram/anagram.sml +2 -6
- data/tracks/sml/exercises/anagram/example.sml +29 -24
- data/tracks/sml/exercises/anagram/test.sml +56 -50
- data/tracks/sml/exercises/anagram/testlib.sml +159 -0
- data/tracks/sml/exercises/diamond/README.md +89 -0
- data/tracks/sml/exercises/diamond/diamond.sml +2 -0
- data/tracks/sml/exercises/diamond/example.sml +25 -0
- data/tracks/sml/exercises/diamond/test.sml +27 -0
- data/tracks/sml/exercises/diamond/testlib.sml +159 -0
- data/tracks/sml/exercises/raindrops/raindrops.sml +2 -2
- data/tracks/sml/exercises/raindrops/test.sml +66 -95
- data/tracks/sml/exercises/raindrops/testlib.sml +159 -0
- metadata +265 -3
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
structure Expect =
|
|
2
|
+
struct
|
|
3
|
+
datatype expectation = Pass | Fail of string * string
|
|
4
|
+
|
|
5
|
+
local
|
|
6
|
+
fun failEq b a =
|
|
7
|
+
Fail ("Expected: " ^ b, "Got: " ^ a)
|
|
8
|
+
|
|
9
|
+
fun failExn b a =
|
|
10
|
+
Fail ("Expected: " ^ b, "Raised: " ^ a)
|
|
11
|
+
|
|
12
|
+
fun exnName (e: exn): string = General.exnName e
|
|
13
|
+
in
|
|
14
|
+
fun truthy a =
|
|
15
|
+
if a
|
|
16
|
+
then Pass
|
|
17
|
+
else failEq "true" "false"
|
|
18
|
+
|
|
19
|
+
fun falsy a =
|
|
20
|
+
if a
|
|
21
|
+
then failEq "false" "true"
|
|
22
|
+
else Pass
|
|
23
|
+
|
|
24
|
+
fun equalTo b a =
|
|
25
|
+
if a = b
|
|
26
|
+
then Pass
|
|
27
|
+
else failEq (PolyML.makestring b) (PolyML.makestring a)
|
|
28
|
+
|
|
29
|
+
fun nearTo b a =
|
|
30
|
+
if Real.== (a, b)
|
|
31
|
+
then Pass
|
|
32
|
+
else failEq (Real.toString b) (Real.toString a)
|
|
33
|
+
|
|
34
|
+
fun anyError f =
|
|
35
|
+
(
|
|
36
|
+
f ();
|
|
37
|
+
failExn "an exception" "Nothing"
|
|
38
|
+
) handle _ => Pass
|
|
39
|
+
|
|
40
|
+
fun error e f =
|
|
41
|
+
(
|
|
42
|
+
f ();
|
|
43
|
+
failExn (exnName e) "Nothing"
|
|
44
|
+
) handle e' => if exnMessage e' = exnMessage e
|
|
45
|
+
then Pass
|
|
46
|
+
else failExn (exnMessage e) (exnMessage e')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
structure TermColor =
|
|
51
|
+
struct
|
|
52
|
+
datatype color = Red | Green | Yellow | Normal
|
|
53
|
+
|
|
54
|
+
fun f Red = "\027[31m"
|
|
55
|
+
| f Green = "\027[32m"
|
|
56
|
+
| f Yellow = "\027[33m"
|
|
57
|
+
| f Normal = "\027[0m"
|
|
58
|
+
|
|
59
|
+
fun colorize color s = (f color) ^ s ^ (f Normal)
|
|
60
|
+
|
|
61
|
+
val redit = colorize Red
|
|
62
|
+
|
|
63
|
+
val greenit = colorize Green
|
|
64
|
+
|
|
65
|
+
val yellowit = colorize Yellow
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
structure Test =
|
|
69
|
+
struct
|
|
70
|
+
datatype testnode = TestGroup of string * testnode list
|
|
71
|
+
| Test of string * (unit -> Expect.expectation)
|
|
72
|
+
|
|
73
|
+
local
|
|
74
|
+
datatype evaluation = Success of string
|
|
75
|
+
| Failure of string * string * string
|
|
76
|
+
| Error of string * string
|
|
77
|
+
|
|
78
|
+
fun indent n s = (implode (List.tabulate (n, fn _ => #" "))) ^ s
|
|
79
|
+
|
|
80
|
+
fun fmt indentlvl ev =
|
|
81
|
+
let
|
|
82
|
+
val check = TermColor.greenit "\226\156\148 " (* ✔ *)
|
|
83
|
+
val cross = TermColor.redit "\226\156\150 " (* ✖ *)
|
|
84
|
+
val indentlvl = indentlvl * 2
|
|
85
|
+
in
|
|
86
|
+
case ev of
|
|
87
|
+
Success descr => indent indentlvl (check ^ descr)
|
|
88
|
+
| Failure (descr, exp, got) =>
|
|
89
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
90
|
+
indent (indentlvl + 2) exp,
|
|
91
|
+
indent (indentlvl + 2) got]
|
|
92
|
+
| Error (descr, reason) =>
|
|
93
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
94
|
+
indent (indentlvl + 2) (TermColor.redit reason)]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
fun eval (TestGroup _) = raise Fail "Only a 'Test' can be evaluated"
|
|
98
|
+
| eval (Test (descr, thunk)) =
|
|
99
|
+
(
|
|
100
|
+
case thunk () of
|
|
101
|
+
Expect.Pass => ((1, 0, 0), Success descr)
|
|
102
|
+
| Expect.Fail (s, s') => ((0, 1, 0), Failure (descr, s, s'))
|
|
103
|
+
)
|
|
104
|
+
handle e => ((0, 0, 1), Error (descr, "Unexpected error: " ^ exnMessage e))
|
|
105
|
+
|
|
106
|
+
fun flatten depth testnode =
|
|
107
|
+
let
|
|
108
|
+
fun sum (x, y, z) (a, b, c) = (x + a, y + b, z + c)
|
|
109
|
+
|
|
110
|
+
fun aux (t, (counter, acc)) =
|
|
111
|
+
let
|
|
112
|
+
val (counter', texts) = flatten (depth + 1) t
|
|
113
|
+
in
|
|
114
|
+
(sum counter' counter, texts :: acc)
|
|
115
|
+
end
|
|
116
|
+
in
|
|
117
|
+
case testnode of
|
|
118
|
+
TestGroup (descr, ts) =>
|
|
119
|
+
let
|
|
120
|
+
val (counter, texts) = foldr aux ((0, 0, 0), []) ts
|
|
121
|
+
in
|
|
122
|
+
(counter, (indent (depth * 2) descr) :: List.concat texts)
|
|
123
|
+
end
|
|
124
|
+
| Test _ =>
|
|
125
|
+
let
|
|
126
|
+
val (counter, evaluation) = eval testnode
|
|
127
|
+
in
|
|
128
|
+
(counter, [fmt depth evaluation])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
fun println s = print (s ^ "\n")
|
|
133
|
+
in
|
|
134
|
+
fun run suite =
|
|
135
|
+
let
|
|
136
|
+
val ((succeeded, failed, errored), texts) = flatten 0 suite
|
|
137
|
+
|
|
138
|
+
val summary = String.concatWith ", " [
|
|
139
|
+
TermColor.greenit ((Int.toString succeeded) ^ " passed"),
|
|
140
|
+
TermColor.redit ((Int.toString failed) ^ " failed"),
|
|
141
|
+
TermColor.redit ((Int.toString errored) ^ " errored"),
|
|
142
|
+
(Int.toString (succeeded + failed + errored)) ^ " total"
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
val status = if failed = 0 andalso errored = 0
|
|
146
|
+
then OS.Process.success
|
|
147
|
+
else OS.Process.failure
|
|
148
|
+
|
|
149
|
+
in
|
|
150
|
+
List.app println texts;
|
|
151
|
+
println "";
|
|
152
|
+
println ("Tests: " ^ summary);
|
|
153
|
+
OS.Process.exit status
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
fun describe description tests = Test.TestGroup (description, tests)
|
|
159
|
+
fun test description thunk = Test.Test (description, thunk)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
fun convert (
|
|
2
|
-
raise Fail "'convert' is not implemented"
|
|
1
|
+
fun convert (number: int): string =
|
|
2
|
+
raise Fail "'convert' is not implemented"
|
|
@@ -1,95 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
number = 105,
|
|
70
|
-
expected = "PlingPlangPlong"
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
number = 3125,
|
|
74
|
-
expected = "Plang"
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
fun run_tests _ [] = []
|
|
79
|
-
| run_tests f (x :: xs) =
|
|
80
|
-
let
|
|
81
|
-
fun aux { number, expected } =
|
|
82
|
-
let
|
|
83
|
-
val output = f number
|
|
84
|
-
val is_correct = output = expected
|
|
85
|
-
val expl =
|
|
86
|
-
"convert " ^ (Int.toString number) ^ ": " ^
|
|
87
|
-
(if not is_correct then "FAILED" else "PASSED") ^ "\n"
|
|
88
|
-
in
|
|
89
|
-
(print (expl); is_correct)
|
|
90
|
-
end
|
|
91
|
-
in
|
|
92
|
-
(aux x) :: run_tests f xs
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
val allTestsPass = List.all (fn x => x) (run_tests convert test_cases)
|
|
1
|
+
(* version 1.0.0 *)
|
|
2
|
+
|
|
3
|
+
use "testlib.sml";
|
|
4
|
+
use "raindrops.sml";
|
|
5
|
+
|
|
6
|
+
infixr |>
|
|
7
|
+
fun x |> f = f x
|
|
8
|
+
|
|
9
|
+
val testsuite =
|
|
10
|
+
describe "raindrops" [
|
|
11
|
+
test "the sound for 1 is 1"
|
|
12
|
+
(fn _ => convert (1) |> Expect.equalTo "1"),
|
|
13
|
+
|
|
14
|
+
test "the sound for 3 is Pling"
|
|
15
|
+
(fn _ => convert (3) |> Expect.equalTo "Pling"),
|
|
16
|
+
|
|
17
|
+
test "the sound for 5 is Plang"
|
|
18
|
+
(fn _ => convert (5) |> Expect.equalTo "Plang"),
|
|
19
|
+
|
|
20
|
+
test "the sound for 7 is Plong"
|
|
21
|
+
(fn _ => convert (7) |> Expect.equalTo "Plong"),
|
|
22
|
+
|
|
23
|
+
test "the sound for 6 is Pling as it has a factor 3"
|
|
24
|
+
(fn _ => convert (6) |> Expect.equalTo "Pling"),
|
|
25
|
+
|
|
26
|
+
test "2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base"
|
|
27
|
+
(fn _ => convert (8) |> Expect.equalTo "8"),
|
|
28
|
+
|
|
29
|
+
test "the sound for 9 is Pling as it has a factor 3"
|
|
30
|
+
(fn _ => convert (9) |> Expect.equalTo "Pling"),
|
|
31
|
+
|
|
32
|
+
test "the sound for 10 is Plang as it has a factor 5"
|
|
33
|
+
(fn _ => convert (10) |> Expect.equalTo "Plang"),
|
|
34
|
+
|
|
35
|
+
test "the sound for 14 is Plong as it has a factor of 7"
|
|
36
|
+
(fn _ => convert (14) |> Expect.equalTo "Plong"),
|
|
37
|
+
|
|
38
|
+
test "the sound for 15 is PlingPlang as it has factors 3 and 5"
|
|
39
|
+
(fn _ => convert (15) |> Expect.equalTo "PlingPlang"),
|
|
40
|
+
|
|
41
|
+
test "the sound for 21 is PlingPlong as it has factors 3 and 7"
|
|
42
|
+
(fn _ => convert (21) |> Expect.equalTo "PlingPlong"),
|
|
43
|
+
|
|
44
|
+
test "the sound for 25 is Plang as it has a factor 5"
|
|
45
|
+
(fn _ => convert (25) |> Expect.equalTo "Plang"),
|
|
46
|
+
|
|
47
|
+
test "the sound for 27 is Pling as it has a factor 3"
|
|
48
|
+
(fn _ => convert (27) |> Expect.equalTo "Pling"),
|
|
49
|
+
|
|
50
|
+
test "the sound for 35 is PlangPlong as it has factors 5 and 7"
|
|
51
|
+
(fn _ => convert (35) |> Expect.equalTo "PlangPlong"),
|
|
52
|
+
|
|
53
|
+
test "the sound for 49 is Plong as it has a factor 7"
|
|
54
|
+
(fn _ => convert (49) |> Expect.equalTo "Plong"),
|
|
55
|
+
|
|
56
|
+
test "the sound for 52 is 52"
|
|
57
|
+
(fn _ => convert (52) |> Expect.equalTo "52"),
|
|
58
|
+
|
|
59
|
+
test "the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7"
|
|
60
|
+
(fn _ => convert (105) |> Expect.equalTo "PlingPlangPlong"),
|
|
61
|
+
|
|
62
|
+
test "the sound for 3125 is Plang as it has a factor 5"
|
|
63
|
+
(fn _ => convert (3125) |> Expect.equalTo "Plang")
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
val _ = Test.run testsuite
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
structure Expect =
|
|
2
|
+
struct
|
|
3
|
+
datatype expectation = Pass | Fail of string * string
|
|
4
|
+
|
|
5
|
+
local
|
|
6
|
+
fun failEq b a =
|
|
7
|
+
Fail ("Expected: " ^ b, "Got: " ^ a)
|
|
8
|
+
|
|
9
|
+
fun failExn b a =
|
|
10
|
+
Fail ("Expected: " ^ b, "Raised: " ^ a)
|
|
11
|
+
|
|
12
|
+
fun exnName (e: exn): string = General.exnName e
|
|
13
|
+
in
|
|
14
|
+
fun truthy a =
|
|
15
|
+
if a
|
|
16
|
+
then Pass
|
|
17
|
+
else failEq "true" "false"
|
|
18
|
+
|
|
19
|
+
fun falsy a =
|
|
20
|
+
if a
|
|
21
|
+
then failEq "false" "true"
|
|
22
|
+
else Pass
|
|
23
|
+
|
|
24
|
+
fun equalTo b a =
|
|
25
|
+
if a = b
|
|
26
|
+
then Pass
|
|
27
|
+
else failEq (PolyML.makestring b) (PolyML.makestring a)
|
|
28
|
+
|
|
29
|
+
fun nearTo b a =
|
|
30
|
+
if Real.== (a, b)
|
|
31
|
+
then Pass
|
|
32
|
+
else failEq (Real.toString b) (Real.toString a)
|
|
33
|
+
|
|
34
|
+
fun anyError f =
|
|
35
|
+
(
|
|
36
|
+
f ();
|
|
37
|
+
failExn "an exception" "Nothing"
|
|
38
|
+
) handle _ => Pass
|
|
39
|
+
|
|
40
|
+
fun error e f =
|
|
41
|
+
(
|
|
42
|
+
f ();
|
|
43
|
+
failExn (exnName e) "Nothing"
|
|
44
|
+
) handle e' => if exnMessage e' = exnMessage e
|
|
45
|
+
then Pass
|
|
46
|
+
else failExn (exnMessage e) (exnMessage e')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
structure TermColor =
|
|
51
|
+
struct
|
|
52
|
+
datatype color = Red | Green | Yellow | Normal
|
|
53
|
+
|
|
54
|
+
fun f Red = "\027[31m"
|
|
55
|
+
| f Green = "\027[32m"
|
|
56
|
+
| f Yellow = "\027[33m"
|
|
57
|
+
| f Normal = "\027[0m"
|
|
58
|
+
|
|
59
|
+
fun colorize color s = (f color) ^ s ^ (f Normal)
|
|
60
|
+
|
|
61
|
+
val redit = colorize Red
|
|
62
|
+
|
|
63
|
+
val greenit = colorize Green
|
|
64
|
+
|
|
65
|
+
val yellowit = colorize Yellow
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
structure Test =
|
|
69
|
+
struct
|
|
70
|
+
datatype testnode = TestGroup of string * testnode list
|
|
71
|
+
| Test of string * (unit -> Expect.expectation)
|
|
72
|
+
|
|
73
|
+
local
|
|
74
|
+
datatype evaluation = Success of string
|
|
75
|
+
| Failure of string * string * string
|
|
76
|
+
| Error of string * string
|
|
77
|
+
|
|
78
|
+
fun indent n s = (implode (List.tabulate (n, fn _ => #" "))) ^ s
|
|
79
|
+
|
|
80
|
+
fun fmt indentlvl ev =
|
|
81
|
+
let
|
|
82
|
+
val check = TermColor.greenit "\226\156\148 " (* ✔ *)
|
|
83
|
+
val cross = TermColor.redit "\226\156\150 " (* ✖ *)
|
|
84
|
+
val indentlvl = indentlvl * 2
|
|
85
|
+
in
|
|
86
|
+
case ev of
|
|
87
|
+
Success descr => indent indentlvl (check ^ descr)
|
|
88
|
+
| Failure (descr, exp, got) =>
|
|
89
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
90
|
+
indent (indentlvl + 2) exp,
|
|
91
|
+
indent (indentlvl + 2) got]
|
|
92
|
+
| Error (descr, reason) =>
|
|
93
|
+
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
|
94
|
+
indent (indentlvl + 2) (TermColor.redit reason)]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
fun eval (TestGroup _) = raise Fail "Only a 'Test' can be evaluated"
|
|
98
|
+
| eval (Test (descr, thunk)) =
|
|
99
|
+
(
|
|
100
|
+
case thunk () of
|
|
101
|
+
Expect.Pass => ((1, 0, 0), Success descr)
|
|
102
|
+
| Expect.Fail (s, s') => ((0, 1, 0), Failure (descr, s, s'))
|
|
103
|
+
)
|
|
104
|
+
handle e => ((0, 0, 1), Error (descr, "Unexpected error: " ^ exnMessage e))
|
|
105
|
+
|
|
106
|
+
fun flatten depth testnode =
|
|
107
|
+
let
|
|
108
|
+
fun sum (x, y, z) (a, b, c) = (x + a, y + b, z + c)
|
|
109
|
+
|
|
110
|
+
fun aux (t, (counter, acc)) =
|
|
111
|
+
let
|
|
112
|
+
val (counter', texts) = flatten (depth + 1) t
|
|
113
|
+
in
|
|
114
|
+
(sum counter' counter, texts :: acc)
|
|
115
|
+
end
|
|
116
|
+
in
|
|
117
|
+
case testnode of
|
|
118
|
+
TestGroup (descr, ts) =>
|
|
119
|
+
let
|
|
120
|
+
val (counter, texts) = foldr aux ((0, 0, 0), []) ts
|
|
121
|
+
in
|
|
122
|
+
(counter, (indent (depth * 2) descr) :: List.concat texts)
|
|
123
|
+
end
|
|
124
|
+
| Test _ =>
|
|
125
|
+
let
|
|
126
|
+
val (counter, evaluation) = eval testnode
|
|
127
|
+
in
|
|
128
|
+
(counter, [fmt depth evaluation])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
fun println s = print (s ^ "\n")
|
|
133
|
+
in
|
|
134
|
+
fun run suite =
|
|
135
|
+
let
|
|
136
|
+
val ((succeeded, failed, errored), texts) = flatten 0 suite
|
|
137
|
+
|
|
138
|
+
val summary = String.concatWith ", " [
|
|
139
|
+
TermColor.greenit ((Int.toString succeeded) ^ " passed"),
|
|
140
|
+
TermColor.redit ((Int.toString failed) ^ " failed"),
|
|
141
|
+
TermColor.redit ((Int.toString errored) ^ " errored"),
|
|
142
|
+
(Int.toString (succeeded + failed + errored)) ^ " total"
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
val status = if failed = 0 andalso errored = 0
|
|
146
|
+
then OS.Process.success
|
|
147
|
+
else OS.Process.failure
|
|
148
|
+
|
|
149
|
+
in
|
|
150
|
+
List.app println texts;
|
|
151
|
+
println "";
|
|
152
|
+
println ("Tests: " ^ summary);
|
|
153
|
+
OS.Process.exit status
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
fun describe description tests = Test.TestGroup (description, tests)
|
|
159
|
+
fun test description thunk = Test.Test (description, thunk)
|