regexchar-0.9.0.10: src/Grecce/Test/QC/RepeatableMetaChar.hs
{-# LANGUAGE CPP #-}
{-
Copyright (C) 2010 Dr. Alistair Ward
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' & defines tests based on it.
-}
module Grecce.Test.QC.RepeatableMetaChar(
-- * Types
-- ** Data-types
-- RepeatableMetaChar,
-- ** Type-synonyms
-- Testable,
-- * Functions
-- deconstruct,
quickChecks
) where
import qualified Data.Maybe
import Control.Applicative((<$>))
import Grecce.Test.QC.MetaChar()
import qualified RegExChar.MetaChar as MetaChar
import qualified RegExDot.Consumer
import qualified RegExDot.ConsumptionBounds
import qualified RegExDot.ConsumptionProfile
import qualified RegExDot.Repeatable
import qualified Test.QuickCheck
import qualified ToolShed.SelfValidate
import qualified ToolShed.Test.ReversibleIO
-- | A specialised instance, required to instantiate 'Test.QuickCheck.Arbitrary'.
newtype RepeatableMetaChar = MkRepeatableMetaChar (RegExDot.Repeatable.Repeatable MetaChar.MetaChar) deriving (Eq, Read, Show)
-- | Accessor.
deconstruct :: RepeatableMetaChar -> RegExDot.Repeatable.Repeatable MetaChar.MetaChar
deconstruct (MkRepeatableMetaChar repeatableMetaChar) = repeatableMetaChar
instance ToolShed.SelfValidate.SelfValidator RepeatableMetaChar where
getErrors = ToolShed.SelfValidate.getErrors . deconstruct
instance RegExDot.Consumer.Consumer RepeatableMetaChar where
consumptionProfile = RegExDot.Consumer.consumptionProfile . deconstruct
starHeight = RegExDot.Consumer.starHeight . deconstruct
instance Test.QuickCheck.Arbitrary RepeatableMetaChar where
arbitrary = do
metaChar <- Test.QuickCheck.arbitrary
fewest <- Test.QuickCheck.elements [0 .. 9] --Could be more, but this is an adequate test.
most <- Test.QuickCheck.oneof [return Nothing, Just <$> Test.QuickCheck.elements [max fewest 1 .. 9]]
isGreedy <- Test.QuickCheck.arbitrary
let
repetitionBounds :: RegExDot.Repeatable.RepetitionBounds
repetitionBounds = (fewest, most)
return {-to Gen-monad-} . MkRepeatableMetaChar $ RegExDot.Repeatable.MkRepeatable {
RegExDot.Repeatable.base = metaChar,
RegExDot.Repeatable.repetitionBounds = repetitionBounds,
RegExDot.Repeatable.isGreedy = RegExDot.Repeatable.hasPreciseBounds repetitionBounds || isGreedy --Only specify 'non-greedy' where space exists.
}
#if !(MIN_VERSION_QuickCheck(2,1,0))
coarbitrary = undefined --CAVEAT: stops warnings from ghc.
#endif
type Testable = RepeatableMetaChar -> Test.QuickCheck.Property
-- | Defines invariant properties, which must hold for any 'RepeatableMetaChar'.
quickChecks :: (Testable -> IO ()) -> IO ()
quickChecks checker = checker `mapM_` [prop_consumptionProfile, prop_io, prop_isValid, prop_starHeight] where
prop_consumptionProfile, prop_io, prop_isValid, prop_starHeight :: Testable
prop_consumptionProfile r = Test.QuickCheck.label "prop_consumptionProfile" $ Data.Maybe.maybe True (>= minData) maybeMaxData && b == RegExDot.Consumer.getHasSpecificRequirement (RegExDot.Repeatable.base $ deconstruct r) where RegExDot.ConsumptionProfile.MkConsumptionProfile {
RegExDot.ConsumptionProfile.consumptionBounds = (minData, maybeMaxData),
RegExDot.ConsumptionProfile.hasSpecificRequirement = b
} = RegExDot.Consumer.consumptionProfile r
prop_io (MkRepeatableMetaChar r) = Test.QuickCheck.label "prop_io" $ ToolShed.Test.ReversibleIO.isReversible r
prop_isValid r = Test.QuickCheck.label "prop_isValid" $ ToolShed.SelfValidate.isValid r
prop_starHeight (MkRepeatableMetaChar r) = Test.QuickCheck.label "prop_starHeight" $ RegExDot.Consumer.starHeight r == if RegExDot.ConsumptionBounds.isPrecise (RegExDot.Consumer.getConsumptionBounds r) then 0 else 1