module Test.Data.List.NonEmpty where

import Prelude hiding (reverse)
import Data.List.NonEmpty
import Data.Foldable
import Data.Semigroup
import Test.QuickCheck hiding (NonEmpty)
import Test.Framework
import Test.Framework.Providers.QuickCheck2 (testProperty)

main :: IO ()
main = defaultMain tests

tests :: [Test]
tests =
  [
    testGroup "NonEmpty"
      [
        testProperty "neHead" prop_neHead,
        testProperty "neTail" prop_neTail,
        testProperty "nonEmpty" prop_nonEmpty,
        testProperty "nonEmptyAlias" prop_nonEmptyAlias,
        testProperty "toNonEmpty" prop_toNonEmpty,
        testProperty "unsafeNonEmpty" prop_unsafeNonEmpty,
        testProperty "cons" prop_cons,
        testProperty "append" prop_append,
        testProperty "reverse" prop_reverse
      ]
  ]

prop_neHead :: String
               -> [String]
               -> Bool
prop_neHead h t = neHead (nonEmpty h t) == h

prop_neTail :: String
               -> [String]
               -> Bool
prop_neTail h t = neTail (nonEmpty h t) == t

prop_nonEmpty :: String
                 -> [String]
                 -> Bool
prop_nonEmpty h t = toList (nonEmpty h t) == h:t

prop_nonEmptyAlias :: String
                      -> [String]
                      -> Bool
prop_nonEmptyAlias h t = nonEmpty h t == h |: t

prop_toNonEmpty :: [String]
                  -> Bool
prop_toNonEmpty x = toNonEmpty x == case x of [] -> Nothing
                                              (h:t) -> Just (nonEmpty h t)

prop_unsafeNonEmpty :: [String]
                       -> Property
prop_unsafeNonEmpty x = not (null x) ==> prop_toNonEmpty x

prop_cons :: String
             -> NonEmpty String
             -> Bool
prop_cons a as = toList (a .: as) == a : toList as

prop_append :: NonEmpty String
               -> NonEmpty String
               -> Bool
prop_append a b = toList (a .++. b) == neHead a : neTail a ++ neHead b : neTail b

prop_reverse :: NonEmpty String
                -> Bool
prop_reverse x = (reverse . reverse) x == x