From 65e0bec3e9802b5f404f7136774147da1508d818 Mon Sep 17 00:00:00 2001 From: Grzegorz Bielski Date: Wed, 14 Aug 2024 10:13:57 +0200 Subject: [PATCH] Scala 3 support (#836) * update build * update exerices build * fix compile errors * reformat and restructure testgen * port word-count * remove old test-gens * fix exercises * fix sgf, sieve and linked list exercise * update docs * update about page --- .gitignore | 5 +- .scalafmt.conf | 9 + README.md | 30 +- build.sbt | 22 ++ docs/ABOUT.md | 5 +- docs/INSTALLATION.md | 17 +- docs/LEARNING.md | 23 +- docs/RESOURCES.md | 18 +- docs/TESTS.md | 12 +- exercises/concept/basics/build.sbt | 4 +- .../concept/basics/project/build.properties | 1 + exercises/practice/accumulate/build.sbt | 4 +- .../accumulate/project/build.properties | 1 + exercises/practice/acronym/build.sbt | 4 +- .../practice/acronym/project/build.properties | 1 + exercises/practice/all-your-base/build.sbt | 4 +- .../all-your-base/project/build.properties | 1 + exercises/practice/allergies/build.sbt | 4 +- .../allergies/project/build.properties | 1 + exercises/practice/alphametics/build.sbt | 4 +- .../alphametics/project/build.properties | 1 + exercises/practice/anagram/build.sbt | 4 +- .../practice/anagram/project/build.properties | 1 + .../practice/armstrong-numbers/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/atbash-cipher/build.sbt | 4 +- .../atbash-cipher/project/build.properties | 1 + exercises/practice/bank-account/build.sbt | 4 +- .../bank-account/project/build.properties | 1 + exercises/practice/beer-song/build.sbt | 4 +- .../beer-song/project/build.properties | 1 + .../binary-search-tree/.meta/Example.scala | 8 +- .../practice/binary-search-tree/build.sbt | 4 +- .../project/build.properties | 1 + .../binary-search/.meta/Example.scala | 1 + exercises/practice/binary-search/build.sbt | 4 +- .../binary-search/project/build.properties | 1 + exercises/practice/binary/build.sbt | 4 +- .../practice/binary/project/build.properties | 1 + exercises/practice/bob/build.sbt | 4 +- .../practice/bob/project/build.properties | 1 + exercises/practice/book-store/build.sbt | 4 +- .../book-store/project/build.properties | 1 + exercises/practice/bowling/build.sbt | 4 +- .../practice/bowling/project/build.properties | 1 + exercises/practice/change/build.sbt | 4 +- .../practice/change/project/build.properties | 1 + exercises/practice/circular-buffer/build.sbt | 4 +- .../circular-buffer/project/build.properties | 1 + exercises/practice/clock/build.sbt | 4 +- .../practice/clock/project/build.properties | 1 + .../practice/collatz-conjecture/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/complex-numbers/build.sbt | 4 +- .../complex-numbers/project/build.properties | 1 + .../src/test/scala/ComplexNumberTest.scala | 2 +- exercises/practice/connect/build.sbt | 4 +- .../practice/connect/project/build.properties | 1 + exercises/practice/crypto-square/build.sbt | 4 +- .../crypto-square/project/build.properties | 1 + exercises/practice/custom-set/build.sbt | 4 +- .../custom-set/project/build.properties | 1 + exercises/practice/darts/build.sbt | 4 +- .../practice/darts/project/build.properties | 1 + exercises/practice/diamond/build.sbt | 4 +- .../practice/diamond/project/build.properties | 1 + .../practice/difference-of-squares/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/dominoes/build.sbt | 4 +- .../dominoes/project/build.properties | 1 + exercises/practice/etl/build.sbt | 4 +- .../practice/etl/project/build.properties | 1 + exercises/practice/flatten-array/build.sbt | 4 +- .../flatten-array/project/build.properties | 1 + exercises/practice/food-chain/build.sbt | 4 +- .../food-chain/project/build.properties | 1 + exercises/practice/forth/build.sbt | 4 +- .../practice/forth/project/build.properties | 1 + exercises/practice/gigasecond/build.sbt | 4 +- .../gigasecond/project/build.properties | 1 + .../practice/grade-school/.meta/Example.scala | 2 +- exercises/practice/grade-school/build.sbt | 4 +- .../grade-school/project/build.properties | 1 + exercises/practice/grains/build.sbt | 4 +- .../practice/grains/project/build.properties | 1 + exercises/practice/hamming/build.sbt | 4 +- .../practice/hamming/project/build.properties | 1 + exercises/practice/hello-world/build.sbt | 4 +- .../hello-world/project/build.properties | 1 + exercises/practice/hexadecimal/build.sbt | 4 +- .../hexadecimal/project/build.properties | 1 + exercises/practice/high-scores/build.sbt | 4 +- .../high-scores/project/build.properties | 1 + exercises/practice/house/build.sbt | 4 +- .../practice/house/project/build.properties | 1 + exercises/practice/isogram/build.sbt | 4 +- .../practice/isogram/project/build.properties | 1 + .../practice/kindergarten-garden/build.sbt | 4 +- .../project/build.properties | 1 + .../practice/largest-series-product/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/leap/build.sbt | 4 +- .../practice/leap/project/build.properties | 1 + .../practice/lens-person/.meta/Example.scala | 2 +- exercises/practice/lens-person/build.sbt | 14 +- .../lens-person/project/build.properties | 1 + exercises/practice/linked-list/build.sbt | 4 +- .../linked-list/project/build.properties | 1 + exercises/practice/luhn/build.sbt | 4 +- .../practice/luhn/project/build.properties | 1 + .../practice/matching-brackets/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/matrix/build.sbt | 4 +- .../practice/matrix/project/build.properties | 1 + exercises/practice/meetup/build.sbt | 4 +- .../practice/meetup/project/build.properties | 1 + exercises/practice/minesweeper/build.sbt | 4 +- .../minesweeper/project/build.properties | 1 + exercises/practice/nth-prime/build.sbt | 4 +- .../nth-prime/project/build.properties | 1 + exercises/practice/nucleotide-count/build.sbt | 4 +- .../nucleotide-count/project/build.properties | 1 + exercises/practice/ocr-numbers/build.sbt | 4 +- .../ocr-numbers/project/build.properties | 1 + exercises/practice/octal/build.sbt | 4 +- .../practice/octal/project/build.properties | 1 + .../practice/palindrome-products/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/pangram/build.sbt | 4 +- .../practice/pangram/project/build.properties | 1 + .../parallel-letter-frequency/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/pascals-triangle/build.sbt | 4 +- .../pascals-triangle/project/build.properties | 1 + exercises/practice/perfect-numbers/build.sbt | 4 +- .../perfect-numbers/project/build.properties | 1 + .../practice/phone-number/.meta/Example.scala | 8 +- exercises/practice/phone-number/build.sbt | 4 +- .../phone-number/project/build.properties | 1 + exercises/practice/pig-latin/build.sbt | 4 +- .../pig-latin/project/build.properties | 1 + exercises/practice/prime-factors/build.sbt | 4 +- .../prime-factors/project/build.properties | 1 + .../practice/protein-translation/build.sbt | 4 +- .../project/build.properties | 1 + .../practice/pythagorean-triplet/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/queen-attack/build.sbt | 4 +- .../queen-attack/project/build.properties | 1 + .../practice/rail-fence-cipher/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/raindrops/build.sbt | 4 +- .../raindrops/project/build.properties | 1 + exercises/practice/reverse-string/build.sbt | 4 +- .../reverse-string/project/build.properties | 1 + .../practice/rna-transcription/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/robot-name/build.sbt | 4 +- .../robot-name/project/build.properties | 1 + exercises/practice/robot-simulator/build.sbt | 4 +- .../robot-simulator/project/build.properties | 1 + exercises/practice/roman-numerals/build.sbt | 4 +- .../roman-numerals/project/build.properties | 1 + .../practice/rotational-cipher/build.sbt | 4 +- .../project/build.properties | 1 + .../practice/run-length-encoding/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/saddle-points/build.sbt | 4 +- .../saddle-points/project/build.properties | 1 + exercises/practice/say/build.sbt | 4 +- .../practice/say/project/build.properties | 1 + exercises/practice/scrabble-score/build.sbt | 4 +- .../scrabble-score/project/build.properties | 1 + exercises/practice/secret-handshake/build.sbt | 4 +- .../secret-handshake/project/build.properties | 1 + exercises/practice/series/build.sbt | 4 +- .../practice/series/project/build.properties | 1 + .../practice/sgf-parsing/.meta/Example.scala | 4 +- exercises/practice/sgf-parsing/build.sbt | 4 +- .../sgf-parsing/project/build.properties | 1 + exercises/practice/sieve/.meta/Example.scala | 2 +- exercises/practice/sieve/build.sbt | 4 +- .../practice/sieve/project/build.properties | 1 + exercises/practice/simple-cipher/build.sbt | 4 +- .../simple-cipher/project/build.properties | 1 + .../practice/simple-linked-list/build.sbt | 6 +- .../project/build.properties | 1 + .../src/test/scala/SimpleLinkedListTest.scala | 12 +- exercises/practice/space-age/build.sbt | 4 +- .../space-age/project/build.properties | 1 + exercises/practice/spiral-matrix/build.sbt | 4 +- .../spiral-matrix/project/build.properties | 1 + exercises/practice/strain/build.sbt | 4 +- .../practice/strain/project/build.properties | 1 + exercises/practice/sublist/build.sbt | 4 +- .../practice/sublist/project/build.properties | 1 + exercises/practice/sum-of-multiples/build.sbt | 4 +- .../sum-of-multiples/project/build.properties | 1 + exercises/practice/triangle/build.sbt | 4 +- .../triangle/project/build.properties | 1 + exercises/practice/trinary/build.sbt | 4 +- .../practice/trinary/project/build.properties | 1 + exercises/practice/two-fer/build.sbt | 4 +- .../practice/two-fer/project/build.properties | 1 + .../variable-length-quantity/build.sbt | 4 +- .../project/build.properties | 1 + exercises/practice/word-count/build.sbt | 4 +- .../word-count/project/build.properties | 1 + exercises/practice/wordy/build.sbt | 4 +- .../practice/wordy/project/build.properties | 1 + exercises/practice/yacht/build.sbt | 4 +- .../practice/yacht/project/build.properties | 1 + exercises/practice/zebra-puzzle/build.sbt | 4 +- .../zebra-puzzle/project/build.properties | 1 + exercises/practice/zipper/build.sbt | 4 +- .../practice/zipper/project/build.properties | 1 + project/Build.scala | 54 ---- project/build.properties | 2 +- project/plugins.sbt | 2 + testgen/build.sbt | 17 -- testgen/project/build.properties | 2 - testgen/project/plugins.sbt | 2 - .../src/main/scala/AcronymTestGenerator.scala | 16 -- .../main/scala/AllYourBaseTestGenerator.scala | 36 --- .../main/scala/AllergiesTestGenerator.scala | 63 ----- .../main/scala/AlphameticsTestGenerator.scala | 42 --- .../src/main/scala/AnagramTestGenerator.scala | 15 - .../scala/ArmstrongNumbersTestGenerator.scala | 33 --- .../scala/AtbashCipherTestGenerator.scala | 16 -- .../main/scala/BeerSongTestGenerator.scala | 35 --- .../scala/BinarySearchTestGenerator.scala | 36 --- testgen/src/main/scala/BobTestGenerator.scala | 16 -- .../main/scala/BookStoreTestGenerator.scala | 15 - .../src/main/scala/BowlingTestGenerator.scala | 43 --- .../src/main/scala/ChangeTestGenerator.scala | 37 --- .../src/main/scala/ClockTestGenerator.scala | 69 ----- .../CollatzConjectureTestGenerator.scala | 35 --- .../scala/ComplexNumberTestGenerator.scala | 129 --------- .../src/main/scala/ConnectTestGenerator.scala | 52 ---- .../scala/CryptoSquareTestGenerator.scala | 17 -- .../main/scala/CustomSetTestGenerator.scala | 257 ------------------ .../src/main/scala/DartsTestGenerator.scala | 15 - .../src/main/scala/DiamondTestGenerator.scala | 40 --- .../DifferenceOfSquaresTestGenerator.scala | 17 -- .../main/scala/DominoesTestGenerator.scala | 71 ----- testgen/src/main/scala/EtlTestGenerator.scala | 52 ---- .../scala/FlattenArrayTestGenerator.scala | 44 --- .../main/scala/FoodChainTestGenerator.scala | 40 --- .../src/main/scala/ForthTestGenerator.scala | 66 ----- .../main/scala/GigasecondTestGenerator.scala | 51 ---- .../src/main/scala/GrainsTestGenerator.scala | 56 ---- .../src/main/scala/HammingTestGenerator.scala | 34 --- .../main/scala/HelloWorldTestGenerator.scala | 14 - .../main/scala/HighScoresTestGenerator.scala | 21 -- .../src/main/scala/HouseTestGenerator.scala | 41 --- .../src/main/scala/IsogramTestGenerator.scala | 16 -- .../KindergartenGardenTestGenerator.scala | 43 --- .../src/main/scala/LeapTestGenerator.scala | 15 - .../src/main/scala/LuhnTestGenerator.scala | 15 - .../scala/MatchingBracketsTestGenerator.scala | 15 - .../src/main/scala/MatrixTestGenerator.scala | 37 --- .../src/main/scala/MeetupTestGenerator.scala | 51 ---- .../main/scala/MinesweeperTestGenerator.scala | 15 - .../main/scala/NthPrimeTestGenerator.scala | 34 --- .../scala/NucleotideCountTestGenerator.scala | 49 ---- .../main/scala/OcrNumbersTestGenerator.scala | 34 --- .../PalindromeProductsTestGenerator.scala | 50 ---- .../main/scala/PangramsTestGenerator.scala | 25 -- .../scala/PascalsTriangleTestGenerator.scala | 51 ---- .../scala/PerfectNumbersTestGenerator.scala | 42 --- .../main/scala/PhoneNumberTestGenerator.scala | 34 --- .../main/scala/PigLatinTestGenerator.scala | 16 -- .../scala/PrimeFactorsTestGenerator.scala | 53 ---- .../main/scala/QueenAttackTestGenerator.scala | 81 ------ .../scala/RailFenceCipherTestGenerator.scala | 15 - .../main/scala/RaindropsTestGenerator.scala | 15 - .../scala/RnaTranscriptionTestGenerator.scala | 34 --- .../scala/RobotSimulatorTestGenerator.scala | 110 -------- .../scala/RomanNumeralsTestGenerator.scala | 15 - .../scala/RotationalCipherTestGenerator.scala | 16 -- .../RunLengthEncodingTestGenerator.scala | 34 --- .../scala/SaddlePointsTestGenerator.scala | 35 --- testgen/src/main/scala/SayTestGenerator.scala | 50 ---- .../scala/ScrabbleScoreTestGenerator.scala | 15 - .../scala/SecretHandshakeTestGenerator.scala | 15 - .../src/main/scala/SeriesTestGenerator.scala | 44 --- .../src/main/scala/SieveTestGenerator.scala | 15 - .../main/scala/SpaceAgeTestGenerator.scala | 40 --- .../scala/SpiralMatrixTestGenerator.scala | 15 - .../src/main/scala/SublistTestGenerator.scala | 38 --- .../scala/SumOfMultiplesTestGenerator.scala | 46 ---- testgen/src/main/scala/TestBuilder.scala | 98 ------- .../main/scala/TriangleTestGenerator.scala | 38 --- .../src/main/scala/TwoferTestGenerator.scala | 45 --- .../VariableLengthQuantityTestGenerator.scala | 78 ------ testgen/src/main/scala/VersionCheck.scala | 72 ----- .../main/scala/WordCountTestGenerator.scala | 35 --- .../src/main/scala/WordyTestGenerator.scala | 35 --- .../scala/testgen/CanonicalDataParser.scala | 224 ++++++++------- .../src/main/scala/testgen/TestGenError.scala | 10 + .../main/scala/testgen/TestGenerator.scala | 48 ++++ .../scala/testgen/TestGeneratorRunner.scala | 46 ++++ .../main/scala/testgen/TestSuiteBuilder.scala | 204 -------------- .../generator/WordCountTestGenerator.scala | 19 ++ .../src/main/twirl/funSuiteTemplate.scala.txt | 20 +- .../funSuiteTemplateIgnoreExpected.scala.txt | 17 -- 306 files changed, 680 insertions(+), 3829 deletions(-) create mode 100644 .scalafmt.conf create mode 100644 build.sbt create mode 100644 exercises/concept/basics/project/build.properties create mode 100644 exercises/practice/accumulate/project/build.properties create mode 100644 exercises/practice/acronym/project/build.properties create mode 100644 exercises/practice/all-your-base/project/build.properties create mode 100644 exercises/practice/allergies/project/build.properties create mode 100644 exercises/practice/alphametics/project/build.properties create mode 100644 exercises/practice/anagram/project/build.properties create mode 100644 exercises/practice/armstrong-numbers/project/build.properties create mode 100644 exercises/practice/atbash-cipher/project/build.properties create mode 100644 exercises/practice/bank-account/project/build.properties create mode 100644 exercises/practice/beer-song/project/build.properties create mode 100644 exercises/practice/binary-search-tree/project/build.properties create mode 100644 exercises/practice/binary-search/project/build.properties create mode 100644 exercises/practice/binary/project/build.properties create mode 100644 exercises/practice/bob/project/build.properties create mode 100644 exercises/practice/book-store/project/build.properties create mode 100644 exercises/practice/bowling/project/build.properties create mode 100644 exercises/practice/change/project/build.properties create mode 100644 exercises/practice/circular-buffer/project/build.properties create mode 100644 exercises/practice/clock/project/build.properties create mode 100644 exercises/practice/collatz-conjecture/project/build.properties create mode 100644 exercises/practice/complex-numbers/project/build.properties create mode 100644 exercises/practice/connect/project/build.properties create mode 100644 exercises/practice/crypto-square/project/build.properties create mode 100644 exercises/practice/custom-set/project/build.properties create mode 100644 exercises/practice/darts/project/build.properties create mode 100644 exercises/practice/diamond/project/build.properties create mode 100644 exercises/practice/difference-of-squares/project/build.properties create mode 100644 exercises/practice/dominoes/project/build.properties create mode 100644 exercises/practice/etl/project/build.properties create mode 100644 exercises/practice/flatten-array/project/build.properties create mode 100644 exercises/practice/food-chain/project/build.properties create mode 100644 exercises/practice/forth/project/build.properties create mode 100644 exercises/practice/gigasecond/project/build.properties create mode 100644 exercises/practice/grade-school/project/build.properties create mode 100644 exercises/practice/grains/project/build.properties create mode 100644 exercises/practice/hamming/project/build.properties create mode 100644 exercises/practice/hello-world/project/build.properties create mode 100644 exercises/practice/hexadecimal/project/build.properties create mode 100644 exercises/practice/high-scores/project/build.properties create mode 100644 exercises/practice/house/project/build.properties create mode 100644 exercises/practice/isogram/project/build.properties create mode 100644 exercises/practice/kindergarten-garden/project/build.properties create mode 100644 exercises/practice/largest-series-product/project/build.properties create mode 100644 exercises/practice/leap/project/build.properties create mode 100644 exercises/practice/lens-person/project/build.properties create mode 100644 exercises/practice/linked-list/project/build.properties create mode 100644 exercises/practice/luhn/project/build.properties create mode 100644 exercises/practice/matching-brackets/project/build.properties create mode 100644 exercises/practice/matrix/project/build.properties create mode 100644 exercises/practice/meetup/project/build.properties create mode 100644 exercises/practice/minesweeper/project/build.properties create mode 100644 exercises/practice/nth-prime/project/build.properties create mode 100644 exercises/practice/nucleotide-count/project/build.properties create mode 100644 exercises/practice/ocr-numbers/project/build.properties create mode 100644 exercises/practice/octal/project/build.properties create mode 100644 exercises/practice/palindrome-products/project/build.properties create mode 100644 exercises/practice/pangram/project/build.properties create mode 100644 exercises/practice/parallel-letter-frequency/project/build.properties create mode 100644 exercises/practice/pascals-triangle/project/build.properties create mode 100644 exercises/practice/perfect-numbers/project/build.properties create mode 100644 exercises/practice/phone-number/project/build.properties create mode 100644 exercises/practice/pig-latin/project/build.properties create mode 100644 exercises/practice/prime-factors/project/build.properties create mode 100644 exercises/practice/protein-translation/project/build.properties create mode 100644 exercises/practice/pythagorean-triplet/project/build.properties create mode 100644 exercises/practice/queen-attack/project/build.properties create mode 100644 exercises/practice/rail-fence-cipher/project/build.properties create mode 100644 exercises/practice/raindrops/project/build.properties create mode 100644 exercises/practice/reverse-string/project/build.properties create mode 100644 exercises/practice/rna-transcription/project/build.properties create mode 100644 exercises/practice/robot-name/project/build.properties create mode 100644 exercises/practice/robot-simulator/project/build.properties create mode 100644 exercises/practice/roman-numerals/project/build.properties create mode 100644 exercises/practice/rotational-cipher/project/build.properties create mode 100644 exercises/practice/run-length-encoding/project/build.properties create mode 100644 exercises/practice/saddle-points/project/build.properties create mode 100644 exercises/practice/say/project/build.properties create mode 100644 exercises/practice/scrabble-score/project/build.properties create mode 100644 exercises/practice/secret-handshake/project/build.properties create mode 100644 exercises/practice/series/project/build.properties create mode 100644 exercises/practice/sgf-parsing/project/build.properties create mode 100644 exercises/practice/sieve/project/build.properties create mode 100644 exercises/practice/simple-cipher/project/build.properties create mode 100644 exercises/practice/simple-linked-list/project/build.properties create mode 100644 exercises/practice/space-age/project/build.properties create mode 100644 exercises/practice/spiral-matrix/project/build.properties create mode 100644 exercises/practice/strain/project/build.properties create mode 100644 exercises/practice/sublist/project/build.properties create mode 100644 exercises/practice/sum-of-multiples/project/build.properties create mode 100644 exercises/practice/triangle/project/build.properties create mode 100644 exercises/practice/trinary/project/build.properties create mode 100644 exercises/practice/two-fer/project/build.properties create mode 100644 exercises/practice/variable-length-quantity/project/build.properties create mode 100644 exercises/practice/word-count/project/build.properties create mode 100644 exercises/practice/wordy/project/build.properties create mode 100644 exercises/practice/yacht/project/build.properties create mode 100644 exercises/practice/zebra-puzzle/project/build.properties create mode 100644 exercises/practice/zipper/project/build.properties delete mode 100644 project/Build.scala create mode 100644 project/plugins.sbt delete mode 100644 testgen/build.sbt delete mode 100644 testgen/project/build.properties delete mode 100644 testgen/project/plugins.sbt delete mode 100644 testgen/src/main/scala/AcronymTestGenerator.scala delete mode 100644 testgen/src/main/scala/AllYourBaseTestGenerator.scala delete mode 100644 testgen/src/main/scala/AllergiesTestGenerator.scala delete mode 100644 testgen/src/main/scala/AlphameticsTestGenerator.scala delete mode 100644 testgen/src/main/scala/AnagramTestGenerator.scala delete mode 100644 testgen/src/main/scala/ArmstrongNumbersTestGenerator.scala delete mode 100644 testgen/src/main/scala/AtbashCipherTestGenerator.scala delete mode 100644 testgen/src/main/scala/BeerSongTestGenerator.scala delete mode 100644 testgen/src/main/scala/BinarySearchTestGenerator.scala delete mode 100644 testgen/src/main/scala/BobTestGenerator.scala delete mode 100644 testgen/src/main/scala/BookStoreTestGenerator.scala delete mode 100644 testgen/src/main/scala/BowlingTestGenerator.scala delete mode 100644 testgen/src/main/scala/ChangeTestGenerator.scala delete mode 100644 testgen/src/main/scala/ClockTestGenerator.scala delete mode 100644 testgen/src/main/scala/CollatzConjectureTestGenerator.scala delete mode 100644 testgen/src/main/scala/ComplexNumberTestGenerator.scala delete mode 100644 testgen/src/main/scala/ConnectTestGenerator.scala delete mode 100644 testgen/src/main/scala/CryptoSquareTestGenerator.scala delete mode 100644 testgen/src/main/scala/CustomSetTestGenerator.scala delete mode 100644 testgen/src/main/scala/DartsTestGenerator.scala delete mode 100644 testgen/src/main/scala/DiamondTestGenerator.scala delete mode 100644 testgen/src/main/scala/DifferenceOfSquaresTestGenerator.scala delete mode 100644 testgen/src/main/scala/DominoesTestGenerator.scala delete mode 100644 testgen/src/main/scala/EtlTestGenerator.scala delete mode 100644 testgen/src/main/scala/FlattenArrayTestGenerator.scala delete mode 100644 testgen/src/main/scala/FoodChainTestGenerator.scala delete mode 100644 testgen/src/main/scala/ForthTestGenerator.scala delete mode 100644 testgen/src/main/scala/GigasecondTestGenerator.scala delete mode 100644 testgen/src/main/scala/GrainsTestGenerator.scala delete mode 100644 testgen/src/main/scala/HammingTestGenerator.scala delete mode 100644 testgen/src/main/scala/HelloWorldTestGenerator.scala delete mode 100644 testgen/src/main/scala/HighScoresTestGenerator.scala delete mode 100644 testgen/src/main/scala/HouseTestGenerator.scala delete mode 100644 testgen/src/main/scala/IsogramTestGenerator.scala delete mode 100644 testgen/src/main/scala/KindergartenGardenTestGenerator.scala delete mode 100644 testgen/src/main/scala/LeapTestGenerator.scala delete mode 100644 testgen/src/main/scala/LuhnTestGenerator.scala delete mode 100644 testgen/src/main/scala/MatchingBracketsTestGenerator.scala delete mode 100644 testgen/src/main/scala/MatrixTestGenerator.scala delete mode 100644 testgen/src/main/scala/MeetupTestGenerator.scala delete mode 100644 testgen/src/main/scala/MinesweeperTestGenerator.scala delete mode 100644 testgen/src/main/scala/NthPrimeTestGenerator.scala delete mode 100644 testgen/src/main/scala/NucleotideCountTestGenerator.scala delete mode 100644 testgen/src/main/scala/OcrNumbersTestGenerator.scala delete mode 100644 testgen/src/main/scala/PalindromeProductsTestGenerator.scala delete mode 100644 testgen/src/main/scala/PangramsTestGenerator.scala delete mode 100644 testgen/src/main/scala/PascalsTriangleTestGenerator.scala delete mode 100644 testgen/src/main/scala/PerfectNumbersTestGenerator.scala delete mode 100644 testgen/src/main/scala/PhoneNumberTestGenerator.scala delete mode 100644 testgen/src/main/scala/PigLatinTestGenerator.scala delete mode 100644 testgen/src/main/scala/PrimeFactorsTestGenerator.scala delete mode 100644 testgen/src/main/scala/QueenAttackTestGenerator.scala delete mode 100644 testgen/src/main/scala/RailFenceCipherTestGenerator.scala delete mode 100644 testgen/src/main/scala/RaindropsTestGenerator.scala delete mode 100644 testgen/src/main/scala/RnaTranscriptionTestGenerator.scala delete mode 100644 testgen/src/main/scala/RobotSimulatorTestGenerator.scala delete mode 100644 testgen/src/main/scala/RomanNumeralsTestGenerator.scala delete mode 100644 testgen/src/main/scala/RotationalCipherTestGenerator.scala delete mode 100644 testgen/src/main/scala/RunLengthEncodingTestGenerator.scala delete mode 100644 testgen/src/main/scala/SaddlePointsTestGenerator.scala delete mode 100644 testgen/src/main/scala/SayTestGenerator.scala delete mode 100644 testgen/src/main/scala/ScrabbleScoreTestGenerator.scala delete mode 100644 testgen/src/main/scala/SecretHandshakeTestGenerator.scala delete mode 100644 testgen/src/main/scala/SeriesTestGenerator.scala delete mode 100644 testgen/src/main/scala/SieveTestGenerator.scala delete mode 100644 testgen/src/main/scala/SpaceAgeTestGenerator.scala delete mode 100644 testgen/src/main/scala/SpiralMatrixTestGenerator.scala delete mode 100644 testgen/src/main/scala/SublistTestGenerator.scala delete mode 100644 testgen/src/main/scala/SumOfMultiplesTestGenerator.scala delete mode 100644 testgen/src/main/scala/TestBuilder.scala delete mode 100644 testgen/src/main/scala/TriangleTestGenerator.scala delete mode 100644 testgen/src/main/scala/TwoferTestGenerator.scala delete mode 100644 testgen/src/main/scala/VariableLengthQuantityTestGenerator.scala delete mode 100644 testgen/src/main/scala/VersionCheck.scala delete mode 100644 testgen/src/main/scala/WordCountTestGenerator.scala delete mode 100644 testgen/src/main/scala/WordyTestGenerator.scala create mode 100644 testgen/src/main/scala/testgen/TestGenError.scala create mode 100644 testgen/src/main/scala/testgen/TestGenerator.scala create mode 100644 testgen/src/main/scala/testgen/TestGeneratorRunner.scala delete mode 100644 testgen/src/main/scala/testgen/TestSuiteBuilder.scala create mode 100644 testgen/src/main/scala/testgen/generator/WordCountTestGenerator.scala delete mode 100644 testgen/src/main/twirl/funSuiteTemplateIgnoreExpected.scala.txt diff --git a/.gitignore b/.gitignore index 0352fe05..43d8e245 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.swp .DS_Store .idea +.vscode tmp target/ bin/configlet @@ -13,9 +14,11 @@ bin/configlet.exe .bloop/ .metals/ -project/ +project/* !project/build.properties !project/plugins.sbt project/target src/test/scala/project/ target + +generated diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 00000000..f631626a --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,9 @@ +version = "3.8.2" +align.preset = most +maxColumn = 160 +trailingCommas = always +continuationIndent.callSite = 2 +continuationIndent.defnSite = 2 +runner.dialect = scala3 +rewrite.scala3.convertToNewSyntax = yes +rewrite.scala3.removeOptionalBraces = yes diff --git a/README.md b/README.md index 6b160619..9bfb6b12 100644 --- a/README.md +++ b/README.md @@ -6,28 +6,24 @@ Exercism Exercises in Scala Please see the [contributing guide](https://github.com/exercism/x-api/blob/master/CONTRIBUTING.md#the-exercise-data) -### Generated Test Suites - -Some of the test suites have been generated from shared test data. If a test suite was -generated from test data, then the test suite should not be modified by hand. Instead -the shared test data should be modified, and the generator rerun. To determine if -a test suite generator was used, look inside the `testgen/src/main/scala` directory. The test -suite generators are named in the form `ProblemNameTestGenerator.scala`. Where -`ProblemName` is a close match for the Exercism problem name. +Scala exercises are run by the [scala-test-runner](https://github.com/exercism/scala-test-runner). +It ignores the dependencies listed in the `sbt` files of the exercises. It's important to add all dependencies necessary to run the exercise to the scala-test-runner's dependencies. -[the shared problem metadata](https://github.com/exercism/x-common). +### Generated Test Suites -For example, take a look at the `bob/canonical-data.json` file in the x-common repository, as well -as the following files in the xscala repository: +`testgen` contains a project for generating test suites from [canonical test data](https://github.com/exercism/problem-specifications). -1. `testgen/src/main/scala/BobTestGenerator.scala` - test suite generator for bob -1. `exercises/bob/src/test/scala/BobTest.scala`- generated test suite +You can run it as follows: +``` +sbt testgen / run +``` -Since a generator was used, the`exercises/bob/src/test/scala/BobTest.scala` will never be edited directly. -If there's a missing test case, then additional inputs/outputs should be submitted to the x-common repository. +where: +- `exercise-slug` is the slug of one of the exercises listed in the [config.json](config.json) file. +- `path-to-canonical-data` is a local path to the canonical data, which could be obtained by running `bin/fetch-configlet` and `bin/configlet info -v d` +- `optional-path-to-generated-file` an optional path for the generated file like `./TestSuite.scala`. -When submitting new exercises we encourage that a test suite generator and generated test suite is -included. +Note, that existing iteration of the `testgen` is not _yet_ used. ## Pull Requests diff --git a/build.sbt b/build.sbt new file mode 100644 index 00000000..4afc1465 --- /dev/null +++ b/build.sbt @@ -0,0 +1,22 @@ +name := "ExcercismScalaTestGenerator" + +ThisBuild / scalaVersion := "3.4.2" +ThisBuild / scalacOptions ++= Seq("-source:future") + +lazy val root = project + .in(file(".")) + .aggregate(testgen) + +lazy val testgen = project + .enablePlugins(SbtTwirl) + .settings( + Compile / TwirlKeys.compileTemplates / sourceDirectories + += (baseDirectory.value.getParentFile / "src" / "main" / "twirl") + ) + .settings( + libraryDependencies += "org.playframework" %% "play-json" % "3.0.4", + libraryDependencies += "org.playframework.twirl" %% "twirl-api" % "2.0.7", + libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.4.0", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.15.0" + ) + diff --git a/docs/ABOUT.md b/docs/ABOUT.md index fb14c6a3..82447fe8 100644 --- a/docs/ABOUT.md +++ b/docs/ABOUT.md @@ -1,9 +1,12 @@ # About -Scala combines object-oriented and functional programming in one concise, high-level language. Scala's static types help avoid bugs in complex applications, and its JVM and JavaScript runtimes let you build high-performance systems with easy access to huge ecosystems of libraries. +Scala is a a programming language that scales with you: from small scripts to large multiplatform applications. + +Scala combines object-oriented and functional programming in one concise, high-level language. Scala's static types help avoid bugs in complex applications, and its JVM, JavaScript and Native runtimes let you build high-performance systems with easy access to huge ecosystems of libraries. * Features * JVM Interoperability - Scala runs on the JVM, so Java and Scala stacks can be mixed for seamless integration. + * JS and Native interoperability - Scala can run in the browser and on native devices, thanks to [Scala.js](https://www.scala-js.org/) and [Scala Native](https://github.com/scala-native/scala-native) * Type Inference - Scala is statically typed. However, Scala provides type inference to ease the burden of an advanced type system. * Object Oriented - Scala is a pure object-oriented language in the sense that every value is an object. Data types and behaviors of objects are described by classes and traits. Class abstractions are extended by subclassing and by a flexible mixin-based composition mechanism to avoid the problems of multiple inheritance. * Functional - Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala’s case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages. Singleton objects provide a convenient way to group functions that aren’t members of a class. diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 323d86b3..665528f9 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -1,17 +1,14 @@ # Installing [Scala](http://www.scala-lang.org) +In addition to the exercism CLI and your favorite text editor, practicing with Exercism exercises in Scala requires few additional tools. -In addition to the exercism CLI and your favorite text editor, practicing with Exercism exercises in Scala requires: +All of them could be installed automatically by the `Coursier` tool. -* Java Development Kit (JDK) 17 or later. Use your preferred vendor or grab one from [Adoptium](https://adoptium.net/) -* [Scala 2.13.x](https://www.scala-lang.org/download/scala2.html) -* [sbt 1.7.x](https://www.scala-sbt.org/download.html) - -If you don't want install these various dependencies by hand, consider using [SDKMAN](https://sdkman.io/) to manage your java and java-adjacent development tools and libraries. +See: https://www.scala-lang.org/download/ for more details. --- -After installing Java and `sbt` you will be ready to get started with the Scala track of Exercism. +After running `cs setup` you will be ready to get started with the Scala track of Exercism. To get started, see "[Running the Tests](https://exercism.org/docs/tracks/scala/tests)". @@ -19,8 +16,8 @@ To get started, see "[Running the Tests](https://exercism.org/docs/tracks/scala/ # Scala IDEs -* [IntelliJ IDEA with Scala Plugin](https://www.jetbrains.com/idea/) -* [ScalaIDE](http://scala-ide.org/index.html) -* [NetBeans with Scala Plugin](https://netbeans.org/) * [Metals with VS Code](https://scalameta.org/metals/docs/editors/vscode) * [Metals with Vim or Neovim](https://scalameta.org/metals/docs/editors/vim) +* [Metals with Online IDEs such as Gitpod](https://scalameta.org/metals/docs/editors/online-ides) +* [Metals with Zed](https://github.com/scalameta/metals-zed) +* [IntelliJ IDEA with Scala Plugin](https://www.jetbrains.com/idea/) diff --git a/docs/LEARNING.md b/docs/LEARNING.md index d48e3092..c3a3a34f 100644 --- a/docs/LEARNING.md +++ b/docs/LEARNING.md @@ -1,14 +1,27 @@ # Learning +The best place to start your journey with Scala is the short [Tour of Scala](https://docs.scala-lang.org/tour/tour-of-scala.html) and [Scala Book](https://docs.scala-lang.org/scala3/book/introduction.html) + ## Books -* [Programming Scala - Dean Wampler, Ph.D.](http://shop.oreilly.com/product/0636920033073.do) * [Programming in Scala - Oderksy, Spoon, Venners](http://www.artima.com/shop/programming_in_scala_3ed) -* [Functional Programming in Scala - Chiusano, Bjarnason](https://www.manning.com/books/functional-programming-in-scala) -* [Scala for the Impatient - Cay S. Horstmann](http://horstmann.com/scala/) +* [Programming Scala - Dean Wampler](https://deanwampler.github.io/books/programmingscala.html) +* [Functional Programming in Scala - Michael Pilquist, Rúnar Bjarnason, and Paul Chiusano](https://www.manning.com/books/functional-programming-in-scala-second-edition) +* [Grokking Functional Programming - Michał Płachta](https://www.manning.com/books/grokking-functional-programming) +* [Scala With Cats - Noel Welsh](https://scalawithcats.com/) * [Hands on Scala Programming - Li Haoyi](https://www.handsonscala.com/) +* [Functional Event-Driven Architecture - Gabriel Volpe](https://leanpub.com/feda) +* [Modern Systems Programming with Scala Native - Richard Whaling](https://www.amazon.com/Modern-Systems-Programming-Scala-Native/dp/1680506226) +* [Scala Cookbook - Alvin Alexander ](https://www.amazon.com/Scala-Cookbook-Object-Oriented-Functional-Programming-dp-1492051543/dp/1492051543) +* [Scala for the Impatient - Cay S. Horstmann](http://horstmann.com/scala/) + +## YouTube +- https://www.youtube.com/@DevInsideYou +- https://www.youtube.com/@rockthejvm +- https://www.youtube.com/@Scala-for-Fun-and-Profit +- https://www.youtube.com/@scalaspace + ## Online Courses -* [Functional Programming Principles in Scala](https://www.coursera.org/learn/progfun1) - In this course you will discover the elements of the functional programming style and learn how to apply them usefully in your daily programming tasks. You will also develop a solid foundation for reasoning about functional programs, by touching upon proofs of invariants and the tracing of execution symbolically. -* [Functional Program Design in Scala](https://www.coursera.org/learn/progfun2) - In this course you will learn how to apply the functional programming style in the design of larger applications. \ No newline at end of file +You can find a comprehensive list of online courses in [here](https://docs.scala-lang.org/online-courses.html). diff --git a/docs/RESOURCES.md b/docs/RESOURCES.md index 7a75d37b..96d232a0 100644 --- a/docs/RESOURCES.md +++ b/docs/RESOURCES.md @@ -5,12 +5,20 @@ Exercism provides exercises and feedback but can be difficult to jump into for those learning Scala for the first time. These resources can help you get started: * [Scala - Getting Started](http://www.scala-lang.org/documentation/getting-started.html) -* [StackOverflow](http://stackoverflow.com/) +* [Tour of Scala](https://docs.scala-lang.org/tour/tour-of-scala.html) +* [Scala Book](https://docs.scala-lang.org/scala3/book/introduction.html) +* [Scala.js](https://www.scala-js.org/) +* [Scala Native](https://scala-native.org/) +* [Scala Reddit](https://www.reddit.com/r/scala/) +* [Official Scala Discord](https://discord.com/invite/scala) +* [Official Scala users forum](https://users.scala-lang.org/) +* [StackOverflow](http://stackoverflow.com/questions/tagged/scala) * [Scala Exercises](https://www.scala-exercises.org/std_lib) * [The Neophyte's Guide to Scala](https://danielwestheide.com/books/the-neophytes-guide-to-scala/) -## Linting +## Linting and formatting -Scala projects can be linted for further code analysis via a third party tool - [Scalastyle](http://www.scalastyle.org/). - -There are several ways of using Scalastyle including Maven, SBT, Gradle, IntelliJ and Eclipse. For instructions on usage visit [Scalastyle](http://www.scalastyle.org/). +- [scalafmt](https://scalameta.org/scalafmt/) - most popular formatting +- [scalafix](https://scalacenter.github.io/scalafix/) - linting and refactoring tool +- [WartRemover](https://www.wartremover.org/) - alternative linting tool +- [sbt-tpolecat](https://github.com/typelevel/sbt-tpolecat) - a set of recommended compiler options with linting and warning in a form of a sbt plugin diff --git a/docs/TESTS.md b/docs/TESTS.md index b61f008a..d1a6d963 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -6,8 +6,11 @@ With `sbt` installed, the tests can be executed from the command line with: $ sbt test ``` -You can also use `sbt` to re-run your tests whenever the source files change: +Note that executing the `sbt test` every time will be slow, as it'll re-initializes the `sbt` on each invocation. +`sbt` works like a shell, once it's started you can run commands inside it. + +For example, you can use `sbt` to re-run your tests whenever the source files change: ```bash $ sbt >~ test @@ -16,9 +19,12 @@ $ sbt Note that all tests have been disabled except the first one for you to work on. To continue, just remove the `pending` keyword from the beginning of each test case. +Go [here](https://www.scala-sbt.org/) to learn more about the `sbt`. + + Tests can also be run within the following IDEs +* [Metals](https://scalameta.org/metals/docs/#running-tests) * [IntelliJ IDEA with Scala Plugin](https://www.jetbrains.com/idea/) -* [ScalaIDE](http://scala-ide.org/index.html) -* [NetBeans with Scala Plugin](https://netbeans.org/) + diff --git a/exercises/concept/basics/build.sbt b/exercises/concept/basics/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/concept/basics/build.sbt +++ b/exercises/concept/basics/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/concept/basics/project/build.properties b/exercises/concept/basics/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/concept/basics/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/accumulate/build.sbt b/exercises/practice/accumulate/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/accumulate/build.sbt +++ b/exercises/practice/accumulate/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/accumulate/project/build.properties b/exercises/practice/accumulate/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/accumulate/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/acronym/build.sbt b/exercises/practice/acronym/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/acronym/build.sbt +++ b/exercises/practice/acronym/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/acronym/project/build.properties b/exercises/practice/acronym/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/acronym/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/all-your-base/build.sbt b/exercises/practice/all-your-base/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/all-your-base/build.sbt +++ b/exercises/practice/all-your-base/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/all-your-base/project/build.properties b/exercises/practice/all-your-base/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/all-your-base/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/allergies/build.sbt b/exercises/practice/allergies/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/allergies/build.sbt +++ b/exercises/practice/allergies/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/allergies/project/build.properties b/exercises/practice/allergies/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/allergies/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/alphametics/build.sbt b/exercises/practice/alphametics/build.sbt index 1cd653fc..b5469283 100644 --- a/exercises/practice/alphametics/build.sbt +++ b/exercises/practice/alphametics/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" diff --git a/exercises/practice/alphametics/project/build.properties b/exercises/practice/alphametics/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/alphametics/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/anagram/build.sbt b/exercises/practice/anagram/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/anagram/build.sbt +++ b/exercises/practice/anagram/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/anagram/project/build.properties b/exercises/practice/anagram/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/anagram/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/armstrong-numbers/build.sbt b/exercises/practice/armstrong-numbers/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/armstrong-numbers/build.sbt +++ b/exercises/practice/armstrong-numbers/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/armstrong-numbers/project/build.properties b/exercises/practice/armstrong-numbers/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/armstrong-numbers/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/atbash-cipher/build.sbt b/exercises/practice/atbash-cipher/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/atbash-cipher/build.sbt +++ b/exercises/practice/atbash-cipher/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/atbash-cipher/project/build.properties b/exercises/practice/atbash-cipher/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/atbash-cipher/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/bank-account/build.sbt b/exercises/practice/bank-account/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/bank-account/build.sbt +++ b/exercises/practice/bank-account/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/bank-account/project/build.properties b/exercises/practice/bank-account/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/bank-account/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/beer-song/build.sbt b/exercises/practice/beer-song/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/beer-song/build.sbt +++ b/exercises/practice/beer-song/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/beer-song/project/build.properties b/exercises/practice/beer-song/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/beer-song/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/binary-search-tree/.meta/Example.scala b/exercises/practice/binary-search-tree/.meta/Example.scala index 0d13fb15..0bfae0d6 100644 --- a/exercises/practice/binary-search-tree/.meta/Example.scala +++ b/exercises/practice/binary-search-tree/.meta/Example.scala @@ -1,5 +1,7 @@ +import math.Ordered.orderingToOrdered + case class Bst[+T](value: T, left: Option[Bst[T]], right: Option[Bst[T]]) { - def insert[U >: T <% Ordered[U]](x: U): Bst[U] = { + def insert[U >: T](x: U)(using Ordering[U]): Bst[U] = { def insert(x: U, node: Option[Bst[U]]): Option[Bst[U]] = node match { case Some(n) => Option(n.insert(x)) @@ -12,7 +14,7 @@ case class Bst[+T](value: T, left: Option[Bst[T]], right: Option[Bst[T]]) { } object Bst { - def fromList[T <% Ordered[T]](l: List[T]): Bst[T] = l match { + def fromList[T](l: List[T])(using Ordering[T]): Bst[T] = l match { case x::xs => xs.foldLeft(Bst(x, None, None))((r, e) => r.insert(e)) case x::Nil => Bst(x, None, None) case Nil => throw new IllegalArgumentException("Tree must not be empty") @@ -26,4 +28,4 @@ object Bst { } def apply[T](x: T): Bst[T] = Bst(x, None, None) -} \ No newline at end of file +} diff --git a/exercises/practice/binary-search-tree/build.sbt b/exercises/practice/binary-search-tree/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/binary-search-tree/build.sbt +++ b/exercises/practice/binary-search-tree/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/binary-search-tree/project/build.properties b/exercises/practice/binary-search-tree/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/binary-search-tree/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/binary-search/.meta/Example.scala b/exercises/practice/binary-search/.meta/Example.scala index 088a3349..82118935 100644 --- a/exercises/practice/binary-search/.meta/Example.scala +++ b/exercises/practice/binary-search/.meta/Example.scala @@ -1,4 +1,5 @@ import scala.annotation.tailrec +import scala.math.Ordered.orderingToOrdered object BinarySearch { def find[T](seq: Seq[T], value: T)(implicit ord: T => Ordered[T]): Option[Int] diff --git a/exercises/practice/binary-search/build.sbt b/exercises/practice/binary-search/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/binary-search/build.sbt +++ b/exercises/practice/binary-search/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/binary-search/project/build.properties b/exercises/practice/binary-search/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/binary-search/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/binary/build.sbt b/exercises/practice/binary/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/binary/build.sbt +++ b/exercises/practice/binary/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/binary/project/build.properties b/exercises/practice/binary/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/binary/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/bob/build.sbt b/exercises/practice/bob/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/bob/build.sbt +++ b/exercises/practice/bob/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/bob/project/build.properties b/exercises/practice/bob/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/bob/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/book-store/build.sbt b/exercises/practice/book-store/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/book-store/build.sbt +++ b/exercises/practice/book-store/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/book-store/project/build.properties b/exercises/practice/book-store/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/book-store/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/bowling/build.sbt b/exercises/practice/bowling/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/bowling/build.sbt +++ b/exercises/practice/bowling/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/bowling/project/build.properties b/exercises/practice/bowling/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/bowling/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/change/build.sbt b/exercises/practice/change/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/change/build.sbt +++ b/exercises/practice/change/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/change/project/build.properties b/exercises/practice/change/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/change/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/circular-buffer/build.sbt b/exercises/practice/circular-buffer/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/circular-buffer/build.sbt +++ b/exercises/practice/circular-buffer/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/circular-buffer/project/build.properties b/exercises/practice/circular-buffer/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/circular-buffer/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/clock/build.sbt b/exercises/practice/clock/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/clock/build.sbt +++ b/exercises/practice/clock/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/clock/project/build.properties b/exercises/practice/clock/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/clock/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/collatz-conjecture/build.sbt b/exercises/practice/collatz-conjecture/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/collatz-conjecture/build.sbt +++ b/exercises/practice/collatz-conjecture/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/collatz-conjecture/project/build.properties b/exercises/practice/collatz-conjecture/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/collatz-conjecture/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/complex-numbers/build.sbt b/exercises/practice/complex-numbers/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/complex-numbers/build.sbt +++ b/exercises/practice/complex-numbers/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/complex-numbers/project/build.properties b/exercises/practice/complex-numbers/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/complex-numbers/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/complex-numbers/src/test/scala/ComplexNumberTest.scala b/exercises/practice/complex-numbers/src/test/scala/ComplexNumberTest.scala index f18ecc38..3d18b6a0 100644 --- a/exercises/practice/complex-numbers/src/test/scala/ComplexNumberTest.scala +++ b/exercises/practice/complex-numbers/src/test/scala/ComplexNumberTest.scala @@ -7,7 +7,7 @@ class ComplexNumberTest extends AnyFunSuite with Matchers { private val equalityEpsilon = 1e-15 - private def assertEquals(c1: ComplexNumber, c2: ComplexNumber) { + private def assertEquals(c1: ComplexNumber, c2: ComplexNumber) = { c1.real should be (c2.real +- equalityEpsilon) c1.imaginary should be (c2.imaginary +- equalityEpsilon) } diff --git a/exercises/practice/connect/build.sbt b/exercises/practice/connect/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/connect/build.sbt +++ b/exercises/practice/connect/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/connect/project/build.properties b/exercises/practice/connect/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/connect/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/crypto-square/build.sbt b/exercises/practice/crypto-square/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/crypto-square/build.sbt +++ b/exercises/practice/crypto-square/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/crypto-square/project/build.properties b/exercises/practice/crypto-square/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/crypto-square/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/custom-set/build.sbt b/exercises/practice/custom-set/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/custom-set/build.sbt +++ b/exercises/practice/custom-set/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/custom-set/project/build.properties b/exercises/practice/custom-set/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/custom-set/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/darts/build.sbt b/exercises/practice/darts/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/darts/build.sbt +++ b/exercises/practice/darts/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/darts/project/build.properties b/exercises/practice/darts/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/darts/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/diamond/build.sbt b/exercises/practice/diamond/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/diamond/build.sbt +++ b/exercises/practice/diamond/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/diamond/project/build.properties b/exercises/practice/diamond/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/diamond/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/difference-of-squares/build.sbt b/exercises/practice/difference-of-squares/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/difference-of-squares/build.sbt +++ b/exercises/practice/difference-of-squares/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/difference-of-squares/project/build.properties b/exercises/practice/difference-of-squares/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/difference-of-squares/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/dominoes/build.sbt b/exercises/practice/dominoes/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/dominoes/build.sbt +++ b/exercises/practice/dominoes/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/dominoes/project/build.properties b/exercises/practice/dominoes/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/dominoes/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/etl/build.sbt b/exercises/practice/etl/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/etl/build.sbt +++ b/exercises/practice/etl/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/etl/project/build.properties b/exercises/practice/etl/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/etl/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/flatten-array/build.sbt b/exercises/practice/flatten-array/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/flatten-array/build.sbt +++ b/exercises/practice/flatten-array/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/flatten-array/project/build.properties b/exercises/practice/flatten-array/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/flatten-array/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/food-chain/build.sbt b/exercises/practice/food-chain/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/food-chain/build.sbt +++ b/exercises/practice/food-chain/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/food-chain/project/build.properties b/exercises/practice/food-chain/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/food-chain/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/forth/build.sbt b/exercises/practice/forth/build.sbt index 1cd653fc..b5469283 100644 --- a/exercises/practice/forth/build.sbt +++ b/exercises/practice/forth/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" diff --git a/exercises/practice/forth/project/build.properties b/exercises/practice/forth/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/forth/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/gigasecond/build.sbt b/exercises/practice/gigasecond/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/gigasecond/build.sbt +++ b/exercises/practice/gigasecond/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/gigasecond/project/build.properties b/exercises/practice/gigasecond/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/gigasecond/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/grade-school/.meta/Example.scala b/exercises/practice/grade-school/.meta/Example.scala index 900d4453..789e027f 100644 --- a/exercises/practice/grade-school/.meta/Example.scala +++ b/exercises/practice/grade-school/.meta/Example.scala @@ -7,7 +7,7 @@ class School { def db: DB = _db - def add(name: String, g: Int) { + def add(name: String, g: Int) = { _db = db.updated(g, grade(g) :+ name) } diff --git a/exercises/practice/grade-school/build.sbt b/exercises/practice/grade-school/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/grade-school/build.sbt +++ b/exercises/practice/grade-school/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/grade-school/project/build.properties b/exercises/practice/grade-school/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/grade-school/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/grains/build.sbt b/exercises/practice/grains/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/grains/build.sbt +++ b/exercises/practice/grains/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/grains/project/build.properties b/exercises/practice/grains/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/grains/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/hamming/build.sbt b/exercises/practice/hamming/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/hamming/build.sbt +++ b/exercises/practice/hamming/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/hamming/project/build.properties b/exercises/practice/hamming/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/hamming/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/hello-world/build.sbt b/exercises/practice/hello-world/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/hello-world/build.sbt +++ b/exercises/practice/hello-world/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/hello-world/project/build.properties b/exercises/practice/hello-world/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/hello-world/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/hexadecimal/build.sbt b/exercises/practice/hexadecimal/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/hexadecimal/build.sbt +++ b/exercises/practice/hexadecimal/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/hexadecimal/project/build.properties b/exercises/practice/hexadecimal/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/hexadecimal/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/high-scores/build.sbt b/exercises/practice/high-scores/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/high-scores/build.sbt +++ b/exercises/practice/high-scores/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/high-scores/project/build.properties b/exercises/practice/high-scores/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/high-scores/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/house/build.sbt b/exercises/practice/house/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/house/build.sbt +++ b/exercises/practice/house/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/house/project/build.properties b/exercises/practice/house/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/house/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/isogram/build.sbt b/exercises/practice/isogram/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/isogram/build.sbt +++ b/exercises/practice/isogram/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/isogram/project/build.properties b/exercises/practice/isogram/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/isogram/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/kindergarten-garden/build.sbt b/exercises/practice/kindergarten-garden/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/kindergarten-garden/build.sbt +++ b/exercises/practice/kindergarten-garden/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/kindergarten-garden/project/build.properties b/exercises/practice/kindergarten-garden/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/kindergarten-garden/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/largest-series-product/build.sbt b/exercises/practice/largest-series-product/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/largest-series-product/build.sbt +++ b/exercises/practice/largest-series-product/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/largest-series-product/project/build.properties b/exercises/practice/largest-series-product/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/largest-series-product/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/leap/build.sbt b/exercises/practice/leap/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/leap/build.sbt +++ b/exercises/practice/leap/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/leap/project/build.properties b/exercises/practice/leap/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/leap/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/lens-person/.meta/Example.scala b/exercises/practice/lens-person/.meta/Example.scala index 52e973ac..de0e2fd1 100644 --- a/exercises/practice/lens-person/.meta/Example.scala +++ b/exercises/practice/lens-person/.meta/Example.scala @@ -78,7 +78,7 @@ trait MonocleSolution extends ToBeImplemented { def gregorianToEpochDay(g: Gregorian): EpochDay = LocalDate.of(g._year, g._month, g._dayOfMonth).toEpochDay - PIso(epochDayToGregorian _)(gregorianToEpochDay _) + PIso(epochDayToGregorian)(gregorianToEpochDay) } val setBirthMonth: Int => Person => Person = diff --git a/exercises/practice/lens-person/build.sbt b/exercises/practice/lens-person/build.sbt index 4608fed4..8fd75f59 100644 --- a/exercises/practice/lens-person/build.sbt +++ b/exercises/practice/lens-person/build.sbt @@ -1,12 +1,14 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test -val monocleVersion = "2.0.0" +val monocleVersion = "3.2.0" libraryDependencies ++= Seq( - "com.github.julien-truffaut" %% "monocle-core" % monocleVersion, - "com.github.julien-truffaut" %% "monocle-macro" % monocleVersion) + "dev.optics" %% "monocle-core" % monocleVersion, + "dev.optics" %% "monocle-macro" % monocleVersion +) -libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.2.28" +// used for solution example only, not provided in the test runner +libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.3.8" diff --git a/exercises/practice/lens-person/project/build.properties b/exercises/practice/lens-person/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/lens-person/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/linked-list/build.sbt b/exercises/practice/linked-list/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/linked-list/build.sbt +++ b/exercises/practice/linked-list/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/linked-list/project/build.properties b/exercises/practice/linked-list/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/linked-list/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/luhn/build.sbt b/exercises/practice/luhn/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/luhn/build.sbt +++ b/exercises/practice/luhn/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/luhn/project/build.properties b/exercises/practice/luhn/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/luhn/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/matching-brackets/build.sbt b/exercises/practice/matching-brackets/build.sbt index 1cd653fc..b5469283 100644 --- a/exercises/practice/matching-brackets/build.sbt +++ b/exercises/practice/matching-brackets/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" diff --git a/exercises/practice/matching-brackets/project/build.properties b/exercises/practice/matching-brackets/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/matching-brackets/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/matrix/build.sbt b/exercises/practice/matrix/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/matrix/build.sbt +++ b/exercises/practice/matrix/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/matrix/project/build.properties b/exercises/practice/matrix/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/matrix/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/meetup/build.sbt b/exercises/practice/meetup/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/meetup/build.sbt +++ b/exercises/practice/meetup/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/meetup/project/build.properties b/exercises/practice/meetup/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/meetup/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/minesweeper/build.sbt b/exercises/practice/minesweeper/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/minesweeper/build.sbt +++ b/exercises/practice/minesweeper/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/minesweeper/project/build.properties b/exercises/practice/minesweeper/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/minesweeper/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/nth-prime/build.sbt b/exercises/practice/nth-prime/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/nth-prime/build.sbt +++ b/exercises/practice/nth-prime/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/nth-prime/project/build.properties b/exercises/practice/nth-prime/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/nth-prime/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/nucleotide-count/build.sbt b/exercises/practice/nucleotide-count/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/nucleotide-count/build.sbt +++ b/exercises/practice/nucleotide-count/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/nucleotide-count/project/build.properties b/exercises/practice/nucleotide-count/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/nucleotide-count/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/ocr-numbers/build.sbt b/exercises/practice/ocr-numbers/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/ocr-numbers/build.sbt +++ b/exercises/practice/ocr-numbers/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/ocr-numbers/project/build.properties b/exercises/practice/ocr-numbers/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/ocr-numbers/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/octal/build.sbt b/exercises/practice/octal/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/octal/build.sbt +++ b/exercises/practice/octal/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/octal/project/build.properties b/exercises/practice/octal/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/octal/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/palindrome-products/build.sbt b/exercises/practice/palindrome-products/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/palindrome-products/build.sbt +++ b/exercises/practice/palindrome-products/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/palindrome-products/project/build.properties b/exercises/practice/palindrome-products/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/palindrome-products/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/pangram/build.sbt b/exercises/practice/pangram/build.sbt index f9b3bb69..bbbaf96f 100644 --- a/exercises/practice/pangram/build.sbt +++ b/exercises/practice/pangram/build.sbt @@ -1,5 +1,5 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/pangram/project/build.properties b/exercises/practice/pangram/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/pangram/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/parallel-letter-frequency/build.sbt b/exercises/practice/parallel-letter-frequency/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/parallel-letter-frequency/build.sbt +++ b/exercises/practice/parallel-letter-frequency/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/parallel-letter-frequency/project/build.properties b/exercises/practice/parallel-letter-frequency/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/pascals-triangle/build.sbt b/exercises/practice/pascals-triangle/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/pascals-triangle/build.sbt +++ b/exercises/practice/pascals-triangle/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/pascals-triangle/project/build.properties b/exercises/practice/pascals-triangle/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/pascals-triangle/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/perfect-numbers/build.sbt b/exercises/practice/perfect-numbers/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/perfect-numbers/build.sbt +++ b/exercises/practice/perfect-numbers/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/perfect-numbers/project/build.properties b/exercises/practice/perfect-numbers/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/perfect-numbers/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/phone-number/.meta/Example.scala b/exercises/practice/phone-number/.meta/Example.scala index 1789589a..4dfbb172 100644 --- a/exercises/practice/phone-number/.meta/Example.scala +++ b/exercises/practice/phone-number/.meta/Example.scala @@ -1,11 +1,11 @@ object PhoneNumber { type Parts = (String, String, String) - private[this] val AreaCodeLength = 3 - private[this] val PrefixLength = 3 - private[this] val LineNumberLength = 4 + private val AreaCodeLength = 3 + private val PrefixLength = 3 + private val LineNumberLength = 4 - private[this] val PhoneNumberPattern = { + private val PhoneNumberPattern = { def part(length: Int) = s"(\\d{$length})" s"""1?${part(AreaCodeLength)}${part(PrefixLength)}${part(LineNumberLength)}""".r } diff --git a/exercises/practice/phone-number/build.sbt b/exercises/practice/phone-number/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/phone-number/build.sbt +++ b/exercises/practice/phone-number/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/phone-number/project/build.properties b/exercises/practice/phone-number/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/phone-number/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/pig-latin/build.sbt b/exercises/practice/pig-latin/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/pig-latin/build.sbt +++ b/exercises/practice/pig-latin/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/pig-latin/project/build.properties b/exercises/practice/pig-latin/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/pig-latin/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/prime-factors/build.sbt b/exercises/practice/prime-factors/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/prime-factors/build.sbt +++ b/exercises/practice/prime-factors/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/prime-factors/project/build.properties b/exercises/practice/prime-factors/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/prime-factors/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/protein-translation/build.sbt b/exercises/practice/protein-translation/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/protein-translation/build.sbt +++ b/exercises/practice/protein-translation/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/protein-translation/project/build.properties b/exercises/practice/protein-translation/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/protein-translation/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/pythagorean-triplet/build.sbt b/exercises/practice/pythagorean-triplet/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/pythagorean-triplet/build.sbt +++ b/exercises/practice/pythagorean-triplet/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/pythagorean-triplet/project/build.properties b/exercises/practice/pythagorean-triplet/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/pythagorean-triplet/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/queen-attack/build.sbt b/exercises/practice/queen-attack/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/queen-attack/build.sbt +++ b/exercises/practice/queen-attack/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/queen-attack/project/build.properties b/exercises/practice/queen-attack/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/queen-attack/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/rail-fence-cipher/build.sbt b/exercises/practice/rail-fence-cipher/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/rail-fence-cipher/build.sbt +++ b/exercises/practice/rail-fence-cipher/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/rail-fence-cipher/project/build.properties b/exercises/practice/rail-fence-cipher/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/rail-fence-cipher/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/raindrops/build.sbt b/exercises/practice/raindrops/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/raindrops/build.sbt +++ b/exercises/practice/raindrops/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/raindrops/project/build.properties b/exercises/practice/raindrops/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/raindrops/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/reverse-string/build.sbt b/exercises/practice/reverse-string/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/reverse-string/build.sbt +++ b/exercises/practice/reverse-string/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/reverse-string/project/build.properties b/exercises/practice/reverse-string/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/reverse-string/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/rna-transcription/build.sbt b/exercises/practice/rna-transcription/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/rna-transcription/build.sbt +++ b/exercises/practice/rna-transcription/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/rna-transcription/project/build.properties b/exercises/practice/rna-transcription/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/rna-transcription/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/robot-name/build.sbt b/exercises/practice/robot-name/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/robot-name/build.sbt +++ b/exercises/practice/robot-name/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/robot-name/project/build.properties b/exercises/practice/robot-name/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/robot-name/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/robot-simulator/build.sbt b/exercises/practice/robot-simulator/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/robot-simulator/build.sbt +++ b/exercises/practice/robot-simulator/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/robot-simulator/project/build.properties b/exercises/practice/robot-simulator/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/robot-simulator/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/roman-numerals/build.sbt b/exercises/practice/roman-numerals/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/roman-numerals/build.sbt +++ b/exercises/practice/roman-numerals/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/roman-numerals/project/build.properties b/exercises/practice/roman-numerals/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/roman-numerals/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/rotational-cipher/build.sbt b/exercises/practice/rotational-cipher/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/rotational-cipher/build.sbt +++ b/exercises/practice/rotational-cipher/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/rotational-cipher/project/build.properties b/exercises/practice/rotational-cipher/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/rotational-cipher/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/run-length-encoding/build.sbt b/exercises/practice/run-length-encoding/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/run-length-encoding/build.sbt +++ b/exercises/practice/run-length-encoding/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/run-length-encoding/project/build.properties b/exercises/practice/run-length-encoding/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/run-length-encoding/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/saddle-points/build.sbt b/exercises/practice/saddle-points/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/saddle-points/build.sbt +++ b/exercises/practice/saddle-points/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/saddle-points/project/build.properties b/exercises/practice/saddle-points/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/saddle-points/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/say/build.sbt b/exercises/practice/say/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/say/build.sbt +++ b/exercises/practice/say/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/say/project/build.properties b/exercises/practice/say/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/say/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/scrabble-score/build.sbt b/exercises/practice/scrabble-score/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/scrabble-score/build.sbt +++ b/exercises/practice/scrabble-score/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/scrabble-score/project/build.properties b/exercises/practice/scrabble-score/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/scrabble-score/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/secret-handshake/build.sbt b/exercises/practice/secret-handshake/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/secret-handshake/build.sbt +++ b/exercises/practice/secret-handshake/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/secret-handshake/project/build.properties b/exercises/practice/secret-handshake/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/secret-handshake/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/series/build.sbt b/exercises/practice/series/build.sbt index 3acb69f8..62309c0a 100644 --- a/exercises/practice/series/build.sbt +++ b/exercises/practice/series/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/series/project/build.properties b/exercises/practice/series/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/series/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/sgf-parsing/.meta/Example.scala b/exercises/practice/sgf-parsing/.meta/Example.scala index 1c09a73c..d2d29fd8 100644 --- a/exercises/practice/sgf-parsing/.meta/Example.scala +++ b/exercises/practice/sgf-parsing/.meta/Example.scala @@ -47,12 +47,12 @@ object Sgf extends RegexParsers { private val propValue: Parser[String] = "[" ~ rep1(propValuePart) ~ "]" ^^ { - case _ ~ values ~ _ => values mkString + case _ ~ values ~ _ => values.mkString } named "propValue" private val propValuePart: Parser[String] = { implicit class AsStringParser(self: String) { def p: Parser[String] = self } - val ignore = const("") _ + val ignore = const("") val escapedNewline: Parser[String] = "\\\n".p ^^ ignore val escapedChar: Parser[String] = """\\.""".r ^^ (_.takeRight(1)) diff --git a/exercises/practice/sgf-parsing/build.sbt b/exercises/practice/sgf-parsing/build.sbt index 714d7252..2b7e28ab 100644 --- a/exercises/practice/sgf-parsing/build.sbt +++ b/exercises/practice/sgf-parsing/build.sbt @@ -1,5 +1,5 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" diff --git a/exercises/practice/sgf-parsing/project/build.properties b/exercises/practice/sgf-parsing/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/sgf-parsing/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/sieve/.meta/Example.scala b/exercises/practice/sieve/.meta/Example.scala index 32924ccd..1e1153b8 100644 --- a/exercises/practice/sieve/.meta/Example.scala +++ b/exercises/practice/sieve/.meta/Example.scala @@ -6,7 +6,7 @@ object Sieve { val primes = mutable.HashSet.empty ++ (2 to upperBound) // Remove multiples of a possiblePrime from the primes set. - def checkPrime(possiblePrime: Int) { + def checkPrime(possiblePrime: Int) = { if (primes contains possiblePrime) { // remove multiples of possiblePrime from set val possibleSquared = possiblePrime * possiblePrime diff --git a/exercises/practice/sieve/build.sbt b/exercises/practice/sieve/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/sieve/build.sbt +++ b/exercises/practice/sieve/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/sieve/project/build.properties b/exercises/practice/sieve/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/sieve/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/simple-cipher/build.sbt b/exercises/practice/simple-cipher/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/simple-cipher/build.sbt +++ b/exercises/practice/simple-cipher/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/simple-cipher/project/build.properties b/exercises/practice/simple-cipher/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/simple-cipher/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/simple-linked-list/build.sbt b/exercises/practice/simple-linked-list/build.sbt index 7a38faa9..3d94b853 100644 --- a/exercises/practice/simple-linked-list/build.sbt +++ b/exercises/practice/simple-linked-list/build.sbt @@ -1,5 +1,5 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" -libraryDependencies += "org.scalatestplus" %% "scalacheck-1-15" % "3.2.9.0" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test +libraryDependencies += "org.scalatestplus" %% "scalacheck-1-18" % "3.2.19.0" % Test diff --git a/exercises/practice/simple-linked-list/project/build.properties b/exercises/practice/simple-linked-list/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/simple-linked-list/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala b/exercises/practice/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala index a90acd13..f41802f7 100644 --- a/exercises/practice/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala +++ b/exercises/practice/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala @@ -65,21 +65,21 @@ class SimpleLinkedListTest extends AnyFlatSpec with Matchers with ScalaCheckDriv it should "handle arbitrary list fromSeq toSeq" in { pending - forAll { seq: Seq[Int] => + forAll { (seq: Seq[Int]) => assert(SimpleLinkedList.fromSeq(seq).toSeq == seq) } } it should "handle reverse arbitrary list " in { pending - forAll { seq: Seq[Int] => + forAll { (seq: Seq[Int]) => assert(SimpleLinkedList.fromSeq(seq).reverse.toSeq == seq.reverse) } } it should "reverse arbitrary list back to original" in { pending - forAll { list: SimpleLinkedList[Int] => + forAll { (list: SimpleLinkedList[Int]) => assert(list.reverse.reverse.toSeq == list.toSeq) } } @@ -90,7 +90,7 @@ class SimpleLinkedListTest extends AnyFlatSpec with Matchers with ScalaCheckDriv (0 until i).foldLeft(list)((acc, j) => acc.next).value } - forAll { xs: Seq[Int] => + forAll { (xs: Seq[Int]) => whenever(xs.nonEmpty) { val list = SimpleLinkedList.fromSeq(xs) xs.indices.foreach { @@ -102,7 +102,7 @@ class SimpleLinkedListTest extends AnyFlatSpec with Matchers with ScalaCheckDriv it should "return original arbitrary list from added list elements" in { pending - forAll { xs: Seq[Int] => + forAll { (xs: Seq[Int]) => val list = xs.foldLeft(SimpleLinkedList[Int]())(_.add(_)) assert(list.toSeq == xs) } @@ -110,7 +110,7 @@ class SimpleLinkedListTest extends AnyFlatSpec with Matchers with ScalaCheckDriv it should "handle arbitrary generics" in { pending - forAll { xs: Seq[String] => + forAll { (xs: Seq[String]) => assert(SimpleLinkedList.fromSeq(xs).toSeq == xs) } } diff --git a/exercises/practice/space-age/build.sbt b/exercises/practice/space-age/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/space-age/build.sbt +++ b/exercises/practice/space-age/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/space-age/project/build.properties b/exercises/practice/space-age/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/space-age/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/spiral-matrix/build.sbt b/exercises/practice/spiral-matrix/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/spiral-matrix/build.sbt +++ b/exercises/practice/spiral-matrix/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/spiral-matrix/project/build.properties b/exercises/practice/spiral-matrix/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/spiral-matrix/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/strain/build.sbt b/exercises/practice/strain/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/strain/build.sbt +++ b/exercises/practice/strain/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/strain/project/build.properties b/exercises/practice/strain/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/strain/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/sublist/build.sbt b/exercises/practice/sublist/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/sublist/build.sbt +++ b/exercises/practice/sublist/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/sublist/project/build.properties b/exercises/practice/sublist/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/sublist/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/sum-of-multiples/build.sbt b/exercises/practice/sum-of-multiples/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/sum-of-multiples/build.sbt +++ b/exercises/practice/sum-of-multiples/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/sum-of-multiples/project/build.properties b/exercises/practice/sum-of-multiples/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/sum-of-multiples/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/triangle/build.sbt b/exercises/practice/triangle/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/triangle/build.sbt +++ b/exercises/practice/triangle/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/triangle/project/build.properties b/exercises/practice/triangle/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/triangle/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/trinary/build.sbt b/exercises/practice/trinary/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/trinary/build.sbt +++ b/exercises/practice/trinary/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/trinary/project/build.properties b/exercises/practice/trinary/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/trinary/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/two-fer/build.sbt b/exercises/practice/two-fer/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/two-fer/build.sbt +++ b/exercises/practice/two-fer/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/two-fer/project/build.properties b/exercises/practice/two-fer/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/two-fer/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/variable-length-quantity/build.sbt b/exercises/practice/variable-length-quantity/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/variable-length-quantity/build.sbt +++ b/exercises/practice/variable-length-quantity/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/variable-length-quantity/project/build.properties b/exercises/practice/variable-length-quantity/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/variable-length-quantity/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/word-count/build.sbt b/exercises/practice/word-count/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/word-count/build.sbt +++ b/exercises/practice/word-count/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/word-count/project/build.properties b/exercises/practice/word-count/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/word-count/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/wordy/build.sbt b/exercises/practice/wordy/build.sbt index 1cd653fc..b5469283 100644 --- a/exercises/practice/wordy/build.sbt +++ b/exercises/practice/wordy/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" diff --git a/exercises/practice/wordy/project/build.properties b/exercises/practice/wordy/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/wordy/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/yacht/build.sbt b/exercises/practice/yacht/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/yacht/build.sbt +++ b/exercises/practice/yacht/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/yacht/project/build.properties b/exercises/practice/yacht/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/yacht/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/zebra-puzzle/build.sbt b/exercises/practice/zebra-puzzle/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/zebra-puzzle/build.sbt +++ b/exercises/practice/zebra-puzzle/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/zebra-puzzle/project/build.properties b/exercises/practice/zebra-puzzle/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/zebra-puzzle/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/zipper/build.sbt b/exercises/practice/zipper/build.sbt index 6b92ed9c..803f8dc0 100644 --- a/exercises/practice/zipper/build.sbt +++ b/exercises/practice/zipper/build.sbt @@ -1,3 +1,3 @@ -scalaVersion := "2.13.6" +scalaVersion := "3.4.2" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % "test" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/zipper/project/build.properties b/exercises/practice/zipper/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/zipper/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/project/Build.scala b/project/Build.scala deleted file mode 100644 index 8cef6db1..00000000 --- a/project/Build.scala +++ /dev/null @@ -1,54 +0,0 @@ -import java.io.File - -import sbt.Keys._ -import sbt._ - -import scala.io.Source -import scala.util.parsing.json.{JSONArray, JSONObject, JSON} - -object XScalaBuild extends Build { - - scalaVersion := "2.12.8" - name := "xscala" - - val commonSettings = Seq( - updateOptions := updateOptions.value.withCachedResolution(true), - - (unmanagedSources in Test) <<= (unmanagedSources in Test, sourceManaged in Test) map { - case (testSources, managedTestDir) => - copyTestsAndStripPending(testSources, managedTestDir) - } - ) - - override def projects: Seq[Project] = { - fetchProblemNames("config.json").map { - problemName => Project(problemName, new File(problemName)).settings(commonSettings:_*) - } - } - - def copyTestsAndStripPending(tests: Seq[File], managedSourceDir: File): Seq[File] = { - tests.map { originalTestFile => - val filename = originalTestFile.name - val newTestFile = managedSourceDir / filename - IO.writeLines(newTestFile, IO.readLines(originalTestFile).filter(_.trim != "pending")) - newTestFile - } - } - - def fetchProblemNames(configJsonFile: String): Seq[String] = { - val configStr = Source.fromFile(configJsonFile, "UTF-8").getLines().mkString - val configObj = JSON - .parseRaw(configStr) - .map(_.asInstanceOf[JSONObject].obj) - .getOrElse { - throw new IllegalArgumentException(s"Could not parse $configJsonFile as JSON") - } - configObj - .get("exercises") - .map(_.asInstanceOf[JSONArray].list) - .getOrElse { - throw new IllegalArgumentException(s"Could not find array 'exercises' in $configJsonFile") - } - .collect { case problem: JSONObject => problem.obj("slug").toString } - } -} diff --git a/project/build.properties b/project/build.properties index 176a863a..ee4c672c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.9 \ No newline at end of file +sbt.version=1.10.1 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 00000000..3f4876f6 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1,2 @@ +addSbtPlugin("org.playframework.twirl" % "sbt-twirl" % "2.0.7") + diff --git a/testgen/build.sbt b/testgen/build.sbt deleted file mode 100644 index 812c3ead..00000000 --- a/testgen/build.sbt +++ /dev/null @@ -1,17 +0,0 @@ -name := "ExcercismScalaTestGenerator" - -scalaVersion := "2.13.6" - -ThisBuild / scalacOptions ++= Seq("-deprecation") - -lazy val root = (project in file(".")) - .enablePlugins(SbtTwirl) - .settings( - Compile / TwirlKeys.compileTemplates / sourceDirectories - += (baseDirectory.value.getParentFile / "src" / "main" / "twirl")) - -libraryDependencies += "com.typesafe.play" %% "play-json" % "2.9.2" - -libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" - -libraryDependencies += "com.typesafe.play" %% "twirl-api" % "1.5.0" diff --git a/testgen/project/build.properties b/testgen/project/build.properties deleted file mode 100644 index 13ecfea5..00000000 --- a/testgen/project/build.properties +++ /dev/null @@ -1,2 +0,0 @@ -sbt.version=1.6.1 - diff --git a/testgen/project/plugins.sbt b/testgen/project/plugins.sbt deleted file mode 100644 index 8675a4d9..00000000 --- a/testgen/project/plugins.sbt +++ /dev/null @@ -1,2 +0,0 @@ -addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.5.1") - diff --git a/testgen/src/main/scala/AcronymTestGenerator.scala b/testgen/src/main/scala/AcronymTestGenerator.scala deleted file mode 100644 index 7a36408b..00000000 --- a/testgen/src/main/scala/AcronymTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import testgen._ -import TestSuiteBuilder._ -import java.io.File - -object AcronymTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/acronym.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("phrase")) - println(s"-------------") - println(code) - println(s"-------------") - - TestSuiteBuilder.writeToFile(code, new File("AcronymTest.scala")) - } -} diff --git a/testgen/src/main/scala/AllYourBaseTestGenerator.scala b/testgen/src/main/scala/AllYourBaseTestGenerator.scala deleted file mode 100644 index 88e1f407..00000000 --- a/testgen/src/main/scala/AllYourBaseTestGenerator.scala +++ /dev/null @@ -1,36 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object AllYourBaseTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/all-your-base.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""AllYourBase.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, - fromLabeledTestFromInput("inputBase", "digits", "outputBase")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/AllergiesTestGenerator.scala b/testgen/src/main/scala/AllergiesTestGenerator.scala deleted file mode 100644 index 5b7824fd..00000000 --- a/testgen/src/main/scala/AllergiesTestGenerator.scala +++ /dev/null @@ -1,63 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{fromLabeledTestFromInput, _} -import testgen._ - -object AllergiesTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/allergies.json") - - def toAlergenEnum(s: String): String = - "Allergen." + s.toLowerCase.capitalize - - - def toAllergicToExpected(expected: CanonicalDataParser.Expected): List[(String, Boolean)] = { - expected match { - case Right(xs: List[Map[String, Any]]) => - xs.map(f => (toAlergenEnum(f("substance").asInstanceOf[String]), - f("result").asInstanceOf[Boolean])) - case _ => throw new IllegalStateException - } - } - - def toListExpected(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[String]) => s"List(${xs.map(toAlergenEnum).mkString(", ")})" - case _ => throw new IllegalStateException - } - } - - def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => TestSuiteBuilder.toString(parseResult(name))) mkString ", " - - def getScore(labeledTest: LabeledTest): Int = - labeledTest.result("input").asInstanceOf[Map[String, Any]]("score").asInstanceOf[Int] - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseDataList = - withLabeledList { sut => - labeledTest => - val score = getScore(labeledTest) - val property = labeledTest.property - if ("allergicTo".equals(property)) { - val expected: List[(String, Boolean)] = toAllergicToExpected(labeledTest.expected) - expected.map(e => { - val sutCall = - s"""$sut.$property(${e._1}, $score)""" - val result = e._2.toString - TestCaseData(s"${e._1} - ${labeledTest.description}", sutCall, result) - }) - } else { - val args = sutArgsFromInput(labeledTest.result, "score") - val expected = toListExpected(labeledTest.expected) - val sutCall = - s"""$sut.$property($args)""" - List(TestCaseData(labeledTest.description, sutCall, expected)) - } - } - - val code = TestSuiteBuilder.buildFromList(file, fromLabeledTestFromInput("score")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/AlphameticsTestGenerator.scala b/testgen/src/main/scala/AlphameticsTestGenerator.scala deleted file mode 100644 index d7d14eca..00000000 --- a/testgen/src/main/scala/AlphameticsTestGenerator.scala +++ /dev/null @@ -1,42 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object AlphameticsTestGenerator { - - def mapExpectedToString(arg: Map[String, Int]): String = { - s"Map(${arg.toSeq - .sortBy(_._1) - .map{case (key, value) => "\'" + key.toString + "\' -> " + value.toString} - .mkString(",\n")})" - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(n) => s"Some(${mapExpectedToString(n.asInstanceOf[Map[String, Int]])})" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/alphametics.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("puzzle")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/AnagramTestGenerator.scala b/testgen/src/main/scala/AnagramTestGenerator.scala deleted file mode 100644 index eb2ae589..00000000 --- a/testgen/src/main/scala/AnagramTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object AnagramTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/anagram.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("subject", "candidates")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ArmstrongNumbersTestGenerator.scala b/testgen/src/main/scala/ArmstrongNumbersTestGenerator.scala deleted file mode 100644 index bb88765a..00000000 --- a/testgen/src/main/scala/ArmstrongNumbersTestGenerator.scala +++ /dev/null @@ -1,33 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object ArmstrongNumbersTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/armstrong-numbers.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(b: Boolean) => b.toString - case _ => throw new IllegalStateException() - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/AtbashCipherTestGenerator.scala b/testgen/src/main/scala/AtbashCipherTestGenerator.scala deleted file mode 100644 index 410c4bed..00000000 --- a/testgen/src/main/scala/AtbashCipherTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object AtbashCipherTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/atbash-cipher.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAltFromInput("encode" -> Seq("phrase"), "decode" -> Seq("phrase"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/BeerSongTestGenerator.scala b/testgen/src/main/scala/BeerSongTestGenerator.scala deleted file mode 100644 index 3e5d40ff..00000000 --- a/testgen/src/main/scala/BeerSongTestGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -import testgen._ -import TestSuiteBuilder._ -import java.io.File - -object BeerSongTestGenerator { - - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/beer-song.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[String]) => s"""\"${xs.mkString("\\n")}\\n\"""" - case _ => throw new IllegalArgumentException() - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, - fromLabeledTestFromInput("startBottles", "takeDown")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/BinarySearchTestGenerator.scala b/testgen/src/main/scala/BinarySearchTestGenerator.scala deleted file mode 100644 index 7859fee0..00000000 --- a/testgen/src/main/scala/BinarySearchTestGenerator.scala +++ /dev/null @@ -1,36 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object BinarySearchTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/binarysearch.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(-1) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, - fromLabeledTestFromInput("array", "value")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/BobTestGenerator.scala b/testgen/src/main/scala/BobTestGenerator.scala deleted file mode 100644 index 6a90ae3d..00000000 --- a/testgen/src/main/scala/BobTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object BobTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/bob.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("heyBob")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/BookStoreTestGenerator.scala b/testgen/src/main/scala/BookStoreTestGenerator.scala deleted file mode 100644 index 8e9d86be..00000000 --- a/testgen/src/main/scala/BookStoreTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object BookStoreTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/book-store.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("basket")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/BowlingTestGenerator.scala b/testgen/src/main/scala/BowlingTestGenerator.scala deleted file mode 100644 index d7192a80..00000000 --- a/testgen/src/main/scala/BowlingTestGenerator.scala +++ /dev/null @@ -1,43 +0,0 @@ -import testgen._ -import TestSuiteBuilder.{toString, _} -import java.io.File - -object BowlingTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/bowling.json") - - def previousRolls(parseResult: CanonicalDataParser.ParseResult): String = - TestSuiteBuilder.toString(parseResult("previous_rolls")) - - def roll(parseResult: CanonicalDataParser.ParseResult): Option[String] = - if (parseResult contains "roll") - Some(TestSuiteBuilder.toString(parseResult("roll"))) - else - None - - def fromLabeledTest(argNames: String*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val previousRollsVal = previousRolls(labeledTest.result) - val rollVal = roll(labeledTest.result) - - val isDefined = - labeledTest.expected.fold(Function.const(".isLeft"), Function.const("")) - val sutCall = rollVal match { - case Some(r) => s"""val score = ${previousRollsVal}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).roll($r).score() - score$isDefined""" - case None => s"""val score = ${previousRollsVal}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score() - score$isDefined""" - } - - val expected = - labeledTest.expected.fold(Function.const("true"), x => s"Right($x)") - - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTest("previous_rolls", "roll")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ChangeTestGenerator.scala b/testgen/src/main/scala/ChangeTestGenerator.scala deleted file mode 100644 index eb253c60..00000000 --- a/testgen/src/main/scala/ChangeTestGenerator.scala +++ /dev/null @@ -1,37 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object ChangeTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/change.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(-1) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, - fromLabeledTestFromInput("target", "coins")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ClockTestGenerator.scala b/testgen/src/main/scala/ClockTestGenerator.scala deleted file mode 100644 index 860b19be..00000000 --- a/testgen/src/main/scala/ClockTestGenerator.scala +++ /dev/null @@ -1,69 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object ClockTestGenerator { - private def toString(expected: CanonicalDataParser.Expected): String = - expected.fold(_ => "", TestSuiteBuilder.toString) - - private def expectedToClockStr(expected: CanonicalDataParser.Expected): String = - expected.fold(_ => "", { - case str: String => str.split(':').map(_.toInt).mkString(", ") - case _ => throw new IllegalArgumentException - }) - - private def toOperation(function: String): String = - if (function.equalsIgnoreCase("subtract")) "-" else "+" - - def mapArgToStringForEqual(arg: Any): String = { - arg match { - case vals: Map[String, String] => s"${vals("hour")}, ${vals("minute")}" - case _ => throw new IllegalArgumentException - } - } - - def sutArgsForEqual(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => mapArgToStringForEqual(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def fromLabeledTestAltFromInput(propArgs: (String, Seq[String])*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsAltFromInput(labeledTest.result, propArgs:_*) - - val sutFunc = sutFunction.toString - val sutCall = - if (sutFunc == "create") - s"$sut($args)" - else if (sutFunc == "add" || sutFunc == "subtract") { - val constructorArgs = sutArgsFromInput(labeledTest.result, "hour", "minute") - val functionArgs = sutArgsFromInput(labeledTest.result, "value") - s"$sut($constructorArgs) ${toOperation(sutFunc)} $sut(${functionArgs.stripPrefix("-")})" - } else { - val argsForEqual1 = sutArgsForEqual(labeledTest.result, "clock1") - val argsForEqual2 = sutArgsForEqual(labeledTest.result, "clock2") - s"$sut($argsForEqual1) == $sut($argsForEqual2)" - } - - val expected = - if (sutFunc == "create" || sutFunc == "add" || sutFunc == "subtract") - s"$sut(${expectedToClockStr(labeledTest.expected)})" - else - toString(labeledTest.expected) - - TestCaseData(s"${labeledTest.description}", sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/clock.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAltFromInput("create" -> Seq("hour", "minute"), - "add" -> Seq("hour", "minute", "value"), - "subtract" -> Seq("hour", "minute", "value"), - "equal" -> Seq("clock1"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/CollatzConjectureTestGenerator.scala b/testgen/src/main/scala/CollatzConjectureTestGenerator.scala deleted file mode 100644 index e6fc3e3f..00000000 --- a/testgen/src/main/scala/CollatzConjectureTestGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object CollatzConjectureTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/collatz-conjecture.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ComplexNumberTestGenerator.scala b/testgen/src/main/scala/ComplexNumberTestGenerator.scala deleted file mode 100644 index 97ece811..00000000 --- a/testgen/src/main/scala/ComplexNumberTestGenerator.scala +++ /dev/null @@ -1,129 +0,0 @@ -import java.io.File - -import play.twirl.api.{Template1, Txt} -import testgen.TestSuiteBuilder._ -import testgen._ - -object ComplexNumberTestGenerator { - - def main(args: Array[String]): Unit = { - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(n: Double) => s"""$n +- equalityEpsilon""" - case Right(n: Int) => f"""$n%.1f +- equalityEpsilon""" - case Right(xs: List[Any]) => s"""ComplexNumber(${toStringArg(xs.head)}, ${toStringArg(xs.tail.head)})""" - case _ => throw new IllegalArgumentException() - } - } - - def toStringArg(arg: Any) = { - System.out.println(arg.toString) - arg match { - case "pi" => "math.Pi" - case "e" => "math.E" - case "ln(2)" => "math.log(2)" - case _ => arg.toString - } - } - - def getZArg(labeledTest: LabeledTest): (String, String) = { - val inputMap = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val z = inputMap("z").asInstanceOf[List[Any]] - (toStringArg(z.head), toStringArg(z.tail.head)) - } - - def getZArgs(labeledTest: LabeledTest): ((Int, Int), (Int, Int)) = { - val inputMap = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val z1 = inputMap("z1").asInstanceOf[List[Int]] - val z2 = inputMap("z2").asInstanceOf[List[Int]] - ((z1.head, z1.tail.head), (z2.head, z2.tail.head)) - } - - def createAddTestCase(labeledTest: LabeledTest) = - createArithTestCase(labeledTest, "+") - - def createSubTestCase(labeledTest: LabeledTest) = - createArithTestCase(labeledTest, "-") - - def createMulTestCase(labeledTest: LabeledTest) = - createArithTestCase(labeledTest, "*") - - def createDivTestCase(labeledTest: LabeledTest) = - createArithTestCase(labeledTest, "/") - - def createArithTestCase(labeledTest: LabeledTest, op: String) = { - val (z1, z2) = getZArgs(labeledTest) - val sutCall = - s"""val result = ComplexNumber(${z1._1}, ${z1._2}) $op ComplexNumber(${z2._1}, ${z2._2}) - |assertEquals(result, ${toString(labeledTest.expected)})""".stripMargin - TestCaseData(labeledTest.description, sutCall, "") - } - - def createRealTestCase(labeledTest: LabeledTest) = { - val zArg = getZArg(labeledTest) - val sutCall = s"""ComplexNumber(real = ${zArg._1}).${labeledTest.property} should be (${toString(labeledTest.expected)})""" - TestCaseData(labeledTest.description, sutCall, "") - } - - def createImaginaryTestCase(labeledTest: LabeledTest) = { - val zArg = getZArg(labeledTest) - val sutCall = s"""ComplexNumber(imaginary = ${zArg._2}).${labeledTest.property} should be (${toString(labeledTest.expected)})""" - TestCaseData(labeledTest.description, sutCall, "") - } - - def createAbsTestCase(labeledTest: LabeledTest) = { - val zArg = getZArg(labeledTest) - val sutCall = s"""ComplexNumber(${zArg._1}, ${zArg._2}).${labeledTest.property} should be (${toString(labeledTest.expected)})""" - TestCaseData(labeledTest.description, sutCall, "") - } - - def createConjugateTestCase(labeledTest: LabeledTest) = { - val zArg = getZArg(labeledTest) - val sutCall = - s"""val result = ComplexNumber(${zArg._1}, ${zArg._2}).${labeledTest.property} - |assertEquals(result, ${toString(labeledTest.expected)})""".stripMargin - TestCaseData(labeledTest.description, sutCall, "") - } - - def createExpTestCase(labeledTest: LabeledTest) = { - val zArg = getZArg(labeledTest) - val sutCall = - s"""val result = ComplexNumber.${labeledTest.property}(ComplexNumber(${toStringArg(zArg._1)}, ${toStringArg(zArg._2)})) - |assertEquals(result, ${toString(labeledTest.expected)})""".stripMargin - TestCaseData(labeledTest.description, sutCall, "") - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val property = labeledTest.property - property match { - case "real" => createRealTestCase(labeledTest) - case "imaginary" => createImaginaryTestCase(labeledTest) - case "add" => createAddTestCase(labeledTest) - case "sub" => createSubTestCase(labeledTest) - case "mul" => createMulTestCase(labeledTest) - case "div" => createDivTestCase(labeledTest) - case "abs" => createAbsTestCase(labeledTest) - case "conjugate" => createConjugateTestCase(labeledTest) - case "exp" => createExpTestCase(labeledTest) - case _ => throw new IllegalArgumentException("Unknown test case " + property) - } - } - - val file = new File("src/main/resources/complex-numbers.json") - val template: TestSuiteTemplate = - txt.funSuiteTemplateIgnoreExpected.asInstanceOf[Template1[TestSuiteData, Txt]] - val code = TestSuiteBuilder.build(file = file, - toTestCaseData = fromLabeledTestFromInput("ignored"), - statements = List("private val equalityEpsilon = 1e-15", - "", - "private def assertEquals(c1: ComplexNumber, c2: ComplexNumber) { ", - " c1.real should be (c2.real +- equalityEpsilon)", - " c1.imaginary should be (c2.imaginary +- equalityEpsilon)", - "}"))(template) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ConnectTestGenerator.scala b/testgen/src/main/scala/ConnectTestGenerator.scala deleted file mode 100644 index 1d9ea3ac..00000000 --- a/testgen/src/main/scala/ConnectTestGenerator.scala +++ /dev/null @@ -1,52 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object ConnectTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/connect.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right("") => "None" - case Right("X") => s"""Some(Color.Black)""" - case Right("O") => s"""Some(Color.White)""" - case _ => throw new IllegalArgumentException - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString(", ") - - def toArgString(any: Any): String = { - any match { - case list: List[_] => - val vals = list.map(s => TestSuiteBuilder.toString(s)).mkString(", ") - s"mkBoard(List($vals))" - case _ => any.toString - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut($args).$property""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("board"), - Seq(), - Seq("// Filter readable board into valid input", - "private def mkBoard(lines: List[String]): List[String] =", - "lines.map(l => l.filter(!_.isSpaceChar))")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/CryptoSquareTestGenerator.scala b/testgen/src/main/scala/CryptoSquareTestGenerator.scala deleted file mode 100644 index 9883d90f..00000000 --- a/testgen/src/main/scala/CryptoSquareTestGenerator.scala +++ /dev/null @@ -1,17 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object CryptoSquareTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/crypto-square.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAltFromInput("normalizedPlaintext" -> Seq("plaintext"), "plaintextSegments" -> Seq("plaintext"), - "encoded" -> Seq("plaintext"), "ciphertext" -> Seq("plaintext"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/CustomSetTestGenerator.scala b/testgen/src/main/scala/CustomSetTestGenerator.scala deleted file mode 100644 index 69a1edd4..00000000 --- a/testgen/src/main/scala/CustomSetTestGenerator.scala +++ /dev/null @@ -1,257 +0,0 @@ -import play.api.libs.json.Json - -import scala.io.Source - -// Generates test suite from json test definition for the CustomSet exercise. -class CustomSetTestGenerator { - implicit val singleSetInputReader = Json.reads[SingleSetInput] - implicit val doubleSetInputReader = Json.reads[DoubleSetInput] - implicit val setWithElementInputReader = Json.reads[SetWithElementInput] - implicit val emptyTestCaseReader = Json.reads[EmptyTestCase] - implicit val containsTestCasesReader = Json.reads[ContainsTestCase] - implicit val subsetTestCasesReader = Json.reads[SubsetTestCase] - implicit val disjointTestCasesReader = Json.reads[DisjointTestCase] - implicit val equalTestCasesReader = Json.reads[EqualTestCase] - implicit val addTestCasesReader = Json.reads[AddTestCase] - implicit val intersectionTestCasesReader = Json.reads[IntersectionTestCase] - implicit val differenceTestCasesReader = Json.reads[DifferenceTestCase] - implicit val unionTestCasesReader = Json.reads[UnionTestCase] - - private val filename = "src/main/resources/custom-set.json" - private val fileContents = Source.fromFile(filename).getLines.mkString - private val json = Json.parse(fileContents) - - def write { - val testBuilder = new TestBuilder("CustomSetTest") - setVersion(testBuilder) - addEmptyTests(testBuilder) - addContainsTests(testBuilder) - addSubsetTests(testBuilder) - addDisjointTests(testBuilder) - addEqualTests(testBuilder) - addAddTests(testBuilder) - addIntersectionTests(testBuilder) - addDifferenceTests(testBuilder) - addUnionTests(testBuilder) - testBuilder.toFile - } - - private def setVersion(testBuilder: TestBuilder): Unit = { - testBuilder.setVersion((json \ "version").get.as[String]) - } - - private def addEmptyTests(testBuilder: TestBuilder): Unit = { - val description = - "Empty test cases - " + (json \ "cases" \ 0 \ "description").get.as[String] - - val emptyTestCases = (json \ "cases" \ 0 \ "cases").get.as[List[EmptyTestCase]] - - implicit def testCaseToGen(tc: EmptyTestCase): TestCaseGen = { - val set = s"CustomSet.fromList(${tc.input.set})" - val callSUT = s"CustomSet.empty(set)" - val expected = tc.expected.toString - val result = s"val set = $set" - val checkResult = s"$callSUT should be ($expected)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(emptyTestCases, Some(description)) - } - - private def addContainsTests(testBuilder: TestBuilder): Unit = { - val description = - "Contains test cases - " + (json \ "cases" \ 1 \ "description").get.as[String] - - val containsTestCases = (json \ "cases" \ 1 \ "cases").get.as[List[ContainsTestCase]] - - implicit def testCaseToGen(tc: ContainsTestCase): TestCaseGen = { - val set = s"CustomSet.fromList(${tc.input.set})" - val callSUT = s"CustomSet.member(set, ${tc.input.element})" - val expected = tc.expected.toString - val result = s"val set = $set" - val checkResult = s"$callSUT should be ($expected)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(containsTestCases, Some(description)) - } - - private def addSubsetTests(testBuilder: TestBuilder): Unit = { - val description = - "Subset test cases - " + (json \"cases" \ 2 \ "description").get.as[String] - - val subsetTestCases = (json \ "cases" \ 2 \ "cases").get.as[List[SubsetTestCase]] - - implicit def testCaseToGen(tc: SubsetTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.isSubsetOf(set1, set2)" - val expected = tc.expected.toString - val result = -s"""val set1 = $set1 - val set2 = $set2""" - val checkResult = s"$callSUT should be ($expected)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(subsetTestCases, Some(description)) - } - - private def addDisjointTests(testBuilder: TestBuilder): Unit = { - val description = - "Disjoint test cases - " + (json \ "cases" \ 3 \ "description").get.as[String] - - val disjointTestCases = (json \ "cases" \ 3 \ "cases").get.as[List[DisjointTestCase]] - - implicit def testCaseToGen(tc: DisjointTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.isDisjointFrom(set1, set2)" - val expected = tc.expected.toString - val result = -s"""val set1 = $set1 - val set2 = $set2""" - val checkResult = s"$callSUT should be ($expected)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(disjointTestCases, Some(description)) - } - - private def addEqualTests(testBuilder: TestBuilder): Unit = { - val description = - "Equal test cases - " + (json \ "cases" \ 4 \ "description").get.as[String] - - val equalTestCases = (json \ "cases" \ 4 \ "cases").get.as[List[EqualTestCase]] - - implicit def testCaseToGen(tc: EqualTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.isEqual(set1, set2)" - val expected = tc.expected.toString - val result = -s"""val set1 = $set1 - val set2 = $set2""" - val checkResult = s"$callSUT should be ($expected)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(equalTestCases, Some(description)) - } - - private def addAddTests(testBuilder: TestBuilder): Unit = { - val description = - "Add test cases - " + (json \ "cases" \ 5 \ "description").get.as[String] - - val addTestCases = (json \ "cases" \ 5 \ "cases").get.as[List[AddTestCase]] - - implicit def testCaseToGen(tc: AddTestCase): TestCaseGen = { - val set = s"CustomSet.fromList(${tc.input.set})" - val callSUT = s"CustomSet.insert(set, ${tc.input.element})" - val expected = s"CustomSet.fromList(${tc.expected})" - val result = -s"""val set = $set - val expected = $expected""" - val checkResult = s"CustomSet.isEqual($callSUT, expected) should be (true)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(addTestCases, Some(description)) - } - - private def addIntersectionTests(testBuilder: TestBuilder): Unit = { - val description = - "Intersection test cases - " + (json \ "cases" \ 6 \ "description").get.as[String] - - val intersectionTestCases = (json \ "cases" \ 6 \ "cases").get.as[List[IntersectionTestCase]] - - implicit def testCaseToGen(tc: IntersectionTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.intersection(set1, set2)" - val expected = s"CustomSet.fromList(${tc.expected})" - val result = -s"""val set1 = $set1 - val set2 = $set2 - val expected = $expected""" - val checkResult = s"CustomSet.isEqual($callSUT, expected) should be (true)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(intersectionTestCases, Some(description)) - } - - private def addDifferenceTests(testBuilder: TestBuilder): Unit = { - val description = - "Difference test cases - " + (json \ "cases" \ 7 \ "description").get.as[String] - - val differenceTestCases = (json \ "cases" \ 7 \ "cases").get.as[List[DifferenceTestCase]] - - implicit def testCaseToGen(tc: DifferenceTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.difference(set1, set2)" - val expected = s"CustomSet.fromList(${tc.expected})" - val result = -s"""val set1 = $set1 - val set2 = $set2 - val expected = $expected""" - val checkResult = s"CustomSet.isEqual($callSUT, expected) should be (true)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(differenceTestCases, Some(description)) - } - - private def addUnionTests(testBuilder: TestBuilder): Unit = { - val description = - "Union test cases - " + (json \ "cases" \ 8 \ "description").get.as[String] - - val unionTestCases = (json \ "cases" \ 8 \ "cases").get.as[List[UnionTestCase]] - - implicit def testCaseToGen(tc: UnionTestCase): TestCaseGen = { - val set1 = s"CustomSet.fromList(${tc.input.set1})" - val set2 = s"CustomSet.fromList(${tc.input.set2})" - val callSUT = s"CustomSet.union(set1, set2)" - val expected = s"CustomSet.fromList(${tc.expected})" - val result = -s"""val set1 = $set1 - val set2 = $set2 - val expected = $expected""" - val checkResult = s"CustomSet.isEqual($callSUT, expected) should be (true)" - - TestCaseGen(tc.description, callSUT, expected, result, checkResult) - } - - testBuilder.addTestCases(unionTestCases, Some(description)) - } - -} - -case class SingleSetInput(set: List[Int]) -case class DoubleSetInput(set1: List[Int], set2: List[Int]) -case class SetWithElementInput(set: List[Int], element: Int) -case class EmptyTestCase(description: String, input: SingleSetInput, expected: Boolean) -case class ContainsTestCase(description: String, input: SetWithElementInput, expected: Boolean) -case class SubsetTestCase(description: String, input: DoubleSetInput, expected: Boolean) -case class DisjointTestCase(description: String, input: DoubleSetInput, expected: Boolean) -case class EqualTestCase(description: String, input: DoubleSetInput, expected: Boolean) -case class AddTestCase(description: String, input: SetWithElementInput, expected: List[Int]) -case class IntersectionTestCase(description: String, input: DoubleSetInput, expected: List[Int]) -case class DifferenceTestCase(description: String, input: DoubleSetInput, expected: List[Int]) -case class UnionTestCase(description: String, input: DoubleSetInput, expected: List[Int]) - - -object CustomSetTestGenerator { - def main(args: Array[String]): Unit = { - new CustomSetTestGenerator().write - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/DartsTestGenerator.scala b/testgen/src/main/scala/DartsTestGenerator.scala deleted file mode 100644 index f0905cce..00000000 --- a/testgen/src/main/scala/DartsTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object DartsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/darts.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("x", "y")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/DiamondTestGenerator.scala b/testgen/src/main/scala/DiamondTestGenerator.scala deleted file mode 100644 index 68a9833a..00000000 --- a/testgen/src/main/scala/DiamondTestGenerator.scala +++ /dev/null @@ -1,40 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{sutArgsFromInput, _} -import testgen._ - -object DiamondTestGenerator { - - def main(args: Array[String]): Unit = { - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[String]) => s"""List(${xs.map(c => s"""\"$c\"""").mkString(", ")})""" - case _ => throw new IllegalArgumentException() - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = { - val input = parseResult("input").asInstanceOf[Map[String, Int]] - - s"\'${input("letter")}\'" - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - TestCaseData(labeledTest.description, sutCall, toString(labeledTest.expected)) - } - - val file = new File("src/main/resources/diamond.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("letter")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/DifferenceOfSquaresTestGenerator.scala b/testgen/src/main/scala/DifferenceOfSquaresTestGenerator.scala deleted file mode 100644 index f07fcaf6..00000000 --- a/testgen/src/main/scala/DifferenceOfSquaresTestGenerator.scala +++ /dev/null @@ -1,17 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object DifferenceOfSquaresTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/difference-of-squares.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAltFromInput("squareOfSum" -> Seq("number"), "sumOfSquares" -> Seq("number"), - "differenceOfSquares" -> Seq("number"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/DominoesTestGenerator.scala b/testgen/src/main/scala/DominoesTestGenerator.scala deleted file mode 100644 index 5bf873c4..00000000 --- a/testgen/src/main/scala/DominoesTestGenerator.scala +++ /dev/null @@ -1,71 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ -import play.twirl.api.Txt -import play.twirl.api.Template1 - -object DominoesTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/dominoes.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "false" - case Right(false) => "false" - case Right(true) => "true" - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString(", ") - - - def toArgString(any: Any): String = { - any match { - case xs: List[List[_]] => s"List(${xs.map(ys => s"(${ys.mkString(", ")})").mkString(", ")})" - case _ => any.toString - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val expected = toString(labeledTest.expected) - val sutCall = - s"""check($args, $expected)""" - TestCaseData(labeledTest.description, sutCall, expected) - } - - val template: TestSuiteTemplate = - txt.funSuiteTemplateIgnoreExpected.asInstanceOf[Template1[TestSuiteData, Txt]] - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("dominoes"), Seq(), - Seq("private def check(input: List[(Int, Int)], hasResult: Boolean): Unit = {", - " val result = Dominoes.chain(input)", " if (hasResult) {", - " checkChain(result getOrElse fail(\"should have had a chain, but didn't\"), input)", - " }", " else assert(result == None)", " }", - "", - " private def checkChain(result: List[(Int, Int)], input: List[(Int, Int)]): Unit = {", - " def sortDomino(ab: (Int, Int)): (Int, Int) =", " if (ab._1 > ab._2) ab.swap else ab", - " def consecutivesShouldMatch(dominoes: List[((Int, Int), Int)]): Unit =", - " dominoes.tails foreach {", - " case (a@(_,x), i1)::(b@(y,_), i2)::_ =>", - " assert(x == y, s\"dominoes $i1 and $i2 don't match: $a $b\")", - " case _ =>", - " }", - " def endsShouldMatch: Unit =", - " if (!result.isEmpty)", - " consecutivesShouldMatch(List((result.last, result.length - 1),", - " (result.head, 0)))", - "", - " assert(result.map(sortDomino).sorted == input.map(sortDomino).sorted,", - " \"doesn't consist of input dominoes\")", - " consecutivesShouldMatch(result.zipWithIndex)", - " endsShouldMatch", " }"))(template) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/EtlTestGenerator.scala b/testgen/src/main/scala/EtlTestGenerator.scala deleted file mode 100644 index 29cec0c0..00000000 --- a/testgen/src/main/scala/EtlTestGenerator.scala +++ /dev/null @@ -1,52 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object EtlTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/etl.json") - - def seqToString(seq: Seq[String]): String = s"Seq(${seq.map(s => "\"" + s + "\"").mkString(", ")})" - - def mapArgToString(arg: Map[String, List[String]]): String = { - s"Map(${arg.toSeq - .sortBy(_._1.toInt) - .map{case (key, xs) => key.toString + " -> " + seqToString(xs)} - .mkString(",\n")})" - } - - def mapExpectedToString(arg: Map[String, Int]): String = { - s"Map(${arg.toSeq - .sortBy(_._1) - .map{case (key, value) => "\"" + key.toString + "\" -> " + value.toString} - .mkString(",\n")})" - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "" - case Right(m) => mapExpectedToString(m.asInstanceOf[Map[String, Int]]) - } - } - - def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => mapArgToString(parseResult(name).asInstanceOf[Map[String, List[String]]])) mkString(", ") - - def fromLabeledTest(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgs(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""Etl.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTest("input")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/FlattenArrayTestGenerator.scala b/testgen/src/main/scala/FlattenArrayTestGenerator.scala deleted file mode 100644 index 24381f61..00000000 --- a/testgen/src/main/scala/FlattenArrayTestGenerator.scala +++ /dev/null @@ -1,44 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object FlattenArrayTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/flatten-array.json") - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def toArgString(any: Any): String = { - any match { - case xs: List[Any] => s"List(${xs.map(x => toArgString(x)).mkString(", ")})" - case null => "null" - case _ => any.toString - } - } - - def toExpectedString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException() - case Right(xs: List[Any]) => s"List(${xs.mkString(", ")})" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toExpectedString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("array")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/FoodChainTestGenerator.scala b/testgen/src/main/scala/FoodChainTestGenerator.scala deleted file mode 100644 index 7fd3942d..00000000 --- a/testgen/src/main/scala/FoodChainTestGenerator.scala +++ /dev/null @@ -1,40 +0,0 @@ -import testgen._ -import TestSuiteBuilder.{toString, _} -import java.io.File - -object FoodChainTestGenerator { - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = { - val input = parseResult("input").asInstanceOf[Map[String, Int]] - - val firstParam = input("startVerse").toString - val secondParam = input("endVerse").toString - - firstParam + ", " + secondParam - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/food-chain.json") - - val RawQuote = "\"\"\"" - def asRawString(str: String): String = s"$RawQuote$str$RawQuote" - - def fromLabeledTestFromInput(argNames: String*)( - implicit sutFunction: LabeledTest => String = _.property): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val sutCall = s"$sut.$sutFunction(${args})" - val expectedLines = labeledTest.expected.getOrElse(List()).asInstanceOf[List[String]] - val expected = expectedLines mkString ("", "\n", "\n\n") - - TestCaseData(labeledTest.description, sutCall, asRawString(expected)) - } - - val code = TestSuiteBuilder.build(file, - fromLabeledTestFromInput("startVerse", "endVerse")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ForthTestGenerator.scala b/testgen/src/main/scala/ForthTestGenerator.scala deleted file mode 100644 index b83ac063..00000000 --- a/testgen/src/main/scala/ForthTestGenerator.scala +++ /dev/null @@ -1,66 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object ForthTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/forth.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(n: Int) => s""""${n.toString}"""" - case Right(vals: List[Int]) => s""""${vals.map(_.toString).mkString(" ")}"""" - case _ => throw new IllegalArgumentException - } - } - - def isError(expected: CanonicalDataParser.Expected): Boolean = { - expected match { - case Left(_) => true - case Right(null) => true - case Right(n) => false - } - } - - def argsToString(any: Any): String = { - any match { - case list: List[_] => - val vals = list.map(s => argsToString(s)).mkString(" ") - s""""$vals"""" - case str: String => - s"$str" - case _ => any.toString - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => argsToString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val isErr = isError(labeledTest.expected) - val sutCall = if (isErr) - s"""forth.eval($args).isLeft""" - else - s"""forth.eval($args).fold(_ => "", _.toString)""" - - val expected = if (isErr) - "true" - else - toString(labeledTest.expected) - - TestCaseData(s"${labeledTest.parentDescriptions.mkString(" - " )} - ${labeledTest.description}", sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput("instructions"), - Seq(), Seq("private val forth = new Forth")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/GigasecondTestGenerator.scala b/testgen/src/main/scala/GigasecondTestGenerator.scala deleted file mode 100644 index 17918cd2..00000000 --- a/testgen/src/main/scala/GigasecondTestGenerator.scala +++ /dev/null @@ -1,51 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object GigasecondTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/gigasecond.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException - case Right(null) => throw new IllegalStateException - case Right(n) => s""""$n"""" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val expected = toString(labeledTest.expected) - - val useDateTime = labeledTest.result("input") - .asInstanceOf[Map[String, Any]]("birthdate") - .asInstanceOf[String].length > "xxxx-xx-xx".length - val sutCall = if (useDateTime) { - s"""val input = dateTime($args) - val expected = dateTime($expected) - $sut.$property(input)""" - } - else { - s"""val input = date($args) - val expected = dateTime($expected) - $sut.$property(input)""" - } - - TestCaseData(labeledTest.description, sutCall, "expected") - } - - val dateTimeFn = "private def dateTime(str: String): LocalDateTime =\n LocalDateTime.from(DateTimeFormatter.ISO_DATE_TIME.parse(str))" - val dateFn = "private def date(str: String): LocalDate =\n LocalDate.from(DateTimeFormatter.ISO_DATE.parse(str))" - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("birthdate"), - Seq("java.time.LocalDate", "java.time.LocalDateTime", "java.time.format.DateTimeFormatter"), - Seq(dateTimeFn, dateFn)) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/GrainsTestGenerator.scala b/testgen/src/main/scala/GrainsTestGenerator.scala deleted file mode 100644 index a84c30b6..00000000 --- a/testgen/src/main/scala/GrainsTestGenerator.scala +++ /dev/null @@ -1,56 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object GrainsTestGenerator { - def main(args: Array[String]): Unit = { - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(-1) => "None" - case Right(n: BigDecimal) => if (n > Int.MaxValue) s"""Some(BigInt(\"$n\"))""" else s"Some($n)" - case Right(n: Double) => s"""Some(BigInt("${n.toLong}"))""" - case Right(n) => s"Some($n)" - } - } - - def toStringForTotal(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(n: BigDecimal) => s"""BigInt(\"$n\")""" - case Right(l: Long) => s"""Long(\"${l.toString}\")""" - case Right(d: Double) => s"""Long(\"${d.toLong.toString}\")""" - case Right(v) => v.toString - case _ => throw new IllegalStateException - } - } - - val file = new File("src/main/resources/grains.json") - def fromLabeledTestFromInput(): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val square = labeledTest.result("input").asInstanceOf[Map[String, Any]].get("square") - val args = square match { - case None => "" - case Some(s) => s.toString - } - - val property = labeledTest.property.mkString - val sutCall = if (args.length > 0) - s"""Grains.$property($args)""" - else - s"""Grains.$property""" - val expected = if (args.length > 0) - toString(labeledTest.expected) - else - toStringForTotal(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput()) - println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐") - println(code) - println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐") - } -} diff --git a/testgen/src/main/scala/HammingTestGenerator.scala b/testgen/src/main/scala/HammingTestGenerator.scala deleted file mode 100644 index 9c4b0cea..00000000 --- a/testgen/src/main/scala/HammingTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object HammingTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/hamming.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(-1) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""Hamming.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("strand1", "strand2")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/HelloWorldTestGenerator.scala b/testgen/src/main/scala/HelloWorldTestGenerator.scala deleted file mode 100644 index 4397589e..00000000 --- a/testgen/src/main/scala/HelloWorldTestGenerator.scala +++ /dev/null @@ -1,14 +0,0 @@ -import testgen._ -import TestSuiteBuilder._ -import java.io.File - -object HelloWorldTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/hello-world.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTest()) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/HighScoresTestGenerator.scala b/testgen/src/main/scala/HighScoresTestGenerator.scala deleted file mode 100644 index c4bb6c48..00000000 --- a/testgen/src/main/scala/HighScoresTestGenerator.scala +++ /dev/null @@ -1,21 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object HighScoresTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/high-scores.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAltFromInput( - "scores" -> Seq("scores"), - "latest" -> Seq("scores"), - "personalBest" -> Seq("scores"), - "personalTop" -> Seq("scores"), - "report" -> Seq("scores"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/HouseTestGenerator.scala b/testgen/src/main/scala/HouseTestGenerator.scala deleted file mode 100644 index 9fb99994..00000000 --- a/testgen/src/main/scala/HouseTestGenerator.scala +++ /dev/null @@ -1,41 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object HouseTestGenerator { - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult): String = { - val input = parseResult("input").asInstanceOf[Map[String, Int]] - - val firstParam = input("startVerse").toString - val secondParam = input("endVerse").toString - - firstParam + ", " + secondParam - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/house.json") - - val RawQuote = "\"\"\"" - def asRawString(str: String): String = s"$RawQuote$str$RawQuote" - - def fromLabeledTestFromInput(argNames: String*)( - implicit sutFunction: LabeledTest => String = _.property): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsFromInput(labeledTest.result) - val sutCall = s"$sut.$sutFunction($args)" - val expectedLines = labeledTest.expected.right.get.asInstanceOf[List[String]] - val expected = expectedLines mkString ("", "\n", "\n\n") - - TestCaseData(labeledTest.description, sutCall, asRawString(expected)) - } - - val code = TestSuiteBuilder.build(file, - fromLabeledTestFromInput()) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/IsogramTestGenerator.scala b/testgen/src/main/scala/IsogramTestGenerator.scala deleted file mode 100644 index 27565a3c..00000000 --- a/testgen/src/main/scala/IsogramTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object IsogramTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/isogram.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestFromInput("phrase")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/KindergartenGardenTestGenerator.scala b/testgen/src/main/scala/KindergartenGardenTestGenerator.scala deleted file mode 100644 index cb11066a..00000000 --- a/testgen/src/main/scala/KindergartenGardenTestGenerator.scala +++ /dev/null @@ -1,43 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object KindergartenGardenTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/kindergarten-garden.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[String]) => s"List(${xs.map(x => "Plant." + x.capitalize).mkString(", ")})" - case _ => throw new IllegalArgumentException - } - } - - def fromLabeledTestFromInput(): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val diagram = args("diagram") - val student = args("student") - val students: List[String] = (args getOrElse("students", List())).asInstanceOf[List[String]] - val property = labeledTest.property - val sutCall = - if (students.isEmpty) - s"""Garden.defaultGarden(${escape(diagram.toString)}).$property("$student")""" - else - s"""Garden(List(${students.map(s => escape(s)).mkString(", ")}), ${escape(diagram.toString)}).$property(${escape(student.toString)})""" - - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.parentDescriptions.mkString(", ") + " - " + labeledTest.description, - sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput()) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/LeapTestGenerator.scala b/testgen/src/main/scala/LeapTestGenerator.scala deleted file mode 100644 index 3b343648..00000000 --- a/testgen/src/main/scala/LeapTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object LeapTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/leap.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("year")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/LuhnTestGenerator.scala b/testgen/src/main/scala/LuhnTestGenerator.scala deleted file mode 100644 index 4e292da2..00000000 --- a/testgen/src/main/scala/LuhnTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object LuhnGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/luhn.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("value")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/MatchingBracketsTestGenerator.scala b/testgen/src/main/scala/MatchingBracketsTestGenerator.scala deleted file mode 100644 index deacf542..00000000 --- a/testgen/src/main/scala/MatchingBracketsTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object MatchingBracketsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/matching-brackets.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("value")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/MatrixTestGenerator.scala b/testgen/src/main/scala/MatrixTestGenerator.scala deleted file mode 100644 index 9f2a6912..00000000 --- a/testgen/src/main/scala/MatrixTestGenerator.scala +++ /dev/null @@ -1,37 +0,0 @@ -import java.io.File - -import testgen.{CanonicalDataParser, TestCaseData, TestSuiteBuilder} -import testgen.TestSuiteBuilder.{ToTestCaseData, quote, withLabeledTest} - -import scala.language.postfixOps - -object MatrixTestGenerator { - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[Int]) => xs mkString ", " - case _ => throw new IllegalArgumentException - } - } - - def fromLabeledTestFromInput(): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val input = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val matrix = input("string").asInstanceOf[String].lines.map(l => s""""$l""").toString.mkString("\\n\" +") + "\"" - val index = input("index").toString - val property = labeledTest.property - val sutCall = - s"""$sut($matrix).$property($index)""" - val expected = s"""Vector(${toString(labeledTest.expected)})""" - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/matrix.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput()) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/MeetupTestGenerator.scala b/testgen/src/main/scala/MeetupTestGenerator.scala deleted file mode 100644 index 2405b613..00000000 --- a/testgen/src/main/scala/MeetupTestGenerator.scala +++ /dev/null @@ -1,51 +0,0 @@ -import java.io.File - -import testgen.CanonicalDataParser.{Expected, ParseResult, getRequired} -import testgen.TestSuiteBuilder._ -import testgen._ - -import scala.util.Try - -object MeetupTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/meetup.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(s: String) => val tokens = s.split("-") - s"LocalDate.of(${tokens(0)}, ${trimLeadingZero(tokens(1))}," + - s" ${trimLeadingZero(tokens(2))})" - case _ => throw new IllegalArgumentException - } - } - - def trimLeadingZero(s: String) = s.replaceFirst("^0+(?!$)", "") - - def getYear(labeledTest: LabeledTest): Map[String, String] = { - labeledTest.result("queen"). - asInstanceOf[Map[String, String]] - } - - def fromLabeledTestFromInput(): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val month = args("month") - val year = args("year") - val dayOfWeek = args("dayofweek").toString.take(3) - val week = args("week").toString.capitalize - val sutCall = - s"""$sut($month, $year).day(Meetup.$dayOfWeek, Schedule.$week)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, - fromLabeledTestFromInput(), - Seq("java.time.LocalDate")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/MinesweeperTestGenerator.scala b/testgen/src/main/scala/MinesweeperTestGenerator.scala deleted file mode 100644 index 909494e7..00000000 --- a/testgen/src/main/scala/MinesweeperTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object MinesweeperTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/minesweeper.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("minefield")) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/NthPrimeTestGenerator.scala b/testgen/src/main/scala/NthPrimeTestGenerator.scala deleted file mode 100644 index 7af2cef6..00000000 --- a/testgen/src/main/scala/NthPrimeTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object NthPrimerTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/nth-prime.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(false) => "None" - case Right(n) => s"Some($n)" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/NucleotideCountTestGenerator.scala b/testgen/src/main/scala/NucleotideCountTestGenerator.scala deleted file mode 100644 index dc56e092..00000000 --- a/testgen/src/main/scala/NucleotideCountTestGenerator.scala +++ /dev/null @@ -1,49 +0,0 @@ -import testgen._ -import TestSuiteBuilder._ -import java.io.File - -object NucleotideCountTestGenerator { - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/nucleotide-count.json") - - def mapExpectedToString(arg: Map[String, Int]): String = { - s"Right(Map(${arg.toSeq - .sortBy(_._1) - .map{case (key, value) => "\'" + key.toString + "\' -> " + value.toString} - .mkString(",\n")}))" - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(s: String) => "true" - case Right(m: Map[String, Int]) => mapExpectedToString(m) - case _ => throw new IllegalArgumentException - } - } - - def toSutCall(labeledTest: LabeledTest, argNames: String*): String = { - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - labeledTest.expected match { - case Left(_) => s"""new DNA($args).$property.isLeft""" - case Right(_) => s"""new DNA($args).$property""" - case _ => throw new IllegalArgumentException - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val sutCall = toSutCall(labeledTest, argNames: _*) - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("strand")) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/OcrNumbersTestGenerator.scala b/testgen/src/main/scala/OcrNumbersTestGenerator.scala deleted file mode 100644 index a8a85657..00000000 --- a/testgen/src/main/scala/OcrNumbersTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object OcrNumbersTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/ocr-numbers.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException() - case Right(-1) => "\"?\"" - case Right(n) => s"""\"$n\"""" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("rows")) - println(s"-------------") - println(code) - println(s"-------------") - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/PalindromeProductsTestGenerator.scala b/testgen/src/main/scala/PalindromeProductsTestGenerator.scala deleted file mode 100644 index 8995b911..00000000 --- a/testgen/src/main/scala/PalindromeProductsTestGenerator.scala +++ /dev/null @@ -1,50 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object PalindromeProductsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/palindrome-products.json") - - def toStringFromMap(m: Map[String, Any]): String = - s"Some((${m("value").toString}, " + - s"Set(${m("factors").asInstanceOf[List[List[Int]]].map(xs => "(" + xs.map(_.toString).mkString(", ") + ")").mkString(", ")})))" - - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(m: Map[String, any]) => toStringFromMap(m) - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = s"""$sut($args).$property""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput("min", "max"), - Seq(), - Seq("// PalindromeProducts largest call is expecting a return type of", - "// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.", - "// Some is expected for valid cases. The first element of the tuple ", - "// is the largest palindrome product value. The second element of the", - "// tuple is the list of factors.", - "// PalindromeProducts smallest call is expecting a return type of", - "// Option[(Int, Set[(Int, Int)])] - None is expected for error cases.", - "// Some is expected for valid cases. The first element of the tuple ", - "// is the smallest palindrome product value. The second element of the", - "// tuple is the list of factors.")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/PangramsTestGenerator.scala b/testgen/src/main/scala/PangramsTestGenerator.scala deleted file mode 100644 index 578ad912..00000000 --- a/testgen/src/main/scala/PangramsTestGenerator.scala +++ /dev/null @@ -1,25 +0,0 @@ -import testgen._ -import TestSuiteBuilder._ -import java.io.File - -object PangramsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/pangram.json") - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val isPangram = labeledTest.property.mkString - val sutCall = - s"""Pangrams.$isPangram($args)""" - val expected = - labeledTest.expected.fold(Function.const("true"), x => s"$x") - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("sentence")) - println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐") - println(code) - println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐") - } -} diff --git a/testgen/src/main/scala/PascalsTriangleTestGenerator.scala b/testgen/src/main/scala/PascalsTriangleTestGenerator.scala deleted file mode 100644 index b16e69c0..00000000 --- a/testgen/src/main/scala/PascalsTriangleTestGenerator.scala +++ /dev/null @@ -1,51 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object PascalsTriangleTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/pascals-triangle.json") - - def toStr(any: Any): String = { - any match { - case list: List[_] => - val vals = list.map(s => toStr(s)).mkString(", ") - s"List($vals)" - case n: Int => - if (n == -1) - "List()" - else - n.toString - case v => throw new IllegalStateException("Unexpected value - " + v) - } - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(error) => throw new IllegalStateException("Unexpected error - " + error) - case Right(exp) => toStr(exp) - } - } - - def withLabeledTestOption(argNames: String*): ToOptionTestCaseData = - withLabeledTestOpt { sut => - labeledTest => - if (labeledTest.result.valuesIterator.contains(null)) { - None - } else { - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.$property($args)""" - val expected = toString(labeledTest.expected) - Some(TestCaseData(labeledTest.description, sutCall, expected)) - } - } - - val code = TestSuiteBuilder.buildFromOption(file, withLabeledTestOption("count")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/PerfectNumbersTestGenerator.scala b/testgen/src/main/scala/PerfectNumbersTestGenerator.scala deleted file mode 100644 index f7c52c45..00000000 --- a/testgen/src/main/scala/PerfectNumbersTestGenerator.scala +++ /dev/null @@ -1,42 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object PerfectNumbersTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/perfect-numbers.json") - - def toEnumStr(str: String): String = { - str match { - case "perfect" => "NumberType.Perfect" - case "abundant" => "NumberType.Abundant" - case "deficient" => "NumberType.Deficient" - case _ => throw new IllegalStateException("Invalid NumberType -" + str) - } - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(error) => s"Left(${TestSuiteBuilder.toString(error)})" - case Right(exp) => s"Right(${toEnumStr(exp.toString)})" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""PerfectNumbers.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/PhoneNumberTestGenerator.scala b/testgen/src/main/scala/PhoneNumberTestGenerator.scala deleted file mode 100644 index a2b51e8b..00000000 --- a/testgen/src/main/scala/PhoneNumberTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object PhoneNumberTestGenerator { - def fromLabeledTest(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""PhoneNumber.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(str) => s"""Some("$str")""" - } - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/phone-number.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTest("phrase")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/PigLatinTestGenerator.scala b/testgen/src/main/scala/PigLatinTestGenerator.scala deleted file mode 100644 index ddae8666..00000000 --- a/testgen/src/main/scala/PigLatinTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object PigLatinTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/pig-latin.json") - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput("phrase")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/PrimeFactorsTestGenerator.scala b/testgen/src/main/scala/PrimeFactorsTestGenerator.scala deleted file mode 100644 index 213a5da8..00000000 --- a/testgen/src/main/scala/PrimeFactorsTestGenerator.scala +++ /dev/null @@ -1,53 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen.{CanonicalDataParser, TestCaseData, TestSuiteBuilder} - -object PrimeFactorsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/prime-factors.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("value")) - println(s"-------------") - println(code) - println(s"-------------") - } - - private def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val sutCall = s"$sut.$sutFunction($args)" - val expected = toString(labeledTest.expected) - - TestCaseData(labeledTest.description, sutCall, expected) - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException("Unexpected Left") - case Right(exp) => s"${toString(exp)}" - } - } - - private def toString(any: Any): String = { - def quote(str: String): String = - if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\"" - - any match { - case list: List[_] => - val vals = list.map(s => toString(s)).mkString(", ") - s"List($vals)" - case str: String => - val quot = quote(str) - s"$quot$str$quot" - case dbl: Double => - dbl.asInstanceOf[Long].toString + "l" - case _ => any.toString - } - } -} \ No newline at end of file diff --git a/testgen/src/main/scala/QueenAttackTestGenerator.scala b/testgen/src/main/scala/QueenAttackTestGenerator.scala deleted file mode 100644 index ce5208dc..00000000 --- a/testgen/src/main/scala/QueenAttackTestGenerator.scala +++ /dev/null @@ -1,81 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object QueenAttackTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/queen-attack.json") - - def getPosition(labeledTest: LabeledTest, - queenType: String): (Int, Int) = { - val inputMap = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val queenMap = inputMap(queenType).asInstanceOf[Map[String, Any]] - val positionMap = queenMap("position").asInstanceOf[Map[String, Int]] - - (positionMap("row"), positionMap("column")) - } - - def getQueenPosition(labeledTest: LabeledTest): (Int, Int) = - getPosition(labeledTest, "queen") - - def getWhiteQueenPosition(labeledTest: LabeledTest): (Int, Int) = - getPosition(labeledTest, "white_queen") - - def getBlackQueenPosition(labeledTest: LabeledTest): (Int, Int) = - getPosition(labeledTest, "black_queen") - - def toPositionArgs(position: (Int, Int)) = - s"${position._1}, ${position._2}" - - def toCanAttackArgs(labeledTest: LabeledTest): String = { - val whiteQueenArgs = toPositionArgs(getWhiteQueenPosition(labeledTest)) - val blackQueenArgs = toPositionArgs(getBlackQueenPosition(labeledTest)) - s"create($whiteQueenArgs), create($blackQueenArgs)" - } - - def toCreateExpected(labeledTest: LabeledTest): String = { - val expected = labeledTest.expected - expected match { - case Right(-1) => s"None" - case Right(0) => - val args = toPositionArgs(getQueenPosition(labeledTest)) - s"Some(Queen($args))" - case _ => throw new IllegalStateException - } - } - - def fromLabeledTestFromInput: ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val property = labeledTest.property - val (clazz, args, expected) = property match { - case "create" => - ("Queen", - toPositionArgs(getQueenPosition(labeledTest)), - toCreateExpected(labeledTest)) - case "canAttack" => - ("QueenAttack", - toCanAttackArgs(labeledTest), - labeledTest.expected.fold(_ => "false", _.toString)) - case _ => throw new IllegalStateException() - } - val sutCall = s"""$clazz.$property($args)""" - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput, - Seq(), - Seq(" private def create(x: Int, y: Int): Queen = {", - " Queen.create(x, y) match {", - " case Some(q) => q", - " case None => fail(\"Error creating queen\")", - " }", - " }")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RailFenceCipherTestGenerator.scala b/testgen/src/main/scala/RailFenceCipherTestGenerator.scala deleted file mode 100644 index 7c3cb99a..00000000 --- a/testgen/src/main/scala/RailFenceCipherTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object RailFenceCipherTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/rail-fence-cipher.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("msg", "rails")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RaindropsTestGenerator.scala b/testgen/src/main/scala/RaindropsTestGenerator.scala deleted file mode 100644 index 073e1dfa..00000000 --- a/testgen/src/main/scala/RaindropsTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object RaindropsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/raindrops.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RnaTranscriptionTestGenerator.scala b/testgen/src/main/scala/RnaTranscriptionTestGenerator.scala deleted file mode 100644 index c7b5bc2c..00000000 --- a/testgen/src/main/scala/RnaTranscriptionTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object RnaTranscriptionTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/rna-transcription.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(n) => s"""Some(\"$n\")""" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""RnaTranscription.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("dna")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RobotSimulatorTestGenerator.scala b/testgen/src/main/scala/RobotSimulatorTestGenerator.scala deleted file mode 100644 index 01cded6f..00000000 --- a/testgen/src/main/scala/RobotSimulatorTestGenerator.scala +++ /dev/null @@ -1,110 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object RobotSimulatorTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/robot-simulator.json") - - def getPosition(labeledTest: LabeledTest): (Int, Int) = { - val inputMap = fromInputMap(labeledTest.result, "position") - .asInstanceOf[Map[String, Any]] - getPosition2(inputMap) - } - - def getPosition2(positionMap: Map[String, Any]): (Int, Int) = - (positionMap("x").asInstanceOf[Int], positionMap("y").asInstanceOf[Int]) - - - def getDirection(labeledTest: LabeledTest): String = - fromInputMap(labeledTest.result, "direction").toString - - def toPositionArgs(position: (Int, Int)): String = - s"${position._1}, ${position._2}" - - - def getExpectedMap(labeledTest: LabeledTest): Map[String, Any] = - labeledTest.result("expected").asInstanceOf[Map[String, Any]] - - def directionToBearing(direction: String): String = - direction.toLowerCase match { - case "north" => "Bearing.North" - case "south" => "Bearing.South" - case "east" => "Bearing.East" - case "west" => "Bearing.West" - } - - def toCreateSutCall(labeledTest: LabeledTest): String = { - val bearing = directionToBearing(getDirection(labeledTest)) - s"Robot($bearing, (${toPositionArgs(getPosition(labeledTest))}))" - } - - def toCreateExpected(labeledTest: LabeledTest): String = { - val robotMap = getExpectedMap(labeledTest) - val bearing = directionToBearing(robotMap("direction").toString) - val positionArgs = toPositionArgs(getPosition2(robotMap("position") - .asInstanceOf[Map[String, Int]])) - s"Robot($bearing, ($positionArgs))" - } - - def toTurnFunction(map: Map[String, Any]) = - map.get("direction") match { - case Some(_) => "bearing" - case None => "coordinates" - } - - def toTurnSutCall(labeledTest: LabeledTest): String = { - val property = labeledTest.property - val expected = getExpectedMap(labeledTest) - s"${toCreateSutCall(labeledTest)}.$property.${toTurnFunction(expected)}" - } - - def toTurnExpected(labeledTest: LabeledTest): String = { - val expected = getExpectedMap(labeledTest) - expected.foreach{case (k, v) => System.out.println(s"$k")} - expected.get("direction") match { - case Some(s: String) => directionToBearing(s) - case None => { - val positionMap = expected("position").asInstanceOf[Map[String, Int]] - s"(${toPositionArgs(getPosition2(positionMap))})" - } - } - } - - def toInstructSutCall(labeledTest: LabeledTest): String = { - val instructions = fromInputMap(labeledTest.result, "instructions") - s"""${toCreateSutCall(labeledTest)}.simulate("$instructions")""" - } - - def toInstructExpected(labeledTest: LabeledTest): String = - toCreateExpected(labeledTest) - - def fromLabeledTest(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val property = labeledTest.property - val (sutCall, expected) = property match { - case "create" => - (toCreateSutCall(labeledTest), - toCreateExpected(labeledTest)) - case "turnRight" | "turnLeft" | "advance" => - (toTurnSutCall(labeledTest), - toTurnExpected(labeledTest)) - case "instructions" => - (toInstructSutCall(labeledTest), - toInstructExpected(labeledTest)) - case _ => throw new IllegalStateException() - } - TestCaseData(labeledTest.parentDescriptions.mkString(" - ") + " - " + labeledTest.description, - sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTest()) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RomanNumeralsTestGenerator.scala b/testgen/src/main/scala/RomanNumeralsTestGenerator.scala deleted file mode 100644 index 4856af76..00000000 --- a/testgen/src/main/scala/RomanNumeralsTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object RomanNumeralsTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/roman-numerals.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RotationalCipherTestGenerator.scala b/testgen/src/main/scala/RotationalCipherTestGenerator.scala deleted file mode 100644 index 08f6d747..00000000 --- a/testgen/src/main/scala/RotationalCipherTestGenerator.scala +++ /dev/null @@ -1,16 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object RotationalCipherTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/rotational-cipher.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("text", "shiftKey")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/RunLengthEncodingTestGenerator.scala b/testgen/src/main/scala/RunLengthEncodingTestGenerator.scala deleted file mode 100644 index 3f38ab1f..00000000 --- a/testgen/src/main/scala/RunLengthEncodingTestGenerator.scala +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object RunLengthEncodingTestGenerator { - private def toString(expected: CanonicalDataParser.Expected): String = - expected.fold(_ => "", TestSuiteBuilder.toString) - - def fromLabeledTestAlt(propArgs: (String, Seq[String])*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsAlt(labeledTest.result, propArgs:_*) - val sutCall = - if (sutFunction.toString == "consistency") - s"$sut.decode($sut.encode($args))" - else - s"$sut.$sutFunction($args)" - val expected = toString(labeledTest.expected) - - TestCaseData(s"$sutFunction - ${labeledTest.description}", sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/run-length-encoding.json") - - val code = TestSuiteBuilder.build(file, - fromLabeledTestAlt("encode" -> Seq("input"), "decode" -> Seq("input"), - "consistency" -> Seq("input"))) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SaddlePointsTestGenerator.scala b/testgen/src/main/scala/SaddlePointsTestGenerator.scala deleted file mode 100644 index d1d4667a..00000000 --- a/testgen/src/main/scala/SaddlePointsTestGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object SaddlePointsTestGenerator { - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(xs: List[Map[String, Int]]) => - val tuples = xs.map(m => s"(${m("row")}, ${m("column")})").mkString(", ") - s"""Set($tuples)""" - case _ => throw new IllegalArgumentException - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""Matrix($args).$property""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/saddle-points.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("matrix")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SayTestGenerator.scala b/testgen/src/main/scala/SayTestGenerator.scala deleted file mode 100644 index 62295ab9..00000000 --- a/testgen/src/main/scala/SayTestGenerator.scala +++ /dev/null @@ -1,50 +0,0 @@ -import java.io.File - -import PrimeFactorsTestGenerator.toString -import testgen.TestSuiteBuilder.{sutArgs, toString, _} -import testgen._ - -object SayTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/say.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(-1) => "None" - case Right(n) => s"""Some("$n")""" - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def toArgString(any: Any): String = { - any match { - case lstr: Long => - lstr.toString + "l" - case istr: Integer => - istr.toString - case dstr: Double => - dstr.toLong + "l" - case _ => any.toString - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""$sut.inEnglish($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/ScrabbleScoreTestGenerator.scala b/testgen/src/main/scala/ScrabbleScoreTestGenerator.scala deleted file mode 100644 index 5eb397d5..00000000 --- a/testgen/src/main/scala/ScrabbleScoreTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object ScrabbleScoreTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/scrabble-score.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("word")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SecretHandshakeTestGenerator.scala b/testgen/src/main/scala/SecretHandshakeTestGenerator.scala deleted file mode 100644 index 6137cd4c..00000000 --- a/testgen/src/main/scala/SecretHandshakeTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object SecretHandshakeTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/secret-handshake.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("number")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SeriesTestGenerator.scala b/testgen/src/main/scala/SeriesTestGenerator.scala deleted file mode 100644 index edb4cdc3..00000000 --- a/testgen/src/main/scala/SeriesTestGenerator.scala +++ /dev/null @@ -1,44 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object SeriesTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/largest-series-product.json") - - def toExpected(any: Any): String = { - any match { - case -1 => "None" - case i: Int => s"Some($i)" - case s: String => - val quot = quote(s) - s"$quot$s$quot" - case _ => throw new IllegalStateException("Invalid expected val -" + any) - } - } - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(error) => s"None" - case Right(exp) => toExpected(exp) - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"""Series.$property($args)""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("span", "digits")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SieveTestGenerator.scala b/testgen/src/main/scala/SieveTestGenerator.scala deleted file mode 100644 index bcd62520..00000000 --- a/testgen/src/main/scala/SieveTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object SieveTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/sieve.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("limit")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SpaceAgeTestGenerator.scala b/testgen/src/main/scala/SpaceAgeTestGenerator.scala deleted file mode 100644 index 376736c7..00000000 --- a/testgen/src/main/scala/SpaceAgeTestGenerator.scala +++ /dev/null @@ -1,40 +0,0 @@ -import java.io.File - -import testgen.CanonicalDataParser.ParseResult -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object SpaceAgeTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/space-age.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException() - case Right(n) => s"$n" - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => TestSuiteBuilder.toString(fromInputMap(parseResult, name))) mkString ", " - - def functionName(parseResult: CanonicalDataParser.ParseResult): String = - "on" + fromInputMap(parseResult, "planet").toString - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val sutCall = - s"""$sut.${functionName(labeledTest.result)}($args)""" - val expected = toString(labeledTest.expected) + " +- 0.01" - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("seconds")) - println(s"-------------") - println(code) - println(s"-------------") - } - -} diff --git a/testgen/src/main/scala/SpiralMatrixTestGenerator.scala b/testgen/src/main/scala/SpiralMatrixTestGenerator.scala deleted file mode 100644 index d210fab6..00000000 --- a/testgen/src/main/scala/SpiralMatrixTestGenerator.scala +++ /dev/null @@ -1,15 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder -import testgen.TestSuiteBuilder.fromLabeledTestFromInput - -object SpiralMatrixGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/spiral-matrix.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("size")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SublistTestGenerator.scala b/testgen/src/main/scala/SublistTestGenerator.scala deleted file mode 100644 index d5470765..00000000 --- a/testgen/src/main/scala/SublistTestGenerator.scala +++ /dev/null @@ -1,38 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object SublistTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/sublist.json") - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right("equal") => s"Sublist.Equal" - case Right("sublist") => s"Sublist.Sublist" - case Right("superlist") => s"Sublist.Superlist" - case Right("unequal") => s"Sublist.Unequal" - case _ => throw new IllegalStateException() - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"$sut.$property($args)" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - val code = - TestSuiteBuilder.build(file, fromLabeledTestFromInput("listOne", "listTwo")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala b/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala deleted file mode 100644 index dcbc6cfe..00000000 --- a/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala +++ /dev/null @@ -1,46 +0,0 @@ -import testgen._ -import TestSuiteBuilder.{toString, _} -import java.io.File - -object SumOfMultiplesTestGenerator { - def toArgString(any: Any): String = { - any match { - case list: List[_] => - val vals = list.map(s => TestSuiteBuilder.toString(s)).mkString(", ") - s"Set($vals)" - case lstr: Long => - lstr.toString + "l" - case _ => any.toString - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException() - case Right(n) => s"$n" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"$sut.$property($args)" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/sum-of-multiples.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("factors", "limit")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/TestBuilder.scala b/testgen/src/main/scala/TestBuilder.scala deleted file mode 100644 index 7e9c3685..00000000 --- a/testgen/src/main/scala/TestBuilder.scala +++ /dev/null @@ -1,98 +0,0 @@ -import scala.language.postfixOps -import java.io.FileWriter -import java.io.File - -case class TestCaseGen(description: String, callSUT: String, expected: String, - result: String, checkResult: String) - -object TestCaseGen { - def apply(description: String, callSUT: String, expected: String): TestCaseGen = - TestCaseGen(description, callSUT, expected, - s"val result = $callSUT", s"result should be ($expected)") - - implicit def toTestCaseGenSeq[T](ts: Seq[T])( - implicit toGen: T => TestCaseGen): Seq[TestCaseGen] = - ts map toGen -} - -class TestBuilder(testName: String) { - - private var imports: Seq[String] = Seq() - def addImport(imprt: String): Unit = imports = imports :+ imprt - - private var version: Option[String] = None - def setVersion(v: String): Unit = this.version = Some(v) - - private var testCases: Seq[(Seq[TestCaseGen], Option[String])] = Seq() - def addTestCases(testCases: Seq[TestCaseGen], description: Option[String] = None): Unit = - this.testCases = this.testCases :+ (testCases, description) - - def toFile: Unit = { - val file = new File(s"$testName.scala") - val fileWriter = new FileWriter(file) - try { fileWriter.write(build) } finally fileWriter.close - - println(s"file ${file.getAbsolutePath} created") - } - - def build: String = -s"""$printImports -$printVersion -class $testName extends AnyFunSuite with Matchers { -$printTestCases -} -""" - - private lazy val printVersion: String = - version match { - case Some(v) => s"""/** @version $v */""" - case None => "" - } - - private lazy val printImports: String = - "import org.scalatest.funsuite.AnyFunSuite\n" + - "import org.scalatest.matchers.should.Matchers\n" + - (imports map (imp => s"import $imp\n") mkString) - - private lazy val printTestCases: String = { - var pending = false - def printPending: String = - if (pending) s"pending\n " else { pending = true; "" } - - def printTestCaseGroup(testCaseGroup: Seq[TestCaseGen], - groupDescription: Option[String]): String = - { - val description = groupDescription map (s => s"\n // $s") getOrElse "" - val testCases = testCaseGroup map printTestCase mkString - - s"$description$testCases" - } - - def printTestCase(tc: TestCaseGen): String = -s""" - test("${tc.description}") { - ${printPending}${tc.result} - ${tc.checkResult} - } -""" - - testCases map (printTestCaseGroup _).tupled mkString - } -} - -object TestBuilder { - def main(args: Array[String]): Unit = { - val testCases13 = - (1 to 3) map (i => TestCaseGen(s"test$i", s"identity($i)", s"$i")) - val testCases45 = - (4 to 5) map (i => TestCaseGen(s"test$i", s"identity($i)", s"$i")) - val tb = new TestBuilder("IdentityTest") - tb.addImport("scala.collection.mutable") - tb.addTestCases(testCases13, Some("identity tests 1-3")) - tb.addTestCases(testCases45) - println("-----") - println(tb.build) - println("-----") - tb.toFile - } -} diff --git a/testgen/src/main/scala/TriangleTestGenerator.scala b/testgen/src/main/scala/TriangleTestGenerator.scala deleted file mode 100644 index 31351317..00000000 --- a/testgen/src/main/scala/TriangleTestGenerator.scala +++ /dev/null @@ -1,38 +0,0 @@ -import java.io.File -import scala.language.postfixOps - -import testgen.TestSuiteBuilder.{toString, _} -import testgen._ - -object TriangleTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/triangle.json") - - def mapArgToString(arg: Any): String = { - arg match { - case vals: List[_] => vals.mkString(", ") - case _ => throw new IllegalStateException - } - } - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => mapArgToString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val func = labeledTest.property.mkString - val sutCall = s"""Triangle(${args}).$func""" - val expected = - labeledTest.expected.fold(Function.const("true"), x => s"$x") - TestCaseData(labeledTest.property + " - " + labeledTest.description, sutCall, expected) - } - - val code = TestSuiteBuilder.build(file, - fromLabeledTestFromInput("sides")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/TwoferTestGenerator.scala b/testgen/src/main/scala/TwoferTestGenerator.scala deleted file mode 100644 index 3d60ca80..00000000 --- a/testgen/src/main/scala/TwoferTestGenerator.scala +++ /dev/null @@ -1,45 +0,0 @@ -import java.io.File - -import testgen.{CanonicalDataParser, TestCaseData, TestSuiteBuilder} -import testgen.TestSuiteBuilder.{ToTestCaseData, withLabeledTest} - -object TwoferTestGenerator { - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/two-fer.json") - - - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def toArgString(any: Any): String = { - any match { - case null => "" - case _ => s""""${any.toString}"""" - } - } - - def toExpectedString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => throw new IllegalStateException() - case Right(s: String) => s""""$s"""" - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = s"""Twofer.twofer($args)""" - val expected = toExpectedString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("name")) - - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/VariableLengthQuantityTestGenerator.scala b/testgen/src/main/scala/VariableLengthQuantityTestGenerator.scala deleted file mode 100644 index 282c0a17..00000000 --- a/testgen/src/main/scala/VariableLengthQuantityTestGenerator.scala +++ /dev/null @@ -1,78 +0,0 @@ -import java.io.File - -import testgen.{CanonicalDataParser, TestCaseData, TestSuiteBuilder} -import TestSuiteBuilder.{toString, _} - -object VariableLengthQuantityTestGenerator { - - private def mapListToString(arg: List[_]): String = { - s"List(${arg - .map { - case d: Double => "0x" + d.toLong.toHexString.toUpperCase - case i: Int => "0x" + i.toLong.toHexString.toUpperCase - case _ => throw new IllegalArgumentException() - } - .mkString(", ")})" - } - - private def toEncodeString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "None" - case Right(null) => "None" - case Right(n) => s"${mapListToString(n.asInstanceOf[List[_]])}" - } - } - - private def toDecodeString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Left(_) => "true" - case Right(null) => "true" - case Right(n) => s"Right(${mapListToString(n.asInstanceOf[List[Any]])})" - } - } - - private def toSutCall(sut: String, property: String, args: String, expected: CanonicalDataParser.Expected): String = { - if (property.toString.equals("encode")) - s"""$sut.$property($args)""" - else { - expected match { - case Left(_) => s"""$sut.$property($args).isLeft""" - case Right(null) => s"""$sut.$property($args).isLeft""" - case Right(n) => s"""$sut.$property($args)""" - } - } - } - - private def toArgString(any: Any): String = { - any match { - case list: List[_] => s"${mapListToString(list)}" - case _ => any.toString - } - } - - private def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toArgString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString ", " - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = toSutCall(sut, property, args, labeledTest.expected) - val expected = - if (labeledTest.property.toString.equals("encode")) - toEncodeString(labeledTest.expected) - else - toDecodeString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/variable-length-quantity.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("integers")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/VersionCheck.scala b/testgen/src/main/scala/VersionCheck.scala deleted file mode 100644 index 826a0f14..00000000 --- a/testgen/src/main/scala/VersionCheck.scala +++ /dev/null @@ -1,72 +0,0 @@ -import java.io.File - -import testgen.{CanonicalDataParser, Exercise} - -import scala.io.Source - -/** - * Tool to verify implemented version of exercises vs the canonical version. - * The scala project and the problem-specifications project should be - * pulled before running this tool. - */ -object VersionCheck { - private def getImplementedVersion(file: File): String = { - val prefix = "/** @version " - val suffix1 = " */" - val suffix2 = " **/" - val versionLine = Source.fromFile(file).getLines - .find(l => l.startsWith(prefix)) - versionLine match { - case Some(l) => - l.stripPrefix(prefix) - .stripSuffix(suffix1) - .stripSuffix(suffix2) - case None => "No version in file" - } - } - - private def getCanonicalVersion(file: File): String = { - val exercise @ Exercise(name, version, cases, comments) = - CanonicalDataParser.parse(file) - version - } - - private def getCanonicaDataPath(exerciseName: String, - problemSpecDir: String): File = - new File(new File(problemSpecDir, exerciseName), "canonical-data.json") - - private val ignoreExercises: Set[String] = - Source.fromFile(new File("./src/main/resources/version-check-ignore.txt")).getLines.toSet - - def main(args: Array[String]): Unit = { - if (args.length != 1) { - println("Usage VersionCheck /path/ where path is the filesystem path to the problem-specifications exercises directory.") - System.exit(-1) - } - - val problemSpecDir = args.head - - val exerciseDirs = new File("../exercises").listFiles() - .toList - .filter(f => f.isDirectory) - .filter(f => !ignoreExercises.contains(f.getName)) - .sorted - - exerciseDirs.foreach(f => { - new File(f, "src/test/scala").listFiles() - .toList - .filter(testFile => testFile.getName.endsWith("Test.scala")) match { - case x::_ => - val implementedVersion = getImplementedVersion(x) - val canonicalDataPath = getCanonicaDataPath(f.getName, problemSpecDir) - if (canonicalDataPath.exists()) { - val canonicalVersion = getCanonicalVersion(canonicalDataPath) - if (!implementedVersion.equals(canonicalVersion)) { - println(s"${f.getName}\timplemented version - $implementedVersion\tcanonical version - $canonicalVersion") - } - } - case _ => - } - }) - } -} diff --git a/testgen/src/main/scala/WordCountTestGenerator.scala b/testgen/src/main/scala/WordCountTestGenerator.scala deleted file mode 100644 index 3abebe65..00000000 --- a/testgen/src/main/scala/WordCountTestGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object WordCountTestGenerator { - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(m: Map[String, Int]) => - s"""Map(${m.map{case (s, i) => s"""("$s", $i)"""}.mkString(", ")})""" - case _ => throw new IllegalArgumentException - } - } - - def fromLabeledTestFromInput(): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = labeledTest.result("input").asInstanceOf[Map[String, Any]] - val sentence = escape(args("sentence").toString) - val property = labeledTest.property - val sutCall = - s"""$sut($sentence).$property""" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/word-count.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput()) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/WordyTestGenerator.scala b/testgen/src/main/scala/WordyTestGenerator.scala deleted file mode 100644 index 7c607b75..00000000 --- a/testgen/src/main/scala/WordyTestGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -import java.io.File - -import testgen.TestSuiteBuilder._ -import testgen._ - -object WordyTestGenerator { - - def toString(expected: CanonicalDataParser.Expected): String = { - expected match { - case Right(false) => s"None" - case Right(n) => s"Some($n)" - case _ => throw new IllegalStateException() - } - } - - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => - labeledTest => - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val property = labeledTest.property - val sutCall = - s"$sut.$property($args)" - val expected = toString(labeledTest.expected) - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val file = new File("src/main/resources/wordy.json") - - val code = TestSuiteBuilder.build(file, fromLabeledTestFromInput("question")) - println(s"-------------") - println(code) - println(s"-------------") - } -} diff --git a/testgen/src/main/scala/testgen/CanonicalDataParser.scala b/testgen/src/main/scala/testgen/CanonicalDataParser.scala index 4b9bb302..ea4fc1cf 100644 --- a/testgen/src/main/scala/testgen/CanonicalDataParser.scala +++ b/testgen/src/main/scala/testgen/CanonicalDataParser.scala @@ -1,106 +1,126 @@ package testgen -import scala.io.Source -import play.api.libs.json.Json -import CanonicalDataParser._ -import scala.util.Try -import scala.Left -import scala.Right +import play.api.libs.json.* +import play.api.libs.functional.syntax.* import java.io.File -object CanonicalDataParser { - type ParseResult = Map[String,Any] - - type Description = String - type Comments = Seq[String] - type Cases = Seq[LabeledTestItem] - type Property = String - type Result = Any - type Error = String - type Expected = Either[Error, Result] - type Properties = Option[Map[String,Any]] - - def getOptional[T](result: ParseResult, key: String): Option[T] = - result.get(key).asInstanceOf[Option[T]] - def getRequired[T](result: ParseResult, key: String): T = - getOptional(result, key) getOrElse (throw new Exception(s"missing: $key")) - - def parse(file: File): Exercise = { - val fileContents = Source.fromFile(file).getLines.mkString - val rawParseResult = - Json.parse(fileContents).asInstanceOf[ParseResult] - val parseResult = rawParseResult mapValues restoreInts - Exercise.fromParseResult(parseResult.toMap) - } - - private def restoreInts(any: Any): Any = - any match { - case double: Double if (double.toInt.toDouble == double) => double.toInt - case map: Map[_,_] => map mapValues restoreInts - case seq: Seq[_] => seq map restoreInts - case any => any - } - - def main(args: Array[String]): Unit = { - val path = "src/main/resources" -// val name = "hello-world.json" -// val name = "sum-of-multiples.json" - val name = "bowling.json" - val result = parse(new File(s"$path/$name")) - println(result) - } -} - -case class Exercise(name: String, version: String, cases: Cases, - comments: Option[Comments]) -object Exercise { - implicit def fromParseResult(result: ParseResult): Exercise = { - val cases: Cases = - getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult - Exercise(getRequired(result, "exercise"), getRequired(result, "version"), - flattenCases(cases, List()), getOptional(result, "comments")) - } - - // so far there are to few LabeledTestGroups to handle them separately - private def flattenCases(cases: Cases, parentDescriptions: List[String]): Cases = - cases match { - case Seq() => Seq() - case (ltg: LabeledTestGroup) +: xs => flattenCases(ltg.cases, ltg.description :: parentDescriptions) ++ - flattenCases(xs, parentDescriptions) - case (lt: LabeledTest) +: xs => LabeledTest(lt.description, lt.property, lt.expected, lt.result, parentDescriptions) +: - flattenCases(xs, parentDescriptions) - } -} - -sealed trait LabeledTestItem -object LabeledTestItem { - implicit def fromParseResult(result: ParseResult): LabeledTestItem = - if (result.contains("cases")) result: LabeledTestGroup - else result: LabeledTest -} - -case class LabeledTest(description: Description, property: Property, - expected: Expected, result: ParseResult, parentDescriptions: List[String] = List()) extends LabeledTestItem -object LabeledTest { - implicit def fromParseResult(result: ParseResult): LabeledTest = { - val expected: Expected = { - val any = getOptional[Any](result, "expected").getOrElse("unknown") - val error = Try { - Left(any.asInstanceOf[Map[String,String]]("error")) - } - error.getOrElse(Right(any)) - } - LabeledTest(getRequired(result, "description"), getRequired(result, "property"), - expected, result) - } -} - -case class LabeledTestGroup(description: Description, cases: Cases) extends LabeledTestItem -object LabeledTestGroup { - implicit def fromParseResult(result: ParseResult): LabeledTestGroup = { - val description = getRequired[String](result, "description") - val cases = - getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult - LabeledTestGroup(description, cases) - } -} +import Exercise.* + +object CanonicalDataParser: + def parse[Input: Reads, Success: Reads](fileContents: String): Result[Exercise[Input, Success]] = + Json + .parse(fileContents) + .validate[Exercise[Input, Success]] + .asEither + .left + .map(v => TestGenError.ParserError(v.toString)) + +/** Represents a single exercise in the canonical data. + * + * Based on the JSON schema at: https://github.com/exercism/problem-specifications/blob/9c864c448fc1cc85cf2959ccffe9c768001a7a39/canonical-data.schema.json#L11 + * + * @param name + * the name of the exercise + * @param version + * not provided in the current schema (!) + * @param cases + * a list of test cases + * @param comments + * a list of multiline comments + */ +final case class Exercise[Input, Success]( + name: String, + version: Option[String], + cases: Cases[Input, Success], + comments: Option[Comments], // TODO: flatten the None comments to empty collection? +) +object Exercise: + type Description = String + type Comments = Vector[String] + type Cases[Input, Success] = Seq[LabeledTestItem[Input, Success]] + type Property = String + type Error = String + + opaque type Expected[S] = Either[Error, S] + object Expected: + inline def apply[R](value: R): Expected[R] = Right(value) + inline def apply[R](error: Error): Expected[R] = Left(error) + + extension [S](e: Expected[S]) + def toCode(fromSuccess: S => String): String = + e.fold(identity, fromSuccess) + + given [I: Reads, S: Reads]: Reads[Exercise[I, S]] = ( + (__ \ "exercise").read[String] and + (__ \ "version").readNullable[String] and + (__ \ "cases").read[Seq[LabeledTestItem[I, S]]].map(flattenCases(_, parentDescriptions = Nil)) and + (__ \ "comments").readNullable[Comments] + )(Exercise.apply(_, _, _, _)) + + // Flattens the nested LabeledTestGroups into a flat list of LabeledTests + // So far there are too few LabeledTestGroups to handle them separately + private def flattenCases[I, S](cases: Seq[LabeledTestItem[I, S]], parentDescriptions: List[String]): Seq[LabeledTestItem[I, S]] = + cases match + case Seq() => Seq() + case (ltg: LabeledTestGroup[?, ?]) +: xs => + flattenCases(ltg.cases, ltg.description :: parentDescriptions) ++ + flattenCases(xs, parentDescriptions) + case (lt: LabeledTest[?, ?]) +: xs => + lt.copy(parentDescriptions = parentDescriptions) +: + flattenCases(xs, parentDescriptions) + +enum LabeledTestItem[+Input, +Success]: + /** A single test case. + * @param uuid + * test case identifier + * @param description + * a description of the test case + * @param property + * the property being tested + * @param expected + * the expected result of the test + * @param result + * not available in the schema, JsObject of the whole test case + * @param parentDescriptions + * not available in the schema, used for flattening + */ + case LabeledTest[Input, Success]( + uuid: String, + // scenario + description: Description, + property: Property, + expected: Expected[Success], + input: Input, + parentDescriptions: List[String] = List(), + ) extends LabeledTestItem[Input, Success] + + /** A group of test cases. + * + * @param description + * the description of the group + * @param cases + * the test cases in the group + */ + case LabeledTestGroup[Input, Success](description: Description, cases: Cases[Input, Success]) extends LabeledTestItem[Input, Success] + +export LabeledTestItem.* + +object LabeledTestItem: + given [S: Reads]: Reads[Expected[S]] = Reads[Expected[S]]: json => + (json \ "error").asOpt[String] match + case Some(error) => JsSuccess(Expected(error)) + case None => json.validate[S].map(Expected(_)) + + given labeledTestReads[I: Reads, S: Reads]: Reads[LabeledTest[I, S]] = + Json.reads[LabeledTest[I, S]] + + given labeledTestGroupReads[I: Reads, S: Reads]: Reads[LabeledTestGroup[I, S]] = + Json.reads[LabeledTestGroup[I, S]] + + given [I: Reads, S: Reads]: Reads[LabeledTestItem[I, S]] = + labeledTestGroupReads[I, S].widen[LabeledTestItem[I, S]] orElse + labeledTestReads[I, S].widen[LabeledTestItem[I, S]] + +// add `derives` syntax +extension [A](reads: Reads.type) + inline def derived: Reads[A] = Json.reads[A] diff --git a/testgen/src/main/scala/testgen/TestGenError.scala b/testgen/src/main/scala/testgen/TestGenError.scala new file mode 100644 index 00000000..c8e7b305 --- /dev/null +++ b/testgen/src/main/scala/testgen/TestGenError.scala @@ -0,0 +1,10 @@ +package testgen + +import scala.util.control.NoStackTrace + +enum TestGenError extends NoStackTrace: + case ParserError(value: String) + + override def getMessage(): String = productPrefix + +type Result[A] = Either[TestGenError, A] diff --git a/testgen/src/main/scala/testgen/TestGenerator.scala b/testgen/src/main/scala/testgen/TestGenerator.scala new file mode 100644 index 00000000..c8a66119 --- /dev/null +++ b/testgen/src/main/scala/testgen/TestGenerator.scala @@ -0,0 +1,48 @@ +package testgen + +import play.twirl.api.* +import play.api.libs.json.* +import org.apache.commons.lang3.StringEscapeUtils + +type TestSuiteTemplate = Template1[TestSuiteData, Txt] +type Code = String + +final case class TestCaseData(description: String, suiteCall: String, expected: String, pending: Boolean = true) + +final case class TestSuiteData(name: String, version: String, imports: Seq[String], testCases: Seq[TestCaseData], statements: Seq[String] = Seq()) + +trait TestGenerator[I: Reads, S: Reads]: + final type Input = I + final type Success = S + + def slug: String + protected def toTestCaseData(suite: String, testItem: TestItem): Seq[TestCaseData] + protected def imports: Seq[String] = Seq() + protected def statements: Seq[String] = Seq() + protected def template: TestSuiteTemplate = txt.funSuiteTemplate.asInstanceOf[Template1[TestSuiteData, Txt]] + + final type TestItem = LabeledTestItem.LabeledTest[Input, Success] + final type ToTestCaseData = String => TestItem => TestCaseData + + final def generate(fileContents: String): Result[Code] = + CanonicalDataParser + .parse[Input, Success](fileContents) + .map: exercise => + import exercise.* + + val suiteName = suiteNameOf(name) + val tsName = suiteName + "Test" + val testCasesAllPending = cases.flatMap: item => + // atm all test cases are flattened in the `Exercise.flattenCases` method, so this is safe + toTestCaseData(suiteName, item.asInstanceOf[TestItem]) + val testCases = + testCasesAllPending.prepended(testCasesAllPending.head.copy(pending = false)) // TODO: head could throw here + val testSuiteData = + TestSuiteData(tsName, version.getOrElse(""), imports, testCases, statements) + + template.render(testSuiteData).toString + + private def suiteNameOf(exerciseName: String): String = + exerciseName.split("-").map(_.capitalize).mkString + + protected def escape(raw: String): String = StringEscapeUtils.escapeJava(raw) diff --git a/testgen/src/main/scala/testgen/TestGeneratorRunner.scala b/testgen/src/main/scala/testgen/TestGeneratorRunner.scala new file mode 100644 index 00000000..14522ef9 --- /dev/null +++ b/testgen/src/main/scala/testgen/TestGeneratorRunner.scala @@ -0,0 +1,46 @@ +package testgen + +import scala.io.Source + +import java.nio.file.* +import java.nio.charset.StandardCharsets + +lazy val allGenerators: Vector[TestGenerator[?, ?]] = + Vector( + generator.WordCountTestGenerator, + ) + +/** Generates test code for a given exercise. + * + * @param exerciseSlug + * The slug of the exercise for which to generate test code like `word-count` + * @param problemSpecsPath + * The path to the problem-specifications repository + * @param otherParams + * Additional parameters like the `targetPath` for the generated test code + */ +@main +def generateTest(exerciseSlug: String, problemSpecsPath: String, otherParams: String*): Unit = + lazy val targetPath = otherParams.headOption + + allGenerators.find(_.slug == exerciseSlug) match + case Some(generator) => + val canonicalDataPath = s"$problemSpecsPath/exercises/$exerciseSlug/canonical-data.json" + val fileContents = Source.fromFile(canonicalDataPath).mkString + + generator.generate(fileContents) match + case Left(value) => println("Error generating test code: " + value) + case Right(testCode) => + targetPath match + case Some(path) => + Files.write(Paths.get(path), testCode.getBytes(StandardCharsets.UTF_8)) + println("Test code generated and saved to: " + path) + + case None => + println("Generated test code:") + println("--------------------") + println(testCode) + println("--------------------") + + case None => + println(s"No test generator found for exercise: $exerciseSlug") diff --git a/testgen/src/main/scala/testgen/TestSuiteBuilder.scala b/testgen/src/main/scala/testgen/TestSuiteBuilder.scala deleted file mode 100644 index c916e656..00000000 --- a/testgen/src/main/scala/testgen/TestSuiteBuilder.scala +++ /dev/null @@ -1,204 +0,0 @@ -package testgen - -import java.io.FileWriter -import java.io.File - -import play.twirl.api.Txt -import play.twirl.api.Template1 -import TestSuiteBuilder._ -import testgen.CanonicalDataParser.ParseResult -import scala.language.postfixOps - -object TestSuiteBuilder { - - type TestSuiteTemplate = Template1[TestSuiteData, Txt] - type ToTestCaseData = String => LabeledTestItem => TestCaseData - type ToTestCaseDataList = String => LabeledTestItem => List[TestCaseData] - type ToOptionTestCaseData = String => LabeledTestItem => Option[TestCaseData] - - private val DefaultTemplate: TestSuiteTemplate = - txt.funSuiteTemplate.asInstanceOf[Template1[TestSuiteData, Txt]] - - def build(file: File, toTestCaseData: ToTestCaseData, imports: Seq[String] = Seq(), statements: Seq[String] = Seq())( - implicit template: TestSuiteTemplate = DefaultTemplate): String = - { - val exercise @ Exercise(name, version, cases, comments) = - CanonicalDataParser.parse(file) - val tsName = testSuiteName(name) - val testCasesAllPending = cases map toTestCaseData(sutName(name)) - val testCases = - testCasesAllPending updated(0, testCasesAllPending.head.copy(pending = false)) - val testSuiteData = - TestSuiteData(tsName, version, imports, testCases, statements) - - template.render(testSuiteData).toString - } - - - def buildFromList(file: File, toTestCaseData: ToTestCaseDataList, imports: Seq[String] = Seq(), statements: Seq[String] = Seq())( - implicit template: TestSuiteTemplate = DefaultTemplate): String = - { - val exercise @ Exercise(name, version, cases, comments) = - CanonicalDataParser.parse(file) - val tsName = testSuiteName(name) - val testCasesAllPending = cases.flatMap(toTestCaseData(sutName(name))) - val testCases = - testCasesAllPending updated(0, testCasesAllPending.head.copy(pending = false)) - val testSuiteData = - TestSuiteData(tsName, version, imports, testCases, statements) - - template.render(testSuiteData).toString - } - - def buildFromOption(file: File, toTestCaseData: ToOptionTestCaseData, imports: Seq[String] = Seq())( - implicit template: TestSuiteTemplate = DefaultTemplate): String = - { - val exercise @ Exercise(name, version, cases, comments) = - CanonicalDataParser.parse(file) - val tsName = testSuiteName(name) - val testCasesAllPending = cases.map(toTestCaseData(sutName(name))).flatten - val testCases = - testCasesAllPending updated(0, testCasesAllPending.head.copy(pending = false)) - val testSuiteData = - TestSuiteData(tsName, version, imports, testCases) - - template.render(testSuiteData).toString - } - - def withLabeledTest(f: String => LabeledTest => TestCaseData): ToTestCaseData = - sut => item => f(sut)(item.asInstanceOf[LabeledTest]) - - def withLabeledList(f: String => LabeledTest => List[TestCaseData]): ToTestCaseDataList = - sut => item => f(sut)(item.asInstanceOf[LabeledTest]) - - def withLabeledTestOpt(f: String => LabeledTest => Option[TestCaseData]): ToOptionTestCaseData = - sut => item => f(sut)(item.asInstanceOf[LabeledTest]) - - def fromLabeledTest(argNames: String*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgs(labeledTest.result, argNames: _*) - val sutCall = s"$sut.$sutFunction(${args})" - val expected = toString(labeledTest.expected) - - TestCaseData(labeledTest.description, sutCall, expected) - } - - // Use when arguments are layered under "input" json element - def fromLabeledTestFromInput(argNames: String*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsFromInput(labeledTest.result, argNames: _*) - val sutCall = s"$sut.$sutFunction(${args})" - val expected = toString(labeledTest.expected) - - TestCaseData(labeledTest.description, sutCall, expected) - } - - def fromLabeledTestAlt(propArgs: (String, Seq[String])*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsAlt(labeledTest.result, propArgs:_*) - val sutCall = s"$sut.$sutFunction(${args})" - val expected = toString(labeledTest.expected) - - TestCaseData(labeledTest.description, sutCall, expected) - } - - // Use when arguments are layered under "input" json element - def fromLabeledTestAltFromInput(propArgs: (String, Seq[String])*): ToTestCaseData = - withLabeledTest { sut => labeledTest => - val sutFunction = labeledTest.property - val args = sutArgsAltFromInput(labeledTest.result, propArgs:_*) - val sutCall = s"$sut.$sutFunction(${args})" - val expected = toString(labeledTest.expected) - - TestCaseData(labeledTest.description, sutCall, expected) - } - - def main(args: Array[String]): Unit = { - val path = "src/main/resources" - val input: Map[String, ToTestCaseData] = - Map("hello-world" -> fromLabeledTest(), - "sum-of-multiples" -> fromLabeledTest("factors", "limit"), - "bowling" -> fromLabeledTest("previous_rolls")) - - input foreach { case ((name, toTestCaseData)) => - val file = new File(s"$path/$name.json") - - val code = build(file, toTestCaseData) - println(s"------ $name -------") - println(code) - println(s"------ \\$name -------") - } - } - - def sutName(exerciseName: String) = - exerciseName split "-" map (_.capitalize) mkString - - def testSuiteName(exerciseName: String): String = - sutName(exerciseName) + "Test" - - def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toString(parseResult(name))) mkString(", ") - - // Use when arguments are layered under "input" json element - def sutArgsFromInput(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String = - argNames map (name => toString(parseResult("input").asInstanceOf[Map[String, Any]](name))) mkString(", ") - - def sutArgsAlt(parseResult: CanonicalDataParser.ParseResult, propArgs: (String, Seq[String])*): String = - propArgs collect { - case ((property, argNames)) if parseResult("property") == property => - sutArgs(parseResult, argNames:_*) - } head - - // Use when arguments are layered under "input" json element - def sutArgsAltFromInput(parseResult: CanonicalDataParser.ParseResult, propArgs: (String, Seq[String])*): String = - propArgs collect { - case ((property, argNames)) if parseResult("property") == property => - sutArgsFromInput(parseResult, argNames:_*) - } head - - - private def toString(expected: CanonicalDataParser.Expected): String = - expected.fold(error => s"Left(${toString(error)})", toString) - - def quote(str: String): String = - if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\"" - - def escape(raw: String): String = { - import scala.reflect.runtime.universe._ - Literal(Constant(raw)).toString - } - - def toString(any: Any): String = { - any match { - case list: List[_] => - val vals = list.map(s => toString(s)).mkString(", ") - s"List($vals)" - case str: String => - val quot = quote(str) - s"$quot$str$quot" - case lstr: Long => - lstr.toString + "l" - case _ => any.toString - } - } - - /** - * Get value from "input" map - */ - def fromInputMap(parseResult: ParseResult, name: String) = - parseResult("input").asInstanceOf[Map[String, Any]](name) - - def writeToFile(text: String, dest: File): Unit = { - val fileWriter = new FileWriter(dest) - try { fileWriter.write(text) } finally fileWriter.close - } -} - -case class TestCaseData(description: String, sutCall: String, expected: String, - pending: Boolean = true) - -case class TestSuiteData(name: String, version: String, imports: Seq[String], - testCases: Seq[TestCaseData], statements: Seq[String] = Seq()) diff --git a/testgen/src/main/scala/testgen/generator/WordCountTestGenerator.scala b/testgen/src/main/scala/testgen/generator/WordCountTestGenerator.scala new file mode 100644 index 00000000..da54168c --- /dev/null +++ b/testgen/src/main/scala/testgen/generator/WordCountTestGenerator.scala @@ -0,0 +1,19 @@ +package testgen +package generator + +import play.api.libs.json.* + +final case class WordCountInput(sentence: String) derives Reads + +object WordCountTestGenerator extends TestGenerator[WordCountInput, Map[String, Int]]: + override def slug: String = "word-count" + + override def toTestCaseData(suite: String, testItem: TestItem): Seq[TestCaseData] = + Seq( + TestCaseData( + description = testItem.description, + suiteCall = s"""$suite("${escape(testItem.input.sentence)}").${testItem.property}""", + expected = testItem.expected.toCode: success => + s"""Map(${success.map { case (s, i) => s"""("$s", $i)""" }.mkString(", ")})""", + ), + ) diff --git a/testgen/src/main/twirl/funSuiteTemplate.scala.txt b/testgen/src/main/twirl/funSuiteTemplate.scala.txt index 71f81483..0ad5a6c8 100644 --- a/testgen/src/main/twirl/funSuiteTemplate.scala.txt +++ b/testgen/src/main/twirl/funSuiteTemplate.scala.txt @@ -1,17 +1,11 @@ -@(data: testgen.TestSuiteData)@for(imp <- data.imports) { -import @imp} - +@(data: testgen.TestSuiteData)@for(imp <- data.imports) {import @imp} import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers -@import testgen.TestSuiteBuilder._ -/** @@version @data.version */ -class @data.name extends AnyFunSuite with Matchers { -@for(statement <- data.statements) { - @statement} +class @data.name extends AnyFunSuite, Matchers: +@for(statement <- data.statements) { @statement } @for(testCase <- data.testCases) { - test("@testCase.description") { @if(testCase.pending) { - pending} - @testCase.sutCall should be (@testCase.expected) - } -}} + test("@testCase.description"): + @if(testCase.pending) {pending} + @testCase.suiteCall should be (@testCase.expected) +} diff --git a/testgen/src/main/twirl/funSuiteTemplateIgnoreExpected.scala.txt b/testgen/src/main/twirl/funSuiteTemplateIgnoreExpected.scala.txt deleted file mode 100644 index d6a338d0..00000000 --- a/testgen/src/main/twirl/funSuiteTemplateIgnoreExpected.scala.txt +++ /dev/null @@ -1,17 +0,0 @@ -@(data: testgen.TestSuiteData)@for(imp <- data.imports) { -import @imp} - -import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.matchers.should.Matchers -@import testgen.TestSuiteBuilder._ - -/** @@version @data.version */ -class @data.name extends AnyFunSuite with Matchers { -@for(statement <- data.statements) { - @statement} -@for(testCase <- data.testCases) { - test("@testCase.description") { @if(testCase.pending) { - pending} - @testCase.sutCall - } -}}