{-# LANGUAGE ScopedTypeVariables #-} module Test.SmartCheck.Extrapolate ( extrapolate ) where import Test.SmartCheck.Args import Test.SmartCheck.Types import Test.SmartCheck.DataToTree import Test.SmartCheck.SmartGen import Test.SmartCheck.Render import qualified Test.QuickCheck as Q -------------------------------------------------------------------------------- -- | Test d with arbitrary values replacing its children. For anything we get -- 100% failure for, we claim we can generalize it---any term in that hole -- fails. -- -- We extrapolate if there exists at least one test that satisfies the -- precondition, and for all tests that satisfy the precondition, they fail. -- We extrapolate w.r.t. the original property since extrapolation throws away -- any values that fail the precondition of the property (i.e., before the -- Q.==>). extrapolate :: SubTypes a => ScArgs -- ^ Arguments -> a -- ^ Current failed value -> (a -> Q.Property) -- ^ Original property -> IO ([Idx]) extrapolate args d origProp = do putStrLn "" smartPrtLn "Extrapolating values ..." (_, idxs) <- iter' forest (Idx 0 0) [] return idxs where forest = mkSubstForest d True iter' = iter d test next origProp (scMaxDepth args) -- In this call to iterateArb, we want to claim we can extrapolate iff at -- least one test passes a precondition, and for every test in which the -- precondition is passed, it fails. We test values of all possible sizes, up -- to Q.maxSize. test _ idx = iterateArbIdx d (idx, scMaxDepth args) (scMaxForall args) (scMaxSize args) origProp -- Control-flow. -- None of the tries satisfy prop (but something passed the precondition). -- Prevent recurring down this tree, since we can generalize. next _ (i, FailedProp) forest' idx idxs | scMinForall args < i = nextIter (forestReplaceChildren forest' idx False) idx (idx : idxs) next _ _ forest' idx idxs = nextIter forest' idx idxs nextIter f idx = iter' f idx { column = column idx + 1 } --------------------------------------------------------------------------------