sbv-14.4: SBVTestSuite/TestSuite/Basics/SmtFunctionUnique.hs
-----------------------------------------------------------------------------
-- |
-- Module : TestSuite.Basics.SmtFunctionUnique
-- Copyright : (c) Levent Erkok
-- License : BSD3
-- Maintainer: erkokl@gmail.com
-- Stability : experimental
--
-- Tests for smtFunction name uniqueness enforcement.
-----------------------------------------------------------------------------
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module TestSuite.Basics.SmtFunctionUnique(tests) where
import Utils.SBVTestFramework
import qualified Control.Exception as C
-- Test suite
tests :: TestTree
tests = testGroup "Basics.SmtFunctionUnique"
[
-- Same name, same body: should succeed (idempotent re-registration).
goldenCapturedIO "smtFuncUniq_sameOk" $ \rf -> do
let f :: SInteger -> SInteger
f = smtFunction "f" $ \x -> x + 1
m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> f x + f x .== 4
appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
-- Same name, different body: should error.
, goldenCapturedIO "smtFuncUniq_conflict" $ \rf -> do
let f :: SInteger -> SInteger
f = smtFunction "f" $ \x -> x + 1
g :: SInteger -> SInteger
g = smtFunction "f" $ \x -> x + 2
r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> f x + g x .== 5
case r of
Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
Right m -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
-- Same name, same recursive body: should succeed.
, goldenCapturedIO "smtFuncUniq_recursiveOk" $ \rf -> do
let f :: SInteger -> SInteger
f = smtFunction "f" $ \x -> ite (x .<= 0) 0 (x + f (x - 1))
m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> x .>= 0 .&& x .<= 3 .&& f x .== 6
appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
-- Same name, different recursive body: should error.
, goldenCapturedIO "smtFuncUniq_recursiveConflict" $ \rf -> do
let f :: SInteger -> SInteger
f = smtFunction "f" $ \x -> ite (x .<= 0) 0 (x + f (x - 1))
g :: SInteger -> SInteger
g = smtFunction "f" $ \x -> ite (x .<= 0) 1 (x * g (x - 1))
r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> f x + g x .== 10
case r of
Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
Right m -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
-- Same name via parameter capture: bar 2 and bar 3 create different closures
-- for "bar", which should be detected as a conflict.
, goldenCapturedIO "smtFuncUniq_captureConflict" $ \rf -> do
let bar :: SInteger -> SInteger -> SInteger
bar k = smtFunction "bar" (+ k)
r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> bar 2 x + bar 3 x .== 10
case r of
Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
Right m -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
-- Fix for the above: use a tag to give each instantiation a unique name.
, goldenCapturedIO "smtFuncUniq_captureTagged" $ \rf -> do
let bar :: String -> SInteger -> SInteger -> SInteger
bar tag k = smtFunction ("bar_" ++ tag) (+ k)
m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
\x -> bar "two" 2 x + bar "three" 3 x .== 10
appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
]