bahuvrihi-tap 0.10.6 → 0.10.7
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rap +13 -5
- data/lib/tap.rb +0 -4
- data/lib/tap/app.rb +10 -138
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/declarations.rb +201 -0
- data/lib/tap/env.rb +10 -2
- data/lib/tap/exe.rb +2 -2
- data/lib/tap/generator/generators/root/templates/Rakefile +1 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
- data/lib/tap/spec.rb +38 -63
- data/lib/tap/spec/adapter.rb +8 -31
- data/lib/tap/spec/inheritable_class_test_root.rb +9 -0
- data/lib/tap/support/audit.rb +0 -2
- data/lib/tap/support/combinator.rb +83 -31
- data/lib/tap/support/configurable_class.rb +7 -7
- data/lib/tap/support/{dependable.rb → dependencies.rb} +9 -7
- data/lib/tap/support/executable.rb +226 -19
- data/lib/tap/support/gems/rake.rb +6 -3
- data/lib/tap/support/join.rb +87 -0
- data/lib/tap/support/joins.rb +13 -0
- data/lib/tap/support/joins/fork.rb +18 -0
- data/lib/tap/support/joins/merge.rb +20 -0
- data/lib/tap/support/joins/sequence.rb +21 -0
- data/lib/tap/support/joins/switch.rb +23 -0
- data/lib/tap/support/joins/sync_merge.rb +57 -0
- data/lib/tap/support/lazydoc/document.rb +10 -0
- data/lib/tap/support/node.rb +58 -0
- data/lib/tap/support/parser.rb +379 -0
- data/lib/tap/support/schema.rb +350 -0
- data/lib/tap/support/tdoc.rb +5 -0
- data/lib/tap/support/validation.rb +2 -0
- data/lib/tap/task.rb +26 -61
- data/lib/tap/test.rb +9 -82
- data/lib/tap/test/assertions.rb +38 -0
- data/lib/tap/test/extensions.rb +78 -0
- data/lib/tap/test/{file_methods.rb → file_test.rb} +64 -37
- data/lib/tap/test/{file_methods_class.rb → file_test_class.rb} +2 -2
- data/lib/tap/test/regexp_escape.rb +87 -0
- data/lib/tap/test/script_test.rb +46 -0
- data/lib/tap/test/script_tester.rb +109 -0
- data/lib/tap/test/{subset_methods.rb → subset_test.rb} +9 -9
- data/lib/tap/test/{subset_methods_class.rb → subset_test_class.rb} +22 -14
- data/lib/tap/test/{tap_methods.rb → tap_test.rb} +43 -6
- data/lib/tap/test/utils.rb +6 -3
- metadata +27 -24
- data/lib/tap/parser.rb +0 -619
- data/lib/tap/spec/file_methods.rb +0 -16
- data/lib/tap/spec/file_methods_class.rb +0 -13
- data/lib/tap/spec/subset_methods.rb +0 -14
- data/lib/tap/support/batchable.rb +0 -47
- data/lib/tap/support/batchable_class.rb +0 -107
- data/lib/tap/support/declarations.rb +0 -131
- data/lib/tap/support/lazydoc/declaration.rb +0 -20
- data/lib/tap/support/parsers/base.rb +0 -81
- data/lib/tap/support/parsers/server.rb +0 -113
- data/lib/tap/test/script_methods.rb +0 -75
- data/lib/tap/test/script_methods/regexp_escape.rb +0 -94
- data/lib/tap/test/script_methods/script_test.rb +0 -109
- data/lib/tap/workflow.rb +0 -161
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'tap/test/subset_methods'
|
2
|
-
require 'tap/test/script_methods/script_test'
|
3
|
-
|
4
|
-
module Tap
|
5
|
-
module Test
|
6
|
-
module ScriptMethods
|
7
|
-
|
8
|
-
def self.included(base)
|
9
|
-
super
|
10
|
-
base.send(:include, Tap::Test::SubsetMethods)
|
11
|
-
end
|
12
|
-
|
13
|
-
def assert_output_equal(a, b, msg=nil)
|
14
|
-
a = a[1..-1] if a[0] == ?\n
|
15
|
-
if a == b
|
16
|
-
assert true
|
17
|
-
else
|
18
|
-
flunk %Q{
|
19
|
-
#{msg}
|
20
|
-
==================== expected output ====================
|
21
|
-
#{Utils.whitespace_escape(a)}
|
22
|
-
======================== but was ========================
|
23
|
-
#{Utils.whitespace_escape(b)}
|
24
|
-
=========================================================
|
25
|
-
}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def assert_alike(a, b, msg=nil)
|
30
|
-
if b =~ a
|
31
|
-
assert true
|
32
|
-
else
|
33
|
-
flunk %Q{
|
34
|
-
#{msg}
|
35
|
-
================= expected output like ==================
|
36
|
-
#{a}
|
37
|
-
======================== but was ========================
|
38
|
-
#{Utils.whitespace_escape(b)}
|
39
|
-
=========================================================
|
40
|
-
}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def default_command_path
|
45
|
-
nil
|
46
|
-
end
|
47
|
-
|
48
|
-
def script_test(test_dir=method_root.root)
|
49
|
-
subset_test("SCRIPT", "s") do
|
50
|
-
Tap::Root.chdir(test_dir, true) do
|
51
|
-
Utils.with_argv do
|
52
|
-
puts "\n# == #{method_name}"
|
53
|
-
|
54
|
-
cmd = ScriptTest.new(default_command_path, env('stepwise')) do |expected, result, msg|
|
55
|
-
case expected
|
56
|
-
when String
|
57
|
-
assert_output_equal(expected, result, msg)
|
58
|
-
when Regexp
|
59
|
-
assert_alike(expected, result, msg)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
yield(cmd)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'tap/test/utils'
|
2
|
-
|
3
|
-
module Tap
|
4
|
-
module Test
|
5
|
-
module ScriptMethods
|
6
|
-
|
7
|
-
# RegexpEscape is a subclass of regexp that escapes all but the text in a
|
8
|
-
# special escape sequence. This allows the creation of complex regexps
|
9
|
-
# to match, for instance, console output.
|
10
|
-
#
|
11
|
-
# The RegexpEscape.escape (or equivalently the quote) method does the
|
12
|
-
# work; all regexp-active characters are escaped except for characters
|
13
|
-
# enclosed by ':.' and '.:' delimiters.
|
14
|
-
#
|
15
|
-
# RegexpEscape.escape('reg[exp]+ chars. are(quoted)') # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
|
16
|
-
# RegexpEscape.escape('these are not: :.a(b*)c.:') # => 'these\ are\ not:\ a(b*)c'
|
17
|
-
#
|
18
|
-
# In addition, all-period regexps are automatically upgraded to '.*?';
|
19
|
-
# use the '.{n}' notation to specify n arbitrary characters.
|
20
|
-
#
|
21
|
-
# RegexpEscape.escape('_:..:_:...:_:....:') # => '_.*?_.*?_.*?'
|
22
|
-
# RegexpEscape.escape(':..{1}.:') # => '.{1}'
|
23
|
-
#
|
24
|
-
# RegexpEscape instances are initialized using the escaped input string
|
25
|
-
# and format the original string upon to_s, to simplify their use in
|
26
|
-
# tests.
|
27
|
-
#
|
28
|
-
# r = RegexpEscape.new %q{
|
29
|
-
# a multiline
|
30
|
-
# :...:
|
31
|
-
# example}
|
32
|
-
#
|
33
|
-
# r =~ %q{
|
34
|
-
# a multiline
|
35
|
-
# matching
|
36
|
-
# example} # => true
|
37
|
-
#
|
38
|
-
# r !~ %q{
|
39
|
-
# a failing multiline
|
40
|
-
# example} # => true
|
41
|
-
#
|
42
|
-
# r.to_s
|
43
|
-
# # => %q{\n
|
44
|
-
# # a multiline\n
|
45
|
-
# # :...:\n
|
46
|
-
# # example}
|
47
|
-
#
|
48
|
-
class RegexpEscape < Regexp
|
49
|
-
|
50
|
-
# matches the escape sequence
|
51
|
-
ESCAPE_SEQUENCE = /:\..*?\.:/
|
52
|
-
|
53
|
-
class << self
|
54
|
-
|
55
|
-
# Escapes regexp-active characters in str, except for character
|
56
|
-
# delimited by ':.' and '.:'. See the class description for
|
57
|
-
# details.
|
58
|
-
def escape(str)
|
59
|
-
substituents = []
|
60
|
-
str.scan(ESCAPE_SEQUENCE) do
|
61
|
-
regexp_str = $&[2...-2]
|
62
|
-
regexp_str = ".*?" if regexp_str =~ /^\.*$/
|
63
|
-
substituents << regexp_str
|
64
|
-
end
|
65
|
-
substituents << ""
|
66
|
-
|
67
|
-
splits = str.split(ESCAPE_SEQUENCE).collect do |split|
|
68
|
-
super(split)
|
69
|
-
end
|
70
|
-
splits << "" if splits.empty?
|
71
|
-
|
72
|
-
splits.zip(substituents).to_a.flatten.join
|
73
|
-
end
|
74
|
-
|
75
|
-
# Same as escape.
|
76
|
-
def quote(str)
|
77
|
-
escape(str)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def initialize(str)
|
82
|
-
super(RegexpEscape.escape(str))
|
83
|
-
@original_str = str
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns the original string for self, but with
|
87
|
-
# whitespace escaped as in Utils#whitespace_escape
|
88
|
-
def to_s
|
89
|
-
Utils.whitespace_escape(@original_str)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'tap/support/shell_utils'
|
2
|
-
require 'tap/test/script_methods/regexp_escape'
|
3
|
-
|
4
|
-
module Tap
|
5
|
-
module Test
|
6
|
-
module ScriptMethods
|
7
|
-
class ScriptTest
|
8
|
-
include Tap::Support::ShellUtils
|
9
|
-
|
10
|
-
# The command path for self, returned by to_s
|
11
|
-
attr_accessor :command_path
|
12
|
-
|
13
|
-
# An array of (command, message, expected, validation)
|
14
|
-
# entries, representing the accumulated test commands.
|
15
|
-
attr_reader :commands
|
16
|
-
|
17
|
-
attr_reader :stepwise, :run_block
|
18
|
-
|
19
|
-
def initialize(command_path=nil, stepwise=false, &run_block)
|
20
|
-
@command_path = command_path
|
21
|
-
@commands = []
|
22
|
-
@stepwise = stepwise
|
23
|
-
@run_block = run_block
|
24
|
-
end
|
25
|
-
|
26
|
-
# Splits the input string, collecting single-line commands
|
27
|
-
# and expected results. Nil will be used as the expected
|
28
|
-
# result if the result is whitespace, or not present.
|
29
|
-
#
|
30
|
-
# cmd = ScriptTest.new
|
31
|
-
# cmd.split %Q{
|
32
|
-
# % command one
|
33
|
-
# expected text for command one
|
34
|
-
# % command two
|
35
|
-
# % command three
|
36
|
-
# expected text for command three
|
37
|
-
# }
|
38
|
-
# # => [
|
39
|
-
# # ["command one", "expected text for command one\n"],
|
40
|
-
# # ["command two", nil],
|
41
|
-
# # ["command three", "expected text for command three\n"]]
|
42
|
-
#
|
43
|
-
def split(str)
|
44
|
-
str.split(/^%\s*/).collect do |s|
|
45
|
-
next(nil) if s.strip.empty?
|
46
|
-
command, expected = s.split(/\n/, 2)
|
47
|
-
expected = nil if expected && expected.strip.empty?
|
48
|
-
[command.strip, expected]
|
49
|
-
end.compact
|
50
|
-
end
|
51
|
-
|
52
|
-
def time(msg, command)
|
53
|
-
commands << [command, msg, nil, nil]
|
54
|
-
end
|
55
|
-
|
56
|
-
def check(msg, command, use_regexp_escapes=true, &validation)
|
57
|
-
new_commands = split(command)
|
58
|
-
commands = new_commands.collect do |cmd, expected|
|
59
|
-
expected = RegexpEscape.new(expected) if expected && use_regexp_escapes
|
60
|
-
[cmd, msg, expected, validation]
|
61
|
-
end
|
62
|
-
|
63
|
-
run(commands)
|
64
|
-
end
|
65
|
-
|
66
|
-
def match(msg, command, regexp=nil, &validation)
|
67
|
-
new_commands = split(command)
|
68
|
-
commands = new_commands.collect do |cmd, expected|
|
69
|
-
raise "expected text specified in match command" unless expected == nil
|
70
|
-
[cmd, msg, regexp, validation]
|
71
|
-
end
|
72
|
-
|
73
|
-
run(commands)
|
74
|
-
end
|
75
|
-
|
76
|
-
def run(commands)
|
77
|
-
commands.each_with_index do |(cmd, msg, expected, validation), i|
|
78
|
-
start = Time.now
|
79
|
-
result = capture_sh(cmd) {|ok, status, tempfile_path| }
|
80
|
-
elapsed = Time.now - start
|
81
|
-
|
82
|
-
cmd_msg = commands.length > 1 ? "#{msg} (#{i})" : msg
|
83
|
-
run_block.call(expected, result, %Q{#{cmd_msg}\n% #{cmd}}) if expected
|
84
|
-
validation.call(result) if validation
|
85
|
-
|
86
|
-
if stepwise
|
87
|
-
print %Q{
|
88
|
-
------------------------------------
|
89
|
-
%s
|
90
|
-
> %s
|
91
|
-
%s
|
92
|
-
Time Elapsed: %.3fs} % [cmd_msg, cmd, result, elapsed]
|
93
|
-
|
94
|
-
print "\nContinue? (y/n): "
|
95
|
-
break if gets.strip =~ /^no?$/i
|
96
|
-
else
|
97
|
-
puts "%.3fs : %s" % [elapsed, cmd_msg]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Returns the command path.
|
103
|
-
def to_s
|
104
|
-
command_path
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
data/lib/tap/workflow.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
module Tap
|
2
|
-
|
3
|
-
# Workflow is a specialized type of Task allowing the encapsulation and reuse of
|
4
|
-
# workflow logic. Workflows are still under construction.
|
5
|
-
#
|
6
|
-
# === Workflow Definition
|
7
|
-
#
|
8
|
-
# During initialization, Workflow executes the workflow method (by default the
|
9
|
-
# block provided to Workflow.new) to define the workflow logic. This method
|
10
|
-
# defines one or more entry_points and zero or more exit points, as well as
|
11
|
-
# the internal logic for the workflow.
|
12
|
-
#
|
13
|
-
# Workflow.new do |w|
|
14
|
-
# factor = w.config[:factor] || 1
|
15
|
-
#
|
16
|
-
# t1 = Task.new {|task, input| input += 1 }
|
17
|
-
# t2 = Task.new {|task, input| input += 10 }
|
18
|
-
# t3 = Task.new {|task, input| input *= factor }
|
19
|
-
#
|
20
|
-
# w.app.sequence(t1, t2, t3)
|
21
|
-
# w.entry_point = t1
|
22
|
-
# w.exit_point = t3
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# Or equivalently:
|
26
|
-
#
|
27
|
-
# class SimpleSequence < Workflow
|
28
|
-
# config :factor, 1
|
29
|
-
#
|
30
|
-
# def workflow
|
31
|
-
# t1 = Task.new {|task, input| input += 5 }
|
32
|
-
# t2 = Task.new {|task, input| input += 3 }
|
33
|
-
# t3 = Task.new {|task, input| input *= factor }
|
34
|
-
#
|
35
|
-
# app.sequence(t1, t2, t3)
|
36
|
-
# self.entry_point = t1
|
37
|
-
# self.exit_point = t3
|
38
|
-
# end
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# To facilitate the specification of entry and exit points, workflow
|
42
|
-
# can accomodate either single-task assignments or a collection. By
|
43
|
-
# default both are hashes, but they can be reassigned:
|
44
|
-
#
|
45
|
-
# Workflow.new do |w|
|
46
|
-
# w.entry_point.class # => Hash
|
47
|
-
# w.exit_point.class # => Hash
|
48
|
-
# w.entry_point[:main] = Task.new
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# Workflow.new {|w| w.entry_point = Task.new }
|
52
|
-
# Workflow.new {|w| w.entry_point = [Task.new, Task.new] }
|
53
|
-
#
|
54
|
-
# Access to the group of entry/exit points is standardized to an
|
55
|
-
# array via the entry_points and exit_points methods.
|
56
|
-
#
|
57
|
-
# === Workflow Behavior
|
58
|
-
#
|
59
|
-
# The entry points act as an enque batch; when the workflow is enqued, the
|
60
|
-
# entry points are enqued. The exit points act as an on_complete batch; their
|
61
|
-
# on_complete blocks are set for workflow.on_complete.
|
62
|
-
#
|
63
|
-
# w = SimpleSequence.new
|
64
|
-
# w.enq(0)
|
65
|
-
# app.run
|
66
|
-
# app.results(w.exit_points) # => [8]
|
67
|
-
#
|
68
|
-
# The batching of entry and exit points is distinct from workflow.batch itself.
|
69
|
-
# Workflows can be batched like Tasks, such that all entry points from all
|
70
|
-
# workflows in a batch are enqued at once.
|
71
|
-
#
|
72
|
-
# w1 = SimpleSequence.new nil, :factor => 1
|
73
|
-
# w2 = w1.initialize_batch_obj nil, :factor => -1
|
74
|
-
#
|
75
|
-
# w1.enq(0)
|
76
|
-
# app.run
|
77
|
-
# app.results(w1.exit_points, w2.exit_points)) # => [8, -8]
|
78
|
-
#
|
79
|
-
class Workflow < Task
|
80
|
-
|
81
|
-
# The entry point for self.
|
82
|
-
attr_accessor :entry_point
|
83
|
-
|
84
|
-
# The exit point for self.
|
85
|
-
attr_accessor :exit_point
|
86
|
-
|
87
|
-
# Creates a new Task with the specified attributes.
|
88
|
-
def initialize(config={}, name=nil, app=App.instance, &task_block)
|
89
|
-
super
|
90
|
-
initialize_workflow
|
91
|
-
end
|
92
|
-
|
93
|
-
# Initializes a new batch object, running workflow to set the
|
94
|
-
# instance-specific entry/exit points. Raises an error if
|
95
|
-
# no entry points are defined.
|
96
|
-
def initialize_copy(orig)
|
97
|
-
super
|
98
|
-
initialize_workflow
|
99
|
-
end
|
100
|
-
|
101
|
-
def initialize_workflow
|
102
|
-
@entry_point = {}
|
103
|
-
@exit_point = {}
|
104
|
-
workflow
|
105
|
-
end
|
106
|
-
|
107
|
-
# Returns an array of entry points, determined from entry_point.
|
108
|
-
def entry_points
|
109
|
-
case @entry_point
|
110
|
-
when Hash then @entry_point.values
|
111
|
-
when Support::Executable then [@entry_point]
|
112
|
-
when Array then @entry_point
|
113
|
-
when nil then []
|
114
|
-
else raise "unable to determine entry points from entry_point: #{@entry_point}"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Returns an array of exit points, determined from exit_point.
|
119
|
-
def exit_points
|
120
|
-
case @exit_point
|
121
|
-
when Hash then @exit_point.values
|
122
|
-
when Support::Executable then [@exit_point]
|
123
|
-
when Array then @exit_point
|
124
|
-
when nil then []
|
125
|
-
else raise "unable to determine exit points from exit_point: #{@exit_point}"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# Enqueues all entry points for self and self.batch to app
|
130
|
-
# with the inputs. The number of inputs provided should match
|
131
|
-
# the number of inputs required by all the entry points;
|
132
|
-
# if the entry points have different input requirements, they
|
133
|
-
# have to be enqued separately.
|
134
|
-
def unbatched_enq(*inputs)
|
135
|
-
entry_points.each do |task|
|
136
|
-
app.enq(task, *inputs)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Sets the on_complete_block for all exit points for self and
|
141
|
-
# self.batch. Use unbatched_on_complete to set the on_complete_block
|
142
|
-
# for just self.exit_points.
|
143
|
-
def unbatched_on_complete(override=false, &block)
|
144
|
-
exit_points.each do |task|
|
145
|
-
task.on_complete(override, &block)
|
146
|
-
end
|
147
|
-
self
|
148
|
-
end
|
149
|
-
|
150
|
-
# The workflow definition method. By default workflow
|
151
|
-
# simply calls the task_block. In subclasses, workflow
|
152
|
-
# should be overridden to provide the workflow definition.
|
153
|
-
def workflow
|
154
|
-
task_block.call(self) if task_block
|
155
|
-
end
|
156
|
-
|
157
|
-
def process(*inputs)
|
158
|
-
enq(*inputs)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|