mirror of
https://github.com/haskell-nix/hnix-store.git
synced 2025-01-06 03:06:58 +03:00
tests: add Test.Hspec.Nix.roundtrip
This commit is contained in:
parent
49dc678060
commit
ee40d47a67
@ -112,19 +112,18 @@ test-suite remote
|
||||
ghc-options: -Wall
|
||||
other-modules:
|
||||
SerializeSpec
|
||||
build-tool-depends:
|
||||
hspec-discover:hspec-discover
|
||||
build-depends:
|
||||
base >=4.12 && <5
|
||||
, hnix-store-core
|
||||
, hnix-store-remote
|
||||
, hnix-store-tests
|
||||
, bytestring
|
||||
, cereal
|
||||
, text
|
||||
, time
|
||||
, hspec
|
||||
, tasty
|
||||
, tasty-hspec
|
||||
, tasty-quickcheck
|
||||
, QuickCheck
|
||||
, quickcheck-instances
|
||||
, unordered-containers
|
||||
|
||||
@ -142,6 +141,8 @@ test-suite remote-io
|
||||
other-modules:
|
||||
NixDaemon
|
||||
, Spec
|
||||
build-tool-depends:
|
||||
tasty-discover:tasty-discover
|
||||
build-depends:
|
||||
base >=4.12 && <5
|
||||
, hnix-store-core
|
||||
|
@ -1 +1 @@
|
||||
{-# OPTIONS_GHC -F -pgmF tasty-discover #-}
|
||||
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
|
||||
|
@ -1,18 +1,18 @@
|
||||
{-# LANGUAGE NumericUnderscores #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module SerializeSpec where
|
||||
module SerializeSpec (spec) where
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Fixed (Uni)
|
||||
import Data.HashSet (HashSet)
|
||||
import Data.Serialize (Serialize(..))
|
||||
import Data.Serialize.Get (Get, runGet)
|
||||
import Data.Serialize.Put (Putter, runPut)
|
||||
import Data.Text (Text)
|
||||
import Data.Time (NominalDiffTime)
|
||||
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||
import Test.Tasty.QuickCheck
|
||||
import Test.Hspec (Expectation, Spec, describe, it, shouldBe)
|
||||
import Test.Hspec.QuickCheck (prop)
|
||||
import Test.Hspec.Nix (roundtrips)
|
||||
import Test.QuickCheck (arbitrary, forAll, suchThat)
|
||||
import Test.QuickCheck.Instances ()
|
||||
|
||||
import qualified Data.Either
|
||||
@ -23,139 +23,110 @@ import qualified System.Nix.Build
|
||||
import System.Nix.Arbitrary ()
|
||||
import System.Nix.Build (BuildMode, BuildStatus)
|
||||
import System.Nix.Derivation (Derivation(..))
|
||||
import System.Nix.StorePath (StoreDir, StorePath)
|
||||
import System.Nix.Store.Remote.Serialize (getDerivation, putDerivation)
|
||||
import System.Nix.Store.Remote.Serialize.Prim
|
||||
|
||||
roundTrip :: (Eq a, Show a) => Putter a -> Get a -> a -> Property
|
||||
roundTrip p g a = res === Right a
|
||||
where res = runGet g (runPut (p a))
|
||||
-- | Test for roundtrip using @Putter@ and @Get@ functions
|
||||
roundtrips2
|
||||
:: ( Eq a
|
||||
, Show a
|
||||
)
|
||||
=> Putter a
|
||||
-> Get a
|
||||
-> a
|
||||
-> Expectation
|
||||
roundtrips2 putter getter =
|
||||
roundtrips
|
||||
(runPut . putter)
|
||||
(runGet getter)
|
||||
|
||||
-- * Prim
|
||||
-- ** Int
|
||||
-- | Test for roundtrip using @Serialize@ instance
|
||||
roundtripS
|
||||
:: ( Eq a
|
||||
, Serialize a
|
||||
, Show a
|
||||
)
|
||||
=> a
|
||||
-> Expectation
|
||||
roundtripS =
|
||||
roundtrips
|
||||
(runPut . put)
|
||||
(runGet get)
|
||||
|
||||
prop_int :: Int -> Property
|
||||
prop_int = roundTrip putInt getInt
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "Prim" $ do
|
||||
prop "Int" $ roundtrips2 putInt getInt
|
||||
prop "Bool" $ roundtrips2 putBool getBool
|
||||
|
||||
-- ** Bool
|
||||
prop "UTCTime" $ do
|
||||
let
|
||||
-- scale to seconds and back
|
||||
toSeconds :: Int -> NominalDiffTime
|
||||
toSeconds n = realToFrac (toEnum n :: Uni)
|
||||
fromSeconds :: NominalDiffTime -> Int
|
||||
fromSeconds = (fromEnum :: Uni -> Int) . realToFrac
|
||||
|
||||
prop_bool :: Bool -> Property
|
||||
prop_bool = roundTrip putBool getBool
|
||||
roundtrips2
|
||||
(putTime . Data.Time.Clock.POSIX.posixSecondsToUTCTime . toSeconds)
|
||||
(fromSeconds . Data.Time.Clock.POSIX.utcTimeToPOSIXSeconds <$> getTime)
|
||||
|
||||
-- ** UTCTime
|
||||
describe "Combinators" $ do
|
||||
prop "Many" $ roundtrips2 (putMany putInt) (getMany getInt)
|
||||
prop "ByteString" $ roundtrips2 putByteString getByteString
|
||||
prop "[ByteString]" $ roundtrips2 putByteStrings getByteStrings
|
||||
prop "Text" $ roundtrips2 putText getText
|
||||
prop "[Text]" $ roundtrips2 putTexts getTexts
|
||||
|
||||
prop_time :: Int -> Property
|
||||
prop_time =
|
||||
roundTrip
|
||||
(putTime . Data.Time.Clock.POSIX.posixSecondsToUTCTime . toSeconds)
|
||||
(fromSeconds . Data.Time.Clock.POSIX.utcTimeToPOSIXSeconds <$> getTime)
|
||||
where
|
||||
-- scale to seconds and back
|
||||
toSeconds :: Int -> NominalDiffTime
|
||||
toSeconds n = realToFrac (toEnum n :: Uni)
|
||||
fromSeconds :: NominalDiffTime -> Int
|
||||
fromSeconds = (fromEnum :: Uni -> Int) . realToFrac
|
||||
prop "StorePath" $ \sd ->
|
||||
roundtrips2
|
||||
(putPath sd)
|
||||
(Data.Either.fromRight undefined <$> getPath sd)
|
||||
|
||||
-- ** Combinators
|
||||
prop "HashSet StorePath" $ \sd ->
|
||||
roundtrips2
|
||||
(putPaths sd)
|
||||
(Data.HashSet.map (Data.Either.fromRight undefined) <$> getPaths sd)
|
||||
|
||||
prop_many :: [Int] -> Property
|
||||
prop_many = roundTrip (putMany putInt) (getMany getInt)
|
||||
describe "Serialize instances" $ do
|
||||
prop "Text" $ roundtripS @Text
|
||||
prop "BuildMode" $ roundtripS @BuildMode
|
||||
prop "BuildStatus" $ roundtripS @BuildStatus
|
||||
it "BuildResult" $
|
||||
forAll (arbitrary `suchThat` ((/= Just "") . System.Nix.Build.errorMessage))
|
||||
$ \br ->
|
||||
roundtripS
|
||||
-- fix time to 0 as we test UTCTime above
|
||||
$ br { System.Nix.Build.startTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
|
||||
, System.Nix.Build.stopTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
|
||||
}
|
||||
|
||||
-- ** ByteString
|
||||
prop "Derivation StorePath Text" $ \sd ->
|
||||
roundtrips2
|
||||
(putDerivation sd)
|
||||
(getDerivation sd)
|
||||
-- inputDrvs is not used in remote protocol serialization
|
||||
. (\drv -> drv { inputDrvs = mempty })
|
||||
|
||||
prop_bytestring :: ByteString -> Property
|
||||
prop_bytestring = roundTrip putByteString getByteString
|
||||
|
||||
prop_bytestrings :: [ByteString] -> Property
|
||||
prop_bytestrings = roundTrip putByteStrings getByteStrings
|
||||
|
||||
-- ** Text
|
||||
|
||||
prop_text :: Text -> Property
|
||||
prop_text = roundTrip putText getText
|
||||
|
||||
prop_texts :: [Text] -> Property
|
||||
prop_texts = roundTrip putTexts getTexts
|
||||
|
||||
-- ** StorePath
|
||||
|
||||
prop_path :: StoreDir -> StorePath -> Property
|
||||
prop_path = \sd ->
|
||||
roundTrip
|
||||
(putPath sd)
|
||||
(Data.Either.fromRight undefined <$> getPath sd)
|
||||
|
||||
prop_paths :: StoreDir -> HashSet StorePath -> Property
|
||||
prop_paths = \sd ->
|
||||
roundTrip
|
||||
(putPaths sd)
|
||||
(Data.HashSet.map (Data.Either.fromRight undefined) <$> getPaths sd)
|
||||
|
||||
-- * Serialize
|
||||
roundTripS :: (Eq a, Serialize a, Show a) => a -> Property
|
||||
roundTripS a = res === Right a
|
||||
where res = runGet get (runPut (put a))
|
||||
|
||||
-- ** Text
|
||||
|
||||
prop_Text :: Text -> Property
|
||||
prop_Text = roundTripS
|
||||
|
||||
-- ** BuildMode
|
||||
|
||||
prop_buildMode :: BuildMode -> Property
|
||||
prop_buildMode = roundTripS
|
||||
|
||||
-- ** BuildStatus
|
||||
|
||||
prop_buildStatus :: BuildStatus -> Property
|
||||
prop_buildStatus = roundTripS
|
||||
|
||||
-- ** BuildResult
|
||||
|
||||
prop_buildResult :: Property
|
||||
prop_buildResult =
|
||||
forAll (arbitrary `suchThat` ((/= Just "") . System.Nix.Build.errorMessage))
|
||||
$ \br ->
|
||||
roundTripS
|
||||
$ br { System.Nix.Build.startTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
|
||||
, System.Nix.Build.stopTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
|
||||
}
|
||||
|
||||
-- ** Enums
|
||||
|
||||
spec_buildEnums :: Spec
|
||||
spec_buildEnums =
|
||||
let it' name constr value = it name $ runPut (put constr) `shouldBe` runPut (putInt value)
|
||||
in do
|
||||
describe "Build enum order matches Nix" $ do
|
||||
it' "Normal" System.Nix.Build.Normal 0
|
||||
it' "Repair" System.Nix.Build.Repair 1
|
||||
it' "Check" System.Nix.Build.Check 2
|
||||
describe "Build enum order matches Nix" $ do
|
||||
it' "Normal" System.Nix.Build.Normal 0
|
||||
it' "Repair" System.Nix.Build.Repair 1
|
||||
it' "Check" System.Nix.Build.Check 2
|
||||
|
||||
describe "BuildStatus enum order matches Nix" $ do
|
||||
it' "Built" System.Nix.Build.Built 0
|
||||
it' "Substituted" System.Nix.Build.Substituted 1
|
||||
it' "AlreadyValid" System.Nix.Build.AlreadyValid 2
|
||||
it' "PermanentFailure" System.Nix.Build.PermanentFailure 3
|
||||
it' "InputRejected" System.Nix.Build.InputRejected 4
|
||||
it' "OutputRejected" System.Nix.Build.OutputRejected 5
|
||||
it' "TransientFailure" System.Nix.Build.TransientFailure 6
|
||||
it' "CachedFailure" System.Nix.Build.CachedFailure 7
|
||||
it' "TimedOut" System.Nix.Build.TimedOut 8
|
||||
it' "MiscFailure" System.Nix.Build.MiscFailure 9
|
||||
it' "DependencyFailed" System.Nix.Build.DependencyFailed 10
|
||||
it' "LogLimitExceeded" System.Nix.Build.LogLimitExceeded 11
|
||||
it' "NotDeterministic" System.Nix.Build.NotDeterministic 12
|
||||
it' "ResolvesToAlreadyValid" System.Nix.Build.ResolvesToAlreadyValid 13
|
||||
it' "NoSubstituters" System.Nix.Build.NoSubstituters 14
|
||||
|
||||
-- ** Derivation
|
||||
|
||||
prop_derivation :: StoreDir -> Derivation StorePath Text -> Property
|
||||
prop_derivation sd drv =
|
||||
roundTrip
|
||||
(putDerivation sd)
|
||||
(getDerivation sd)
|
||||
-- inputDrvs is not used in remote protocol serialization
|
||||
(drv { inputDrvs = mempty })
|
||||
describe "BuildStatus enum order matches Nix" $ do
|
||||
it' "Built" System.Nix.Build.Built 0
|
||||
it' "Substituted" System.Nix.Build.Substituted 1
|
||||
it' "AlreadyValid" System.Nix.Build.AlreadyValid 2
|
||||
it' "PermanentFailure" System.Nix.Build.PermanentFailure 3
|
||||
it' "InputRejected" System.Nix.Build.InputRejected 4
|
||||
it' "OutputRejected" System.Nix.Build.OutputRejected 5
|
||||
it' "TransientFailure" System.Nix.Build.TransientFailure 6
|
||||
it' "CachedFailure" System.Nix.Build.CachedFailure 7
|
||||
it' "TimedOut" System.Nix.Build.TimedOut 8
|
||||
it' "MiscFailure" System.Nix.Build.MiscFailure 9
|
||||
it' "DependencyFailed" System.Nix.Build.DependencyFailed 10
|
||||
it' "LogLimitExceeded" System.Nix.Build.LogLimitExceeded 11
|
||||
it' "NotDeterministic" System.Nix.Build.NotDeterministic 12
|
||||
it' "ResolvesToAlreadyValid" System.Nix.Build.ResolvesToAlreadyValid 13
|
||||
it' "NoSubstituters" System.Nix.Build.NoSubstituters 14
|
||||
|
@ -42,6 +42,7 @@ library
|
||||
, System.Nix.Arbitrary.DerivedPath
|
||||
, System.Nix.Arbitrary.Hash
|
||||
, System.Nix.Arbitrary.StorePath
|
||||
, Test.Hspec.Nix
|
||||
build-depends:
|
||||
base >=4.12 && <5
|
||||
, hnix-store-core >= 0.8
|
||||
@ -49,6 +50,7 @@ library
|
||||
, cryptonite
|
||||
, dependent-sum > 0.7
|
||||
, generic-arbitrary < 1.1
|
||||
, hspec
|
||||
, QuickCheck
|
||||
, quickcheck-instances
|
||||
, text
|
||||
@ -73,7 +75,6 @@ test-suite props
|
||||
, hnix-store-core
|
||||
, hnix-store-tests
|
||||
, attoparsec
|
||||
, bytestring
|
||||
, containers
|
||||
, data-default-class
|
||||
, QuickCheck
|
||||
|
20
hnix-store-tests/src/Test/Hspec/Nix.hs
Normal file
20
hnix-store-tests/src/Test/Hspec/Nix.hs
Normal file
@ -0,0 +1,20 @@
|
||||
module Test.Hspec.Nix
|
||||
( roundtrips
|
||||
) where
|
||||
|
||||
import Test.Hspec (Expectation, shouldBe)
|
||||
|
||||
roundtrips
|
||||
:: forall a b f
|
||||
. ( Applicative f
|
||||
, Eq (f a)
|
||||
, Show a
|
||||
, Show b
|
||||
, Show (f a)
|
||||
)
|
||||
=> (a -> b) -- ^ Encode
|
||||
-> (b -> f a) -- ^ Decode
|
||||
-> a
|
||||
-> Expectation
|
||||
roundtrips encode decode x =
|
||||
decode (encode x) `shouldBe` pure x
|
@ -1,33 +1,30 @@
|
||||
module BaseEncodingSpec where
|
||||
|
||||
import Test.Hspec (Spec, describe, shouldBe)
|
||||
import Test.Hspec (Spec, describe)
|
||||
import Test.Hspec.QuickCheck (prop)
|
||||
import Test.QuickCheck (Gen, choose, listOf1, forAllShrink, genericShrink)
|
||||
import Test.Hspec.Nix (roundtrips)
|
||||
|
||||
import System.Nix.Base
|
||||
import System.Nix.Arbitrary ()
|
||||
import System.Nix.StorePath (StorePathHashPart(..))
|
||||
import qualified Data.ByteString.Char8
|
||||
import qualified System.Nix.Base32
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "Hash" $ do
|
||||
prop "Nix-like Base32 roundtrips" $
|
||||
-- TODO(srk): use decodeWith
|
||||
forAllShrink nonEmptyString genericShrink $ \x ->
|
||||
(System.Nix.Base32.decode
|
||||
. System.Nix.Base32.encode
|
||||
. Data.ByteString.Char8.pack $ x)
|
||||
`shouldBe`
|
||||
pure (Data.ByteString.Char8.pack x)
|
||||
prop "Base16 roundtrips" $ \x ->
|
||||
decodeWith Base16 (encodeWith Base16 $ unStorePathHashPart x)
|
||||
`shouldBe`
|
||||
pure (unStorePathHashPart x)
|
||||
where
|
||||
nonEmptyString :: Gen String
|
||||
nonEmptyString = listOf1 genSafeChar
|
||||
prop "Base16 roundtrips" $
|
||||
roundtrips
|
||||
(encodeWith Base16)
|
||||
(decodeWith Base16)
|
||||
. unStorePathHashPart
|
||||
|
||||
genSafeChar :: Gen Char
|
||||
genSafeChar = choose ('\1', '\127') -- ASCII without \NUL
|
||||
prop "Nix-like Base32 roundtrips" $
|
||||
roundtrips
|
||||
(encodeWith NixBase32)
|
||||
(decodeWith NixBase32)
|
||||
. unStorePathHashPart
|
||||
|
||||
prop "Base64 roundtrips" $
|
||||
roundtrips
|
||||
(encodeWith Base64)
|
||||
(decodeWith Base64)
|
||||
. unStorePathHashPart
|
||||
|
@ -1,21 +1,16 @@
|
||||
module ContentAddressSpec where
|
||||
|
||||
import Test.Hspec (Spec, describe, shouldBe)
|
||||
import Test.Hspec (Spec, describe)
|
||||
import Test.Hspec.QuickCheck (prop)
|
||||
import Test.Hspec.Nix (roundtrips)
|
||||
import System.Nix.Arbitrary ()
|
||||
|
||||
import qualified Data.Attoparsec.Text.Lazy
|
||||
import qualified Data.Text.Lazy.Builder
|
||||
|
||||
import qualified System.Nix.ContentAddress
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "ContentAddress" $ do
|
||||
prop "roundtrips" $ \caAddr ->
|
||||
Data.Attoparsec.Text.Lazy.parseOnly
|
||||
System.Nix.ContentAddress.contentAddressParser
|
||||
(Data.Text.Lazy.Builder.toLazyText
|
||||
(System.Nix.ContentAddress.contentAddressBuilder caAddr))
|
||||
`shouldBe` pure caAddr
|
||||
|
||||
prop "roundtrips" $
|
||||
roundtrips
|
||||
System.Nix.ContentAddress.buildContentAddress
|
||||
System.Nix.ContentAddress.parseContentAddress
|
||||
|
@ -1,7 +1,8 @@
|
||||
module DerivationSpec where
|
||||
|
||||
import Test.Hspec (Spec, describe, shouldBe)
|
||||
import Test.Hspec (Spec, describe)
|
||||
import Test.Hspec.QuickCheck (xprop)
|
||||
import Test.Hspec.Nix (roundtrips)
|
||||
|
||||
import System.Nix.Arbitrary ()
|
||||
import System.Nix.Derivation (parseDerivation, buildDerivation)
|
||||
@ -17,11 +18,10 @@ import qualified Data.Text.Lazy.Builder
|
||||
spec :: Spec
|
||||
spec = do
|
||||
describe "Derivation" $ do
|
||||
xprop "roundtrips via Text" $ \sd drv ->
|
||||
Data.Attoparsec.Text.parseOnly (parseDerivation sd)
|
||||
( Data.Text.Lazy.toStrict
|
||||
$ Data.Text.Lazy.Builder.toLazyText
|
||||
$ buildDerivation sd drv
|
||||
)
|
||||
`shouldBe` pure drv
|
||||
|
||||
xprop "roundtrips via Text" $ \sd ->
|
||||
roundtrips
|
||||
( Data.Text.Lazy.toStrict
|
||||
. Data.Text.Lazy.Builder.toLazyText
|
||||
. buildDerivation sd
|
||||
)
|
||||
(Data.Attoparsec.Text.parseOnly (parseDerivation sd))
|
||||
|
@ -1,7 +1,8 @@
|
||||
module StorePathSpec where
|
||||
|
||||
import Test.Hspec (Spec, describe, shouldBe)
|
||||
import Test.Hspec (Spec, describe)
|
||||
import Test.Hspec.QuickCheck (prop)
|
||||
import Test.Hspec.Nix (roundtrips)
|
||||
|
||||
import System.Nix.Arbitrary ()
|
||||
import System.Nix.StorePath
|
||||
@ -12,15 +13,19 @@ spec :: Spec
|
||||
spec = do
|
||||
describe "StorePath" $ do
|
||||
prop "roundtrips using parsePath . storePathToRawFilePath" $
|
||||
\storeDir x ->
|
||||
parsePath storeDir (storePathToRawFilePath storeDir x) `shouldBe` pure x
|
||||
\storeDir ->
|
||||
roundtrips
|
||||
(storePathToRawFilePath storeDir)
|
||||
(parsePath storeDir)
|
||||
|
||||
prop "roundtrips using parsePathFromText . storePathToText" $
|
||||
\storeDir x ->
|
||||
parsePathFromText storeDir (storePathToText storeDir x) `shouldBe` pure x
|
||||
\storeDir ->
|
||||
roundtrips
|
||||
(storePathToText storeDir)
|
||||
(parsePathFromText storeDir)
|
||||
|
||||
prop "roundtrips using pathParser . storePathToText" $
|
||||
\storeDir x ->
|
||||
Data.Attoparsec.Text.parseOnly
|
||||
(pathParser storeDir)
|
||||
(storePathToText storeDir x) `shouldBe` pure x
|
||||
\storeDir ->
|
||||
roundtrips
|
||||
(storePathToText storeDir)
|
||||
(Data.Attoparsec.Text.parseOnly $ pathParser storeDir)
|
||||
|
Loading…
Reference in New Issue
Block a user