-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

module UtilsSpec where

import TestImport
import Utils

import qualified Crypto.Saltine.Core.SecretBox as SecretBox
import Data.Aeson

instance Arbitrary Value where
  arbitrary = sized $ \size -> if
    | size <= 0 -> oneof [pure Null, bool', number, string]
    | otherwise -> resize (size `div` 2) $ oneof [pure Null, bool', number, string, array, object']
    where
      bool' = Bool <$> arbitrary
      number = Number <$> arbitrary
      string = String <$> arbitrary
      array = Array <$> arbitrary
      object' = Object <$> arbitrary
  shrink = genericShrink

instance Arbitrary SecretBoxEncoding where
  arbitrary = arbitraryBoundedEnum

spec :: Spec
spec = do
  describe "encodedSecretBox" $ do
    it "has comptabile encryption/decryption" . property $
      \val pretty -> ioProperty $ do
        sKey <- SecretBox.newKey
        ciphertext <- encodedSecretBox' sKey pretty (val :: Value)
        plaintext <- throwExceptT $ encodedSecretBoxOpen' sKey ciphertext
        return $ plaintext == val
    it "produces pretty ciphertext" . property $
      \val -> ioProperty $ do
        sKey <- SecretBox.newKey
        ciphertext <- encodedSecretBox' sKey SecretBoxPretty (val :: Value)
        return . all ((<= 76) . length) $ lines ciphertext
