jsonl-conduit-0.1.3: test/JSONL/ConduitSpec.hs
{-# language DeriveGeneric #-}
{-# language OverloadedStrings #-}
{-# options_ghc -Wno-unused-imports #-}
module JSONL.ConduitSpec where
import Data.Functor.Identity (Identity(..))
import GHC.Generics (Generic)
-- aeson
import qualified Data.Aeson as A (FromJSON(..), ToJSON(..))
-- bytestring
import qualified Data.ByteString as BS (ByteString)
import qualified Data.ByteString.Builder as BBS (toLazyByteString, Builder)
import qualified Data.ByteString.Internal as BS (c2w)
import qualified Data.ByteString.Char8 as BS8 (span)
import qualified Data.ByteString.Lazy as LBS (ByteString, span, toStrict, fromStrict)
-- conduit
import qualified Conduit as C (ConduitT, runConduit, runConduitRes, sourceFile, sinkFile, await, yield, yieldMany, mapC, unfoldC, foldMapC, foldlC, sinkList)
import Conduit ( (.|) , MonadResource)
-- hspec
import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
import JSONL.Conduit (jsonToLBSC, jsonFromLBSC, jsonFromLBSCE, sourceFileC, sinkFileC, sourceFileCE)
spec :: Spec
spec =
describe "JSONL.Conduit" $ do
it "encodes a list of JSONL records" $ do
datsC `shouldBe` datsLBS
it "sourceFileC : reads a JSONL file and decodes its contents" $ do
rs <- readRecords
rs `shouldBe` dats
it "sourceFileCE : reads a JSONL file and decodes its contents" $ do
rs <- readRecordsE
rs `shouldBe` datsE
it "jsonFromLBSCE : decode a JSONL string" $ do
rs <- C.runConduit (jsonFromLBSCE datsLBS .| C.sinkList)
rs `shouldBe` datsE
it "jsonFromLBSCE : decode a JSONL string - one failing entry" $ do
rs <- C.runConduit (jsonFromLBSCE datsLBS_ng .| C.sinkList)
rs `shouldBe` datsE_ng
data Record = R String String Int Bool deriving (Eq, Show, Generic)
instance A.ToJSON Record
instance A.FromJSON Record
datsC :: LBS.ByteString
datsC = runIdentity $ C.runConduit $ C.yieldMany dats .| jsonToLBSC
datsE, datsE_ng :: [Either String Record]
datsE = map Right dats
datsE_ng = [Right (R "Gilbert" "2013" 24 True),Left "Error in $[2]: parsing Int failed, expected Number, but encountered Boolean"]
dats :: [Record]
dats = [R "Gilbert" "2013" 24 True,R "Alexa" "2013" 29 True, R "May" "2012B" 14 False, R "Deloise" "2012A" 19 True]
datsLBS, datsLBS_ng :: LBS.ByteString
datsLBS = "[\"Gilbert\",\"2013\",24,true]\n[\"Alexa\",\"2013\",29,true]\n[\"May\",\"2012B\",14,false]\n[\"Deloise\",\"2012A\",19,true]\n"
datsLBS_ng = "[\"Gilbert\",\"2013\",24,true]\n[\"Alexa\",\"2013\",false,true]\n"
-- data asset
readRecordsE :: IO [Either String Record]
readRecordsE = C.runConduitRes $ sourceFileCE "records" .| C.sinkList
readRecords :: IO [Record]
readRecords = C.runConduitRes $ sourceFileC "records" .| C.sinkList
dump :: IO ()
dump = C.runConduitRes $ C.yieldMany dats .| sinkFileC "records"