libasterix-0.18.0: test/Common.hs
{-# LANGUAGE LambdaCase #-}
module Common where
import Data.Base16.Types (assertBase16, extractBase16)
import Data.Bool
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base16 as B16
import Data.Char
import qualified Data.List.NonEmpty as NE
import Data.Text (Text)
import Test.Tasty.HUnit
import Asterix.Base
import Asterix.Coding
-- | Convert bytestring to hex representation.
hexlify :: BS.ByteString -> Text
hexlify = extractBase16 . B16.encodeBase16
-- | Convert hex representation to bytestring.
unhexlify :: Text -> BS.ByteString
unhexlify = B16.decodeBase16' . assertBase16
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 => Text -> t -> Assertion
assertUnparse s obj = assertEqual "unparse"
(debugBits @Bits $ byteStringToBits (unhexlify s))
(debugBits @Bits $ unparse obj)
assertOne :: [a] -> IO a
assertOne [x] = pure x
assertOne _ = assertFailure "expecting list of length 1"
data StResult
= Bin Text
| Hex Text
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)))]