libasterix-0.17.1: test/Common.hs
{-# LANGUAGE LambdaCase #-}
module Common where
import Data.Bool
import Data.Char
import qualified Data.List.NonEmpty as NE
import Data.Maybe
import Test.Tasty.HUnit
import Asterix.Base
import Asterix.Coding
approximately :: (Ord a, Fractional a) => a -> a -> a -> Bool
approximately err a b = abs (b - a) / a < err
assertApproximately :: (Ord a, Fractional a) =>
String -> a -> a -> a -> Assertion
assertApproximately name err a b = assertEqual name True
(approximately err a b)
assertUint :: Unparsing Bits t => Integer -> t -> Assertion
assertUint n obj = assertEqual "uint" n (asUint obj)
assertUnparse :: Unparsing Bits t => String -> t -> Assertion
assertUnparse s obj = assertEqual "unparse"
(debugBits @Bits $ byteStringToBits (fromJust $ unhexlify s))
(debugBits @Bits $ unparse obj)
assertOne :: [a] -> IO a
assertOne [x] = pure x
assertOne _ = assertFailure "expecting list of length 1"
data StResult
= Bin String
| Hex String
checkBits :: Unparsing Bits a => String -> a -> StResult -> Assertion
checkBits name x = \case
Bin y -> assertEqual name y (debugBits s)
Hex y -> assertEqual name y
(hexlify $ builderToByteStringSlow $ bitsToBuilder s)
where
s = unparse x
rStrip :: String -> String
rStrip
= reverse
. dropWhile isSpace
. reverse
-- | Create record with all items set to zero/one.
populateRecord :: Bool -> VRecord -> URecord
populateRecord val (GRecord schItems) = URecord bld items
where
bld :: SBuilder
bld = rebuildRecord items
items :: [Maybe (RecordItem UNonSpare)]
items = fmap goUapItem schItems
goUapItem :: VUapItem -> Maybe (RecordItem UNonSpare)
goUapItem = \case
GUapItem nsp -> Just . RecordItem $ goNsp nsp
_ -> Nothing
goNsp :: VNonSpare -> UNonSpare
goNsp (GNonSpare _name _title rv) = UNonSpare $ goRuleVar rv
goRuleVar :: VRule VVariation -> URuleVar
goRuleVar sch = URuleVar $ goVar $ case sch of
GContextFree var -> var
GDependent _ var _ -> var
goVar :: VVariation -> UVariation
goVar = \case
GElement o n _rc -> UElement $ integerToBits o n (bool 0 (-1) val)
GGroup _o lst -> UGroup $ fmap goItem lst
GExtended lst ->
let extItems = [fmap goItem i | i <- lst]
extBld = bitsToSBuilder $ recreateExtended extItems
in UExtended extBld extItems
GRepetitive rt var ->
let repVar = goVar var
repLst1 = replicate 9 (goVar var)
in case rt of
GRepetitiveRegular n ->
let repLst2 = repVar : repLst1
repBld = rebuildRepetitiveRegular n repLst2
in URepetitive repBld repLst2
GRepetitiveFx ->
let repLst2 = repVar NE.:| repLst1
repBld = rebuildRepetitiveFx repLst2
in URepetitive repBld (NE.toList repLst2)
GExplicit _met ->
let expBits = byteStringToBits mempty
expN = bitsToSBuilder $ integerToBits 0 8 1
expBld = expN <> bitsToSBuilder expBits
in UExplicit expBld expBits
GCompound lst ->
let compItems = [fmap goNsp i | i <- lst]
compBld = rebuildCompound compItems
in UCompound compBld compItems
goItem :: VItem -> UItem
goItem = \case
GSpare o n -> USpare $ integerToBits o n 0
GItem nsp -> UItem $ goNsp nsp
-- | Generate sample records from the given spec.
-- A result is a list (in case of multiple UAPs) of element, where each element
-- is a tuple (Optional[uap name], record with zeros, record with ones in each item).
sampleRecords :: VAsterix -> [(VInt, ((Maybe VText, VRecord), (URecord, URecord)))]
sampleRecords = \case
GAsterixBasic cat _ed uap -> case uap of
GUap sch -> go cat (Nothing, sch)
GUaps lst _mSel -> lst >>= \(name, sch) -> go cat (Just name, sch)
GAsterixExpansion {} -> []
where
r1 = populateRecord False
r2 = populateRecord True
go :: Int -> (Maybe VText, VRecord)
-> [(Int, ((Maybe VText, VRecord), (URecord, URecord)))]
go cat (mName, sch) = [(cat, ((mName, sch), (r1 sch, r2 sch)))]