casegen 2.0.0 → 3.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 +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +109 -0
- data/.ruby-version +1 -1
- data/Gemfile +3 -1
- data/Gemfile.lock +51 -6
- data/README.md +10 -119
- data/Rakefile +9 -7
- data/bin/casegen +2 -1
- data/casegen.gemspec +13 -9
- data/doc/bounding_box.rb +37 -0
- data/doc/cart.rb +43 -0
- data/doc/expect_only.rb +28 -0
- data/doc/pricing.rb +50 -0
- data/doc/ruby_array.rb +41 -0
- data/lib/case_gen/combination.rb +38 -0
- data/lib/case_gen/combo_matcher.rb +15 -0
- data/lib/case_gen/exclude_rule.rb +50 -0
- data/lib/case_gen/expect_rule.rb +24 -0
- data/lib/case_gen/generator.rb +40 -0
- data/lib/case_gen/output/exclude.rb +6 -0
- data/lib/case_gen/output/exclude_as_table.rb +13 -0
- data/lib/case_gen/output/exclude_as_text.rb +12 -0
- data/lib/case_gen/output/exclude_inline.rb +13 -0
- data/lib/case_gen/output/exclude_inline_footnotes.rb +20 -0
- data/lib/case_gen/output.rb +66 -0
- data/lib/case_gen/rule_description.rb +11 -0
- data/lib/case_gen/set.rb +16 -0
- data/lib/casegen.rb +15 -183
- data/spec/cart_sample_spec.rb +46 -0
- data/spec/case_gen/combination_spec.rb +11 -0
- data/spec/case_gen/exclude_rule_spec.rb +17 -0
- data/spec/exclude_as_table_spec.rb +39 -0
- data/spec/exclude_as_text_spec.rb +58 -0
- data/spec/exclude_inline_footnotes_spec.rb +58 -0
- data/spec/exclude_inline_spec.rb +50 -0
- data/spec/expect_only_spec.rb +30 -0
- data/spec/spec_helper.rb +113 -0
- metadata +101 -35
- data/.idea/encodings.xml +0 -5
- data/.idea/misc.xml +0 -5
- data/.idea/modules.xml +0 -9
- data/.idea/vcs.xml +0 -7
- data/doc/calc.sample.txt +0 -13
- data/doc/cart.sample.rb +0 -3
- data/doc/cart.sample.txt +0 -33
- data/doc/ruby_array.sample.rb +0 -26
- data/lib/agents/sets/enum/by.rb +0 -244
- data/lib/agents/sets/enum/cluster.rb +0 -164
- data/lib/agents/sets/enum/inject.rb +0 -50
- data/lib/agents/sets/enum/nest.rb +0 -117
- data/lib/agents/sets/enum/op.rb +0 -283
- data/lib/agents/sets/enum/pipe.rb +0 -160
- data/lib/agents/sets/enum/tree.rb +0 -442
- data/lib/agents/sets.rb +0 -313
- data/test/agents/console_output_test.rb +0 -27
- data/test/agents/sets.test.rb +0 -227
- data/test/agents_test.rb +0 -41
- data/test/casegen.tests.rb +0 -0
- data/test/parser_test.rb +0 -163
- data/test/test_helper.rb +0 -2
@@ -1,27 +0,0 @@
|
|
1
|
-
require_relative '../test_helper'
|
2
|
-
require_relative '../../lib/agents/sets.rb'
|
3
|
-
|
4
|
-
FakeAgent = Struct.new(:titles, :combinations)
|
5
|
-
|
6
|
-
include CLabs::CaseGen
|
7
|
-
|
8
|
-
class TestConsoleOutput < Minitest::Test
|
9
|
-
def test_simple_output
|
10
|
-
data = nil
|
11
|
-
agents = [
|
12
|
-
FakeAgent.new(["col a", "col b"], [[1, 2], [3, 4]])
|
13
|
-
]
|
14
|
-
sio = StringIO.new
|
15
|
-
ConsoleOutput.new(data, agents, sio)
|
16
|
-
expected = <<~_
|
17
|
-
+-------+-------+
|
18
|
-
| col a | col b |
|
19
|
-
+-------+-------+
|
20
|
-
| 1 | 2 |
|
21
|
-
| 3 | 4 |
|
22
|
-
+-------+-------+
|
23
|
-
|
24
|
-
_
|
25
|
-
assert_equal expected, sio.string
|
26
|
-
end
|
27
|
-
end
|
data/test/agents/sets.test.rb
DELETED
@@ -1,227 +0,0 @@
|
|
1
|
-
$LOAD_PATH << "#{__dir__}/../../lib/agents"
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'sets'
|
4
|
-
|
5
|
-
include CLabs::CaseGen
|
6
|
-
|
7
|
-
class TestParsing < Minitest::Test
|
8
|
-
def test_sets_default
|
9
|
-
data = <<~CASEDATA
|
10
|
-
bar: 1, 2, 3,456.98
|
11
|
-
foo list:a, b, c
|
12
|
-
CASEDATA
|
13
|
-
cases = Sets.new(data)
|
14
|
-
assert_equal(2, cases.sets.length)
|
15
|
-
|
16
|
-
assert_equal("bar", cases.sets[0].name)
|
17
|
-
assert_equal(["1", "2", "3,456.98"], cases.sets[0].data)
|
18
|
-
|
19
|
-
assert_equal("foo list", cases.sets[1].name)
|
20
|
-
assert_equal(["a", "b", "c"], cases.sets[1].data)
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_set_by_name_matching
|
24
|
-
# may seem obvious, but the regex matching used at one point would get confused when a name was reused in sets
|
25
|
-
sets = Sets.new("foo bar: 1, 2\nbar quux: 3, 4")
|
26
|
-
set = sets.set_by_name('bar quux')
|
27
|
-
assert_equal 'bar quux', set.name
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class TestCombinations < Minitest::Test
|
32
|
-
def test_combos_2_by_2
|
33
|
-
sets = Sets.new("a: 1, 2\nb:3, 4")
|
34
|
-
assert_equal([['1', '3'], ['1', '4'], ['2', '3'], ['2', '4']], sets.combinations)
|
35
|
-
assert_equal(['a', 'b'], sets.titles)
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_combos_2_by_3
|
39
|
-
sets = Sets.new("a: 1, 2\nb:3, 4, 5")
|
40
|
-
assert_equal([['1', '3'], ['1', '4'], ['1', '5'],
|
41
|
-
['2', '3'], ['2', '4'], ['2', '5']], sets.combinations)
|
42
|
-
assert_equal(['a', 'b'], sets.titles)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class TestRulesParsing < Minitest::Test
|
47
|
-
def test_rules_single
|
48
|
-
data = <<~RULES
|
49
|
-
exclude foo = bar
|
50
|
-
RULES
|
51
|
-
rules = Rules.new(data)
|
52
|
-
assert_equal(1, rules.length)
|
53
|
-
assert_equal(ExcludeRule, rules[0].class)
|
54
|
-
assert_equal("foo = bar", rules[0].criteria.to_s)
|
55
|
-
assert_equal("", rules[0].description)
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_rules_two
|
59
|
-
data = <<~RULES
|
60
|
-
exclude foo = bar
|
61
|
-
should foo equal bar, we want to exclude that combination
|
62
|
-
|
63
|
-
exclude bar = foo
|
64
|
-
as well, if bar equals foo,
|
65
|
-
that case has got to go
|
66
|
-
RULES
|
67
|
-
rules = Rules.new(data)
|
68
|
-
assert_equal(2, rules.length)
|
69
|
-
assert_equal(ExcludeRule, rules[0].class)
|
70
|
-
assert_equal("foo = bar", rules[0].criteria.to_s)
|
71
|
-
assert_equal("should foo equal bar, we want to exclude that combination", rules[0].description)
|
72
|
-
|
73
|
-
assert_equal(ExcludeRule, rules[1].class)
|
74
|
-
assert_equal("bar = foo", rules[1].criteria.to_s)
|
75
|
-
assert_equal("as well, if bar equals foo,\nthat case has got to go", rules[1].description)
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_exclude_rule_parsing
|
79
|
-
data = <<~RULES
|
80
|
-
exclude foo = bar
|
81
|
-
should foo equal bar, we want to exclude that combination
|
82
|
-
RULES
|
83
|
-
rule = ExcludeRule.new(data)
|
84
|
-
assert_equal("foo = bar", rule.criteria.to_s)
|
85
|
-
assert_equal(["foo"], rule.criteria.set_names)
|
86
|
-
assert_equal(["bar"], rule.criteria.set_values)
|
87
|
-
assert_equal("should foo equal bar, we want to exclude that combination", rule.description)
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_rules_set_name_not_found
|
92
|
-
sets = Sets.new("set.a: foo, bar\nset.b: fu, bahr")
|
93
|
-
data = <<~RULES
|
94
|
-
exclude set_a = bar AND set_b = barh
|
95
|
-
should foo equal bar, we want to exclude that combination
|
96
|
-
RULES
|
97
|
-
begin
|
98
|
-
Rules.new(data, [sets])
|
99
|
-
fail('should throw')
|
100
|
-
rescue ParserException => e
|
101
|
-
assert_equal("Invalid set name <set_a> in rule <set_a = bar AND set_b = barh>. Valid set names are <set.a, set.b>.", e.message)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_rules_set_value_not_found
|
106
|
-
sets = Sets.new("set a: foo, bar\nset b: fu, bahr")
|
107
|
-
data = <<~RULES
|
108
|
-
exclude set a = bar AND set b = barh
|
109
|
-
should foo equal bar, we want to exclude that combination
|
110
|
-
RULES
|
111
|
-
begin
|
112
|
-
Rules.new(data, [sets])
|
113
|
-
fail('should throw')
|
114
|
-
rescue ParserException => e
|
115
|
-
assert_equal("Invalid set value <barh> in rule <set a = bar AND set b = barh>. Valid set values for <set b> are <fu, bahr>.", e.message)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
class TestCriteria < Minitest::Test
|
120
|
-
def test_simple_equality
|
121
|
-
crit = Criteria.new("a = b")
|
122
|
-
assert_equal(['a'], crit.set_names)
|
123
|
-
assert_equal(['b'], crit.set_values)
|
124
|
-
assert_equal(true, crit.match({'a' => 'b'}))
|
125
|
-
assert_equal(false, crit.match({'a' => 'c'}))
|
126
|
-
assert_equal(false, crit.match({'b' => 'a'}))
|
127
|
-
assert_equal(true, crit.match({'a' => 'b', 'f' => 'g'}))
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_boolean_and
|
131
|
-
crit = Criteria.new("a = b AND c == d")
|
132
|
-
assert_equal(['a', 'c'], crit.set_names)
|
133
|
-
assert_equal(['b', 'd'], crit.set_values)
|
134
|
-
assert_equal(true, crit.match({'a' => 'b', 'c' => 'd'}))
|
135
|
-
assert_equal(false, crit.match({'a' => 'd', 'c' => 'b'}))
|
136
|
-
assert_equal(true, crit.match({'c' => 'd', 'a' => 'b'}))
|
137
|
-
assert_equal(false, crit.match({'a' => 'b'}))
|
138
|
-
assert_equal(false, crit.match({'c' => 'd'}))
|
139
|
-
assert_equal(false, crit.match({'a' => 'b', 'd' => 'c'}))
|
140
|
-
assert_equal(false, crit.match({'c' => 'd', 'b' => 'a'}))
|
141
|
-
|
142
|
-
# not case sensitive
|
143
|
-
assert_equal(false, crit.match({'A' => 'b', 'c' => 'd'}))
|
144
|
-
assert_equal(false, crit.match({'a' => 'B', 'c' => 'd'}))
|
145
|
-
assert_equal(false, crit.match({'a' => 'b', 'C' => 'd'}))
|
146
|
-
assert_equal(false, crit.match({'a' => 'b', 'c' => 'D'}))
|
147
|
-
end
|
148
|
-
|
149
|
-
def test_invalid_boolean_and
|
150
|
-
begin
|
151
|
-
Criteria.new("a = b AND a = d")
|
152
|
-
fail("should throw")
|
153
|
-
rescue ParserException => e
|
154
|
-
assert_equal("Rule cannot have the same set <a> equal to different values <b, d>", e.message)
|
155
|
-
end
|
156
|
-
|
157
|
-
begin
|
158
|
-
Criteria.new("a = b AND a = d AND a = c")
|
159
|
-
fail("should throw")
|
160
|
-
rescue ParserException => e
|
161
|
-
# in this case, the exception is figured out before the a = c can be parsed
|
162
|
-
assert_equal("Rule cannot have the same set <a> equal to different values <b, d>", e.message)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
class TestRulesOnSets < Minitest::Test
|
168
|
-
def test_simple
|
169
|
-
sets = Sets.new("a: 1, 2\nb: 3, 4")
|
170
|
-
rules = Rules.new("exclude a = 1\nexclude b=4", [sets])
|
171
|
-
assert_equal([['2', '3']], rules.combinations)
|
172
|
-
assert_equal(['a', 'b'], rules.titles)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
class TestRubyCaseArray < Minitest::Test
|
177
|
-
def test_default_case_name
|
178
|
-
sets = Sets.new("a: 1, 2\nb:3, 4")
|
179
|
-
out = MockStdOut.new
|
180
|
-
RubyArrayOutput.new("", [sets], out)
|
181
|
-
expected = <<~TEXT
|
182
|
-
Case = Struct.new(:a, :b)
|
183
|
-
|
184
|
-
cases = [Case.new("1", "3"),
|
185
|
-
Case.new("1", "4"),
|
186
|
-
Case.new("2", "3"),
|
187
|
-
Case.new("2", "4")]
|
188
|
-
TEXT
|
189
|
-
assert_equal(expected, out.to_s)
|
190
|
-
end
|
191
|
-
|
192
|
-
def test_specified_case_name
|
193
|
-
sets = Sets.new("a: 1, 2\nb:3, 4")
|
194
|
-
out = MockStdOut.new
|
195
|
-
RubyArrayOutput.new("DataSubmitCase", [sets], out)
|
196
|
-
expected = <<~TEXT
|
197
|
-
DataSubmitCase = Struct.new(:a, :b)
|
198
|
-
|
199
|
-
cases = [DataSubmitCase.new("1", "3"),
|
200
|
-
DataSubmitCase.new("1", "4"),
|
201
|
-
DataSubmitCase.new("2", "3"),
|
202
|
-
DataSubmitCase.new("2", "4")]
|
203
|
-
TEXT
|
204
|
-
assert_equal(expected, out.to_s)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
class MockStdOut
|
209
|
-
def initialize
|
210
|
-
@s = ''
|
211
|
-
end
|
212
|
-
|
213
|
-
def puts(s)
|
214
|
-
@s << s << "\n"
|
215
|
-
end
|
216
|
-
|
217
|
-
def print(s)
|
218
|
-
@s << s
|
219
|
-
end
|
220
|
-
|
221
|
-
def to_s
|
222
|
-
@s
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
|
data/test/agents_test.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
$LOAD_PATH << "#{__dir__}/../lib"
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'casegen'
|
4
|
-
|
5
|
-
include CLabs::CaseGen
|
6
|
-
|
7
|
-
class TestAgents < Minitest::Test
|
8
|
-
def setup
|
9
|
-
Agents.instance.clear
|
10
|
-
end
|
11
|
-
|
12
|
-
def teardown
|
13
|
-
Agents.instance.clear
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_register
|
17
|
-
assert_equal(0, Agents.instance.length)
|
18
|
-
begin
|
19
|
-
Agents.instance.register("phil")
|
20
|
-
fail("should have thrown")
|
21
|
-
rescue AgentException
|
22
|
-
# expected -- can't register a non subclass
|
23
|
-
end
|
24
|
-
|
25
|
-
Agents.instance.register(SampleAgent)
|
26
|
-
assert_equal(1, Agents.instance.length)
|
27
|
-
Agents.instance.each do |ag| assert_equal(SampleAgent, ag) end
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_get_agent_by_id
|
31
|
-
Agents.instance.register(SampleAgent)
|
32
|
-
result = Agents.instance.get_agent_by_id("sample")
|
33
|
-
assert_equal(SampleAgent, result)
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_id_registered
|
37
|
-
assert_equal(false, Agents.instance.id_registered?(SampleAgent.agent_id))
|
38
|
-
Agents.instance.register(SampleAgent)
|
39
|
-
assert_equal(true, Agents.instance.id_registered?(SampleAgent.agent_id))
|
40
|
-
end
|
41
|
-
end
|
data/test/casegen.tests.rb
DELETED
File without changes
|
data/test/parser_test.rb
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
$LOAD_PATH << "#{__dir__}/../lib"
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'casegen'
|
4
|
-
|
5
|
-
include CLabs::CaseGen
|
6
|
-
|
7
|
-
class SampleAgent < Agent
|
8
|
-
def SampleAgent.agent_id
|
9
|
-
"sample"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Foo < Agent
|
14
|
-
def Foo.agent_id
|
15
|
-
"foo"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class TestParser < Minitest::Test
|
20
|
-
def setup
|
21
|
-
Agents.instance.register(SampleAgent)
|
22
|
-
Agents.instance.register(Foo)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_parse
|
26
|
-
data = <<~CASEDATA
|
27
|
-
sample
|
28
|
-
------
|
29
|
-
sample_data
|
30
|
-
|
31
|
-
foo
|
32
|
-
---
|
33
|
-
sample_data
|
34
|
-
|
35
|
-
sample(foo, sample)
|
36
|
-
------------
|
37
|
-
sample_data
|
38
|
-
plus
|
39
|
-
some extra
|
40
|
-
CASEDATA
|
41
|
-
|
42
|
-
parser = Parser.new(data)
|
43
|
-
assert_equal(3, parser.agents.length)
|
44
|
-
|
45
|
-
sample_a = parser.agents[0]
|
46
|
-
foo = parser.agents[1]
|
47
|
-
sample_b = parser.agents[2]
|
48
|
-
assert_equal(SampleAgent, sample_a.class)
|
49
|
-
assert_equal("sample_data", sample_a.data)
|
50
|
-
assert_equal([], sample_a.reference_agents)
|
51
|
-
|
52
|
-
assert_equal(Foo, foo.class)
|
53
|
-
assert_equal("sample_data", foo.data)
|
54
|
-
assert_equal([], foo.reference_agents)
|
55
|
-
|
56
|
-
assert_equal(SampleAgent, sample_b.class)
|
57
|
-
assert_equal("sample_data\nplus\n some extra", sample_b.data)
|
58
|
-
assert_equal([foo, sample_a], sample_b.reference_agents)
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_parse_no_sets
|
62
|
-
data = <<~CASEDATA
|
63
|
-
CASEDATA
|
64
|
-
|
65
|
-
parser = Parser.new(data)
|
66
|
-
assert_equal(0, parser.agents.length)
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_parse_agent_with_missing_hyphen_line
|
70
|
-
data = <<~CASEDATA
|
71
|
-
sample
|
72
|
-
|
73
|
-
sample_data
|
74
|
-
CASEDATA
|
75
|
-
|
76
|
-
Parser.new(data)
|
77
|
-
fail("should have thrown")
|
78
|
-
rescue ParserException => e
|
79
|
-
assert_equal("Expected hyphen line after the agent declaration for <SampleAgent>", e.message)
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_parse_agent_name_without_dash_delimiter
|
83
|
-
data = <<~CASEDATA
|
84
|
-
sample
|
85
|
-
CASEDATA
|
86
|
-
|
87
|
-
Parser.new(data)
|
88
|
-
fail("should have thrown")
|
89
|
-
rescue ParserException => e
|
90
|
-
assert_equal("Expected hyphen line after the agent declaration for <SampleAgent>", e.message)
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_parse_agent_name_without_dash_delimiter_and_empty_line_to_start
|
94
|
-
data = <<~CASEDATA
|
95
|
-
|
96
|
-
sample
|
97
|
-
CASEDATA
|
98
|
-
|
99
|
-
Parser.new(data)
|
100
|
-
fail("should have thrown")
|
101
|
-
rescue ParserException => e
|
102
|
-
assert_equal("Expected hyphen line after the agent declaration for <SampleAgent>", e.message)
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_parse_just_agent_with_underline
|
106
|
-
data = <<~CASEDATA
|
107
|
-
sample
|
108
|
-
-
|
109
|
-
CASEDATA
|
110
|
-
|
111
|
-
parser = Parser.new(data)
|
112
|
-
assert_equal(1, parser.agents.length)
|
113
|
-
sample = parser.agents[0]
|
114
|
-
assert_equal(SampleAgent, sample.class)
|
115
|
-
assert_equal("", sample.data)
|
116
|
-
assert_equal([], sample.reference_agents)
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_parse_just_agent_with_empty_data
|
120
|
-
data = <<~CASEDATA
|
121
|
-
sample
|
122
|
-
-
|
123
|
-
|
124
|
-
CASEDATA
|
125
|
-
|
126
|
-
parser = Parser.new(data)
|
127
|
-
assert_equal(1, parser.agents.length)
|
128
|
-
sample = parser.agents[0]
|
129
|
-
assert_equal(SampleAgent, sample.class)
|
130
|
-
assert_equal("", sample.data)
|
131
|
-
assert_equal([], sample.reference_agents)
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_parse_invalid_agent
|
135
|
-
data = <<~CASEDATA
|
136
|
-
sermple
|
137
|
-
------
|
138
|
-
sample_data
|
139
|
-
CASEDATA
|
140
|
-
|
141
|
-
begin
|
142
|
-
Parser.new(data)
|
143
|
-
fail("should throw")
|
144
|
-
rescue ParserException
|
145
|
-
# expected
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def test_parse_invalid_referenced_agent
|
150
|
-
data = <<~CASEDATA
|
151
|
-
sample(fu)
|
152
|
-
------
|
153
|
-
sample_data
|
154
|
-
CASEDATA
|
155
|
-
|
156
|
-
begin
|
157
|
-
Parser.new(data)
|
158
|
-
fail("should throw")
|
159
|
-
rescue ParserException
|
160
|
-
# expected
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|