mirror of
https://github.com/dnlkrgr/hsreduce.git
synced 2024-11-22 06:32:58 +03:00
expanded readme
This commit is contained in:
parent
da985e084c
commit
35de32463a
79
README.md
79
README.md
@ -1,4 +1,77 @@
|
||||
|
||||
|
||||
# hsreduce
|
||||
Reducing Haskell programs for easier debugging of GHC bugs
|
||||
|
||||
Reducing Haskell programs for easier debugging of GHC crashes or performance regressions.
|
||||
|
||||
## Build Status
|
||||
|
||||
[![GHC 8.10.1](https://github.com/dnlkrgr/hsreduce/actions/workflows/haskell.yml/badge.svg)](https://github.com/dnlkrgr/hsreduce/actions/workflows/haskell.yml)
|
||||
|
||||
## Installing
|
||||
|
||||
1. Clone the repo
|
||||
1. (Optional) Run `nix-shell`
|
||||
1. Run `cabal install` or `stack install`
|
||||
|
||||
## Usage
|
||||
|
||||
### Reducing
|
||||
|
||||
The main use case of hsreduce is in reducing Haskell programs.
|
||||
hsreduce expects as inputs a single Haskell file and a shell script which outputs whether the file is interesting.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
hsreduce reduce --shellScript interesting.sh --testCase Bug.hs --numberOfThreads 4 --timeOut 30
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
|Parameter |Explanation |
|
||||
|-----------------|-------------------------------------------------|
|
||||
|--shellScript |path to the interestingness test |
|
||||
|--testCase |path to the Haskell program you want to reduce |
|
||||
|--numberOfThreads|self-explanatory |
|
||||
|--timeout |after how many seconds should tests be terminated|
|
||||
|
||||
### How do I write interestingness tests?
|
||||
|
||||
Example: Let's say you have a large Haskell file that prints "hello world" when you run it, but you're only interested in which part of the program makes it do that.
|
||||
I think a good interestingness test would look like this:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
ghc Bug.s && ./Bug |& grep 'hello world'
|
||||
```
|
||||
|
||||
### Merging
|
||||
|
||||
Another use case is merging cabal projects into single Haskell files, which can then be reduced.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
hsreduce merge --projectType Executable --targetName containers
|
||||
```
|
||||
|
||||
|Parameter |Explanation |
|
||||
|-----------------|------------------------------------------|
|
||||
|--projectType |enter either *Executable* or *Library* |
|
||||
|--targetName |name of the cabal target you want to merge|
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: I find this to be strange behaviour: "a shell script that returns exit code 0 if the file contains interesting behavior (reproduces a bug) and returns 1 otherwise ". Surely it makes more sense that something that checks for buggy behaviour returns a non-zero exitcode if it finds a bug?**
|
||||
|
||||
A: You're correct.
|
||||
But here reproducing the bug is the "normal behavior" that we seek and anything else not.
|
||||
If a reduction is done that leads to a test case that crashes for another reason or leads to a timeout, then it's not "normal behavior".
|
||||
|
||||
**Q: what do you mean by reduction?**
|
||||
|
||||
A: By reduction I mean "making the Haskell file smaller to make it more easily readable by humans".
|
||||
This is done by trying to delete various elements from the Haskell program or by simplifying elements.
|
||||
|
||||
## Other Questions
|
||||
|
||||
Don't hesitate to message me on twitter.com/dnlkrgr
|
||||
|
@ -5,7 +5,7 @@ let
|
||||
name = "nixos-unstable-2020-12-25";
|
||||
url = "https://github.com/nixos/nixpkgs";
|
||||
ref = "refs/heads/nixos-unstable";
|
||||
rev = "257cbbcd3ab7bd96f5d24d50adc807de7c82e06d";
|
||||
rev = "102eb68ceecbbd32ab1906a53ef5a7269dc9794a";
|
||||
}) {};
|
||||
|
||||
in
|
||||
|
@ -36,12 +36,12 @@ import Util.Util
|
||||
|
||||
|
||||
hsmerge :: ProjectType -> T.Text -> IO ()
|
||||
hsmerge isExecutable targetName = do
|
||||
hsmerge projectType targetName = do
|
||||
let
|
||||
filePath = "hie.yaml"
|
||||
targetTypeS = case isExecutable of
|
||||
Executable -> "exe"
|
||||
Library -> "lib"
|
||||
targetTypeS = case projectType of
|
||||
Executable -> "exe"
|
||||
Library -> "lib"
|
||||
fileContent = "cradle: {cabal: {component: \"" <> targetTypeS <> ":" <> targetName <> "\" }}"
|
||||
|
||||
TIO.writeFile filePath fileContent
|
||||
|
@ -127,7 +127,8 @@ hsreduce' allActions (fromIntegral -> numberOfThreads) testAbs filePathAbs fileC
|
||||
|
||||
when recordStatistics $ do
|
||||
|
||||
perfStats <- mkPerformance (fromIntegral oldSize) (fromIntegral newSize) t1 t2 (fromIntegral numberOfThreads) successfulInvocations totalInvocations (getTokenDiff newState beginState) (getNameDiff newState beginState)
|
||||
perfStats <-
|
||||
mkPerformance (fromIntegral oldSize) (fromIntegral newSize) t1 t2 (fromIntegral numberOfThreads) successfulInvocations totalInvocations (getTokenDiff newState beginState) (getNameDiff newState beginState)
|
||||
liftIO $ appendFile "hsreduce_performance.csv" $ show perfStats
|
||||
|
||||
liftIO
|
||||
@ -175,6 +176,8 @@ deleteTempDirs numberOfThreads tChan = do
|
||||
t <- atomically $ readTChan tChan
|
||||
removeDirRecur t
|
||||
|
||||
arst
|
||||
|
||||
|
||||
-- 1. check if the test-case is still interesting (it should be at the start of the loop!)
|
||||
-- 2. set alive variable to false
|
||||
|
Loading…
Reference in New Issue
Block a user