{-# OPTIONS -Wall #-}
{-# OPTIONS -Wcompat #-}
{-# OPTIONS -Wincomplete-record-updates #-}
{-# OPTIONS -Wincomplete-uni-patterns #-}
{-# OPTIONS -Wno-type-defaults #-}
{-# OPTIONS -Wno-redundant-constraints #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveGeneric #-}
module TestJson where
import TastyExtras
import Test.Tasty
import Test.Tasty.HUnit
import Predicate
import Predicate.Refined
import Predicate.Refined3
import Predicate.Refined3Helper
import GHC.Generics (Generic)
import Data.Text (Text)
import Data.Aeson
import qualified Data.ByteString as BS
suite :: IO ()
suite = defaultMain $ testGroup "testrefined"
[ testCase "testperson ok" $ expectIO testPerson (() <$)
, testCase "testperson1 ok" $ expectIO (testPerson1 2) (() <$)
, testCase "testperson1 bad ipaddress" $ expectIO (testPerson1 3) (expectLeftWith "expected between 0 and 255 found 260")
, testCase "testperson1 bad lastname lowercase first letter" $ expectIO (testPerson1 4) (expectLeftWith "invalid name(diaz)")
, testCase "testperson1 age 99 out of range" $ expectIO (testPerson1 5) (expectLeftWith "Error in $[0].age1")
]
testPerson :: IO (Either String [Person])
testPerson = BS.readFile "test1.json" >>= return . eitherDecodeStrict'
testPerson1 :: Int -> IO (Either String [Person1])
testPerson1 i = do
let fn = "test" ++ show i ++ ".json"
BS.readFile fn >>= return . eitherDecodeStrict'
data Person = Person {
firstName :: !Text
, lastName :: !Text
, age :: !Int
, likesPizza :: Bool
} deriving (Show,Generic,Eq)
instance ToJSON Person
instance FromJSON Person
data Person1 = Person1 {
firstName1 :: NameR
, lastName1 :: NameR
, age1 :: AgeR
, likesPizza1 :: Bool
, date1 :: DateTimeNR
, ipaddress1 :: Ip4R'
} deriving (Show,Generic,Eq)
instance ToJSON Person1
instance FromJSON Person1
type ValidName =
Guard (PrintF "invalid name(%s)" Id)
(Re "^[A-Z][a-z']+$" Id) >> 'True
type ValidName' = Msg "invalid name:" (Re "^[A-Z][a-z']+$" Id)
type NameR = Refined ValidName' String
type NameR1 = Refined (Name1 >> 'True) String
type Name1 =
Uncons
>> 'Just Id
>> Guard (PrintF "not upper first(%c)" (Fst Id)) (Fst Id >> '[Id] >> IsUpper)
>> Guard (PrintF "not lower rest(%s)" (Snd Id)) (Snd Id >> IsLower)
type AgeR = Refined (Between 10 60) Int
type Ip4R = MakeR3 '(Ip4ip, Ip4op >> 'True, Ip4fmt, String)
type Ip4R' = MakeR3 '(Ip4ip, Ip4op', Ip4fmt, String)
type Ip4ip = Map (ReadP Int Id) (Resplit "\\." Id)
type Ip4op = Guard (PrintF "expected length 4 found %d" Len) (Len == 4)
>> GuardsN (PrintT "guard(%d): expected between 0 and 255 found %d" Id) 4 (Between 0 255)
type Ip4op' = Msg "length:" (Len == 4)
&& BoolsN (PrintT "guard(%d): expected between 0 and 255 found %d" Id) 4 (Between 0 255)
type Ip4fmt = PrintL 4 "%03d.%03d.%03d.%03d" Id