|
1 |
| -import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..)) |
2 |
| -import System.Exit (ExitCode(..), exitWith) |
3 |
| -import Cipher (caesarEncode, caesarDecode, caesarEncodeRandom) |
| 1 | +import Test.Hspec (Spec, describe, it, shouldBe) |
| 2 | +import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith) |
4 | 3 |
|
5 |
| -exitProperly :: IO Counts -> IO () |
6 |
| -exitProperly m = do |
7 |
| - counts <- m |
8 |
| - exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess |
9 |
| - |
10 |
| -testCase :: String -> Assertion -> Test |
11 |
| -testCase label assertion = TestLabel label (TestCase assertion) |
| 4 | +import Cipher (caesarDecode, caesarEncode, caesarEncodeRandom) |
12 | 5 |
|
13 | 6 | main :: IO ()
|
14 |
| -main = exitProperly $ runTestTT $ TestList |
15 |
| - [ TestList caesarTests ] |
16 |
| - |
17 |
| -caesarTests :: [Test] |
18 |
| -caesarTests = |
19 |
| - [ testCase "no-op encode" $ do |
20 |
| - ['a'..'z'] @=? caesarEncode "a" ['a'..'z'] |
21 |
| - ['a'..'z'] @=? caesarEncode (repeat 'a') ['a'..'z'] |
22 |
| - , testCase "no-op decode" $ do |
23 |
| - ['a'..'z'] @=? caesarDecode "a" ['a'..'z'] |
24 |
| - ['a'..'z'] @=? caesarDecode (repeat 'a') ['a'..'z'] |
25 |
| - , testCase "reversible" $ do |
26 |
| - let k0 = "alkjsdhflkjahsuid" |
27 |
| - "asdf" @=? caesarDecode k0 (caesarEncode k0 "asdf") |
28 |
| - let k1 = ['z','y'..'a'] |
29 |
| - "asdf" @=? caesarDecode k1 (caesarEncode k1 "asdf") |
30 |
| - , testCase "known cipher" $ do |
31 |
| - let k = ['a'..'j'] |
32 |
| - encode = caesarEncode k |
33 |
| - decode = caesarDecode k |
34 |
| - k @=? encode "aaaaaaaaaa" |
35 |
| - "aaaaaaaaaa" @=? decode k |
36 |
| - ['a'..'z'] @=? decode (encode ['a'..'z']) |
37 |
| - 'z':['a'..'i'] @=? encode "zzzzzzzzzz" |
38 |
| - , testCase "double shift" $ do |
39 |
| - let plaintext = "iamapandabear" |
40 |
| - ciphertext = "qayaeaagaciai" |
41 |
| - ciphertext @=? caesarEncode plaintext plaintext |
42 |
| - , testCase "shift cipher" $ do |
43 |
| - let encode = caesarEncode "d" |
44 |
| - decode = caesarDecode "d" |
45 |
| - "dddddddddd" @=? encode "aaaaaaaaaa" |
46 |
| - "aaaaaaaaaa" @=? decode "dddddddddd" |
47 |
| - ['d'..'m'] @=? encode ['a'..'j'] |
48 |
| - ['a'..'j'] @=? decode (encode ['a'..'j']) |
49 |
| - , testCase "random tests" $ do |
50 |
| - let plaintext = take 1000 (cycle ['a'..'z']) |
51 |
| - p1 <- caesarEncodeRandom plaintext |
52 |
| - plaintext @=? uncurry caesarDecode p1 |
53 |
| - p2 <- caesarEncodeRandom plaintext |
54 |
| - plaintext @=? uncurry caesarDecode p2 |
55 |
| - -- There's a small chance this could fail, since it's random. |
56 |
| - False @=? (p1 == p2) |
57 |
| - ] |
| 7 | +main = hspecWith defaultConfig {configFastFail = True} specs |
| 8 | + |
| 9 | +specs :: Spec |
| 10 | +specs = describe "simple-cipher" $ do |
| 11 | + |
| 12 | + -- As of 2016-09-16, there was no reference file |
| 13 | + -- for the test cases in `exercism/x-common`. |
| 14 | + |
| 15 | + it "no-op encode" $ do |
| 16 | + caesarEncode "a" ['a'..'z'] `shouldBe` ['a'..'z'] |
| 17 | + caesarEncode (repeat 'a') ['a'..'z'] `shouldBe` ['a'..'z'] |
| 18 | + |
| 19 | + it "no-op decode" $ do |
| 20 | + caesarDecode "a" ['a'..'z'] `shouldBe` ['a'..'z'] |
| 21 | + caesarDecode (repeat 'a') ['a'..'z'] `shouldBe` ['a'..'z'] |
| 22 | + |
| 23 | + it "reversible" $ do |
| 24 | + let k0 = "alkjsdhflkjahsuid" |
| 25 | + k1 = ['z','y'..'a'] |
| 26 | + caesarDecode k0 (caesarEncode k0 "asdf") `shouldBe` "asdf" |
| 27 | + caesarDecode k1 (caesarEncode k1 "asdf") `shouldBe` "asdf" |
| 28 | + |
| 29 | + it "known cipher" $ do |
| 30 | + let k = ['a'..'j'] |
| 31 | + encode = caesarEncode k |
| 32 | + decode = caesarDecode k |
| 33 | + encode "aaaaaaaaaa" `shouldBe` k |
| 34 | + decode k `shouldBe` "aaaaaaaaaa" |
| 35 | + decode (encode ['a'..'z']) `shouldBe` ['a'..'z'] |
| 36 | + encode "zzzzzzzzzz" `shouldBe` 'z':['a'..'i'] |
| 37 | + |
| 38 | + it "double shift" $ do |
| 39 | + let plaintext = "iamapandabear" |
| 40 | + ciphertext = "qayaeaagaciai" |
| 41 | + caesarEncode plaintext plaintext `shouldBe` ciphertext |
| 42 | + |
| 43 | + it "shift cipher" $ do |
| 44 | + let encode = caesarEncode "d" |
| 45 | + decode = caesarDecode "d" |
| 46 | + encode "aaaaaaaaaa" `shouldBe` "dddddddddd" |
| 47 | + decode "dddddddddd" `shouldBe` "aaaaaaaaaa" |
| 48 | + encode ['a'..'j'] `shouldBe` ['d'..'m'] |
| 49 | + decode (encode ['a'..'j']) `shouldBe` ['a'..'j'] |
| 50 | + |
| 51 | + it "random tests" $ do |
| 52 | + let plaintext = take 1000 (cycle ['a'..'z']) |
| 53 | + p1 <- caesarEncodeRandom plaintext |
| 54 | + uncurry caesarDecode p1 `shouldBe` plaintext |
| 55 | + p2 <- caesarEncodeRandom plaintext |
| 56 | + uncurry caesarDecode p2 `shouldBe` plaintext |
| 57 | + -- There's a small chance this could fail, since it's random. |
| 58 | + (p1 == p2) `shouldBe` False |
0 commit comments