1
+ {-# LANGUAGE DataKinds #-}
1
2
-- | Test copilot-core:Copilot.Core.Type.
2
3
module Test.Copilot.Core.Type where
3
4
4
5
-- External imports
6
+ import Data.Int (Int16 , Int32 , Int64 , Int8 )
7
+ import Data.Maybe (isJust )
8
+ import Data.Type.Equality (testEquality )
9
+ import Data.Word (Word16 , Word32 , Word64 , Word8 )
5
10
import Test.Framework (Test , testGroup )
6
11
import Test.Framework.Providers.QuickCheck2 (testProperty )
7
- import Test.QuickCheck (Gen , Property , elements ,
8
- forAllBlind , shuffle , (==>) )
12
+ import Test.QuickCheck (Gen , Property , arbitrary , elements ,
13
+ expectFailure , forAll , forAllBlind ,
14
+ property , shuffle , (==>) )
9
15
10
16
-- Internal imports: library modules being tested
11
- import Copilot.Core.Type (SimpleType (.. ), Type (.. ), simpleType )
17
+ import Copilot.Core.Type (Field (.. ), SimpleType (.. ), Struct (.. ),
18
+ Type (.. ), Typed , UType (.. ), Value (.. ),
19
+ accessorName , fieldName , simpleType , typeLength ,
20
+ typeOf , typeSize )
21
+ import Copilot.Core.Type.Array (Array )
12
22
13
23
-- | All unit tests for copilot-core:Copilot.Core.Type.
14
24
tests :: Test.Framework. Test
@@ -24,6 +34,38 @@ tests =
24
34
testSimpleTypesEqualityTransitive
25
35
, testProperty " uniqueness of equality of simple types"
26
36
testSimpleTypesEqualityUniqueness
37
+ , testProperty " typeLength matches array size for 1-dimensional arrays"
38
+ testTypeLength1
39
+ , testProperty " typeLength matches array size for 2-dimensional arrays"
40
+ testTypeLength2
41
+ , testProperty " typeSize matches full array size for 1-dimensional arrays"
42
+ testTypeSize1
43
+ , testProperty " typeSize matches full array size for 2-dimensional arrays"
44
+ testTypeSize2
45
+ , testProperty " equality of types"
46
+ testUTypesEqualitySymmetric
47
+ , testProperty " equality of utype"
48
+ testUTypesEq
49
+ , testProperty " inequality of utype"
50
+ testUTypesInequality
51
+ , testProperty " inequality of utype via typeOf"
52
+ testUTypesTypeOfInequality
53
+ , testProperty " fieldName matches field name (positive)"
54
+ testFieldNameOk
55
+ , testProperty " fieldName matches field name (negative)"
56
+ testFieldNameFail
57
+ , testProperty " Show field name"
58
+ testShowField
59
+ , testProperty " Show struct"
60
+ testShowStruct
61
+ , testProperty " accessorName matches field name (positive)"
62
+ testAccessorNameOk
63
+ , testProperty " accessorName matches field name (negative)"
64
+ testAccessorNameFail
65
+ , testProperty " typeName matches struct type name (positive)"
66
+ testTypeNameOk
67
+ , testProperty " typeName matches struct type name (negative)"
68
+ testTypeNameFail
27
69
]
28
70
29
71
-- | Test that the function simpleTypes preserves inequality, that is, it
@@ -53,6 +95,8 @@ testSimpleTypesInequality = forAllBlind twoDiffTypes $ \(t1, t2) ->
53
95
, simpleType Word64
54
96
, simpleType Float
55
97
, simpleType Double
98
+ , simpleType (Array Int8 :: Type (Array 3 Int8 ))
99
+ , simpleType (Struct (S (Field 0 )))
56
100
]
57
101
58
102
-- | Test that the equality relation for simple types is reflexive.
@@ -97,4 +141,199 @@ simpleTypes =
97
141
, SFloat
98
142
, SDouble
99
143
, SStruct
144
+ , SArray Int8
145
+ , SArray Int16
100
146
]
147
+
148
+ -- | Test that the length of an array is as expected.
149
+ testTypeLength1 :: Property
150
+ testTypeLength1 = property $ typeLength a == 3
151
+ where
152
+ a :: Type (Array 3 Int8 )
153
+ a = Array Int8
154
+
155
+ -- | Test that the length of an multi-dimensional array is as expected.
156
+ testTypeLength2 :: Property
157
+ testTypeLength2 = property $ typeLength a == 3
158
+ where
159
+ a :: Type (Array 3 (Array 12 Int8 ))
160
+ a = Array (Array Int8 )
161
+
162
+ -- | Test that the size of an array is as expected.
163
+ testTypeSize1 :: Property
164
+ testTypeSize1 = property $ typeLength a == 3
165
+ where
166
+ a :: Type (Array 3 Int8 )
167
+ a = Array Int8
168
+
169
+ -- | Test that the size of a multi-dimensional array is as expected (flattens
170
+ -- the array).
171
+ testTypeSize2 :: Property
172
+ testTypeSize2 = property $ typeSize a == 36
173
+ where
174
+ a :: Type (Array 3 (Array 12 Int8 ))
175
+ a = Array (Array Int8 )
176
+
177
+ -- | Test that equality is symmetric for UTypes via testEquality.
178
+ testUTypesEqualitySymmetric :: Property
179
+ testUTypesEqualitySymmetric =
180
+ forAllBlind (elements utypes) $ \ (UType t1) -> isJust (testEquality t1 t1)
181
+
182
+ -- | Test that testEquality implies equality for UTypes.
183
+ testUTypesEq :: Property
184
+ testUTypesEq =
185
+ forAllBlind (elements utypes) $ \ t@ (UType t1) -> isJust (testEquality t1 t1) ==> t == t
186
+
187
+ -- | Test that any two different UTypes are not equal.
188
+ --
189
+ -- This function pre-selects two UTypes from a list of different UTypes, which
190
+ -- guarantees that they will be different.
191
+ testUTypesInequality :: Property
192
+ testUTypesInequality = forAllBlind twoDiffTypes $ \ (t1, t2) ->
193
+ t1 /= t2
194
+ where
195
+ twoDiffTypes :: Gen (UType , UType )
196
+ twoDiffTypes = do
197
+ shuffled <- shuffle utypes
198
+ case shuffled of
199
+ (t1: t2: _) -> return (t1, t2)
200
+ _ -> return (UType Bool , UType Bool )
201
+
202
+ -- | Different UTypes.
203
+ utypes :: [UType ]
204
+ utypes =
205
+ [ UType Bool
206
+ , UType Int8
207
+ , UType Int16
208
+ , UType Int32
209
+ , UType Int64
210
+ , UType Word8
211
+ , UType Word16
212
+ , UType Word32
213
+ , UType Word64
214
+ , UType Float
215
+ , UType Double
216
+ , UType a
217
+ , UType b
218
+ , UType c
219
+ ]
220
+ where
221
+ a :: Type (Array 3 Int8 )
222
+ a = Array Int8
223
+
224
+ b :: Type (Array 4 Int8 )
225
+ b = Array Int8
226
+
227
+ c :: Type S
228
+ c = Struct (S (Field 0 ))
229
+
230
+ -- | Test that any two different UTypes are not equal.
231
+ --
232
+ -- This function pre-selects two UTypes from a list of different UTypes built
233
+ -- via the function typeOf, which guarantees that they will be different.
234
+ testUTypesTypeOfInequality :: Property
235
+ testUTypesTypeOfInequality = forAllBlind twoDiffTypes $ \ (t1@ (UType t1'), t2@ (UType t2')) ->
236
+ -- The seqs are important: otherwise, the coverage goes down drastically
237
+ -- because the typeOf function is not really executed.
238
+ t1' `seq` t2' `seq` t1 /= t2
239
+ where
240
+ twoDiffTypes :: Gen (UType , UType )
241
+ twoDiffTypes = do
242
+ shuffled <- shuffle uTypesTypeOf
243
+ case shuffled of
244
+ (t1: t2: _) -> t1 `seq` t2 `seq` return (t1, t2)
245
+ _ -> return (UType Bool , UType Bool )
246
+
247
+ -- | Different UTypes, produced by using the function typeOf.
248
+ uTypesTypeOf :: [UType ]
249
+ uTypesTypeOf =
250
+ [ UType (typeOf :: Type Bool )
251
+ , UType (typeOf :: Type Int8 )
252
+ , UType (typeOf :: Type Int16 )
253
+ , UType (typeOf :: Type Int32 )
254
+ , UType (typeOf :: Type Int64 )
255
+ , UType (typeOf :: Type Word8 )
256
+ , UType (typeOf :: Type Word16 )
257
+ , UType (typeOf :: Type Word32 )
258
+ , UType (typeOf :: Type Word64 )
259
+ , UType (typeOf :: Type Float )
260
+ , UType (typeOf :: Type Double )
261
+ , UType (typeOf :: Type (Array 3 Int8 ))
262
+ , UType (typeOf :: Type S )
263
+ ]
264
+
265
+ -- | Test the fieldName function (should succeed).
266
+ testFieldNameOk :: Property
267
+ testFieldNameOk = forAll arbitrary $ \ k ->
268
+ fieldName (s1 (S (Field k))) == s1FieldName
269
+ where
270
+ s1FieldName = " field"
271
+
272
+ -- | Test the fieldName function (should fail).
273
+ testFieldNameFail :: Property
274
+ testFieldNameFail = expectFailure $ property $
275
+ fieldName (s1 sampleS) == s1FieldName
276
+ where
277
+ sampleS = S (Field 0 )
278
+ s1FieldName = " Field"
279
+
280
+ -- | Test showing a field of a struct.
281
+ testShowField :: Property
282
+ testShowField = forAll arbitrary $ \ k ->
283
+ show (s1 (S (Field k))) == (" field:" ++ show k)
284
+
285
+ -- | Test showing a struct.
286
+ testShowStruct :: Property
287
+ testShowStruct = forAll arbitrary $ \ k ->
288
+ show (S (Field k)) == " <field:" ++ show k ++ " >"
289
+
290
+ -- | Test the accessorName of a field of a struct (should succeed).
291
+ testAccessorNameOk :: Property
292
+ testAccessorNameOk = property $
293
+ accessorName s1 == s1FieldName
294
+ where
295
+ s1FieldName = " field"
296
+
297
+ -- | Test the accessorName of a field of a struct (should fail).
298
+ testAccessorNameFail :: Property
299
+ testAccessorNameFail = expectFailure $ property $
300
+ accessorName s1 == s1FieldName
301
+ where
302
+ s1FieldName = " Field"
303
+
304
+ -- | Test the typeName of a struct (should succeed).
305
+ testTypeNameOk :: Property
306
+ testTypeNameOk = property $
307
+ typeName sampleS == s1TypeName
308
+
309
+ where
310
+
311
+ sampleS :: S
312
+ sampleS = S (Field 0 )
313
+
314
+ s1TypeName :: String
315
+ s1TypeName = " S"
316
+
317
+ -- | Test the typeName of a struct (should fail).
318
+ testTypeNameFail :: Property
319
+ testTypeNameFail = expectFailure $ property $
320
+ typeName sampleS == s1TypeName
321
+
322
+ where
323
+
324
+ sampleS :: S
325
+ sampleS = S (Field 0 )
326
+
327
+ s1TypeName :: String
328
+ s1TypeName = " s"
329
+
330
+ -- | Auxiliary struct defined for testing purposes.
331
+ data S = S { s1 :: Field " field" Int8 }
332
+
333
+ instance Struct S where
334
+ typeName _ = " S"
335
+
336
+ toValues s = [ Value Int8 (s1 s) ]
337
+
338
+ instance Typed S where
339
+ typeOf = Struct (S (Field 0 ))
0 commit comments