content: -- XXX We are using head/tail at one place
  #if __GLASGOW_HASKELL__ >= 908
  {-# OPTIONS_GHC -Wno-x-partial #-}
  #endif
  
  module Main (main) where
  
  import Data.Either (fromRight)
  import Test.Hspec (Spec, hspec, describe, it, expectationFailure, shouldBe)
  import Test.Hspec.QuickCheck
  
  import qualified Streamly.Internal.Data.Array as A
  import qualified Streamly.Internal.Data.Array.Generic as AG
  import qualified Streamly.Internal.Data.Fold as FL
  import qualified Streamly.Internal.Data.Parser as Parser
  import qualified Streamly.Internal.Data.ParserK as ParserK
  import qualified Streamly.Internal.Data.Stream as Stream
  import qualified Streamly.Internal.Data.StreamK as StreamK
  import qualified Test.Hspec as H
  
  import Streamly.Test.Parser.Common
  
  import Prelude hiding (sequence)
  
  maxTestCount :: Int
  maxTestCount = 100
  
  toParser :: Spec
  toParser = do
      let p = ParserK.toParser (ParserK.toParserK Parser.one)
          runP xs = Stream.parsePos p (Stream.fromList xs)
      describe "toParser . toParserK" $ do
          it "empty stream" $ do
              r1 <- runP ([] :: [Int])
              case r1 of
                  Left e -> print e
                  Right x ->
                      expectationFailure $ "Expecting failure, got: " ++ show x
          it "exact stream" $ do
              r2 <- runP [0::Int]
              fromRight undefined r2 `shouldBe` 0
          it "longer stream" $ do
              r3 <- runP [0,1::Int]
              fromRight undefined r3 `shouldBe` 0
  
      let p1 = ParserK.toParserK $ ParserK.toParser (ParserK.toParserK Parser.one)
          runP1 xs = StreamK.parsePos p1 (StreamK.fromStream $ Stream.fromList xs)
      describe "toParserK . toParser . toParserK" $ do
          it "empty stream" $ do
              r1 <- runP1 ([] :: [Int])
              case r1 of
                  Left e -> print e
                  Right x ->
                      expectationFailure $ "Expecting failure, got: " ++ show x
          it "exact stream" $ do
              r2 <- runP1 [0::Int]
              fromRight undefined r2 `shouldBe` 0
          it "longer stream" $ do
              r3 <- runP1 [0,1::Int]
              fromRight undefined r3 `shouldBe` 0
  
      -- NOTE: Without fusionBreaker this test would pass even if toParser has
      -- incorrect implementation because of fusion rules.
      let p2 = Parser.takeWhile (<= 3) FL.toList
          runP2 xs = Stream.parseBreakPos p2 (Stream.fromList xs)
  
          p3 = ParserK.toParserK (Parser.takeWhile (<= 3) FL.toList)
          runP3 xs = StreamK.parseBreakPos p3 (StreamK.fromList xs)
  
          p4 =
              ParserK.toParser
                  $ fusionBreaker
                  $ ParserK.toParserK (Parser.takeWhile (<= 3) FL.toList)
          runP4 xs = Stream.parseBreakPos p4 (Stream.fromList xs)
      describe "toParser . toParserK" $ do
          it "(<= 3) for [1, 2, 3, 4, 5]" $ do
              (a, b) <- runP2 ([1, 2, 3, 4, 5] :: [Int])
              fromRight undefined a `shouldBe` [1, 2, 3]
              rest <- Stream.toList b
              rest `shouldBe` [4, 5]
          it "(<= 3) for [1, 2, 3, 4, 5]" $ do
              (a, b) <- runP3 ([1, 2, 3, 4, 5] :: [Int])
              fromRight undefined a `shouldBe` [1, 2, 3]
              rest <- StreamK.toList b
              rest `shouldBe` [4, 5]
          it "(<= 3) for [1, 2, 3, 4, 5]" $ do
              (a, b) <- runP4 ([1, 2, 3, 4, 5] :: [Int])
              fromRight undefined a `shouldBe` [1,2,3]
              rest <- Stream.toList b
              rest `shouldBe` [4, 5]
          it "(<= 3) for [1, 2, 3]" $ do
              (a, b) <- runP4 ([1, 2, 3] :: [Int])
              fromRight undefined a `shouldBe` [1, 2, 3]
              rest <- Stream.toList b
              rest `shouldBe` []
  
  {-# NOINLINE fusionBreaker #-}
  fusionBreaker :: a -> a
  fusionBreaker = id
  
  -------------------------------------------------------------------------------
  -- Parser driver sanity tests
  -------------------------------------------------------------------------------
  
  sanityParseBreak :: [Move] -> H.SpecWith ()
  sanityParseBreak jumps = it (show jumps) $ do
      (val, rest) <-
          StreamK.parseBreakPos (ParserK.toParserK (jumpParser jumps))
              $ StreamK.fromList tape
      lst <- StreamK.toList rest
      (val, lst) `shouldBe` (expectedResult jumps tape)
  
  sanityParseBreakChunks :: [Move] -> H.SpecWith ()
  sanityParseBreakChunks jumps = it (show jumps) $ do
      (val, rest) <-
          A.parseBreakPos (A.toParserK (jumpParser jumps))
              $ StreamK.fromList $ Prelude.map A.fromList chunkedTape
      lst <- Prelude.map A.toList <$> StreamK.toList rest
      (val, concat lst) `shouldBe` (expectedResult jumps tape)
  
  sanityParseBreakChunksGeneric :: [Move] -> H.SpecWith ()
  sanityParseBreakChunksGeneric jumps = it (show jumps) $ do
      (val, rest) <-
          AG.parseBreakPos (AG.toParserK (jumpParser jumps))
              $ StreamK.fromList $ Prelude.map AG.fromList chunkedTape
      lst <- Prelude.map AG.toList <$> StreamK.toList rest
      (val, concat lst) `shouldBe` (expectedResult jumps tape)
  
  -------------------------------------------------------------------------------
  -- Main
  -------------------------------------------------------------------------------
  
  moduleName :: String
  moduleName = "Data.ParserK"
  
  -- Many ParserK tests are tested in Test.Parser module
  main :: IO ()
  main =
    hspec $
    H.parallel $
    modifyMaxSuccess (const maxTestCount) $ do
    describe moduleName $ do
      parserSanityTests "StreamK.parseBreak" sanityParseBreak
      parserSanityTests "StreamK.parseBreakChunks" sanityParseBreakChunks
      parserSanityTests "StreamK.parseBreakChunksGeneric" sanityParseBreakChunksGeneric
      toParser
  