File size: 6,517 Bytes
a10b189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
{-# LANGUAGE OverloadedStrings #-}

module Test.Backend.Emit
  ( tests
  ) where

import Test.Tasty
import Test.Tasty.HUnit
import qualified Data.Text as T

import Assertica.Backend.CodeGen
import Assertica.Backend.Emit

-- ============================================================================
-- TEST SUITE
-- ============================================================================

tests :: TestTree
tests = testGroup "Assertica.Backend.Emit"
  [ testGroup "Module Header"
      [ testCase "Simple module name" testSimpleModuleHeader
      , testCase "Qualified module name" testQualifiedModuleHeader
      ]
  , testGroup "Imports"
      [ testCase "Empty imports" testEmptyImports
      , testCase "Single import" testSingleImport
      , testCase "Multiple imports" testMultipleImports
      ]
  , testGroup "Type Signatures"
      [ testCase "Format type signature" testTypeSignature
      ]
  , testGroup "Definitions"
      [ testCase "Format simple definition" testSimpleDefinition
      , testCase "Definition with type signature" testDefinitionWithType
      ]
  , testGroup "Module Emission"
      [ testCase "Emit empty module" testEmptyModule
      , testCase "Emit module with definition" testModuleWithDefinition
      ]
  , testGroup "Configuration"
      [ testCase "Default config values" testDefaultConfig
      ]
  ]

-- ============================================================================
-- UNIT TESTS: MODULE HEADER
-- ============================================================================

testSimpleModuleHeader :: Assertion
testSimpleModuleHeader = do
  let header = formatModuleHeader ["Main"]
  assertBool "Should contain module" ("module" `T.isInfixOf` header)
  assertBool "Should contain Main" ("Main" `T.isInfixOf` header)
  assertBool "Should contain where" ("where" `T.isInfixOf` header)

testQualifiedModuleHeader :: Assertion
testQualifiedModuleHeader = do
  let header = formatModuleHeader ["Assertica", "Core", "AST"]
  assertBool "Should contain Assertica" ("Assertica" `T.isInfixOf` header)
  assertBool "Should contain Core" ("Core" `T.isInfixOf` header)
  assertBool "Should contain AST" ("AST" `T.isInfixOf` header)
  assertBool "Should use dots" ("." `T.isInfixOf` header)

-- ============================================================================
-- UNIT TESTS: IMPORTS
-- ============================================================================

testEmptyImports :: Assertion
testEmptyImports = do
  let imports = formatImports defaultEmitConfig []
  assertEqual "Should be empty list" [] imports

testSingleImport :: Assertion
testSingleImport = do
  let imports = formatImports defaultEmitConfig ["Data.List"]
  assertBool "Should contain import" ("import" `T.isInfixOf` (head imports))
  assertBool "Should contain module" ("Data.List" `T.isInfixOf` (head imports))

testMultipleImports :: Assertion
testMultipleImports = do
  let imports = formatImports defaultEmitConfig
                  ["Data.List", "Data.Map", "Control.Monad"]
  assertEqual "Should have 3 imports" 3 (length imports)

-- ============================================================================
-- UNIT TESTS: TYPE SIGNATURES
-- ============================================================================

testTypeSignature :: Assertion
testTypeSignature = do
  let sig = formatTypeSignature "myFunction" "Int -> Bool"
  assertBool "Should contain name" ("myFunction" `T.isInfixOf` sig)
  assertBool "Should contain type" ("Int" `T.isInfixOf` sig)
  assertBool "Should contain ::" ("::" `T.isInfixOf` sig)

-- ============================================================================
-- UNIT TESTS: DEFINITIONS
-- ============================================================================

testSimpleDefinition :: Assertion
testSimpleDefinition = do
  let def = formatDefinition "x" "42"
  assertBool "Should contain name" ("x" `T.isInfixOf` def)
  assertBool "Should contain equals" ("=" `T.isInfixOf` def)
  assertBool "Should contain body" ("42" `T.isInfixOf` def)

testDefinitionWithType :: Assertion
testDefinitionWithType = do
  let config = defaultEmitConfig
  let def = HaskellDefinition
        { hdName = "add"
        , hdTypeSignature = Just "Int -> Int -> Int"
        , hdBody = "\\x y -> x + y"
        , hdSourceLocation = Nothing
        }
  let emitted = emitHaskellDefinition config def
  assertBool "Should contain type sig" ("Int" `T.isInfixOf` emitted)
  assertBool "Should contain definition" ("add" `T.isInfixOf` emitted)
  assertBool "Should contain body" ("+" `T.isInfixOf` emitted)

-- ============================================================================
-- UNIT TESTS: MODULE EMISSION
-- ============================================================================

testEmptyModule :: Assertion
testEmptyModule = do
  let mod = HaskellModule
        { hmName = ["Empty"]
        , hmImports = []
        , hmDefinitions = []
        , hmComments = []
        }
  let emitted = emitHaskellModule defaultEmitConfig mod
  assertBool "Should contain module" ("module" `T.isInfixOf` emitted)
  assertBool "Should contain Empty" ("Empty" `T.isInfixOf` emitted)

testModuleWithDefinition :: Assertion
testModuleWithDefinition = do
  let def = HaskellDefinition
        { hdName = "x"
        , hdTypeSignature = Just "Int"
        , hdBody = "42"
        , hdSourceLocation = Nothing
        }
  let mod = HaskellModule
        { hmName = ["Main"]
        , hmImports = ["Prelude"]
        , hmDefinitions = [def]
        , hmComments = []
        }
  let emitted = emitHaskellModule defaultEmitConfig mod
  assertBool "Should contain module" ("module" `T.isInfixOf` emitted)
  assertBool "Should contain imports" ("Prelude" `T.isInfixOf` emitted)
  assertBool "Should contain definition" ("x" `T.isInfixOf` emitted)
  assertBool "Should contain type sig" ("Int" `T.isInfixOf` emitted)
  assertBool "Should contain body" ("42" `T.isInfixOf` emitted)

-- ============================================================================
-- UNIT TESTS: CONFIGURATION
-- ============================================================================

testDefaultConfig :: Assertion
testDefaultConfig = do
  assertEqual "Indent size should be 2" 2 (ecIndentSize defaultEmitConfig)
  assertEqual "Line length should be 80" 80 (ecLineLength defaultEmitConfig)
  assertEqual "Add comments should be True" True (ecAddComments defaultEmitConfig)
  assertEqual "Prelude imports should be True" True (ecPreludeImports defaultEmitConfig)