casegen 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|