valiant-0.1.0.0: test/Valiant/Binary/ArraySpec.hs
module Valiant.Binary.ArraySpec (spec) where
import Data.ByteString qualified as BS
import Data.Int (Int32, Int64)
import Data.Text (Text)
import Data.Vector (Vector)
import Data.Vector qualified as V
import Valiant.Binary.Array (pgDecodeArray, pgEncodeArray)
import Valiant.Binary.Decode ()
import Valiant.Binary.Encode ()
import PgWire.Protocol.Oid
import Test.Hspec
spec :: Spec
spec = do
describe "Int32 array round-trip" $ do
it "empty array" $ do
let arr = V.empty :: Vector Int32
encoded = pgEncodeArray oidInt4 arr
pgDecodeArray encoded `shouldBe` Right arr
it "single element" $ do
let arr = V.singleton (42 :: Int32)
encoded = pgEncodeArray oidInt4 arr
pgDecodeArray encoded `shouldBe` Right arr
it "multiple elements" $ do
let arr = V.fromList [1, 2, 3, 4, 5] :: Vector Int32
encoded = pgEncodeArray oidInt4 arr
pgDecodeArray encoded `shouldBe` Right arr
it "negative values" $ do
let arr = V.fromList [-100, 0, 100] :: Vector Int32
encoded = pgEncodeArray oidInt4 arr
pgDecodeArray encoded `shouldBe` Right arr
describe "Int64 array round-trip" $ do
it "multiple elements" $ do
let arr = V.fromList [1000000, 2000000, 3000000] :: Vector Int64
encoded = pgEncodeArray oidInt8 arr
pgDecodeArray encoded `shouldBe` Right arr
describe "Text array round-trip" $ do
it "multiple strings" $ do
let arr = V.fromList ["hello", "world", "foo"] :: Vector Text
encoded = pgEncodeArray oidText arr
pgDecodeArray encoded `shouldBe` Right arr
it "empty strings" $ do
let arr = V.fromList ["", "", "x"] :: Vector Text
encoded = pgEncodeArray oidText arr
pgDecodeArray encoded `shouldBe` Right arr
describe "Bool array round-trip" $ do
it "mixed booleans" $ do
let arr = V.fromList [True, False, True, False] :: Vector Bool
encoded = pgEncodeArray oidBool arr
pgDecodeArray encoded `shouldBe` Right arr
describe "decode errors" $ do
it "fails on truncated input" $ do
let result = pgDecodeArray (BS.pack [0, 0, 0, 1]) :: Either String (Vector Int32)
result `shouldSatisfy` isLeft
it "fails on empty input" $ do
let result = pgDecodeArray BS.empty :: Either String (Vector Int32)
result `shouldSatisfy` isLeft
describe "binary format" $ do
it "produces correct header for empty 1-D array" $ do
let encoded = pgEncodeArray oidInt4 (V.empty :: Vector Int32)
-- ndim=1, no null, oid=23, size=0, lbound=1
BS.length encoded `shouldBe` 20
-- First 4 bytes: ndim = 1
BS.take 4 encoded `shouldBe` BS.pack [0, 0, 0, 1]
it "element data follows header" $ do
let encoded = pgEncodeArray oidInt4 (V.singleton (42 :: Int32))
-- 20 bytes header + 4 bytes element length + 4 bytes element data = 28
BS.length encoded `shouldBe` 28
isLeft :: Either a b -> Bool
isLeft (Left _) = True
isLeft _ = False