{-# LANGUAGE TupleSections #-} -- | -- Module : $Header$ -- Copyright : (c) 2013-2015 Galois, Inc. -- License : BSD3 -- Maintainer : cryptol@galois.com -- Stability : provisional -- Portability : portable -- -- Evaluate test cases and handle exceptions appropriately module Cryptol.Testing.Eval where import Cryptol.Eval.Error import Cryptol.Eval.Value import Cryptol.Utils.Panic (panic) import qualified Control.Exception as X -- | A test result is either a pass, a failure due to evaluating to -- @False@, or a failure due to an exception raised during evaluation data TestResult = Pass | FailFalse [Value] | FailError EvalError [Value] -- | Apply a testable value to some arguments. -- Note that this function assumes that the values come from a call to -- `testableType` (i.e., things are type-correct). We run in the IO -- monad in order to catch any @EvalError@s. runOneTest :: Value -> [Value] -> IO TestResult runOneTest v0 vs0 = run `X.catch` handle where run = do result <- X.evaluate (go v0 vs0) if result then return Pass else return (FailFalse vs0) handle e = return (FailError e vs0) go :: Value -> [Value] -> Bool go (VFun f) (v : vs) = go (f v) vs go (VFun _) [] = panic "Not enough arguments while applying function" [] go (VBit b) [] = b go v vs = panic "Type error while running test" $ [ "Function:" , show $ ppValue defaultPPOpts v , "Arguments:" ] ++ map (show . ppValue defaultPPOpts) vs