guard-haskell 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|