Is there an assertException in any of the Haskell test frameworks? - testing

I'm writing some tests using HUnit and I would like to assert that a particular function throws an exception given a certain input. I can't find an assert function which provides the required functionality. Anyone know of a test framework that does?

Although HUnit doesn't come with any exception assertions, it's easy to write your own:
import Control.Exception
import Control.Monad
import Test.HUnit
assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ show ex
where isWanted = guard . (== ex)
testPasses = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 0)
testFails = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 1)
main = runTestTT $ TestList [ testPasses, testFails ]
You can do something more fancy like using a predicate instead of explicit comparison if you like.
$ ./testex
### Failure in: 1
Expected exception: divide by zero
Cases: 2 Tried: 2 Errors: 0 Failures: 1
Note that evaluate here might get optimized away (see GHC ticket #5129), but for testing code in the IO monad this should work fine.

You can use assertRaises from testpack.

hspec (or more precisely hspec-expectations) has shouldThrow.

Related

Last element of a block thrown in sink context

This program
my #bitfields;
for ^3 -> $i {
#bitfields[$i] = Bool.pick xx 3;
}
my #total = 0 xx 3;
for #bitfields -> #row {
#total Z+= #row;
}
say #total;
says [0 0 0]. If we add something to the loop, whatever:
my #bitfields;
for ^3 -> $i {
#bitfields[$i] = Bool.pick xx 3;
}
my #total = 0 xx 3;
for #bitfields -> #row {
#total Z+= #row;
say "foo";
}
say #total;
It will work correctly. Apparently, the last element of the block is thrown into sink context which in this case means it's simply ignored; this trap is related to that. However, that code above looks perfectly fine; and this
{#total Z+= #^þ} for #bitfields;
apparently works, although I don't see the real difference. Any other idea?
It looks like a bug to me.
This looks very closely related to Which context confuses this Perl 6 zip operator? which became a Rakudo repo issue Failure to sink for when Z+= used as last statement which was closed with roast tests Test sunk for sinks last statement sub calls .
The mystery is why there's a new bug. My suspicion is that someone needs to clean the kitchen sink, i.e. pick up where Zoffix left off with his Flaws in implied sinkage / &unwanted helper issue.
Here's my best golf shot so far for narrowing down the new problem or regression:
my $foo = 'a';
ok: for 1 { $foo X= 'b' }
notok: for 1 -> $_ { $foo X= 'c' }
say $foo; # b
halfok: 'd' ~ do for 1 -> $_ { $foo X= 'e' } # Useless use of "~"
say $foo; # e
The ok: line works because it omits the -> argument.
The notok: line is my golf of your problem.
The error message for the halfok: line is because the result of it is thrown away. But the do has forced the compiler to evaluate the $foo X= 'e' expression in the block, as it should, and as it had failed to in the notok: line.
{#total Z+= #^þ} for #bitfields;
Perhaps that's because that's the non-modifier version. And/or because it doesn't use the -> syntax (which is part of the regression or new bug per my golf above).
Or perhaps just luck. I think most of the sink handling code in Rakudo is Larry's work from long ago when he was trying to get things mostly working right.

How to combine WebDriver and Scotty monads

I am beginner, so please bear with me.
I have a following code:
{-# LANGUAGE OverloadedStrings #-}
module Lib where
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Data.Monoid ((<>))
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Test.WebDriver
--import Web.Scotty
import Web.Scotty.Trans
firefoxConfig :: WDConfig
firefoxConfig = defaultConfig
startMyBrowser :: WD a -> IO a
startMyBrowser = runSession firefoxConfig
stopMyBrowser = closeSession
someFunc :: WD String
someFunc = do
openPage "http://maslo.cz"
captionElem <- findElem (ByCSS "h2")
text <- getText captionElem
return $ T.unpack text
helloAction :: ActionT TL.Text WD ()
helloAction = do
a <- lift someFunc
text $ "got this for you: " <> TL.pack a
routes :: ScottyT TL.Text WD ()
routes = get "/hello" helloAction
startServer = startMyBrowser $ do
lift $ scottyT 3000 _ routes
stopMyBrowser
I am not sure if even those filled parts are right - it is supposed to start a Selenium session (startMyBrowser), spin up a web server (the scottyT part) and after web server stops it should end the Selenium session (stopMyBrowser).
After fiddling with types I got to that code above and it seems that I only miss one piece - the hole.
Please, if you make it working, try to explain your solution and/or add some links to more materials. I would love to understand those damned transformers.
Edit 1:
Here are the errors:
• Couldn't match type ‘t0 m0’ with ‘WD’
Expected type: WD ()
Actual type: t0 m0 ()
• In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
In the second argument of ‘($)’, namely
‘do { lift $ scottyT 3000 _ routes;
stopMyBrowser }’
In the expression:
startMyBrowser
$ do { lift $ scottyT 3000 _ routes;
stopMyBrowser }
• Found hole:
_ :: WD wai-3.2.1.1:Network.Wai.Internal.Response
-> IO wai-3.2.1.1:Network.Wai.Internal.Response
• In the second argument of ‘scottyT’, namely ‘_’
In the second argument of ‘($)’, namely ‘scottyT 3000 _ routes’
In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
• Relevant bindings include
startServer :: IO () (bound at src/Lib.hs:37:1)
Kind guy ForTheFunctionGod on reddit answered it, here it is:
There's your problem:
lift $ scottyT 3000 _ routes
Since the return type of scottyT is
MonadIO n => n
You don't need to lift it - it can fit into any monad that can perform IO actions. WD is such a monad - note its MonadIO instance. You'd only need to lift scottyT if its return type would be a simple IO.
Type classes like MonadIO, MonadState, etc. mostly obviate the need to manually lift computations. Whereas you'd need to lift a function to type IO Int if you wanted to embed it into StateT s IO Int, you wouldn't need to lift a function of type MonadIO m => m a, because StateT s IO already is an instance of MonadIO, so m can be instantiated to it.
As for the hole: it has to be of type
WD Response -> IO Response
The only way to make this work is to use runSession or one of its friends. I don't know Selenium that well, but, presumably, you can re-use your already opened session's id:
runWD :: WDSession -> WD a -> IO a
startServer = startMyBrowser $ do
sessionID <- getSession
scottyT 3000 (runWD sessionID) routes
stopMyBrowser
I haven't tried this out, but the types should check out. I hope it helps!
It definitely did :).

How can I call a subprocess in Idris?

Is there some module in the Idris standard library (or a third party library) that allows one to shell out to another program? I'm thinking of modules like Python's subprocess and Haskell's System.Process.
Ideally, I'd like to interact programmatically with the process (writing to its stdin, reading from its stdout, etc.).
There is the system : String -> IO Int function which takes a shell command, runs it, and returns its exit code. You'll need to import System to use it:
import System
main : IO ()
main = do
exitCode <- system "echo HelloWorld!"
putStrLn $ "Exit code: " ++ show exitCode
exitCode <- system "echo HelloWorld!; false"
putStrLn $ "Exit code: " ++ show exitCode
On my system the above code results in the following output:
HelloWorld!
Exit code: 0
HelloWorld!
Exit code: 256
I'd expect it to return 1 instead of 256 in the second case. At least it's what echo $? shows.
Another version can be made basing on the Effects library, which is described in this tutorial:
import Effects
import Effect.System
import Effect.StdIO
execAndPrint : (cmd : String) -> Eff () [STDIO, SYSTEM]
execAndPrint cmd = do
exitCode <- system cmd
putStrLn $ "Exit code: " ++ show exitCode
script : Eff () [STDIO, SYSTEM]
script = do
execAndPrint "echo HelloWorld!"
execAndPrint "sh -c \"echo HelloWorld!; exit 1\""
main : IO ()
main = run script
Here we need to explain to Idris that it needs the Effects package:
idris -p effects <filename.idr>
I'm not aware of any Idris library that lets you easily work with stdin/stdout of a subprocess. As a workaround we can use the pipes facilities of C, utilizing its popen / pclose functions, which aready have bindings in the Idris standard library.
Let me show how we could, for example, read from stdout of a subprocess (please bear in mind that it's a simple snippet with rudimentary error processing):
import System
-- read the contents of a file
readFileH : (fileHandle : File) -> IO String
readFileH h = loop ""
where
loop acc = do
if !(fEOF h) then pure acc
else do
Right l <- fGetLine h | Left err => pure acc
loop (acc ++ l)
execAndReadOutput : (cmd : String) -> IO String
execAndReadOutput cmd = do
Right fh <- popen cmd Read | Left err => pure ""
contents <- readFileH fh
pclose fh
pure contents
main : IO ()
main = do
out <- (execAndReadOutput "echo \"Captured output\"")
putStrLn "Here is what we got:"
putStr out
When you run the program, you should see
Here is what we got:
Captured output

How does the Yosys ConstEval API work?

I'm trying to write a plugin that requires evaluating combinatorial circuits. From what I can gather ConstEval is the tool which does this. However, the API is not so clear to me. Is there somewhere a rundown of the members of ConstEval and what they do?
(Asked by jeremysalwen on github).
Using the ConstEval class is actually quite easy. You create a ConstEval object for a given module and set the known values using the void ConstEval::set(SigSpec, Const) method. After all the known signals have been set, the bool ConstEval::eval(SigSpec&, SigSpec&) method can be used to evaluate nets. The eval() method returns true when the evaluation was successful and replaces the net(s) in the first argument with the constant values the net evaluates to. Otherwise it returns false and sets the 2nd argument to the list of nets that need to be set in order to continue evaluation.
The methods push() and pop() can be used for creating local contexts for set(). The method stop() can be used to declare signals at which the evaluation should stop, even when there are combinatoric cells driving the net.
The following simple Yosys plugin demonstrates how to use the ConstEval API (evaldemo.cc):
#include "kernel/yosys.h"
#include "kernel/consteval.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct EvalDemoPass : public Pass
{
EvalDemoPass() : Pass("evaldemo") { }
virtual void execute(vector<string>, Design *design)
{
Module *module = design->top_module();
if (module == nullptr)
log_error("No top module found!\n");
Wire *wire_a = module->wire("\\A");
Wire *wire_y = module->wire("\\Y");
if (wire_a == nullptr)
log_error("No wire A found!\n");
if (wire_y == nullptr)
log_error("No wire Y found!\n");
ConstEval ce(module);
for (int v = 0; v < 4; v++) {
ce.push();
ce.set(wire_a, Const(v, GetSize(wire_a)));
SigSpec sig_y = wire_y, sig_undef;
if (ce.eval(sig_y, sig_undef))
log("Eval results for A=%d: Y=%s\n", v, log_signal(sig_y));
else
log("Eval failed for A=%d: Missing value for %s\n", v, log_signal(sig_undef));
ce.pop();
}
}
} EvalDemoPass;
PRIVATE_NAMESPACE_END
Example usage:
$ cat > evaldemo.v <<EOT
module main(input [1:0] A, input [7:0] B, C, D, output [7:0] Y);
assign Y = A == 0 ? B : A == 1 ? C : A == 2 ? D : 42;
endmodule
EOT
$ yosys-config --build evaldemo.so evaldemo.cc
$ yosys -m evaldemo.so -p evaldemo evaldemo.v
...
-- Running command `evaldemo' --
Eval failed for A=0: Missing value for \B
Eval failed for A=1: Missing value for \C
Eval failed for A=2: Missing value for \D
Eval results for A=3: Y=8'00101010

Dynamic Compilation in Haskell GHC API Error

I have been trying to get some basic dynamic code compilation working using the GHC API by following a tutorial found here.
This code:
import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce
main :: IO ()
main =
defaultErrorHandler defaultDynFlags $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "Test.hs" Nothing
addTarget target
r <- load LoadAllTargets
case r of
Failed -> error "Compilation failed"
Succeeded -> do
m <- findModule (mkModuleName "Test") Nothing
setContext [] [m]
value <- compileExpr ("Test.print")
do let value' = (unsafeCoerce value) :: String -> IO ()
return value'
func "Hello"
return ()
Should get the print function from another file called Test.hs, load it and run its print function.
I compile the code with ghc version 7.4.1 using the command:
ghc -package ghc --make Api.hs
But receive the following error:
Api.hs:8:25:
Couldn't match expected type `Severity' with actual type `Settings'
Expected type: LogAction
Actual type: Settings -> DynFlags
In the first argument of `defaultErrorHandler', namely
`defaultDynFlags'
In the expression: defaultErrorHandler defaultDynFlags
What am I doing wrong? I have checked the GHC API docs but am not well versed enough in this kind of thing to understand most of it.
The tutorial is out of date. In ghc-7.0.* and previous, the type of defaultErorHandler was
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => DynFlags -> m a -> m a
and defaultDynFlags was just a value.
As of ghc-7.2.*, the type of defaultErrorHandler is
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => LogAction -> m a -> m a
defaultDynFlags is a function
defaultDynFlags :: Settings -> DynFlags
and LogAction is a synonym
type LogAction = Severity -> SrcSpan -> PprStyle -> Message -> IO ()
In 7.6, it has changed again, we now have
defaultErrorHandler :: (ExceptionMonad m, MonadIO m) => FatalMessager -> FlushOut -> m a -> m a
with
type FatalMessager = String -> IO ()
and FlushOut being a newtype wrapper around IO ().
I'm not very familiar with the GHC Api (a too fast-moving target for me), so I'm not sure how the working code should look like, but for the 7.2 and 7.4 series, the first argument to defaultErrorHandler should probably be defaultLogAction.
Also the type of setContext has changed, I don't know if what I have does what you want, but it compiles (with 7.4.2; but you also need the ghc-paths package in addition to ghc for the GHC.Paths module) - I haven't tried to run it, though.
import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce
main :: IO ()
main =
defaultErrorHandler defaultLogAction $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "Test.hs" Nothing
addTarget target
r <- load LoadAllTargets
case r of
Failed -> error "Compilation failed"
Succeeded -> do
m <- findModule (mkModuleName "Test") Nothing
setContext [IIModule m]
value <- compileExpr ("Test.print")
do let value' = (unsafeCoerce value) :: String -> IO ()
return value'
func "Hello"
return ()
Here is a complete example for dynamic loading, also hosted here:
DynLoad.hs
-----------------------------------------------------------------------------
-- | Example for loading Haskell source code dynamically using the GHC api
-- Useful links:
-- GHC api:
-- http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html
-- Wiki:
-- http://www.haskell.org/haskellwiki/GHC/As_a_library
-----------------------------------------------------------------------------
module DynLoad where
import GHC
import GhcMonad (liftIO)
import GHC.Paths (libdir)
import Name (getOccString)
import Data.Dynamic (fromDyn)
-- | List all exports of this module
-- and evaluate a symbol from a module DynTest
main =
runGhc (Just libdir) $ do
putString ":::Display exports of modules:::"
modSums <- initSession ["DynLoad","DynTest"]
let thisModSum = head modSums
exports <- listExports thisModSum
mapM_ putString exports
putString ":::Evaluate a name from module DynTest:::"
importDecl_RdrName <- parseImportDecl "import DynTest as D"
setContext [IIDecl importDecl_RdrName]
dynVal <- dynCompileExpr "D.aString"
liftIO $ print $ (fromDyn dynVal "nope-nothing")
-- | Init interactive session and load modules
initSession modStrNames = do
dflags <- getSessionDynFlags
setSessionDynFlags $ dflags {
hscTarget = HscInterpreted
, ghcLink = LinkInMemory
}
targets <- mapM
(\modStrName -> do
putString modStrName
target <- guessTarget ("*"++modStrName++".hs") Nothing
return target
) modStrNames
setTargets targets
load LoadAllTargets
modSums <- mapM
(\modStrName -> do
putString modStrName
modSum <- getModSummary $ mkModuleName modStrName
return $ ms_mod modSum
) modStrNames
return modSums
-- | List exported names of this or a sibling module
listExports mod = do
maybeModInfo <- getModuleInfo mod
case maybeModInfo of
(Just modInfo) -> do
let expNames = modInfoExports modInfo
expStrNames = map getOccString expNames
return expStrNames
_ -> return []
-- | Util for printing
putString = liftIO . putStrLn
And here is an example file to load:
DynTest.hs
module DynTest where
aString = "Hello"