rutema 2.0.0 → 2.0.1
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 +5 -5
- data/History.txt +2 -0
- data/README.md +3 -3
- data/bin/rutema +4 -2
- data/lib/rutema/application.rb +22 -4
- data/lib/rutema/core/configuration.rb +277 -98
- data/lib/rutema/core/engine.rb +177 -33
- data/lib/rutema/core/framework.rb +115 -26
- data/lib/rutema/core/objectmodel.rb +284 -222
- data/lib/rutema/core/parser.rb +41 -10
- data/lib/rutema/core/reporter.rb +39 -16
- data/lib/rutema/core/runner.rb +103 -35
- data/lib/rutema/elements/minimal.rb +12 -9
- data/lib/rutema/parsers/xml.rb +63 -11
- data/lib/rutema/reporters/json.rb +4 -2
- data/lib/rutema/reporters/junit.rb +35 -12
- data/lib/rutema/version.rb +21 -6
- metadata +24 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b7b895aa680e7df981e4915c65427164a6c0f3e423d7381adcb286c8c625ee11
|
|
4
|
+
data.tar.gz: eb6409e8c312f835dedd4f5f35588113a870b166eef9d73a8f7a84f4ae4c5101
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3f7af65c99c671f3622287ed11ea0cd6fdd95539e339a0cf52561a974cd08f60fd9d57ae9f92328c45d3eb5ba26e37b99ff2d2a6309cee7c14c323cff16567e6
|
|
7
|
+
data.tar.gz: 0f5a684b9fca67d3b9cb6fed542996e27dc43229f77b87154da5d41bb27d88085f5d3335c747cdab6671e2a69eca929d768cf2a4f4730235db1127d05f94069f
|
data/History.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## rutema
|
|
2
|
-
[](http://travis-ci.org/damphyr/rutema) [](https://coveralls.io/r/damphyr/rutema) [](https://codeclimate.com/github/damphyr/rutema) 
|
|
2
|
+
[](http://travis-ci.org/damphyr/rutema) [](https://coveralls.io/r/damphyr/rutema) [](https://codeclimate.com/github/damphyr/rutema)  [](https://badge.fury.io/rb/rutema)
|
|
3
3
|
|
|
4
4
|
rutema [http://github.com/damphyr/rutema](http://github.com/damphyr/rutema)
|
|
5
5
|
|
|
@@ -31,7 +31,7 @@ Rutema core provides a reference implementation of a parser for a simple but ext
|
|
|
31
31
|
* An [example](doc/EXAMPLE.md) of a (very simple) testing DSL with rutema
|
|
32
32
|
* High level [description](README.md) of the concepts behind rutema
|
|
33
33
|
|
|
34
|
-
## Installation
|
|
34
|
+
## Installation
|
|
35
35
|
|
|
36
36
|
* gem install rutema
|
|
37
37
|
|
|
@@ -41,7 +41,7 @@ The core functionality of rutema depends on the following gems:
|
|
|
41
41
|
* [patir](http://github.com/damphyr/patir)
|
|
42
42
|
* [highline](http://highline.rubyforge.org/)
|
|
43
43
|
|
|
44
|
-
## License
|
|
44
|
+
## License
|
|
45
45
|
|
|
46
46
|
(The MIT License)
|
|
47
47
|
|
data/bin/rutema
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2007-2021 Vassilis Rizopoulos. All rights reserved.
|
|
4
|
+
|
|
3
5
|
require 'rutema/application'
|
|
4
6
|
begin
|
|
5
7
|
Rutema::App.new(ARGV)
|
|
6
8
|
rescue Rutema::RutemaError
|
|
7
9
|
puts $!.message
|
|
8
10
|
exit 1
|
|
9
|
-
end
|
|
11
|
+
end
|
data/lib/rutema/application.rb
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
# Copyright (c) 2021 Vassilis Rizopoulos. All rights reserved.
|
|
2
|
+
|
|
1
3
|
require 'optparse'
|
|
4
|
+
|
|
2
5
|
require_relative "core/configuration"
|
|
3
6
|
require_relative "core/engine"
|
|
4
7
|
|
|
5
8
|
module Rutema
|
|
6
|
-
|
|
9
|
+
##
|
|
10
|
+
# Entry-point class for rutema
|
|
11
|
+
#
|
|
12
|
+
# This class parses the commandline, sets up the internal configuration of
|
|
13
|
+
# rutema accordingly and starts the application flow.
|
|
7
14
|
class App
|
|
15
|
+
##
|
|
16
|
+
# Configure and start the application flow according to the passed
|
|
17
|
+
# commandline options
|
|
8
18
|
def initialize command_line_args
|
|
9
19
|
parse_command_line(command_line_args)
|
|
10
20
|
@configuration=Rutema::Configuration.new(@config_file)
|
|
@@ -18,7 +28,12 @@ module Rutema
|
|
|
18
28
|
@engine=Rutema::Engine.new(@configuration)
|
|
19
29
|
application_flow
|
|
20
30
|
end
|
|
31
|
+
|
|
21
32
|
private
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# Define the available commandline options and parse the given commandline
|
|
36
|
+
# accordingly
|
|
22
37
|
def parse_command_line args
|
|
23
38
|
args.options do |opt|
|
|
24
39
|
opt.on("rutema v#{Version::STRING}")
|
|
@@ -45,18 +60,21 @@ module Rutema
|
|
|
45
60
|
end
|
|
46
61
|
end
|
|
47
62
|
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Start the application flow
|
|
48
66
|
def application_flow
|
|
49
67
|
if @check
|
|
50
|
-
#run just the suite setup test
|
|
68
|
+
# run just the suite setup test if requested
|
|
51
69
|
if @configuration.suite_setup
|
|
52
70
|
exit @engine.run(@configuration.suite_setup)
|
|
53
71
|
else
|
|
54
72
|
raise Rutema::RutemaError,"There is no suite setup test defined in the configuration."
|
|
55
73
|
end
|
|
56
74
|
else
|
|
57
|
-
#run everything
|
|
75
|
+
# run everything
|
|
58
76
|
exit @engine.run(@test_identifier)
|
|
59
77
|
end
|
|
60
78
|
end
|
|
61
79
|
end
|
|
62
|
-
end
|
|
80
|
+
end
|
|
@@ -1,131 +1,260 @@
|
|
|
1
|
-
|
|
1
|
+
# Copyright (c) 2007-2021 Vassilis Rizopoulos. All rights reserved.
|
|
2
|
+
|
|
2
3
|
require 'ostruct'
|
|
3
4
|
require_relative 'parser'
|
|
4
5
|
require_relative 'reporter'
|
|
5
6
|
module Rutema
|
|
6
|
-
|
|
7
|
+
##
|
|
8
|
+
# Mix-in module defining all configuration directives available for rutema
|
|
9
|
+
#
|
|
10
|
+
# === Example
|
|
11
|
+
#
|
|
12
|
+
# A configuration file needs at least definitions of which parser to utilize
|
|
13
|
+
# and which tests to run.
|
|
14
|
+
#
|
|
15
|
+
# rutema configuration files are valid Ruby code and can use the full power of
|
|
16
|
+
# the language including _require_ directives.
|
|
17
|
+
#
|
|
18
|
+
# require "rake/file_list"
|
|
19
|
+
#
|
|
20
|
+
# configure do |cfg|
|
|
21
|
+
# cfg.parser = { :class => Rutema::Parsers::XML }
|
|
22
|
+
# cfg.tests = FileList['all/of/the/tests/**/*.*']
|
|
23
|
+
# end
|
|
24
|
+
module ConfigurationDirectives
|
|
25
|
+
##
|
|
26
|
+
# Hash of context data which may be utilized throughout test runs
|
|
7
27
|
#
|
|
8
|
-
#
|
|
9
|
-
|
|
28
|
+
# This could be used for e.g. tester names, version numbers, etc.
|
|
29
|
+
attr_reader :context
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Parser class which shall be used to parse test specifications
|
|
33
|
+
attr_reader :parser
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# A hash of supplementary paths identified by representative names
|
|
37
|
+
attr_reader :paths
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# A hash mapping reporter classes to supplementary definitions
|
|
41
|
+
attr_accessor :reporters
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Runner class which shall be used to execute the tests
|
|
45
|
+
attr_reader :runner
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Path to a setup specification which will be run before every test
|
|
49
|
+
# specification (optional)
|
|
50
|
+
attr_reader :setup
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Path to a suite setup specification (optional)
|
|
10
54
|
#
|
|
11
|
-
#
|
|
55
|
+
# This will be run before all other test specifications. If it fails no
|
|
56
|
+
# other specifications will be executed.
|
|
57
|
+
attr_reader :suite_setup
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Path to a suite teardown specification (optional)
|
|
12
61
|
#
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
62
|
+
# This will be run after all other test specifications
|
|
63
|
+
attr_reader :suite_teardown
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Path to a teardown specification which will be run after every test
|
|
67
|
+
# specification (optional)
|
|
68
|
+
attr_reader :teardown
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Array of (most probably the paths to) the specifications of the tests to
|
|
72
|
+
# be executed
|
|
73
|
+
#
|
|
74
|
+
# In nearly all cases this would contain only paths but generally this can
|
|
75
|
+
# contain any data intelligible by the test specification parser.
|
|
76
|
+
attr_reader :tests
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Hash containing data for tools indexed by their names
|
|
80
|
+
attr_reader :tools
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# Add a hash with arbitrary data concerning one particular tool which can be
|
|
84
|
+
# utilized throughout testing by accessing the +tools+ attribute of classes
|
|
85
|
+
# including this module
|
|
86
|
+
#
|
|
87
|
+
# The hash must include a +:name+ key which will define the key under which
|
|
88
|
+
# the entire passed hash will be stored.
|
|
89
|
+
#
|
|
90
|
+
# New calls only add to the hash. Later calls containing the same +:name+
|
|
91
|
+
# key as earlier ones replace the data these set.
|
|
92
|
+
#
|
|
93
|
+
# === Example
|
|
94
|
+
#
|
|
95
|
+
# configure do |cfg|
|
|
96
|
+
# cfg.tool = { :name => "nunit", :path => "/bin/nunit", :configuration => { :important=>"info" } }
|
|
97
|
+
# end
|
|
98
|
+
#
|
|
99
|
+
# The path to NUnit can be accessed the following way:
|
|
100
|
+
#
|
|
101
|
+
# @configuration.tools["nunit"][:path]
|
|
34
102
|
def tool= definition
|
|
35
103
|
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
|
36
104
|
@tools[definition[:name]]=definition
|
|
37
105
|
end
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
106
|
+
|
|
107
|
+
##
|
|
108
|
+
# Add a path indexed by a representative name to the paths attribute
|
|
109
|
+
#
|
|
110
|
+
# A hash is expected which contains a representative name under the +:name+
|
|
111
|
+
# key and the path itself under the +:path+ key.
|
|
112
|
+
#
|
|
113
|
+
# New calls only add to the hash. Later calls containing the same +:name+
|
|
114
|
+
# key as earlier ones replace the data these set.
|
|
115
|
+
#
|
|
116
|
+
# === Example
|
|
117
|
+
#
|
|
118
|
+
# configure do |cfg|
|
|
119
|
+
# cfg.path = { :name => "doc", :path => "/usr/local/share/doc" }
|
|
120
|
+
# end
|
|
45
121
|
def path= definition
|
|
46
122
|
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
|
47
123
|
raise ConfigurationException,"required key :path is missing from #{definition}" unless definition[:path]
|
|
48
124
|
@paths[definition[:name]]=definition[:path]
|
|
49
125
|
end
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Path to a setup specification (optional)
|
|
129
|
+
#
|
|
130
|
+
# This setup specification will be run before every test specification.
|
|
131
|
+
#
|
|
132
|
+
# Later calls override earlier ones.
|
|
53
133
|
def setup= path
|
|
54
134
|
@setup=check_path(path)
|
|
55
135
|
end
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
136
|
+
|
|
137
|
+
##
|
|
138
|
+
# Path to a teardown specification (optional)
|
|
139
|
+
#
|
|
140
|
+
# This teardown specification will be run after every test specification.
|
|
141
|
+
#
|
|
142
|
+
# Later calls override earlier ones.
|
|
59
143
|
def teardown= path
|
|
60
144
|
@teardown=check_path(path)
|
|
61
145
|
end
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Path to a suite setup specification (optional)
|
|
149
|
+
#
|
|
150
|
+
# This suite setup specification is executed once in the beginning of a test
|
|
151
|
+
# run before any other specifications. If it fails no other test
|
|
152
|
+
# specifications are executed.
|
|
153
|
+
#
|
|
154
|
+
# This is aliased as #check= for backwards compatibility.
|
|
155
|
+
#
|
|
156
|
+
# Later calls override earlier ones.
|
|
69
157
|
def suite_setup= path
|
|
70
158
|
@suite_setup=check_path(path)
|
|
71
159
|
end
|
|
72
160
|
|
|
73
161
|
alias_method :check,:suite_setup
|
|
74
162
|
alias_method :check=,:suite_setup=
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
163
|
+
|
|
164
|
+
##
|
|
165
|
+
# Path to a suite teardown specification (optional)
|
|
166
|
+
#
|
|
167
|
+
# This suite teardown specification is executed once after all other test
|
|
168
|
+
# specifications have been executed.
|
|
169
|
+
#
|
|
170
|
+
# Later calls override earlier ones.
|
|
78
171
|
def suite_teardown= path
|
|
79
172
|
@suite_teardown=check_path(path)
|
|
80
173
|
end
|
|
81
|
-
|
|
82
|
-
|
|
174
|
+
|
|
175
|
+
##
|
|
176
|
+
# Context information which shall be accessible during test execution
|
|
177
|
+
#
|
|
178
|
+
# Data must be passed in form of a hash. In case of key collisions later
|
|
179
|
+
# calls override existing data of colliding keys.
|
|
180
|
+
#
|
|
181
|
+
# This could be used e.g. to pass data as tester names, version numbers,
|
|
182
|
+
# etc. to the reporters.
|
|
83
183
|
def context= definition
|
|
84
184
|
@context||=Hash.new
|
|
85
185
|
raise ConfigurationException,"Only accepting hash values as context_data" unless definition.kind_of?(Hash)
|
|
86
186
|
@context.merge!(definition)
|
|
87
187
|
end
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
188
|
+
|
|
189
|
+
##
|
|
190
|
+
# Add an array of (paths of) test specifications to be executed
|
|
191
|
+
#
|
|
192
|
+
# Usually an array of file paths would be given. Generally the passed array
|
|
193
|
+
# can contain anything intelligible for the parser.
|
|
92
194
|
def tests= array_of_identifiers
|
|
93
195
|
@tests+=array_of_identifiers.map{|f| full_path(f)}
|
|
94
196
|
end
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
197
|
+
|
|
198
|
+
##
|
|
199
|
+
# Set the parser class which shall be used to parse test specifications
|
|
200
|
+
#
|
|
201
|
+
# The only required key is +:class+ which should be set to the fully
|
|
202
|
+
# qualified name of the class to be used for parsing.
|
|
203
|
+
#
|
|
204
|
+
# Later calls overwrite earlier ones.
|
|
205
|
+
#
|
|
206
|
+
# === Example
|
|
207
|
+
#
|
|
208
|
+
# configure do |cfg|
|
|
209
|
+
# cfg.parser = { :class => Rutema::Parsers::XML }
|
|
210
|
+
# end
|
|
103
211
|
def parser= definition
|
|
104
212
|
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
|
105
213
|
@parser=definition
|
|
106
214
|
end
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# Set the runner which shall be used to execute the tests
|
|
218
|
+
#
|
|
219
|
+
# Upon construction of the runner the context set through the configuration
|
|
220
|
+
# is being passed to the initializer.
|
|
221
|
+
#
|
|
222
|
+
# The only required key is +:class+ which should be set to the fully
|
|
223
|
+
# qualified name of the class as runner.
|
|
224
|
+
#
|
|
225
|
+
# Later calls overwrite earlier ones.
|
|
226
|
+
#
|
|
227
|
+
# === Example
|
|
228
|
+
#
|
|
229
|
+
# configure do |cfg|
|
|
230
|
+
# cfg.runner = { :class => Rutema::Runners::Default }
|
|
231
|
+
# end
|
|
115
232
|
def runner= definition
|
|
116
233
|
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
|
117
234
|
@runner=definition
|
|
118
235
|
end
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
236
|
+
|
|
237
|
+
##
|
|
238
|
+
# Add a reporter for the test execution
|
|
239
|
+
#
|
|
240
|
+
# The only required key is +:class+ which should be set to the fully
|
|
241
|
+
# qualified name of the class to be used for reporting.
|
|
242
|
+
#
|
|
243
|
+
# Multiple reporter classes can be set simultaneously.
|
|
244
|
+
#
|
|
245
|
+
# === Example
|
|
246
|
+
#
|
|
247
|
+
# configure do |cfg|
|
|
248
|
+
# cfg.reporters = { :class => Rutema::Reporters::Console }
|
|
249
|
+
# cfg.reporters = { :class => Rutema::Reporters::JUnit }
|
|
250
|
+
# end
|
|
124
251
|
def reporter= definition
|
|
125
252
|
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
|
126
253
|
@reporters[definition[:class]]=definition
|
|
127
254
|
end
|
|
128
|
-
|
|
255
|
+
|
|
256
|
+
##
|
|
257
|
+
# Initialize member variables which are needed to process a configuration
|
|
129
258
|
def init
|
|
130
259
|
@reporters={}
|
|
131
260
|
@context={}
|
|
@@ -133,54 +262,97 @@
|
|
|
133
262
|
@tools=OpenStruct.new
|
|
134
263
|
@paths=OpenStruct.new
|
|
135
264
|
end
|
|
136
|
-
|
|
137
|
-
private
|
|
138
|
-
|
|
265
|
+
|
|
266
|
+
private
|
|
267
|
+
|
|
268
|
+
##
|
|
269
|
+
# Check if the given path exists and raise a ConfigurationException if not
|
|
139
270
|
def check_path path
|
|
140
271
|
path=File.expand_path(path)
|
|
141
272
|
raise ConfigurationException,"#{path} does not exist" unless File.exist?(path)
|
|
142
273
|
return path
|
|
143
274
|
end
|
|
144
|
-
|
|
275
|
+
|
|
276
|
+
##
|
|
277
|
+
# Return a string in the form of "key=value,key=value" for a given hash
|
|
145
278
|
def definition_string definition
|
|
146
279
|
msg=Array.new
|
|
147
280
|
definition.each{|k,v| msg<<"#{k}=#{v}"}
|
|
148
281
|
return msg.join(",")
|
|
149
282
|
end
|
|
150
283
|
|
|
284
|
+
##
|
|
285
|
+
# Convert the given filename to an absolute path if the file exists or
|
|
286
|
+
# otherwise return the passed filename as is
|
|
151
287
|
def full_path filename
|
|
152
288
|
return File.expand_path(filename) if File.exist?(filename)
|
|
153
289
|
return filename
|
|
154
290
|
end
|
|
155
291
|
end
|
|
156
292
|
|
|
293
|
+
##
|
|
294
|
+
# Exception which is being raised upon errors concerning configurations passed
|
|
295
|
+
# to rutema
|
|
296
|
+
#
|
|
297
|
+
# This may be caused by e.g.:
|
|
298
|
+
#
|
|
299
|
+
# * a file or path could not be found/does not exist
|
|
300
|
+
# * passed hash arguments being of an unexpected/unhandled type
|
|
301
|
+
# * passed hash arguments missing required keys
|
|
157
302
|
class ConfigurationException<RuntimeError
|
|
158
303
|
end
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
304
|
+
|
|
305
|
+
##
|
|
306
|
+
# Class for reading, parsing and representing the configuration for a rutema
|
|
307
|
+
# test run
|
|
308
|
+
#
|
|
309
|
+
# The instance will be passed around during testing and instruct each
|
|
310
|
+
# component which tests to execute how.
|
|
311
|
+
#
|
|
312
|
+
# Rutema::ConfigurationDirectives defines all relevant methods and attributes.
|
|
162
313
|
class Configuration
|
|
163
314
|
include ConfigurationDirectives
|
|
315
|
+
|
|
316
|
+
##
|
|
317
|
+
# The filename of the root configuration file from which the Configuration
|
|
318
|
+
# instance was built
|
|
164
319
|
attr_reader :filename
|
|
320
|
+
|
|
321
|
+
##
|
|
322
|
+
# Create a new instance by parsing the given configuration file
|
|
323
|
+
#
|
|
324
|
+
# * +config_file+ - the configuration file which shall be parsed on
|
|
325
|
+
# initializing the new instance
|
|
165
326
|
def initialize config_file
|
|
166
327
|
@filename=config_file
|
|
167
328
|
init
|
|
168
329
|
load_configuration(@filename)
|
|
169
330
|
end
|
|
170
331
|
|
|
332
|
+
##
|
|
333
|
+
# Yield the instance itself if a block is given
|
|
334
|
+
#
|
|
335
|
+
# This can be used e.g. in configuration files to execute a block on the
|
|
336
|
+
# Configuration instance itself (e.g. to modify it through the setter
|
|
337
|
+
# methods of the ConfigurationDirectives module).
|
|
171
338
|
def configure
|
|
172
339
|
if block_given?
|
|
173
340
|
yield self
|
|
174
341
|
end
|
|
175
342
|
end
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
343
|
+
|
|
344
|
+
##
|
|
345
|
+
# Load and import the configuration from a file
|
|
346
|
+
#
|
|
347
|
+
# This method can be used to chain configuration files together.
|
|
348
|
+
#
|
|
349
|
+
# === Example
|
|
350
|
+
#
|
|
351
|
+
# If there is a configuration file "main.rutema" which contains all the
|
|
352
|
+
# generic directives and several others which modify specific aspects, then
|
|
353
|
+
# the specialized configurations can import the "main.rutema" as follows:
|
|
354
|
+
#
|
|
355
|
+
# import("main.rutema")
|
|
184
356
|
def import filename
|
|
185
357
|
fnm = File.expand_path(filename)
|
|
186
358
|
if File.exist?(fnm)
|
|
@@ -189,27 +361,34 @@
|
|
|
189
361
|
raise ConfigurationException, "Import error: Can't find #{fnm}"
|
|
190
362
|
end
|
|
191
363
|
end
|
|
364
|
+
|
|
192
365
|
private
|
|
366
|
+
|
|
367
|
+
##
|
|
368
|
+
# Load the configuration from the file given by +filename+
|
|
369
|
+
#
|
|
370
|
+
# On many common parsing errors a ConfigurationException is being raised.
|
|
193
371
|
def load_configuration filename
|
|
194
372
|
begin
|
|
195
373
|
cfg_txt=File.read(filename)
|
|
196
374
|
cwd=File.expand_path(File.dirname(filename))
|
|
197
|
-
#WORKAROUND for ruby 2.3.1
|
|
375
|
+
# WORKAROUND for ruby 2.3.1
|
|
198
376
|
fname=File.basename(filename)
|
|
199
|
-
#evaluate in the working directory to enable relative paths in
|
|
377
|
+
# evaluate in the working directory to enable relative paths in
|
|
378
|
+
# configuration
|
|
200
379
|
Dir.chdir(cwd){eval(cfg_txt,binding(),fname,__LINE__)}
|
|
201
380
|
rescue ConfigurationException
|
|
202
|
-
#pass it on, do not wrap again
|
|
381
|
+
# pass it on, do not wrap again
|
|
203
382
|
raise
|
|
204
383
|
rescue SyntaxError
|
|
205
|
-
#
|
|
384
|
+
# just wrap the exception so we can differentiate
|
|
206
385
|
raise ConfigurationException.new,"Syntax error in the configuration file '#{filename}':\n#{$!.message}"
|
|
207
386
|
rescue NoMethodError
|
|
208
387
|
raise ConfigurationException.new,"Encountered an unknown directive in configuration file '#{filename}':\n#{$!.message}"
|
|
209
388
|
rescue
|
|
210
|
-
#
|
|
389
|
+
# just wrap the exception so we can differentiate
|
|
211
390
|
raise ConfigurationException.new,"#{$!.message}"
|
|
212
391
|
end
|
|
213
392
|
end
|
|
214
393
|
end
|
|
215
|
-
end
|
|
394
|
+
end
|