laborantin 0.0.14 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- data/INFO +1 -0
- data/README +148 -4
- data/Rakefile +73 -27
- data/TODO +27 -6
- data/bin/labor +2 -404
- data/lib/laborantin.rb +13 -26
- data/lib/laborantin/core/analysis.rb +231 -0
- data/lib/laborantin/core/command.rb +234 -0
- data/lib/laborantin/core/completeable.rb +30 -0
- data/lib/laborantin/core/configurable.rb +28 -0
- data/lib/laborantin/core/datable.rb +13 -0
- data/lib/laborantin/core/describable.rb +11 -0
- data/lib/laborantin/core/environment.rb +90 -52
- data/lib/laborantin/core/hookable.rb +20 -0
- data/lib/laborantin/core/monkey_patches.rb +0 -1
- data/lib/laborantin/core/multi_name.rb +25 -0
- data/lib/laborantin/core/parameter.rb +5 -12
- data/lib/laborantin/core/parameter_hash.rb +6 -2
- data/lib/laborantin/core/scenario.rb +93 -70
- data/lib/laborantin/core/table.rb +84 -0
- data/lib/laborantin/extra/commands/git.rb +40 -0
- data/lib/laborantin/extra/commands/git/check.rb +25 -0
- data/lib/laborantin/extra/commands/git/run.rb +100 -0
- data/lib/laborantin/extra/vectorial_product.rb +31 -0
- data/lib/laborantin/runner.rb +247 -0
- data/lib/laborantin/runner/commands/analyze.rb +58 -0
- data/lib/laborantin/runner/commands/cleanup.rb +40 -0
- data/lib/laborantin/runner/commands/complete.rb +111 -0
- data/lib/laborantin/runner/commands/config.rb +169 -0
- data/lib/laborantin/runner/commands/create.rb +61 -0
- data/lib/laborantin/runner/commands/describe.rb +215 -0
- data/lib/laborantin/runner/commands/find.rb +82 -0
- data/lib/laborantin/runner/commands/load_classes.rb +75 -0
- data/lib/laborantin/runner/commands/load_results.rb +143 -0
- data/lib/laborantin/runner/commands/note.rb +35 -0
- data/lib/laborantin/runner/commands/replay.rb +89 -0
- data/lib/laborantin/runner/commands/rm.rb +107 -0
- data/lib/laborantin/runner/commands/run.rb +131 -0
- data/lib/laborantin/runner/commands/scan.rb +77 -0
- metadata +45 -13
- data/bin/files/README.erb +0 -29
- data/bin/files/TODO.erb +0 -2
- data/bin/files/config/ftp.yaml.erb +0 -6
- data/bin/files/config/xmpp.yaml.erb +0 -7
- data/bin/files/environments/environment.rb.erb +0 -10
- data/bin/files/scenarii/scenario.rb.erb +0 -13
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module Completeable
|
5
|
+
# A block to propose completion on this option
|
6
|
+
attr_reader :completion_block
|
7
|
+
|
8
|
+
# Stores the block argument in the completion_block, usage is for DSLs
|
9
|
+
def complete(&blk)
|
10
|
+
@completion_block = blk
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
# Provides completion facility for comma-separated lists of args, and returns the propositions
|
15
|
+
# - removes items already in list
|
16
|
+
# - prepends commas for items not already in list
|
17
|
+
def completion_propositions_iterating_on(cmd, list)
|
18
|
+
envs_on_cli = cmd.split.last.split(',').reject{|s| s.start_with?('-')}
|
19
|
+
last_env_on_cli = envs_on_cli.last unless cmd.end_with?(',')
|
20
|
+
last_env_on_cli ||= ''
|
21
|
+
complete_envs_on_cli = envs_on_cli - [last_env_on_cli]
|
22
|
+
|
23
|
+
list = list.select{|str| str.start_with?(last_env_on_cli)}
|
24
|
+
candidate_envs = list - envs_on_cli
|
25
|
+
candidate_envs.map{|str| (complete_envs_on_cli + [str]).join(',') }
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module Configurable
|
5
|
+
# A hash placeholder for extra config (e.g. git revision for the git implementation)
|
6
|
+
attr_accessor :config
|
7
|
+
|
8
|
+
# saves the @config in a YAML config file
|
9
|
+
def save_config
|
10
|
+
File.open(config_path, 'w') do |f|
|
11
|
+
f.puts YAML.dump(config)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# restore the configuration from the config file
|
16
|
+
def load_config!(path=config_path)
|
17
|
+
if File.file?(path)
|
18
|
+
@config = YAML.load_file(path)
|
19
|
+
end
|
20
|
+
@config ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def config_path
|
24
|
+
"config.yaml"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -21,9 +21,15 @@ Copyright (c) 2009, Lucas Di Cioccio
|
|
21
21
|
|
22
22
|
=end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
autoload :Time, 'time'
|
25
|
+
autoload :Logger, 'logger'
|
26
|
+
autoload :FileUtils, 'fileutils'
|
27
|
+
|
28
|
+
require 'laborantin/core/datable'
|
29
|
+
require 'laborantin/core/describable'
|
30
|
+
require 'laborantin/core/hookable'
|
31
|
+
require 'laborantin/core/configurable'
|
32
|
+
require 'laborantin/core/multi_name'
|
27
33
|
|
28
34
|
module Laborantin
|
29
35
|
|
@@ -37,26 +43,38 @@ module Laborantin
|
|
37
43
|
# If you want to do that, you must know that Environment @@all class variable
|
38
44
|
# holds a reference to every child class from Environment.
|
39
45
|
class Environment
|
46
|
+
include Metaprog::Datable
|
47
|
+
include Metaprog::Configurable
|
48
|
+
extend Metaprog::Describable
|
49
|
+
extend Metaprog::Hookable
|
50
|
+
extend Metaprog::MultiName
|
51
|
+
|
40
52
|
@@all = []
|
41
53
|
|
42
54
|
# Populates loaded (i.e. put in @@all class variable when self.inherited
|
43
55
|
# is called) environment classes from existing results that are stored in
|
44
56
|
# the dir parameter.
|
45
57
|
def self.scan_resdir(dir)
|
46
|
-
|
58
|
+
list = []
|
47
59
|
Dir.entries(dir).each do |f|
|
48
|
-
envklass = Laborantin::Environment.all.find{|e| e.
|
60
|
+
envklass = Laborantin::Environment.all.find{|e| e.fs_name == f}
|
49
61
|
if envklass
|
50
62
|
Dir.entries(envklass.envdir).each do |e|
|
51
63
|
if e =~ /\d+-\w+-\d+_\d+-\d+-\d+/
|
52
|
-
env = envklass.
|
53
|
-
|
54
|
-
ret << env
|
64
|
+
env = envklass.new_loading_from_dir(File.join(envklass.envdir, e))
|
65
|
+
list << env
|
55
66
|
end
|
56
67
|
end
|
57
68
|
end
|
58
69
|
end
|
59
|
-
|
70
|
+
list
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.new_loading_from_dir(path)
|
74
|
+
obj = self.new
|
75
|
+
obj.load_config!
|
76
|
+
obj.rundir = path
|
77
|
+
obj
|
60
78
|
end
|
61
79
|
|
62
80
|
class << self
|
@@ -66,15 +84,6 @@ module Laborantin
|
|
66
84
|
# CURRENTLY NOT HERITED
|
67
85
|
attr_accessor :verifications
|
68
86
|
|
69
|
-
# A description used for printing summary and debug purposes. Will be
|
70
|
-
# used to create .tex report in the future.
|
71
|
-
# CURRENTLY NOT HERITED
|
72
|
-
attr_accessor :description
|
73
|
-
|
74
|
-
# A hash to store setup/teardown hooks.
|
75
|
-
# CURRENTLY NOT HERITED
|
76
|
-
attr_accessor :hooks
|
77
|
-
|
78
87
|
# Prepares attributes' default values whenever a subclass is created.
|
79
88
|
def inherited(klass)
|
80
89
|
klass.verifications = []
|
@@ -83,40 +92,20 @@ module Laborantin
|
|
83
92
|
@@all << klass
|
84
93
|
end
|
85
94
|
|
86
|
-
# Registers new verifiers.
|
95
|
+
# Registers new verifiers methods that will be verified at beginning.
|
87
96
|
def verify(*args)
|
88
97
|
self.verifications = [*args].flatten
|
89
98
|
end
|
90
99
|
|
91
|
-
# Sets the description.
|
92
|
-
def describe(str)
|
93
|
-
self.description = str
|
94
|
-
end
|
95
|
-
|
96
|
-
# Registers setup hooks, called before any scenario is instantiated.
|
97
|
-
def setup(*args)
|
98
|
-
self.hooks[:setup] = [*args].flatten
|
99
|
-
end
|
100
|
-
|
101
|
-
# Registers teardown hooks, called after every scenarii has been
|
102
|
-
# performed and analyzed.
|
103
|
-
def teardown(*args)
|
104
|
-
self.hooks[:teardown] = [*args].flatten
|
105
|
-
end
|
106
|
-
|
107
|
-
def to_s
|
108
|
-
"#{self.name}:\n\t#{self.description}"
|
109
|
-
end
|
110
|
-
|
111
100
|
# Returns all the known subklasses of Environment.
|
112
101
|
def all
|
113
102
|
@@all
|
114
103
|
end
|
115
104
|
|
116
105
|
# The path where the results for instance of a subklass of Environment
|
117
|
-
# are stored (needs the
|
106
|
+
# are stored (needs the Runner's resultdir).
|
118
107
|
def envdir
|
119
|
-
File.join(
|
108
|
+
File.join(Runner.instance.resultdir, self.fs_name)
|
120
109
|
end
|
121
110
|
end
|
122
111
|
|
@@ -124,28 +113,76 @@ module Laborantin
|
|
124
113
|
# are stored. Can be overridden (e.g. Environment.scan_resdir does that).
|
125
114
|
attr_accessor :rundir
|
126
115
|
|
127
|
-
# A date that holds the creation of the instance, it is not meaningful
|
128
|
-
# when an env was created by a call to Environment.scan_resdir.
|
129
|
-
# TODO better
|
130
|
-
attr_accessor :date
|
131
|
-
|
132
116
|
# An array of loggers objects.
|
133
117
|
attr_accessor :loggers
|
134
118
|
|
135
|
-
|
119
|
+
# The (optional) commmand instanciating this environment
|
120
|
+
attr_accessor :command
|
121
|
+
|
122
|
+
# Initializes a new instance:
|
123
|
+
# the date is Time.now
|
124
|
+
# the rundir is the Environment.envdir followed by the date_str
|
125
|
+
# the loggers contains an empty Array
|
126
|
+
# Does NOT create any directory, so the accessors can be overwritten if needed.
|
127
|
+
def initialize(command=nil)
|
128
|
+
@command = command
|
136
129
|
@date = Time.now
|
137
130
|
@rundir = File.join(self.class.envdir, date_str)
|
138
131
|
@loggers = []
|
132
|
+
@config = {}
|
139
133
|
end
|
140
134
|
|
135
|
+
def runner
|
136
|
+
command.runner if command
|
137
|
+
end
|
138
|
+
|
139
|
+
# sends all the methods registered in Environment.verify
|
140
|
+
# returns the method symbol of the failed verification if any
|
141
141
|
def valid?
|
142
142
|
self.class.verifications.find{|v| not send(v)}.nil?
|
143
143
|
end
|
144
144
|
|
145
|
+
# complete path to the environment.log file
|
145
146
|
def logfile_path
|
146
147
|
File.join(rundir, 'environment.log')
|
147
148
|
end
|
148
149
|
|
150
|
+
# complete path to the config.yaml file
|
151
|
+
def config_path
|
152
|
+
File.join(rundir, 'config.yaml')
|
153
|
+
end
|
154
|
+
|
155
|
+
def scenarii_dirs
|
156
|
+
config[:scenarii_dirs]
|
157
|
+
end
|
158
|
+
|
159
|
+
def record_scenario_dir(dir, save=false)
|
160
|
+
config[:scenarii_dirs] ||= []
|
161
|
+
config[:scenarii_dirs] << dir
|
162
|
+
save_config if save
|
163
|
+
end
|
164
|
+
|
165
|
+
# gets the state of the environment
|
166
|
+
def state
|
167
|
+
config[:state]
|
168
|
+
end
|
169
|
+
|
170
|
+
# changes the state of the environment
|
171
|
+
def state=(val, save=true)
|
172
|
+
config[:state] = val
|
173
|
+
save_config if save
|
174
|
+
end
|
175
|
+
|
176
|
+
# returns if the environment succeeded
|
177
|
+
def successful?
|
178
|
+
config[:state] == :success
|
179
|
+
end
|
180
|
+
|
181
|
+
# returns if the environment exited with error
|
182
|
+
def failed?
|
183
|
+
config[:state] == :error
|
184
|
+
end
|
185
|
+
|
149
186
|
# In the following order:
|
150
187
|
# * Creates the envdir if needed.
|
151
188
|
# * Adds some loggers.
|
@@ -159,6 +196,8 @@ module Laborantin
|
|
159
196
|
@loggers << Logger.new(STDOUT)
|
160
197
|
log(self.class.description, :info) unless self.class.description.empty?
|
161
198
|
log "Directories prepared"
|
199
|
+
log "Writing config file"
|
200
|
+
save_config
|
162
201
|
call_hooks :setup
|
163
202
|
end
|
164
203
|
|
@@ -178,15 +217,14 @@ module Laborantin
|
|
178
217
|
Laborantin::Scenario.scan_env(self)
|
179
218
|
end
|
180
219
|
|
181
|
-
def date_str
|
182
|
-
date.strftime("%Y-%h-%d_%H-%M-%S")
|
183
|
-
end
|
184
|
-
|
185
220
|
private
|
186
221
|
|
187
222
|
def call_hooks(name)
|
188
223
|
log "Calling #{name} hooks"
|
189
|
-
self.class.hooks[name].each
|
224
|
+
self.class.hooks[name].each do |sym|
|
225
|
+
log "(#{sym})"
|
226
|
+
send sym
|
227
|
+
end
|
190
228
|
end
|
191
229
|
|
192
230
|
end # class
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module Hookable
|
5
|
+
# A hash to store setup/teardown hooks.
|
6
|
+
attr_accessor :hooks
|
7
|
+
|
8
|
+
# Registers setup hooks.
|
9
|
+
def setup(*args)
|
10
|
+
hooks[:setup] = [*args].flatten
|
11
|
+
end
|
12
|
+
|
13
|
+
# Register teardown hooks.
|
14
|
+
def teardown(*args)
|
15
|
+
hooks[:teardown] = [*args].flatten
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module MultiName
|
5
|
+
AVAILABLE_NAMES = [:cli, :fs]
|
6
|
+
|
7
|
+
def set_name(sym, val)
|
8
|
+
raise ArgumentError, "invalid name sym: #{sym}, expected in #{AVAILABLE_NAMES.inspect}" unless AVAILABLE_NAMES.include?(sym)
|
9
|
+
send "#{sym}_name=", val
|
10
|
+
end
|
11
|
+
|
12
|
+
# a way to name on the command line
|
13
|
+
attr_writer :cli_name
|
14
|
+
def cli_name
|
15
|
+
@cli_name || name.duck_case
|
16
|
+
end
|
17
|
+
|
18
|
+
# a way to name on the filesystem
|
19
|
+
attr_writer :fs_name
|
20
|
+
def fs_name
|
21
|
+
@fs_name || name.duck_case
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -21,19 +21,20 @@ Copyright (c) 2009, Lucas Di Cioccio
|
|
21
21
|
|
22
22
|
=end
|
23
23
|
|
24
|
+
require 'laborantin/core/describable'
|
25
|
+
|
24
26
|
module Laborantin
|
25
27
|
|
26
28
|
# A ParameterRange instance is more or less a wrapper over an Array of allowed values.
|
27
29
|
class ParameterRange
|
28
30
|
|
31
|
+
include Metaprog::Describable
|
32
|
+
|
29
33
|
# The name of the parameter (should be unique in a Scenario's parameters)
|
30
34
|
# Usually a symbol.
|
31
35
|
attr_accessor :name
|
32
36
|
|
33
|
-
#
|
34
|
-
# used to create .tex report in the future.
|
35
|
-
attr_accessor :description
|
36
|
-
|
37
|
+
# initialize a new instance with the desired name
|
37
38
|
def initialize(name)
|
38
39
|
@name = name
|
39
40
|
@values = []
|
@@ -54,13 +55,5 @@ module Laborantin
|
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
57
|
-
# Sets the description.
|
58
|
-
def describe(str)
|
59
|
-
@description = str
|
60
|
-
end
|
61
|
-
|
62
|
-
def to_s
|
63
|
-
"#{values.inspect}\n\t\t#{@description}"
|
64
|
-
end
|
65
58
|
end
|
66
59
|
end
|
@@ -21,11 +21,18 @@ Copyright (c) 2009, Lucas Di Cioccio
|
|
21
21
|
|
22
22
|
=end
|
23
23
|
|
24
|
-
require
|
25
|
-
require
|
24
|
+
require 'laborantin/core/parameter'
|
25
|
+
require 'laborantin/core/parameter_hash'
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
autoload :FileUtils, 'fileutils'
|
28
|
+
autoload :YAML, 'yaml'
|
29
|
+
|
30
|
+
require 'laborantin/core/datable'
|
31
|
+
require 'laborantin/core/describable'
|
32
|
+
require 'laborantin/core/hookable'
|
33
|
+
require 'laborantin/core/configurable'
|
34
|
+
require 'laborantin/core/multi_name'
|
35
|
+
require 'laborantin/core/table'
|
29
36
|
|
30
37
|
module Laborantin
|
31
38
|
|
@@ -41,42 +48,45 @@ module Laborantin
|
|
41
48
|
# Like the Environment, all the subklasses will be stored in a @@all
|
42
49
|
# class variable for convenience purpose.
|
43
50
|
class Scenario
|
51
|
+
include Metaprog::Datable
|
52
|
+
include Metaprog::Configurable
|
53
|
+
extend Metaprog::Describable
|
54
|
+
extend Metaprog::Hookable
|
55
|
+
extend Metaprog::MultiName
|
56
|
+
|
44
57
|
@@all = []
|
45
58
|
|
46
59
|
# Scans the env's envdir (should be an Environment) for scenarii results.
|
47
|
-
# It will set their configuration
|
48
|
-
# in YAML format.
|
49
|
-
#
|
60
|
+
# It will set their configuration (i.e. run date and parameters hash)
|
61
|
+
# according to the stored config.yaml in YAML format. Returns an array of
|
62
|
+
# such built scenarii.
|
50
63
|
def self.scan_env(env)
|
51
|
-
|
64
|
+
list = []
|
52
65
|
Dir.entries(env.rundir).each do |s|
|
53
|
-
scklass = Laborantin::Scenario.all.find{|t| t.
|
66
|
+
scklass = Laborantin::Scenario.all.find{|t| t.fs_name == s}
|
54
67
|
if scklass
|
55
68
|
Dir.entries(scklass.scenardir(env)).each do |r|
|
56
69
|
if r =~ /\d+-\w+-\d+_\d+-\d+-\d+/
|
57
|
-
scenar = scklass.
|
58
|
-
|
59
|
-
scenar.rundir = File.join(scklass.scenardir(env), r)
|
60
|
-
tst, params = YAML.load_file(File.join(scenar.rundir, 'config.yaml'))
|
61
|
-
scenar.params = params
|
70
|
+
scenar = scklass.new_loading_from_dir(env, File.join(scklass.scenardir(env), r))
|
71
|
+
list << scenar
|
62
72
|
end
|
63
73
|
end
|
64
74
|
end
|
65
75
|
end
|
66
|
-
|
76
|
+
list
|
67
77
|
end
|
68
78
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
attr_accessor :hooks
|
79
|
+
def self.new_loading_from_dir(env, path)
|
80
|
+
obj = self.new(env)
|
81
|
+
yml_path = File.join(path, 'config.yaml')
|
82
|
+
tst, params = obj.load_config!(yml_path)
|
83
|
+
obj.params = params
|
84
|
+
obj.date = tst
|
85
|
+
obj.rundir = path
|
86
|
+
obj
|
87
|
+
end
|
79
88
|
|
89
|
+
class << self
|
80
90
|
# The set of parameters that will vary for this Scenario.
|
81
91
|
attr_accessor :parameters
|
82
92
|
|
@@ -95,21 +105,6 @@ module Laborantin
|
|
95
105
|
@@all << klass
|
96
106
|
end
|
97
107
|
|
98
|
-
# Sets the description.
|
99
|
-
def describe(str)
|
100
|
-
self.description = str
|
101
|
-
end
|
102
|
-
|
103
|
-
# Registers setup hooks.
|
104
|
-
def setup(*args)
|
105
|
-
self.hooks[:setup] = [*args].flatten
|
106
|
-
end
|
107
|
-
|
108
|
-
# Register teardown hooks.
|
109
|
-
def teardown(*args)
|
110
|
-
self.hooks[:teardown] = [*args].flatten
|
111
|
-
end
|
112
|
-
|
113
108
|
# Defines a new ParameterRange instance for this Scenario.
|
114
109
|
# A block should be passed that will be evaluated in this
|
115
110
|
# ParameterRange instance's context.
|
@@ -133,10 +128,6 @@ module Laborantin
|
|
133
128
|
self.products = [*args].flatten
|
134
129
|
end
|
135
130
|
|
136
|
-
def to_s
|
137
|
-
"#{self.name}:\n\t#{self.description}\n#{self.parameters}"
|
138
|
-
end
|
139
|
-
|
140
131
|
# Returns all the known subklasses of Scenario.
|
141
132
|
def all
|
142
133
|
@@all
|
@@ -147,7 +138,7 @@ module Laborantin
|
|
147
138
|
# will use '.' as rootdir for the Scenario results.
|
148
139
|
def scenardir(env=nil)
|
149
140
|
envdir = env.rundir || '.'
|
150
|
-
File.join(envdir, self.
|
141
|
+
File.join(envdir, self.fs_name)
|
151
142
|
end
|
152
143
|
end # class <<
|
153
144
|
|
@@ -157,19 +148,20 @@ module Laborantin
|
|
157
148
|
# The environment in which we run this scenario.
|
158
149
|
attr_accessor :environment
|
159
150
|
|
160
|
-
# A date that holds the creation of the instance, it is not meaningful
|
161
|
-
# when an env was created by a call to Environment.scan_resdir.
|
162
|
-
# TODO better
|
163
|
-
attr_accessor :date
|
164
|
-
|
165
151
|
# An attribute that holds the directory where the config and the results
|
166
152
|
# are stored. Can be overridden (e.g. Scenario.scan_env does that).
|
167
153
|
attr_accessor :rundir
|
168
154
|
|
155
|
+
# Initializes a new instance contains in the env Environment, and
|
156
|
+
# for the parameter set params.
|
157
|
+
# Sets the date to Time.now for unicity (with 1sec granularity)
|
158
|
+
# Sets the rundir accessor in the directory.
|
159
|
+
# Does NOT create any directory, so the accessors can be overwritten if needed.
|
169
160
|
def initialize(env, params={})
|
170
161
|
@environment = env
|
171
162
|
@params = params
|
172
163
|
@date = Time.now
|
164
|
+
@config = {}
|
173
165
|
@rundir = File.join(self.class.scenardir(environment), date_str)
|
174
166
|
end
|
175
167
|
|
@@ -185,8 +177,10 @@ module Laborantin
|
|
185
177
|
log self.params.inspect, :info
|
186
178
|
log "Preparing directory #{rundir}"
|
187
179
|
FileUtils.mkdir_p(rundir) #TODO: ensure unicity
|
180
|
+
environment.record_scenario_dir(rundir, true)
|
188
181
|
log "Storing configuration in YAML format"
|
189
|
-
|
182
|
+
@config = [date, params]
|
183
|
+
save_config
|
190
184
|
end
|
191
185
|
|
192
186
|
# In the following order:
|
@@ -216,53 +210,82 @@ module Laborantin
|
|
216
210
|
# Appends each yielded line from this method.
|
217
211
|
def analyze!
|
218
212
|
self.class.products.each do |name|
|
219
|
-
log "
|
213
|
+
log "(#{name})"
|
220
214
|
product_file(name.to_s, 'w') do |f|
|
221
|
-
send
|
215
|
+
send(name) do |l|
|
222
216
|
f.puts l
|
223
217
|
end
|
224
218
|
end
|
225
|
-
log "Product #{name} done"
|
226
219
|
end
|
227
220
|
end
|
228
221
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
log "Calling #{name} hooks"
|
237
|
-
self.class.hooks[name].each{|sym| send sym}
|
238
|
-
end
|
239
|
-
|
240
|
-
def log(*args)
|
241
|
-
environment.log *args
|
242
|
-
end
|
243
|
-
|
222
|
+
# Returns the absolute path to a product file (see File.join) If brutname
|
223
|
+
# is true, then resultname is appended to the rundir of the scenario. If
|
224
|
+
# brutname is false, then before being appended to the rundir of the
|
225
|
+
# scenario, the name is surronded by result.<resultname>.txt
|
226
|
+
#
|
227
|
+
# The idea behind this is to avoid name collisions between simple users of
|
228
|
+
# Laborantin, and people developping extensions or modules.
|
244
229
|
def product_path(resultname, brutname=false)
|
245
230
|
resultname = "result.#{resultname}.txt" unless brutname
|
246
231
|
File.join(rundir, resultname)
|
247
232
|
end
|
248
233
|
|
234
|
+
# Yields an open file for a given product, will make sure it is closed.
|
235
|
+
# mode is the mode in which the file is opened (you should leave it to 'r')
|
236
|
+
# see the doc for product_path to understand the role of brutname
|
249
237
|
def product_file(resultname, mode='r', brutname=false)
|
250
238
|
File.open(product_path(resultname, brutname), mode) do |f|
|
251
239
|
yield f
|
252
240
|
end
|
253
241
|
end
|
254
242
|
|
243
|
+
# The path to the config.yaml file that holds the scenario parameters.
|
255
244
|
def config_path
|
256
245
|
product_path('config.yaml', true)
|
257
246
|
end
|
258
247
|
|
248
|
+
# The path to the "raw result", i.e. the one built when you yield in the
|
249
|
+
# run method.
|
259
250
|
def raw_result_path
|
260
251
|
product_path('result.raw', true)
|
261
252
|
end
|
262
253
|
|
254
|
+
# Yield the opened raw result file, will close it afterwards.
|
255
|
+
# mode is the mode in which the file is opened (default to 'r')
|
256
|
+
# never open the file in another mode, unless you know what you're doing,
|
257
|
+
# because this file most likely contains the value of your work, i.e., your
|
258
|
+
# data.
|
263
259
|
def raw_result_file(mode='r')
|
264
|
-
product_file('result.raw', mode, true)
|
260
|
+
product_file('result.raw', mode, true) do |f|
|
261
|
+
yield f
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def table(name, struct)
|
266
|
+
Table.new(name, struct, self.product_path(name))
|
265
267
|
end
|
266
268
|
|
269
|
+
private
|
270
|
+
|
271
|
+
def call_hooks(name)
|
272
|
+
log "Calling #{name} hooks"
|
273
|
+
self.class.hooks[name].each do |sym|
|
274
|
+
log "(#{sym})"
|
275
|
+
send sym
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def log(*args)
|
280
|
+
environment.log *args
|
281
|
+
end
|
282
|
+
|
283
|
+
def command
|
284
|
+
environment.command
|
285
|
+
end
|
286
|
+
|
287
|
+
def runner
|
288
|
+
environment.runner
|
289
|
+
end
|
267
290
|
end # class
|
268
291
|
end
|