guard-haskell 1.6.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +12 -0
- data/README.md +51 -33
- data/{spec/run-files/hspec-exception.error → asset/failed/exception.err} +0 -0
- data/{spec/run-files/missing-preprocessor.error → asset/failed/invalid-preprocessor.err} +0 -0
- data/{spec/run-files/cpp-exception.error → asset/failed/phase-c-pre-processor-failed.err} +0 -0
- data/{spec/run-files/preprocessor-phase-failed.error → asset/failed/phase-haskell-pre-processor-failed.err} +0 -0
- data/asset/failed/phase-linker-failed.err +4 -0
- data/{spec/run-files/runtime-linker-cannot-find-object-file.error → asset/failed/runtime-linker-cannot-find-object-file.err} +0 -0
- data/{spec/run-files/runtime-linker-couldn't-find-symbol.error → asset/failed/runtime-linker-couldn't-find-symbol.err} +0 -0
- data/{spec/run-files/runtime-linker-duplicate-definition-for-symbol.error → asset/failed/runtime-linker-duplicate-definition-for-symbol.err} +0 -0
- data/{spec/run-files/spec-failure.error → asset/failed/spec-failure.err} +0 -0
- data/{spec/run-files/spec-pass.success → asset/passed/spec-pass.ok} +0 -0
- data/lib/guard/haskell.rb +17 -27
- data/lib/guard/haskell/repl.rb +35 -59
- data/lib/guard/haskell/templates/Guardfile +3 -3
- data/lib/guard/haskell/version.rb +1 -1
- data/spec/guard/haskell/repl_spec.rb +55 -131
- data/spec/guard/haskell_spec.rb +68 -57
- metadata +12 -20
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Y2MzNjQ5MjQ2NjNmMzU0ODQxZWIwMDU4MTZhZTA3OTE4NmFkNDc2NA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YWRkOThmYzYxOWE1ZmQ3ZmQ4YmFhNGVkN2JiNTJmNTM2NTE1YWZmZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZjYyNTMxYzVkNjM1YjljMDZkNTg5Mzc1ZjFhZWMwNTQ1OTUwNjI0MTc5OTk2
|
10
|
+
ZjY5OGQ1YjY3NjVmNTQzOTMzMDE5MzNlYjNjNjJkNDNkOTE5MDIyYzkyMTlh
|
11
|
+
ZmVmY2ZmNWFhMTI0NzA0NGRiMzk0ZWIxYjUwY2I2YzQzMWVhNTI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjgyMGZlYTcwMjMxMTU5ZDc0MDM3N2Q2ZTQ1NGNjMDM1MGQ4NTZkNWRkNDli
|
14
|
+
MWVlOWM5ZTc2NjEzMmM3NjI2ZGIyMzk3OGZhYmJjYWUzNWEyNWZlZmU3ZDAw
|
15
|
+
MmFkNjA0ZGNiOGIwYThiYmIxYmFkY2FkZDIxNjNkYmZkOWRkZDY=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
2.0.0
|
2
|
+
=====
|
3
|
+
|
4
|
+
* Switch to `cabal repl` as an inferior shell
|
5
|
+
|
6
|
+
* Fix the bug where the cursor does not reappear on guard shutdown
|
7
|
+
|
1
8
|
1.6.0
|
2
9
|
=====
|
3
10
|
|
@@ -11,6 +18,7 @@
|
|
11
18
|
=====
|
12
19
|
|
13
20
|
* Add `sandbox_glob` option
|
21
|
+
|
14
22
|
* Separate stages for [re]loading and rerunning specs
|
15
23
|
|
16
24
|
1.4.0
|
@@ -22,14 +30,18 @@
|
|
22
30
|
=====
|
23
31
|
|
24
32
|
* Ignore user cabal package database if sandbox is found
|
33
|
+
|
25
34
|
* Catch CPP failures (previously didn't work because of the typo)
|
35
|
+
|
26
36
|
* Add `focus_on_fail` option
|
27
37
|
|
28
38
|
1.2.0
|
29
39
|
=====
|
30
40
|
|
31
41
|
* Catch GHCI runtime linker failures
|
42
|
+
|
32
43
|
* Separate runtime and compile time failures for `--rerun` to work better
|
44
|
+
|
33
45
|
* Fix ignored spec results if spec was run directly from guard repl
|
34
46
|
|
35
47
|
1.1.0
|
data/README.md
CHANGED
@@ -7,43 +7,40 @@ guard-haskell
|
|
7
7
|
|
8
8
|
`Guard::Haskell` automatically runs your specs
|
9
9
|
|
10
|
-
|
10
|
+
Install
|
11
|
+
-------
|
11
12
|
|
12
13
|
```shell
|
13
14
|
% cabal install hspec
|
14
15
|
% gem install guard-haskell
|
15
16
|
```
|
16
17
|
|
17
|
-
|
18
|
+
Usage
|
19
|
+
-----
|
18
20
|
|
19
|
-
|
21
|
+
### How does it work?
|
20
22
|
|
21
23
|
For explanation what `guard` is and how to use it, please refer to the [`guard manual`][0]
|
22
24
|
|
23
|
-
`guard-haskell` uses [`hspec`][1] to run specs and check results, so it makes
|
25
|
+
`guard-haskell` uses [`hspec`][1] to run specs and check results, so it makes
|
26
|
+
some assumptions about your code organization and style:
|
24
27
|
|
25
|
-
* `hspec` is your testing framework
|
28
|
+
* `hspec` is your testing framework of choice; therefore,
|
26
29
|
|
27
|
-
* [`hspec-discover`][2]
|
28
|
-
i.e. there is a "top" spec (usually `test/Spec.hs`) that pulls others in
|
30
|
+
* [`hspec-discover`][2] organizes your specs
|
29
31
|
|
30
|
-
When you type
|
31
|
-
|
32
|
+
When you type `guard` in the terminal, `guard-haskell` fires up a `cabal repl` instance
|
33
|
+
to talk to, running (parts of) examples when files are modified.
|
32
34
|
|
33
|
-
|
35
|
+
### Guard::Haskell setup
|
34
36
|
|
35
|
-
For `guard-haskell` to be ready to work we need a
|
37
|
+
For `guard-haskell` to be ready to work we need a test suite named "spec" (that's
|
38
|
+
configurable, any test suite name will do) defined in the cabal file and a Guardfile
|
39
|
+
(which you can get by running `guard init haskell`)
|
36
40
|
|
37
|
-
|
38
|
-
mkdir --parents test
|
39
|
-
echo '{-# OPTIONS_GHC -F -pgmF hspec-discover #-}' > test/Spec.hs
|
40
|
-
guard init haskell
|
41
|
-
guard
|
42
|
-
```
|
43
|
-
|
44
|
-
## Guardfile examples
|
41
|
+
### Guardfile examples
|
45
42
|
|
46
|
-
|
43
|
+
A typical haskell project:
|
47
44
|
|
48
45
|
```ruby
|
49
46
|
guard :haskell do
|
@@ -52,17 +49,41 @@ guard :haskell do
|
|
52
49
|
end
|
53
50
|
```
|
54
51
|
|
55
|
-
|
52
|
+
A customized haskell project:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
options = ["--ghc-options=-ignore-dot-ghci -DTEST"]
|
56
|
+
|
57
|
+
guard :haskell, all_on_start: true, repl_options: options do
|
58
|
+
watch(%r{test/.+Spec\.l?hs$})
|
59
|
+
watch(%r{lib/.+\.l?hs$})
|
60
|
+
watch(%r{bin/.+\.l?hs$})
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
Another customized haskell project:
|
56
65
|
|
57
66
|
```ruby
|
58
|
-
guard :haskell, all_on_pass: true,
|
67
|
+
guard :haskell, all_on_start: true, all_on_pass: true, cabal_target: "not-spec" do
|
59
68
|
watch(%r{test/.+Spec\.l?hs$})
|
60
69
|
watch(%r{lib/.+\.l?hs$})
|
61
70
|
watch(%r{bin/.+\.l?hs$})
|
62
71
|
end
|
63
72
|
```
|
64
73
|
|
65
|
-
|
74
|
+
#### Gemfile
|
75
|
+
|
76
|
+
It's also advised to have a trivial `Gemfile` in the repository for
|
77
|
+
`bundler exec guard` to be able to pick the correct versions of the dependencies:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
source "https://rubygems.org"
|
81
|
+
|
82
|
+
gem "guard-haskell", "~>2.0"
|
83
|
+
```
|
84
|
+
|
85
|
+
Options
|
86
|
+
-------
|
66
87
|
|
67
88
|
`Guard::Haskell` has a bunch of options:
|
68
89
|
|
@@ -72,25 +93,22 @@ Run all examples on start (default: `false`).
|
|
72
93
|
|
73
94
|
### `all_on_pass`
|
74
95
|
|
75
|
-
Run all examples
|
96
|
+
Run all examples when a failed spec passes again (default: `false`).
|
76
97
|
|
77
98
|
### `focus_on_fail`
|
78
99
|
|
79
100
|
Rerun only failed examples until they pass (default: `true`).
|
80
101
|
|
81
|
-
### `
|
82
|
-
|
83
|
-
Pass custom ghci options, for example, `-XCPP` directives like `-DTEST` (default: `[]`).
|
84
|
-
|
85
|
-
### `top_spec`
|
102
|
+
### `repl_options`
|
86
103
|
|
87
|
-
|
104
|
+
Pass custom cabal repl options (default: `[]`).
|
88
105
|
|
89
|
-
### `
|
106
|
+
### `cabal_target`
|
90
107
|
|
91
|
-
|
108
|
+
The cabal build target to load (default: `spec`).
|
92
109
|
|
93
|
-
|
110
|
+
Known problems
|
111
|
+
--------------
|
94
112
|
|
95
113
|
### App you test uses the GHC API
|
96
114
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,4 @@
|
|
1
|
+
*Main> /usr/bin/ld: dist/build/spec/spec-tmp/Paths_X.o: relocation R_X86_64_32S against `stg_bh_upd_frame_info' can not be used when making a shared object; recompile with -fPIC
|
2
|
+
dist/build/spec/spec-tmp/Paths_X.o: could not read symbols: Bad value
|
3
|
+
collect2: error: ld returned 1 exit status
|
4
|
+
phase `Linker' failed (exitcode = 1)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/guard/haskell.rb
CHANGED
@@ -3,17 +3,8 @@ require 'guard/plugin'
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
class ::String
|
6
|
-
def
|
7
|
-
|
8
|
-
if matches
|
9
|
-
matches[1].strip_lowercase_directories
|
10
|
-
else
|
11
|
-
self
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def path_to_module_name
|
16
|
-
self.gsub(/\//, ".")
|
6
|
+
def to_module_name
|
7
|
+
self.split('/').drop_while{|x| /^[[:lower:]]/.match(x)}.join('.')
|
17
8
|
end
|
18
9
|
end
|
19
10
|
|
@@ -25,22 +16,20 @@ module ::Guard
|
|
25
16
|
attr_accessor :opts, :repl
|
26
17
|
attr_reader :targets, :last_run
|
27
18
|
|
28
|
-
Options = Struct.new(
|
29
|
-
:
|
30
|
-
:
|
19
|
+
Options = ::Struct.new(
|
20
|
+
:cabal_target,
|
21
|
+
:repl_options,
|
31
22
|
:all_on_start,
|
32
23
|
:all_on_pass,
|
33
24
|
:focus_on_fail,
|
34
|
-
:sandbox_glob,
|
35
25
|
)
|
36
26
|
|
37
27
|
DEFAULT_OPTIONS = {
|
38
|
-
|
39
|
-
|
28
|
+
cabal_target: "spec",
|
29
|
+
repl_options: [],
|
40
30
|
all_on_start: false,
|
41
31
|
all_on_pass: false,
|
42
32
|
focus_on_fail: true,
|
43
|
-
sandbox_glob: ".cabal-sandbox/*packages.conf.d",
|
44
33
|
}
|
45
34
|
|
46
35
|
def initialize(user_options = {})
|
@@ -50,8 +39,9 @@ module ::Guard
|
|
50
39
|
|
51
40
|
def start
|
52
41
|
@last_run = :success # try to prove it wasn't :-)
|
53
|
-
self.repl = Repl.new(opts.
|
54
|
-
repl.
|
42
|
+
self.repl = Repl.new(opts.cabal_target, opts.repl_options)
|
43
|
+
throw :cabal_repl_initialization_has_failed if self.repl.status == :loading_failure
|
44
|
+
success?
|
55
45
|
|
56
46
|
@targets = ::Set.new(::Dir.glob("**/*.{hs,lhs}"))
|
57
47
|
|
@@ -74,7 +64,7 @@ module ::Guard
|
|
74
64
|
success?
|
75
65
|
end
|
76
66
|
|
77
|
-
def run
|
67
|
+
def run(pattern)
|
78
68
|
if opts.focus_on_fail and last_run == :runtime_failure
|
79
69
|
repl.reload_and_rerun
|
80
70
|
else
|
@@ -84,7 +74,7 @@ module ::Guard
|
|
84
74
|
end
|
85
75
|
|
86
76
|
def success?
|
87
|
-
case [last_run, repl.
|
77
|
+
case [last_run, repl.status]
|
88
78
|
when [:runtime_failure, :success],
|
89
79
|
[:compile_failure, :success]
|
90
80
|
@last_run = :success
|
@@ -108,17 +98,17 @@ module ::Guard
|
|
108
98
|
end
|
109
99
|
end
|
110
100
|
|
111
|
-
def run_on_additions
|
112
|
-
unless paths.all? { |path| targets.include?
|
101
|
+
def run_on_additions(paths)
|
102
|
+
unless paths.all? { |path| targets.include?(path) }
|
113
103
|
@targets += paths
|
114
|
-
|
104
|
+
reload
|
115
105
|
end
|
116
106
|
end
|
117
107
|
|
118
|
-
def run_on_modifications
|
108
|
+
def run_on_modifications(paths)
|
119
109
|
case paths.first
|
120
110
|
when /(.+)Spec\.l?hs$/, /(.+)\.l?hs$/
|
121
|
-
run($1.
|
111
|
+
run($1.to_module_name)
|
122
112
|
end
|
123
113
|
end
|
124
114
|
end
|
data/lib/guard/haskell/repl.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'open3'
|
2
2
|
|
3
3
|
class ::Guard::Haskell::Repl
|
4
|
-
attr_reader :stdin, :listener, :
|
4
|
+
attr_reader :stdin, :listener, :inferior, :status
|
5
5
|
|
6
|
-
def self.
|
6
|
+
def self.finished_with(str)
|
7
7
|
case str
|
8
8
|
when /\d+ examples?, 0 failures/,
|
9
9
|
/Ok, modules loaded:/
|
@@ -15,6 +15,7 @@ class ::Guard::Haskell::Repl
|
|
15
15
|
/cannot find object file for module/,
|
16
16
|
/phase `C pre-processor' failed/,
|
17
17
|
/phase `Haskell pre-processor' failed/,
|
18
|
+
/phase `Linker' failed/,
|
18
19
|
/GHCi runtime linker: fatal error:/,
|
19
20
|
/During interactive linking, GHCi couldn't find the following symbol:/,
|
20
21
|
/ghc: could not execute:/
|
@@ -22,36 +23,21 @@ class ::Guard::Haskell::Repl
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
def initialize(
|
26
|
-
@
|
27
|
-
@
|
28
|
-
|
29
|
-
cmd = ["ghci"]
|
30
|
-
|
31
|
-
Dir["*"].each { |d| cmd << "-i#{d}" if File.directory?(d) }
|
32
|
-
lookup_sandbox(cmd, sandbox_glob)
|
33
|
-
cmd.concat(ghci_options)
|
34
|
-
|
35
|
-
@stdin, stdout, @thread = ::Open3.popen2e(*cmd)
|
36
|
-
@listener = ::Thread.new { listen(stdout, STDOUT) }
|
37
|
-
end
|
38
|
-
|
39
|
-
def lookup_sandbox(cmd, sandbox_glob)
|
40
|
-
sandboxes = Sandbox.new(sandbox_glob)
|
41
|
-
sandboxes.with_best_sandbox(->(str) { str.scan(/\d+/).map(&:to_i) }) do |best_sandbox|
|
42
|
-
puts "Cabal sandboxes found:"
|
43
|
-
sandboxes.each { |sandbox| puts " #{sandbox}" }
|
44
|
-
puts "Cabal sandbox used:\n #{best_sandbox}"
|
45
|
-
cmd.concat(["-no-user-package-db", "-package-db=#{best_sandbox}"])
|
46
|
-
end
|
26
|
+
def initialize(cabal_target, repl_options)
|
27
|
+
@listening = false
|
28
|
+
@status = :success
|
29
|
+
start("cabal", "repl", cabal_target, *repl_options)
|
47
30
|
end
|
48
31
|
|
49
|
-
def
|
50
|
-
|
32
|
+
def start(*cmd)
|
33
|
+
@listening = true
|
34
|
+
@stdin, stdout, @inferior = ::Open3.popen2e(*cmd)
|
35
|
+
@listener = ::Thread.new { listen_or_die(stdout, STDOUT) }
|
36
|
+
wait_for_result
|
51
37
|
end
|
52
38
|
|
53
39
|
def exit
|
54
|
-
|
40
|
+
stdin.write(":quit\n")
|
55
41
|
::Thread.kill(listener)
|
56
42
|
end
|
57
43
|
|
@@ -71,53 +57,43 @@ class ::Guard::Haskell::Repl
|
|
71
57
|
end
|
72
58
|
end
|
73
59
|
|
74
|
-
class Sandbox
|
75
|
-
attr_reader :sandboxes
|
76
|
-
|
77
|
-
include ::Enumerable
|
78
|
-
|
79
|
-
def initialize(glob)
|
80
|
-
@sandboxes = ::Dir[glob]
|
81
|
-
end
|
82
|
-
|
83
|
-
def each(&block)
|
84
|
-
sandboxes.each(&block)
|
85
|
-
end
|
86
|
-
|
87
|
-
def with_best_sandbox(ordering)
|
88
|
-
best = sandboxes.max_by(&ordering)
|
89
|
-
yield best if best
|
90
|
-
best
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
60
|
private
|
95
61
|
def run_command_and_wait_for_result(command)
|
96
|
-
|
62
|
+
@listening = true
|
63
|
+
stdin.write(command)
|
97
64
|
wait_for_result == :success
|
98
65
|
end
|
99
66
|
|
100
67
|
def wait_for_result
|
101
|
-
while @
|
102
|
-
@
|
68
|
+
while @listening do sleep(0.01) end
|
69
|
+
@status
|
103
70
|
end
|
104
71
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
72
|
+
def listen_or_die(in_stream, out_stream)
|
73
|
+
listen(in_stream, out_stream) # should never return
|
74
|
+
stop(:loading_failure)
|
108
75
|
end
|
109
76
|
|
110
77
|
def listen(in_stream, out_stream)
|
111
|
-
while (
|
112
|
-
out_stream.print(
|
113
|
-
if @
|
114
|
-
res = self.class.
|
78
|
+
while (line = in_stream.gets)
|
79
|
+
out_stream.print(line)
|
80
|
+
if @listening
|
81
|
+
res = self.class.finished_with(line)
|
115
82
|
case res
|
116
83
|
when :success, :runtime_failure, :compile_failure
|
117
|
-
|
118
|
-
|
84
|
+
# A horrible hack to show the cursor again
|
85
|
+
#
|
86
|
+
# The problem is that '\e[?25h' code from hspec is waiting on
|
87
|
+
# the next line, which we probably will never read :-(
|
88
|
+
out_stream.print("\e[?25h")
|
89
|
+
stop(res)
|
119
90
|
end
|
120
91
|
end
|
121
92
|
end
|
122
93
|
end
|
94
|
+
|
95
|
+
def stop(status)
|
96
|
+
@status = status
|
97
|
+
@listening = false
|
98
|
+
end
|
123
99
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
[ "-ignore-dot-ghci" \
|
1
|
+
repl_options =
|
2
|
+
[ "--ghc-options=-ignore-dot-ghci" \
|
3
3
|
]
|
4
4
|
|
5
|
-
guard :haskell,
|
5
|
+
guard :haskell, repl_options: repl_options do
|
6
6
|
watch(%r{test/.+Spec\.l?hs$})
|
7
7
|
watch(%r{src/.+\.l?hs$})
|
8
8
|
end
|
@@ -3,25 +3,13 @@ require 'spec_helper'
|
|
3
3
|
require 'guard/notifier'
|
4
4
|
|
5
5
|
dev_null = ::File.open("/dev/null", "w")
|
6
|
-
|
6
|
+
asset = ->(file) { "asset/#{file}" }
|
7
7
|
|
8
8
|
describe ::Guard::Haskell::Repl do
|
9
9
|
let(:repl) do
|
10
10
|
::Guard::Haskell::Repl.new
|
11
11
|
end
|
12
12
|
|
13
|
-
describe '#init' do
|
14
|
-
it "calls :load on ghci instance" do
|
15
|
-
expect(repl).to receive(:run_command_and_wait_for_result).with(/:load/)
|
16
|
-
repl.init("Spec.hs")
|
17
|
-
end
|
18
|
-
|
19
|
-
it "loads provided spec" do
|
20
|
-
expect(repl).to receive(:run_command_and_wait_for_result).with(/FooBarSpec.hs/)
|
21
|
-
repl.init("FooBarSpec.hs")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
13
|
context "running spec" do
|
26
14
|
before(:each) do
|
27
15
|
repl.stub(:run_command_and_wait_for_result) { |_| true }
|
@@ -62,215 +50,151 @@ describe ::Guard::Haskell::Repl do
|
|
62
50
|
end
|
63
51
|
end
|
64
52
|
|
65
|
-
describe '#
|
53
|
+
describe '#finished_with' do
|
66
54
|
it "handles zero examples/failures" do
|
67
|
-
expect(::Guard::Haskell::Repl.
|
55
|
+
expect(::Guard::Haskell::Repl.finished_with("0 examples, 0 failures")).to eq(:success)
|
68
56
|
end
|
69
57
|
|
70
58
|
it "handles one example/zero failures" do
|
71
|
-
expect(::Guard::Haskell::Repl.
|
59
|
+
expect(::Guard::Haskell::Repl.finished_with("1 example, 0 failures")).to eq(:success)
|
72
60
|
end
|
73
61
|
|
74
62
|
it "handles multiple examples/zero failures" do
|
75
|
-
expect(::Guard::Haskell::Repl.
|
63
|
+
expect(::Guard::Haskell::Repl.finished_with("37 examples, 0 failures")).to eq(:success)
|
76
64
|
end
|
77
65
|
|
78
66
|
it "handles one example/failure" do
|
79
|
-
expect(::Guard::Haskell::Repl.
|
67
|
+
expect(::Guard::Haskell::Repl.finished_with("1 example, 1 failure")).to eq(:runtime_failure)
|
80
68
|
end
|
81
69
|
|
82
70
|
it "handles multiple examples/multiple failures" do
|
83
|
-
expect(::Guard::Haskell::Repl.
|
71
|
+
expect(::Guard::Haskell::Repl.finished_with("26 examples, 2 failures")).to eq(:runtime_failure)
|
84
72
|
end
|
85
73
|
|
86
74
|
it "handles failure to load the module" do
|
87
|
-
expect(::Guard::Haskell::Repl.
|
75
|
+
expect(::Guard::Haskell::Repl.finished_with("Failed, modules loaded:")).to eq(:compile_failure)
|
88
76
|
end
|
89
77
|
|
90
78
|
it "handles uncaught exceptions" do
|
91
|
-
expect(::Guard::Haskell::Repl.
|
79
|
+
expect(::Guard::Haskell::Repl.finished_with("*** Exception: Prelude.undefined")).to eq(:compile_failure)
|
92
80
|
end
|
93
81
|
|
94
82
|
it "handles CPP errors" do
|
95
|
-
expect(::Guard::Haskell::Repl.
|
83
|
+
expect(::Guard::Haskell::Repl.finished_with("phase `C pre-processor' failed")).to eq(:compile_failure)
|
96
84
|
end
|
97
85
|
|
98
86
|
it "handles Haskell pre-processor errors" do
|
99
|
-
expect(::Guard::Haskell::Repl.
|
87
|
+
expect(::Guard::Haskell::Repl.finished_with("phase `Haskell pre-processor' failed")).to eq(:compile_failure)
|
100
88
|
end
|
101
89
|
|
102
90
|
it "handles runtime linker errors" do
|
103
|
-
expect(::Guard::Haskell::Repl.
|
91
|
+
expect(::Guard::Haskell::Repl.finished_with("GHCi runtime linker: fatal error:")).to eq(:compile_failure)
|
104
92
|
end
|
105
93
|
end
|
106
94
|
|
107
95
|
describe '#listen' do
|
108
96
|
context 'real world' do
|
109
97
|
it "handles typical pass run" do
|
110
|
-
in_stream = ::File.open(
|
111
|
-
repl.instance_variable_set(:@
|
98
|
+
in_stream = ::File.open(asset["passed/spec-pass.ok"])
|
99
|
+
repl.instance_variable_set(:@listening, true)
|
112
100
|
|
113
101
|
repl.send(:listen, in_stream, dev_null)
|
114
102
|
|
115
|
-
expect(repl.instance_variable_get(:@
|
116
|
-
expect(repl.instance_variable_get(:@
|
103
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
104
|
+
expect(repl.instance_variable_get(:@status)).to eq(:success)
|
117
105
|
end
|
118
106
|
|
119
107
|
it "handles typical failure run" do
|
120
|
-
in_stream = ::File.open(
|
121
|
-
repl.instance_variable_set(:@
|
108
|
+
in_stream = ::File.open(asset["failed/spec-failure.err"])
|
109
|
+
repl.instance_variable_set(:@listening, true)
|
122
110
|
|
123
111
|
repl.send(:listen, in_stream, dev_null)
|
124
112
|
|
125
|
-
expect(repl.instance_variable_get(:@
|
126
|
-
expect(repl.instance_variable_get(:@
|
113
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
114
|
+
expect(repl.instance_variable_get(:@status)).to eq(:runtime_failure)
|
127
115
|
end
|
128
116
|
|
129
117
|
it 'handles "duplicate definition" runtime linker error' do
|
130
|
-
in_stream = ::File.open(
|
131
|
-
repl.instance_variable_set(:@
|
118
|
+
in_stream = ::File.open(asset["failed/runtime-linker-duplicate-definition-for-symbol.err"])
|
119
|
+
repl.instance_variable_set(:@listening, true)
|
132
120
|
|
133
121
|
repl.send(:listen, in_stream, dev_null)
|
134
122
|
|
135
|
-
expect(repl.instance_variable_get(:@
|
136
|
-
expect(repl.instance_variable_get(:@
|
123
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
124
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
137
125
|
end
|
138
126
|
|
139
127
|
# Unfortunately I can't remember why it happened :-(
|
140
128
|
it 'handles "couldn\'t find symbol" runtime linker error' do
|
141
|
-
in_stream = ::File.open(
|
142
|
-
repl.instance_variable_set(:@
|
129
|
+
in_stream = ::File.open(asset["failed/runtime-linker-couldn't-find-symbol.err"])
|
130
|
+
repl.instance_variable_set(:@listening, true)
|
143
131
|
|
144
132
|
repl.send(:listen, in_stream, dev_null)
|
145
133
|
|
146
|
-
expect(repl.instance_variable_get(:@
|
147
|
-
expect(repl.instance_variable_get(:@
|
134
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
135
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
148
136
|
end
|
149
137
|
|
150
138
|
# This one's even trickier to reproduce than the previous one
|
151
139
|
it 'handles "cannot find object file" runtime linker error' do
|
152
|
-
in_stream = ::File.open(
|
153
|
-
repl.instance_variable_set(:@
|
140
|
+
in_stream = ::File.open(asset["failed/runtime-linker-cannot-find-object-file.err"])
|
141
|
+
repl.instance_variable_set(:@listening, true)
|
154
142
|
|
155
143
|
repl.send(:listen, in_stream, dev_null)
|
156
144
|
|
157
|
-
expect(repl.instance_variable_get(:@
|
158
|
-
expect(repl.instance_variable_get(:@
|
145
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
146
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
159
147
|
end
|
160
148
|
|
161
149
|
it "handles hspec exceptions" do
|
162
|
-
in_stream = ::File.open(
|
163
|
-
repl.instance_variable_set(:@
|
150
|
+
in_stream = ::File.open(asset["failed/exception.err"])
|
151
|
+
repl.instance_variable_set(:@listening, true)
|
164
152
|
|
165
153
|
repl.send(:listen, in_stream, dev_null)
|
166
154
|
|
167
|
-
expect(repl.instance_variable_get(:@
|
168
|
-
expect(repl.instance_variable_get(:@
|
155
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
156
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
169
157
|
end
|
170
158
|
|
171
159
|
it "handles CPP exceptions" do
|
172
|
-
in_stream = ::File.open(
|
173
|
-
repl.instance_variable_set(:@
|
160
|
+
in_stream = ::File.open(asset["failed/phase-c-pre-processor-failed.err"])
|
161
|
+
repl.instance_variable_set(:@listening, true)
|
174
162
|
|
175
163
|
repl.send(:listen, in_stream, dev_null)
|
176
164
|
|
177
|
-
expect(repl.instance_variable_get(:@
|
178
|
-
expect(repl.instance_variable_get(:@
|
165
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
166
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
179
167
|
end
|
180
168
|
|
181
169
|
it "handles preprocessor phase failures" do
|
182
|
-
in_stream = ::File.open(
|
183
|
-
repl.instance_variable_set(:@
|
170
|
+
in_stream = ::File.open(asset["failed/phase-haskell-pre-processor-failed.err"])
|
171
|
+
repl.instance_variable_set(:@listening, true)
|
184
172
|
|
185
173
|
repl.send(:listen, in_stream, dev_null)
|
186
174
|
|
187
|
-
expect(repl.instance_variable_get(:@
|
188
|
-
expect(repl.instance_variable_get(:@
|
175
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
176
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
189
177
|
end
|
190
178
|
|
191
179
|
it "handles missing preprocessor error" do
|
192
|
-
in_stream = ::File.open(
|
193
|
-
repl.instance_variable_set(:@
|
180
|
+
in_stream = ::File.open(asset["failed/invalid-preprocessor.err"])
|
181
|
+
repl.instance_variable_set(:@listening, true)
|
194
182
|
|
195
183
|
repl.send(:listen, in_stream, dev_null)
|
196
184
|
|
197
|
-
expect(repl.instance_variable_get(:@
|
198
|
-
expect(repl.instance_variable_get(:@
|
185
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
186
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
199
187
|
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
describe "#lookup_sandbox" do
|
204
|
-
include FakeFS::SpecHelpers
|
205
188
|
|
206
|
-
|
189
|
+
it "handles linker phase failures" do
|
190
|
+
in_stream = ::File.open(asset["failed/phase-linker-failed.err"])
|
191
|
+
repl.instance_variable_set(:@listening, true)
|
207
192
|
|
208
|
-
|
209
|
-
expect_any_instance_of(::IO).not_to receive(:puts)
|
210
|
-
expect(repl.lookup_sandbox([], "*packages.conf.d")).to be_nil
|
211
|
-
end
|
212
|
-
|
213
|
-
it "finds a sandbox" do
|
214
|
-
::FileUtils.mkdir_p(["ghc-7.6.3-packages.conf.d"])
|
215
|
-
expect_any_instance_of(::IO).to receive(:puts).with("Cabal sandboxes found:")
|
216
|
-
expect(repl.lookup_sandbox([], "*packages.conf.d")).to eq("/ghc-7.6.3-packages.conf.d")
|
217
|
-
end
|
218
|
-
|
219
|
-
it "finds a sandbox with the default settings" do
|
220
|
-
::FileUtils.mkdir_p([".cabal-sandbox/foo-bar-ghc-7.6.3-packages.conf.d"])
|
221
|
-
expect_any_instance_of(::IO).to receive(:puts).with("Cabal sandboxes found:")
|
222
|
-
expect(repl.lookup_sandbox([], ::Guard::Haskell::DEFAULT_OPTIONS[:sandbox_glob])).to eq("/.cabal-sandbox/foo-bar-ghc-7.6.3-packages.conf.d")
|
223
|
-
end
|
193
|
+
repl.send(:listen, in_stream, dev_null)
|
224
194
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
"ghc-1.1-packages.conf.d",
|
229
|
-
"ghc-1.2-packages.conf.d",
|
230
|
-
"ghc-1.10-packages.conf.d",
|
231
|
-
])
|
232
|
-
expect(repl.lookup_sandbox([], "*packages.conf.d")).to eq("/ghc-1.10-packages.conf.d")
|
195
|
+
expect(repl.instance_variable_get(:@listening)).to eq(false)
|
196
|
+
expect(repl.instance_variable_get(:@status)).to eq(:compile_failure)
|
197
|
+
end
|
233
198
|
end
|
234
199
|
end
|
235
200
|
end
|
236
|
-
|
237
|
-
describe ::Guard::Haskell::Repl::Sandbox do
|
238
|
-
::Sandbox = ::Guard::Haskell::Repl::Sandbox
|
239
|
-
include FakeFS::SpecHelpers
|
240
|
-
|
241
|
-
let(:id) { ->(x) { x } }
|
242
|
-
let(:reversed) { ->(str) { str.reverse } }
|
243
|
-
|
244
|
-
before(:each) { ::IO.any_instance.stub(:puts) }
|
245
|
-
|
246
|
-
it "has an empty list of sandboxes if no sandboxes are found" do
|
247
|
-
expect(::Sandbox.new("*").sandboxes).to eq([])
|
248
|
-
end
|
249
|
-
|
250
|
-
it "has a singleton list of sandboxes if one sandbox is found" do
|
251
|
-
::FileUtils.touch(["foo", "bar", "baz"])
|
252
|
-
expect(::Sandbox.new("foo").sandboxes).to eq(["/foo"])
|
253
|
-
end
|
254
|
-
|
255
|
-
it "has a list of sandboxes if more than one sandbox is found" do
|
256
|
-
::FileUtils.touch(["foo", "bar", "baz"])
|
257
|
-
expect(::Sandbox.new("ba*").sandboxes).to eq(["/bar", "/baz"])
|
258
|
-
end
|
259
|
-
|
260
|
-
it "has a nil for the best sandbox of an empty list of sandboxes" do
|
261
|
-
expect_any_instance_of(::IO).not_to receive(:puts)
|
262
|
-
expect(::Sandbox.new("*").with_best_sandbox(id) { |s| puts s }).to be_nil
|
263
|
-
end
|
264
|
-
|
265
|
-
it "chooses a \"maximum\" for the best sandbox" do
|
266
|
-
::FileUtils.touch(["foo", "bar", "baz"])
|
267
|
-
expect_any_instance_of(::IO).to receive(:puts).with("/foo")
|
268
|
-
expect(::Sandbox.new("*").with_best_sandbox(id) { |s| puts s }).to eq("/foo")
|
269
|
-
end
|
270
|
-
|
271
|
-
it "chooses a \"maximum\" of the complex ordering for the best sandbox" do
|
272
|
-
::FileUtils.touch(["foo", "bar", "baz", "zap"])
|
273
|
-
expect_any_instance_of(::IO).to receive(:puts).with("/baz")
|
274
|
-
expect(::Sandbox.new("*").with_best_sandbox(reversed) { |s| puts s }).to eq("/baz")
|
275
|
-
end
|
276
|
-
end
|
data/spec/guard/haskell_spec.rb
CHANGED
@@ -3,31 +3,21 @@ require 'guard/notifier'
|
|
3
3
|
|
4
4
|
describe "monkey patching" do
|
5
5
|
describe ::String do
|
6
|
-
describe "#
|
7
|
-
it "
|
8
|
-
expect("".
|
6
|
+
describe "#to_module_name" do
|
7
|
+
it "converts the empty string to the empty module name" do
|
8
|
+
expect("".to_module_name).to eq("")
|
9
9
|
end
|
10
10
|
|
11
|
-
it "
|
12
|
-
expect("Foo".
|
11
|
+
it "is identity for very simple module paths" do
|
12
|
+
expect("Foo".to_module_name).to eq("Foo")
|
13
13
|
end
|
14
14
|
|
15
|
-
it "
|
16
|
-
expect("foo/
|
15
|
+
it "drops lowercase directory prefixes and substitutes / with ." do
|
16
|
+
expect("foo/bar/Qux/Quux".to_module_name).to eq("Qux.Quux")
|
17
17
|
end
|
18
18
|
|
19
|
-
it "
|
20
|
-
expect("foo/bar/
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#path_to_module_name" do
|
25
|
-
it "works on string without path separators" do
|
26
|
-
expect("Foo".path_to_module_name).to eq("Foo")
|
27
|
-
end
|
28
|
-
|
29
|
-
it "works on string with path separators" do
|
30
|
-
expect("Foo/Bar/Baz".path_to_module_name).to eq("Foo.Bar.Baz")
|
19
|
+
it "does not deal with extensions in the path" do
|
20
|
+
expect("foo/bar/Qux/Quux.hs".to_module_name).to eq("Qux.Quux.hs")
|
31
21
|
end
|
32
22
|
end
|
33
23
|
end
|
@@ -36,6 +26,10 @@ end
|
|
36
26
|
class ::Guard::Haskell::Repl
|
37
27
|
def initialize(*args)
|
38
28
|
end
|
29
|
+
|
30
|
+
def status
|
31
|
+
:success
|
32
|
+
end
|
39
33
|
end
|
40
34
|
|
41
35
|
describe ::Guard::Haskell do
|
@@ -56,14 +50,19 @@ describe ::Guard::Haskell do
|
|
56
50
|
|
57
51
|
describe "#start" do
|
58
52
|
it "starts repl" do
|
59
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
53
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:initialize).with("spec", [])
|
54
|
+
|
55
|
+
guard.start
|
56
|
+
end
|
57
|
+
|
58
|
+
it "checks the repl has been loaded successfully" do
|
59
|
+
expect(guard).to receive(:success?)
|
60
60
|
|
61
61
|
guard.start
|
62
62
|
end
|
63
63
|
|
64
64
|
it "does not run all examples on start by default" do
|
65
65
|
expect(guard).not_to receive(:run_all)
|
66
|
-
expect(guard).not_to receive(:success?)
|
67
66
|
|
68
67
|
guard.start
|
69
68
|
end
|
@@ -72,15 +71,23 @@ describe ::Guard::Haskell do
|
|
72
71
|
custom_guard = ::Guard::Haskell.new(all_on_start: true)
|
73
72
|
|
74
73
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with(no_args)
|
75
|
-
expect(custom_guard).to receive(:success?)
|
74
|
+
expect(custom_guard).to receive(:success?).twice
|
76
75
|
|
77
76
|
custom_guard.start
|
78
77
|
end
|
79
78
|
|
80
|
-
it "starts repl with custom
|
81
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
79
|
+
it "starts repl with custom target specified with :cabal_target option" do
|
80
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:initialize).with("not-spec", [])
|
82
81
|
|
83
|
-
custom_guard = ::Guard::Haskell.new(
|
82
|
+
custom_guard = ::Guard::Haskell.new(cabal_target: "not-spec")
|
83
|
+
custom_guard.start
|
84
|
+
end
|
85
|
+
|
86
|
+
it "starts repl with custom options specified with :repl_options option" do
|
87
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:initialize)
|
88
|
+
.with("spec", ["--ghc-options=-Werror"])
|
89
|
+
|
90
|
+
custom_guard = ::Guard::Haskell.new(repl_options: ["--ghc-options=-Werror"])
|
84
91
|
custom_guard.start
|
85
92
|
end
|
86
93
|
end
|
@@ -105,10 +112,10 @@ describe ::Guard::Haskell do
|
|
105
112
|
describe "#run" do
|
106
113
|
it "checks success after run" do
|
107
114
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Foo")
|
108
|
-
expect(guard).to receive(:success?)
|
109
115
|
guard.instance_variable_set(:@last_run, :success)
|
110
|
-
|
111
116
|
guard.start
|
117
|
+
|
118
|
+
expect(guard).to receive(:success?)
|
112
119
|
guard.run("Foo")
|
113
120
|
end
|
114
121
|
|
@@ -152,20 +159,20 @@ describe ::Guard::Haskell do
|
|
152
159
|
describe "#run_all" do
|
153
160
|
it "checks success after run" do
|
154
161
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching)
|
155
|
-
expect(guard).to receive(:success?)
|
156
|
-
|
157
162
|
guard.start
|
163
|
+
|
164
|
+
expect(guard).to receive(:success?)
|
158
165
|
guard.run_all
|
159
166
|
end
|
160
167
|
end
|
161
168
|
|
162
169
|
describe "#success" do
|
163
170
|
def notify(before, received, after)
|
164
|
-
|
165
|
-
|
171
|
+
guard.start
|
172
|
+
::Guard::Haskell::Repl.any_instance.stub(:status) { received }
|
173
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
166
174
|
yield
|
167
175
|
|
168
|
-
guard.start
|
169
176
|
guard.instance_variable_set(:@last_run, before)
|
170
177
|
guard.success?
|
171
178
|
expect(guard.instance_variable_get(:@last_run)).to eq(after)
|
@@ -235,7 +242,7 @@ describe ::Guard::Haskell do
|
|
235
242
|
end
|
236
243
|
|
237
244
|
it "runs all examples on success after runtime failure with :all_on_pass option" do
|
238
|
-
::Guard::Haskell::Repl.any_instance.stub(:
|
245
|
+
::Guard::Haskell::Repl.any_instance.stub(:status) { :success }
|
239
246
|
custom_guard = ::Guard::Haskell.new(all_on_pass: true)
|
240
247
|
expect(custom_guard).to receive(:run_all)
|
241
248
|
|
@@ -245,7 +252,7 @@ describe ::Guard::Haskell do
|
|
245
252
|
end
|
246
253
|
|
247
254
|
it "runs all examples on success after compile time failure with :all_on_pass option" do
|
248
|
-
::Guard::Haskell::Repl.any_instance.stub(:
|
255
|
+
::Guard::Haskell::Repl.any_instance.stub(:status) { :success }
|
249
256
|
custom_guard = ::Guard::Haskell.new(all_on_pass: true)
|
250
257
|
expect(custom_guard).to receive(:run_all)
|
251
258
|
|
@@ -255,28 +262,14 @@ describe ::Guard::Haskell do
|
|
255
262
|
end
|
256
263
|
end
|
257
264
|
|
258
|
-
describe "#
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
guard.start
|
263
|
-
guard.instance_variable_set(:@targets, [])
|
264
|
-
guard.run_on_additions ["foo", "bar"]
|
265
|
-
end
|
266
|
-
|
267
|
-
it "does not reinitialize the repl if new files were seen before" do
|
268
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:init).once
|
269
|
-
|
270
|
-
guard.start
|
271
|
-
guard.instance_variable_set(:@targets, ["foo", "bar"])
|
272
|
-
guard.run_on_additions ["foo", "bar"]
|
265
|
+
describe "#run_on_modifications" do
|
266
|
+
before :each do
|
267
|
+
::Guard::Haskell::Repl.any_instance.stub(:status) { :success }
|
273
268
|
end
|
274
|
-
end
|
275
269
|
|
276
|
-
describe "#run_on_modifications" do
|
277
270
|
it "run examples for simple haskell files" do
|
278
271
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Foo")
|
279
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
272
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
280
273
|
|
281
274
|
guard.start
|
282
275
|
guard.run_on_modifications(["Foo.hs"])
|
@@ -284,7 +277,7 @@ describe ::Guard::Haskell do
|
|
284
277
|
|
285
278
|
it "run examples for simple literate haskell files" do
|
286
279
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Foo")
|
287
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
280
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
288
281
|
|
289
282
|
guard.start
|
290
283
|
guard.run_on_modifications(["Foo.lhs"])
|
@@ -292,7 +285,7 @@ describe ::Guard::Haskell do
|
|
292
285
|
|
293
286
|
it "run examples for *complex* haskell files" do
|
294
287
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Bar.Baz")
|
295
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
288
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
296
289
|
|
297
290
|
guard.start
|
298
291
|
guard.run_on_modifications(["foo/Bar/Baz.hs"])
|
@@ -300,7 +293,7 @@ describe ::Guard::Haskell do
|
|
300
293
|
|
301
294
|
it "run examples for simple haskell spec files" do
|
302
295
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Foo")
|
303
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
296
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
304
297
|
|
305
298
|
guard.start
|
306
299
|
guard.run_on_modifications(["FooSpec.hs"])
|
@@ -308,7 +301,7 @@ describe ::Guard::Haskell do
|
|
308
301
|
|
309
302
|
it "run examples for simple literate haskell spec files" do
|
310
303
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Foo")
|
311
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
304
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
312
305
|
|
313
306
|
guard.start
|
314
307
|
guard.run_on_modifications(["FooSpec.lhs"])
|
@@ -316,10 +309,28 @@ describe ::Guard::Haskell do
|
|
316
309
|
|
317
310
|
it "run examples for *complex* haskell spec files" do
|
318
311
|
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:reload_and_run_matching).with("Bar.Baz")
|
319
|
-
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:
|
312
|
+
expect_any_instance_of(::Guard::Haskell::Repl).to receive(:status)
|
320
313
|
|
321
314
|
guard.start
|
322
315
|
guard.run_on_modifications(["foo/Bar/BazSpec.hs"])
|
323
316
|
end
|
324
317
|
end
|
318
|
+
|
319
|
+
describe "#run_on_additions" do
|
320
|
+
it "reinitializes the repl on new files" do
|
321
|
+
expect_any_instance_of(::Guard::Haskell).to receive(:reload).once
|
322
|
+
|
323
|
+
guard.start
|
324
|
+
guard.instance_variable_set(:@targets, [])
|
325
|
+
guard.run_on_additions(["foo", "bar"])
|
326
|
+
end
|
327
|
+
|
328
|
+
it "does not reinitialize the repl if new files were seen before" do
|
329
|
+
expect_any_instance_of(::Guard::Haskell).not_to receive(:reload).once
|
330
|
+
|
331
|
+
guard.start
|
332
|
+
guard.instance_variable_set(:@targets, ["foo", "bar"])
|
333
|
+
guard.run_on_additions(["foo", "bar"])
|
334
|
+
end
|
335
|
+
end
|
325
336
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard-haskell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matvey Aksenov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard
|
@@ -108,6 +108,16 @@ files:
|
|
108
108
|
- LICENSE
|
109
109
|
- README.md
|
110
110
|
- Rakefile
|
111
|
+
- asset/failed/exception.err
|
112
|
+
- asset/failed/invalid-preprocessor.err
|
113
|
+
- asset/failed/phase-c-pre-processor-failed.err
|
114
|
+
- asset/failed/phase-haskell-pre-processor-failed.err
|
115
|
+
- asset/failed/phase-linker-failed.err
|
116
|
+
- asset/failed/runtime-linker-cannot-find-object-file.err
|
117
|
+
- asset/failed/runtime-linker-couldn't-find-symbol.err
|
118
|
+
- asset/failed/runtime-linker-duplicate-definition-for-symbol.err
|
119
|
+
- asset/failed/spec-failure.err
|
120
|
+
- asset/passed/spec-pass.ok
|
111
121
|
- guard-haskell.gemspec
|
112
122
|
- lib/guard/haskell.rb
|
113
123
|
- lib/guard/haskell/repl.rb
|
@@ -115,15 +125,6 @@ files:
|
|
115
125
|
- lib/guard/haskell/version.rb
|
116
126
|
- spec/guard/haskell/repl_spec.rb
|
117
127
|
- spec/guard/haskell_spec.rb
|
118
|
-
- spec/run-files/cpp-exception.error
|
119
|
-
- spec/run-files/hspec-exception.error
|
120
|
-
- spec/run-files/missing-preprocessor.error
|
121
|
-
- spec/run-files/preprocessor-phase-failed.error
|
122
|
-
- spec/run-files/runtime-linker-cannot-find-object-file.error
|
123
|
-
- spec/run-files/runtime-linker-couldn't-find-symbol.error
|
124
|
-
- spec/run-files/runtime-linker-duplicate-definition-for-symbol.error
|
125
|
-
- spec/run-files/spec-failure.error
|
126
|
-
- spec/run-files/spec-pass.success
|
127
128
|
- spec/spec_helper.rb
|
128
129
|
homepage: https://github.com/supki/guard-haskell#readme
|
129
130
|
licenses:
|
@@ -152,13 +153,4 @@ summary: Guard gem for Haskell
|
|
152
153
|
test_files:
|
153
154
|
- spec/guard/haskell/repl_spec.rb
|
154
155
|
- spec/guard/haskell_spec.rb
|
155
|
-
- spec/run-files/cpp-exception.error
|
156
|
-
- spec/run-files/hspec-exception.error
|
157
|
-
- spec/run-files/missing-preprocessor.error
|
158
|
-
- spec/run-files/preprocessor-phase-failed.error
|
159
|
-
- spec/run-files/runtime-linker-cannot-find-object-file.error
|
160
|
-
- spec/run-files/runtime-linker-couldn't-find-symbol.error
|
161
|
-
- spec/run-files/runtime-linker-duplicate-definition-for-symbol.error
|
162
|
-
- spec/run-files/spec-failure.error
|
163
|
-
- spec/run-files/spec-pass.success
|
164
156
|
- spec/spec_helper.rb
|