casegen 1.3.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.
- data/bin/casegen +11 -0
- data/src/agents/sets.rb +336 -0
- data/src/agents/sets/enum/by.rb +244 -0
- data/src/agents/sets/enum/cluster.rb +164 -0
- data/src/agents/sets/enum/inject.rb +50 -0
- data/src/agents/sets/enum/install.rb +73 -0
- data/src/agents/sets/enum/nest.rb +117 -0
- data/src/agents/sets/enum/op.rb +283 -0
- data/src/agents/sets/enum/pipe.rb +160 -0
- data/src/agents/sets/enum/tree.rb +442 -0
- data/src/calc.sample.txt +13 -0
- data/src/cart.sample.txt +33 -0
- data/src/casegen.rb +191 -0
- data/src/ruby_array.sample.txt +20 -0
- metadata +66 -0
data/src/calc.sample.txt
ADDED
data/src/cart.sample.txt
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
sets
|
2
|
+
------------
|
3
|
+
payment: Credit, Check, Online Bank
|
4
|
+
amount: 100, 1,000, 10,000
|
5
|
+
shipping: Ground, Air
|
6
|
+
ship to country: US, Outside US
|
7
|
+
bill to country: US, Outside US
|
8
|
+
|
9
|
+
|
10
|
+
rules(sets)
|
11
|
+
---------------------------
|
12
|
+
# Comments supported
|
13
|
+
exclude shipping = Ground AND ship to country = Outside US
|
14
|
+
Our ground shipper will only ship things within the US.
|
15
|
+
|
16
|
+
# Single or double equals sign supported - they're synonymous
|
17
|
+
exclude payment = Check AND bill to country == Outside US
|
18
|
+
Our bank will not accept checks written from banks outside the US.
|
19
|
+
|
20
|
+
#[Complex booleans not supported yet]
|
21
|
+
#exclude payment = Online Bank AND (amount == 1,000 OR amount = 10,000)
|
22
|
+
exclude payment = Online Bank AND amount == 1,000
|
23
|
+
exclude payment = Online Bank AND amount == 10,000
|
24
|
+
While the online bank will process amounts > $1,000, we've experienced
|
25
|
+
occasional problems with their services and have had to write off some
|
26
|
+
transactions, so we no longer allow this payment option for amounts greater
|
27
|
+
than $1,000
|
28
|
+
|
29
|
+
exclude ship to country = US AND bill to country = Outside US
|
30
|
+
If we're shipping to the US, billing party cannot be outside US
|
31
|
+
|
32
|
+
console(rules)
|
33
|
+
----------
|
data/src/casegen.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class Fixnum
|
4
|
+
def even?
|
5
|
+
self.divmod(2)[1] == 0
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class String
|
10
|
+
def outdent
|
11
|
+
a = $1 if match(/\A(\s*)(.*\n)(?:\1.*\n|\n)*\z/)
|
12
|
+
gsub(/^#{a}/, '')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module CLabs
|
17
|
+
module CaseGen
|
18
|
+
class AgentException < Exception
|
19
|
+
end
|
20
|
+
|
21
|
+
class Agent # base class
|
22
|
+
attr_reader :data, :reference_agents
|
23
|
+
|
24
|
+
def initialize(data, agents)
|
25
|
+
@data = data
|
26
|
+
@reference_agents = agents
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Agents
|
31
|
+
include Singleton
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
clear
|
35
|
+
end
|
36
|
+
|
37
|
+
def register(agent)
|
38
|
+
if agent.class == Class && agent.ancestors.include?(Agent)
|
39
|
+
@agents << agent
|
40
|
+
else
|
41
|
+
raise AgentException.new("To register an agent, you must pass in a Class instance that's a subclass of Agent")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(methid, *args, &block)
|
46
|
+
@agents.send(methid, *args, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_agent_by_id(id)
|
50
|
+
@agents.each do |agent|
|
51
|
+
return agent if agent.agent_id =~ /#{id}/i
|
52
|
+
end
|
53
|
+
# rather than return nil and allow the client to get bumfuzzled if
|
54
|
+
# they forget to check for nil, let's blow up and tell them how to
|
55
|
+
# not let it happen again
|
56
|
+
raise AgentException.new("Requested an agent that does not exist. You can query for existance with .id_registered?")
|
57
|
+
end
|
58
|
+
|
59
|
+
def id_registered?(id)
|
60
|
+
begin
|
61
|
+
get_agent_by_id(id)
|
62
|
+
return true
|
63
|
+
rescue AgentException
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# removes all registered agents
|
69
|
+
def clear
|
70
|
+
@agents = []
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ParserException < Exception
|
75
|
+
end
|
76
|
+
|
77
|
+
class Parser
|
78
|
+
attr_reader :agents
|
79
|
+
|
80
|
+
def initialize(data)
|
81
|
+
@data = data
|
82
|
+
@agents = []
|
83
|
+
parse
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse
|
87
|
+
lines = @data.split(/\n/)
|
88
|
+
while !lines.empty?
|
89
|
+
line = lines.shift
|
90
|
+
next if line.strip.empty?
|
91
|
+
|
92
|
+
data = nil
|
93
|
+
agent_class, reference_agents = parse_agent(line)
|
94
|
+
|
95
|
+
next_line = lines.shift
|
96
|
+
if next_line =~ /^-+/
|
97
|
+
data = parse_data(lines).join("\n")
|
98
|
+
else
|
99
|
+
raise ParserException.new("Expected hyphen line after the agent declaration for <#{agent_class}>")
|
100
|
+
end
|
101
|
+
|
102
|
+
@agents << agent_class.new(data, reference_agents)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse_data(lines)
|
107
|
+
end_index = -1
|
108
|
+
lines.each_with_index do |line, index|
|
109
|
+
if line =~ /^-+/
|
110
|
+
end_index = index - 2
|
111
|
+
return lines.slice!(0, end_index)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
return lines.slice!(0, lines.length)
|
115
|
+
end
|
116
|
+
|
117
|
+
def parse_agent(line)
|
118
|
+
agent_name, *reference_agent_names = line.split(/(?=\()/)
|
119
|
+
raise ParserException.new("Nested agents ( e.g. a(b(c)) ) not supported yet") if reference_agent_names.length > 1
|
120
|
+
if reference_agent_names.length > 0
|
121
|
+
reference_agent_names = reference_agent_names[0].gsub(/\(|\)/, '').split(/,/)
|
122
|
+
reference_agent_names.collect! do |name|
|
123
|
+
name.strip
|
124
|
+
end
|
125
|
+
else
|
126
|
+
reference_agent_names = []
|
127
|
+
end
|
128
|
+
|
129
|
+
[agent_name, reference_agent_names].flatten.each do |a_name|
|
130
|
+
raise ParserException.new("Unregistered agent <#{a_name}> in agent name data <#{line}>") if !Agents.instance.id_registered?(a_name)
|
131
|
+
end
|
132
|
+
|
133
|
+
reference_agents = []
|
134
|
+
reference_agent_names.each do |ref_name|
|
135
|
+
@agents.each do |agent|
|
136
|
+
reference_agents << agent if agent.class.agent_id =~ /#{ref_name}/i
|
137
|
+
end
|
138
|
+
end
|
139
|
+
agent_class = Agents.instance.get_agent_by_id(agent_name)
|
140
|
+
[agent_class, reference_agents]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class CaseGen
|
145
|
+
def CaseGen.version
|
146
|
+
'1.3.0'
|
147
|
+
end
|
148
|
+
|
149
|
+
def initialize(data)
|
150
|
+
load_agents
|
151
|
+
Parser.new(data)
|
152
|
+
end
|
153
|
+
|
154
|
+
def load_agents
|
155
|
+
agent_dir = "#{File.dirname(__FILE__)}/agents"
|
156
|
+
agent_fns = Dir[File.join(agent_dir, '*.rb')]
|
157
|
+
agent_fns.each do |fn|
|
158
|
+
require fn
|
159
|
+
end
|
160
|
+
ObjectSpace.each_object(Class) do |klass|
|
161
|
+
if klass.ancestors.include?(Agent) && (klass != Agent)
|
162
|
+
Agents.instance.register(klass)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class Console
|
169
|
+
def initialize
|
170
|
+
put_banner
|
171
|
+
|
172
|
+
if ARGV[0].nil? || !File.exists?(ARGV[0])
|
173
|
+
puts "Case file required: #{File.basename($0)} [case filename]. For example:"
|
174
|
+
puts " #{File.basename($0)} cases.txt"
|
175
|
+
puts
|
176
|
+
exit
|
177
|
+
end
|
178
|
+
|
179
|
+
CaseGen.new(File.read(ARGV[0]))
|
180
|
+
end
|
181
|
+
|
182
|
+
def put_banner
|
183
|
+
$stderr.puts "cLabs Casegen #{CaseGen.version}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
if __FILE__ == $0
|
190
|
+
CLabs::CaseGen::Console.new
|
191
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
sets
|
2
|
+
----
|
3
|
+
role: admin, standard
|
4
|
+
authorization code: none, invalid, valid
|
5
|
+
submit enabled: true, false
|
6
|
+
|
7
|
+
rules(sets)
|
8
|
+
-----------
|
9
|
+
exclude role = admin AND submit enabled = false
|
10
|
+
Admin role can always submit
|
11
|
+
|
12
|
+
exclude role = standard AND authorization code = none AND submit enabled = true
|
13
|
+
exclude role = standard AND authorization code = invalid AND submit enabled = true
|
14
|
+
exclude role = standard AND authorization code = valid AND submit enabled = false
|
15
|
+
Standard role can only submit when authorization code is valid
|
16
|
+
|
17
|
+
|
18
|
+
ruby_array(rules)
|
19
|
+
-------------
|
20
|
+
DataSubmitCase
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: casegen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- chrismo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-28 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: chrismo@clabs.org
|
16
|
+
executables:
|
17
|
+
- casegen
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- src/agents/sets/enum/by.rb
|
22
|
+
- src/agents/sets/enum/cluster.rb
|
23
|
+
- src/agents/sets/enum/inject.rb
|
24
|
+
- src/agents/sets/enum/install.rb
|
25
|
+
- src/agents/sets/enum/nest.rb
|
26
|
+
- src/agents/sets/enum/op.rb
|
27
|
+
- src/agents/sets/enum/pipe.rb
|
28
|
+
- src/agents/sets/enum/tree.rb
|
29
|
+
- src/agents/sets.rb
|
30
|
+
- src/calc.sample.txt
|
31
|
+
- src/cart.sample.txt
|
32
|
+
- src/casegen.rb
|
33
|
+
- src/ruby_array.sample.txt
|
34
|
+
- bin/casegen
|
35
|
+
homepage: https://github.com/chrismo/casegen
|
36
|
+
licenses:
|
37
|
+
- BSD
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- src
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
hash: -3949454406001861969
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
hash: -3949454406001861969
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.8.23
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Simple Ruby DSL to generate use cases restricted by sets of rules
|
66
|
+
test_files: []
|