Search code examples
haskellghcquickcheck

How to tap into hpc information during execution


Consider the following use case: I have a QuickCheck test suite consisting of two test cases prop_testCase1 and prop_testCase2. Using hpc I can observe the code coverage of my test suite.

However, I'd like to get separate results for the coverage of prop_testCase1 and prop_testCase2 (to then further process the results). One way out could be to run the executable several times explicitly specifying the test case as a command line argument and to process the generated tix file after each run.

Yet, I would prefer to hide away this logic in a library. Also in reality I would like to run significantly more than just two test cases. Thus explicitly re-executing the binary for each test case seems rather inconvenient. At the same time I'd imagine that hpc keeps the coverage data in some kind of intermediate data structure during the program execution.

Question: Is there a way to recognize that the program has been compiled with hpc symbols and to somehow access the data hpc generates at runtime?


Solution

  • I think I found a way to achieve the desired effect. The required functions are provided by the Trace.Hpc.Reflect module. Unfortunately the documentation is somewhat lacking.

    Nevertheless, here is a minimal example that seems to work:

    import Trace.Hpc.Reflect
    
    main :: IO () 
    main = do 
      print (show $ f 5)
      tix <- examineTix 
      print (show tix)
      print (show $ f 6)
      print (show $ f 7)
      tix <- examineTix 
      print (show tix)
      return ()
    
    
    f x = x*2
    

    Compile and run this as follows:

    $ ghc -fhpc Main
    [1 of 1] Compiling Main             ( Main.hs, Main.o )
    Linking Main ...
    $ ./Main
    "10"
    "Tix [TixModule \"Main\" 3889152622 31 [1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1]]"
    "12"
    "14"
    "Tix [TixModule \"Main\" 3889152622 31 [3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, in1,1,1,1,0,0,0,0,0,1,1]]"
    

    So using this you can tap into the coverage data provided by hpc while your program is executing.

    If the executable is compiled without hpc support the program still works but the Tix object returned by examineTix contains the empty list.