-- | -- Copyright: (c) 2022 Andrew Lelechenko -- Licence: BSD3 -- Maintainer: Andrew Lelechenko module Main where import Data.Foldable import qualified Data.Text as T import Data.Text.Builder.Linear.Buffer import Data.Text.Internal (Text(..)) import Data.Text.Lazy (toStrict) import Data.Text.Lazy.Builder (toLazyText) import Data.Text.Lazy.Builder.Int (decimal, hexadecimal) import Data.Text.Lazy.Builder.RealFloat (realFloat) import GHC.Generics import Test.Tasty import Test.Tasty.QuickCheck hiding ((><)) instance Arbitrary Text where arbitrary = do xs ← T.pack <$> arbitrary d ← (`mod` (T.length xs + 1)) <$> arbitrary pure $ T.drop d xs shrink t@(Text arr off len) = map (T.drop d . T.pack) (shrink ys) ++ map (\d' → T.drop d' $ T.pack $ drop (d - d') ys) (shrink d) where xs = T.unpack t ys = T.unpack (Text arr 0 (off + len)) d = length ys - length xs data Action = AppendText Text | PrependText Text | AppendChar Char | PrependChar Char | AppendHex Word | PrependHex Word | AppendDec Int | PrependDec Int | AppendDouble Double | PrependDouble Double | AppendSpaces Word | PrependSpaces Word deriving (Eq, Ord, Show, Generic) instance Arbitrary Action where arbitrary = oneof [ AppendText <$> arbitrary , PrependText <$> arbitrary , AppendChar <$> arbitraryUnicodeChar , PrependChar <$> arbitraryUnicodeChar , AppendHex <$> arbitraryBoundedIntegral , PrependHex <$> arbitraryBoundedIntegral , AppendDec <$> arbitraryBoundedIntegral , PrependDec <$> arbitraryBoundedIntegral , pure $ AppendHex minBound , pure $ AppendHex maxBound , pure $ AppendDec minBound , pure $ AppendDec maxBound , pure $ AppendDec 0 , AppendDouble <$> arbitrary , PrependDouble <$> arbitrary , AppendSpaces . getNonNegative <$> arbitrary , PrependSpaces . getNonNegative <$> arbitrary ] shrink = genericShrink interpretOnText ∷ [Action] → Text → Text interpretOnText xs z = foldl' go z xs where go ∷ Text → Action → Text go b (AppendText x) = b <> x go b (PrependText x) = x <> b go b (AppendChar x) = T.snoc b x go b (PrependChar x) = T.cons x b go b (AppendHex x) = b <> toStrict (toLazyText (hexadecimal x)) go b (PrependHex x) = toStrict (toLazyText (hexadecimal x)) <> b go b (AppendDec x) = b <> toStrict (toLazyText (decimal x)) go b (PrependDec x) = toStrict (toLazyText (decimal x)) <> b go b (AppendDouble x) = b <> toStrict (toLazyText (realFloat x)) go b (PrependDouble x) = toStrict (toLazyText (realFloat x)) <> b go b (AppendSpaces n) = b <> T.replicate (fromIntegral n) (T.singleton ' ') go b (PrependSpaces n) = T.replicate (fromIntegral n) (T.singleton ' ') <> b interpretOnBuffer ∷ [Action] → Buffer ⊸ Buffer interpretOnBuffer xs z = foldlIntoBuffer go z xs where go ∷ Buffer ⊸ Action → Buffer go b (AppendText x) = b |> x go b (PrependText x) = x <| b go b (AppendChar x) = b |>. x go b (PrependChar x) = x .<| b go b (AppendHex x) = b |>& x go b (PrependHex x) = x &<| b go b (AppendDec x) = b |>$ x go b (PrependDec x) = x $<| b go b (AppendDouble x) = b |>% x go b (PrependDouble x) = x %<| b go b (AppendSpaces n) = b |>… n go b (PrependSpaces n) = n …<| b main ∷ IO () main = defaultMain $ testGroup "All" [ testProperty "sequence of actions" prop1 , testProperty "two sequences of actions" prop2 , testProperty "append addr#" prop3 , testProperty "prepend addr#" prop4 ] prop1 ∷ [Action] → Property prop1 acts = interpretOnText acts mempty === runBuffer (\b → interpretOnBuffer acts b) prop2 ∷ [Action] → [Action] → Property prop2 acts1 acts2 = interpretOnText acts1 mempty <> interpretOnText acts2 mempty === runBuffer (\b → go (dupBuffer b)) where go ∷ (# Buffer, Buffer #) ⊸ Buffer go (# b1, b2 #) = interpretOnBuffer acts1 b1 >< interpretOnBuffer acts2 b2 prop3 :: [Action] → Property prop3 acts = runBuffer f1 === runBuffer f2 where addr# = "foo"# f1, f2 :: Buffer ⊸ Buffer f1 = \b → interpretOnBuffer acts b |># addr# f2 = \b → interpretOnBuffer acts b |> T.pack "foo" prop4 :: [Action] → Property prop4 acts = runBuffer f1 === runBuffer f2 where addr# = "foo"# f1, f2 :: Buffer ⊸ Buffer f1 = \b → addr# <|# interpretOnBuffer acts b f2 = \b → T.pack "foo" <| interpretOnBuffer acts b