laborantin 0.0.14 → 0.0.21
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/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
|