{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-type-defaults #-}

module Main where

import Control.Applicative
import Data.Monoid
import Text.Radexp.Simple

import Test.Framework
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2
import Test.HUnit
import Test.QuickCheck

newtype StringAbc = StringAbc String
    deriving ( Show )

instance Arbitrary StringAbc where
    arbitrary = StringAbc <$> listOf (elements "abc")

newtype StringRe = StringRe String
    deriving ( Show )

instance Arbitrary StringRe where
    arbitrary = StringRe <$> listOf (elements "abc*+?()|.")

main :: IO ()
main = defaultMainWithOpts
       [ testCase "simple" testSimple
       , testCase "dot" testDot
       , testCase "alternation" testAlternation
       , testCase "star" testStar
       , testProperty "matchSelf" propMatchSelf
       ] opts
  where
    opts = mempty {
             ropt_test_options =
                 Just (mempty
                       { topt_maximum_generated_tests            = Just 500
                       , topt_maximum_unsuitable_generated_tests = Just 5000
                       })}

--------------------------------
-- Unit tests
--------------------------------

testSimple :: Assertion
testSimple = do
    match "" "" @?= Just True
    match "ab" "ab" @?= Just True

testDot :: Assertion
testDot = do
    match "." "." @?= Just True
    match "." "a" @?= Just True
    match "a.b" "axb" @?= Just True
    match "a.." "abc" @?= Just True

testAlternation :: Assertion
testAlternation = do
    match "a|b" "a" @?= Just True
    match "a|b" "b" @?= Just True
    match "a|b" "c" @?= Just False
    match "ac|bd" "ac" @?= Just True
    match "ac|bd" "a" @?= Just False
    match "ac|bd" "bd" @?= Just True
    match "ac|bd" "b" @?= Just False

testStar :: Assertion
testStar = do
    match ".*" "abc" @?= Just True
    match ".*" "" @?= Just True

testAnchored :: Assertion
testAnchored = do
    match "a" "a" @?= Just True
    match "a" "ab" @?= Just False
    match "a" "ba" @?= Just False

--------------------------------
-- QuickCheck properties
--------------------------------

propMatchSelf :: StringAbc -> Bool
propMatchSelf (StringAbc text) =
    match text text == Just True
