{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module System.Nix.Arbitrary.StorePath where

#if !MIN_VERSION_base(4,18,0)
import Control.Applicative (liftA2)
#endif
import Crypto.Hash (MD5, SHA1, SHA256, SHA512)
import qualified Data.ByteString.Char8
import qualified Data.Text
import System.Nix.StorePath (StoreDir(..)
  , StorePath
  , StorePathName
  , StorePathHashPart
  )
import qualified System.Nix.StorePath

import Test.QuickCheck (Arbitrary(arbitrary), choose, elements, oneof, vectorOf)

instance Arbitrary StoreDir where
  arbitrary :: Gen StoreDir
arbitrary =
    RawFilePath -> StoreDir
StoreDir
    (RawFilePath -> StoreDir)
-> (String -> RawFilePath) -> String -> StoreDir
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> RawFilePath
Data.ByteString.Char8.singleton Char
'/' RawFilePath -> RawFilePath -> RawFilePath
forall a. Semigroup a => a -> a -> a
<>) -- TODO(srk): nasty, see #237
    (RawFilePath -> RawFilePath)
-> (String -> RawFilePath) -> String -> RawFilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RawFilePath
Data.ByteString.Char8.pack (String -> StoreDir) -> Gen String -> Gen StoreDir
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String
forall a. Arbitrary a => Gen a
arbitrary

instance Arbitrary StorePath where
  arbitrary :: Gen StorePath
arbitrary =
    (StorePathHashPart -> StorePathName -> StorePath)
-> Gen StorePathHashPart -> Gen StorePathName -> Gen StorePath
forall a b c. (a -> b -> c) -> Gen a -> Gen b -> Gen c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 StorePathHashPart -> StorePathName -> StorePath
System.Nix.StorePath.unsafeMakeStorePath
      Gen StorePathHashPart
forall a. Arbitrary a => Gen a
arbitrary
      Gen StorePathName
forall a. Arbitrary a => Gen a
arbitrary

instance Arbitrary StorePathName where
  arbitrary :: Gen StorePathName
arbitrary =
      (InvalidNameError -> StorePathName)
-> (StorePathName -> StorePathName)
-> Either InvalidNameError StorePathName
-> StorePathName
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either InvalidNameError -> StorePathName
forall a. HasCallStack => a
undefined StorePathName -> StorePathName
forall a. a -> a
id
    (Either InvalidNameError StorePathName -> StorePathName)
-> (String -> Either InvalidNameError StorePathName)
-> String
-> StorePathName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either InvalidNameError StorePathName
System.Nix.StorePath.mkStorePathName
    (Text -> Either InvalidNameError StorePathName)
-> (String -> Text)
-> String
-> Either InvalidNameError StorePathName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Data.Text.pack (String -> StorePathName) -> Gen String -> Gen StorePathName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((:) (Char -> String -> String) -> Gen Char -> Gen (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Char
s1 Gen (String -> String) -> Gen String -> Gen String
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Char -> Gen String
forall {a}. Gen a -> Gen [a]
limited Gen Char
sn)
   where
    alphanum :: String
alphanum = [Char
'a' .. Char
'z'] String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [Char
'A' .. Char
'Z'] String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [Char
'0' .. Char
'9']
    s1 :: Gen Char
s1 = String -> Gen Char
forall a. HasCallStack => [a] -> Gen a
elements (String -> Gen Char) -> String -> Gen Char
forall a b. (a -> b) -> a -> b
$ String
alphanum String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"+-_?="
    sn :: Gen Char
sn = String -> Gen Char
forall a. HasCallStack => [a] -> Gen a
elements (String -> Gen Char) -> String -> Gen Char
forall a b. (a -> b) -> a -> b
$ String
alphanum String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"+-._?="
    limited :: Gen a -> Gen [a]
limited Gen a
n = do
      Int
k <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
210)
      Int -> Gen a -> Gen [a]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
k Gen a
n

instance Arbitrary StorePathHashPart where
  arbitrary :: Gen StorePathHashPart
arbitrary =
    [Gen StorePathHashPart] -> Gen StorePathHashPart
forall a. HasCallStack => [Gen a] -> Gen a
oneof
      [ forall hashAlgo.
HashAlgorithm hashAlgo =>
RawFilePath -> StorePathHashPart
System.Nix.StorePath.mkStorePathHashPart @MD5
        (RawFilePath -> StorePathHashPart)
-> (String -> RawFilePath) -> String -> StorePathHashPart
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RawFilePath
Data.ByteString.Char8.pack (String -> StorePathHashPart)
-> Gen String -> Gen StorePathHashPart
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String
forall a. Arbitrary a => Gen a
arbitrary
      , forall hashAlgo.
HashAlgorithm hashAlgo =>
RawFilePath -> StorePathHashPart
System.Nix.StorePath.mkStorePathHashPart @SHA1
        (RawFilePath -> StorePathHashPart)
-> (String -> RawFilePath) -> String -> StorePathHashPart
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RawFilePath
Data.ByteString.Char8.pack (String -> StorePathHashPart)
-> Gen String -> Gen StorePathHashPart
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String
forall a. Arbitrary a => Gen a
arbitrary
      , forall hashAlgo.
HashAlgorithm hashAlgo =>
RawFilePath -> StorePathHashPart
System.Nix.StorePath.mkStorePathHashPart @SHA256
        (RawFilePath -> StorePathHashPart)
-> (String -> RawFilePath) -> String -> StorePathHashPart
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RawFilePath
Data.ByteString.Char8.pack (String -> StorePathHashPart)
-> Gen String -> Gen StorePathHashPart
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String
forall a. Arbitrary a => Gen a
arbitrary
      , forall hashAlgo.
HashAlgorithm hashAlgo =>
RawFilePath -> StorePathHashPart
System.Nix.StorePath.mkStorePathHashPart @SHA512
        (RawFilePath -> StorePathHashPart)
-> (String -> RawFilePath) -> String -> StorePathHashPart
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RawFilePath
Data.ByteString.Char8.pack (String -> StorePathHashPart)
-> Gen String -> Gen StorePathHashPart
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String
forall a. Arbitrary a => Gen a
arbitrary
      ]