coderunner 0.12.7 → 0.12.8
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/coderunner.gemspec +4 -2
- data/lib/coderunner.rb +1 -1
- data/lib/coderunner/class_methods.rb +1 -1
- data/lib/coderunner/instance_methods.rb +27 -5
- data/lib/coderunner/run.rb +24 -8
- data/lib/coderunner/system_modules/generic_linux.rb +3 -1
- data/lib/coderunner/version.rb +4 -0
- data/lib/cubecalccrmod.rb +1 -106
- data/lib/cubecalccrmod/cubecalc.rb +108 -0
- data/lib/cubecalccrmod/{cubecalc_defaults.rb → defaults_files/cubecalc_defaults.rb} +0 -0
- data/test/old_test.rb +472 -0
- data/test/test_coderunner.rb +269 -423
- metadata +4 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.12.
|
1
|
+
0.12.8
|
data/coderunner.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "coderunner"
|
8
|
-
s.version = "0.12.
|
8
|
+
s.version = "0.12.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Edmund Highcock"]
|
@@ -64,13 +64,15 @@ Gem::Specification.new do |s|
|
|
64
64
|
"lib/coderunner/test.rb",
|
65
65
|
"lib/coderunner/version.rb",
|
66
66
|
"lib/cubecalccrmod.rb",
|
67
|
-
"lib/cubecalccrmod/
|
67
|
+
"lib/cubecalccrmod/cubecalc.rb",
|
68
68
|
"lib/cubecalccrmod/default_modlets/empty_defaults.rb",
|
69
|
+
"lib/cubecalccrmod/defaults_files/cubecalc_defaults.rb",
|
69
70
|
"lib/cubecalccrmod/defaults_files/sleep_defaults.rb",
|
70
71
|
"lib/cubecalccrmod/empty.rb",
|
71
72
|
"lib/cubecalccrmod/sleep.rb",
|
72
73
|
"test/cubecalc.cc",
|
73
74
|
"test/helper.rb",
|
75
|
+
"test/old_test.rb",
|
74
76
|
"test/test_coderunner.rb"
|
75
77
|
]
|
76
78
|
s.homepage = "http://coderunner.sourceforge.net"
|
data/lib/coderunner.rb
CHANGED
@@ -111,7 +111,7 @@ eprint '.' unless $has_put_startup_message_for_code_runner
|
|
111
111
|
load CodeRunner::SCRIPT_FOLDER + "/fortran_namelist.rb"
|
112
112
|
eprint '.' unless $has_put_startup_message_for_code_runner
|
113
113
|
|
114
|
-
CodeRunner::CODE_RUNNER_VERSION = Version.new(Gem.loaded_specs['coderunner'].version.to_s)
|
114
|
+
CodeRunner::CODE_RUNNER_VERSION = Version.new(Gem.loaded_specs['coderunner'].version.to_s) rescue "test"
|
115
115
|
|
116
116
|
CodeRunner::GLOBAL_BINDING = binding
|
117
117
|
|
@@ -630,7 +630,7 @@ EOF
|
|
630
630
|
set_class_defaults(copts)
|
631
631
|
copts[:running_remotely] = true
|
632
632
|
else
|
633
|
-
copts[:Y].gsub
|
633
|
+
copts[:Y] = copts[:Y].gsub(/~/, ENV['HOME']) if copts[:Y]
|
634
634
|
Dir.chdir((copts[:Y] or Dir.pwd)) do
|
635
635
|
set_runner_defaults(copts)
|
636
636
|
# ep DEFAULT_RUNNER_OPTIONS
|
@@ -179,7 +179,8 @@ class CodeRunner
|
|
179
179
|
|
180
180
|
@version= options[:version]
|
181
181
|
# ep 'ex', @executable
|
182
|
-
|
182
|
+
ep 'modlet is ', @modlet
|
183
|
+
get_run_class
|
183
184
|
|
184
185
|
@cache = {}
|
185
186
|
|
@@ -201,6 +202,10 @@ class CodeRunner
|
|
201
202
|
@maxes = {}; @mins = {}
|
202
203
|
@cmaxes = {}; @cmins = {}
|
203
204
|
end
|
205
|
+
|
206
|
+
def get_run_class
|
207
|
+
@run_class = setup_run_class(@code, modlet: @modlet, version: @version, executable: @executable)
|
208
|
+
end
|
204
209
|
|
205
210
|
# Read the default values of runner options from the constant hash <tt>CodeRunner::DEFAULT_RUNNER_OPTIONS</tt>. This hash usually contains options set from the command line, but it can have its values edited manually in a script.
|
206
211
|
#
|
@@ -212,6 +217,7 @@ class CodeRunner
|
|
212
217
|
#ep DEFAULT_RUNNER_OPTIONS, @multiple_processes
|
213
218
|
|
214
219
|
read_folder_defaults
|
220
|
+
get_run_class
|
215
221
|
end
|
216
222
|
|
217
223
|
# Increase the value of <tt>@max_id</tt> by 1.
|
@@ -344,10 +350,11 @@ class CodeRunner
|
|
344
350
|
|
345
351
|
|
346
352
|
def self.repair_marshal_run_class_not_found_error(err)
|
353
|
+
#ep 'error', err, err.message
|
347
354
|
code, modlet = err.message.scan(/CodeRunner\:\:([A-Z][a-z0-9_]+)(?:::([A-Z]\w+))?/)[0]
|
348
355
|
#ep 'merror', err, code, modlet; gets
|
349
356
|
code.gsub!(/([a-z0-9])([A-Z])/, '\1_\2')
|
350
|
-
(modlet.gsub!(/([a-z0-9])([A-Z])/, '\1_\2'); modlet.downcase) if modlet
|
357
|
+
(modlet.gsub!(/([a-z0-9])([A-Z])/, '\1_\2'); modlet.downcase!) if modlet
|
351
358
|
setup_run_class(code.downcase, modlet: modlet)
|
352
359
|
end
|
353
360
|
|
@@ -487,7 +494,22 @@ class CodeRunner
|
|
487
494
|
#interrupted = false;
|
488
495
|
#old_trap2 = trap(2){}
|
489
496
|
#old_trap2 = trap(2){eputs "Interrupt acknowledged...#{Dir.pwd} finishing folder analyis. Interrupt again to override (may cause file corruption)."; interrupted = true}
|
490
|
-
|
497
|
+
|
498
|
+
# Here we make sure we are creating a run object of the right class for this folder
|
499
|
+
if FileTest.exist?('code_runner_info.rb') and File.read('code_runner_info.rb') =~ /Classname:.*?(?<class>[A-Z][\w:]+)/
|
500
|
+
classname = $~[:class]
|
501
|
+
begin
|
502
|
+
run_cls = Object.recursive_const_get(classname)
|
503
|
+
rescue NameError=>err
|
504
|
+
ep err, err.message
|
505
|
+
self.class.repair_marshal_run_class_not_found_error(StandardError.new(classname))
|
506
|
+
run_cls = Object.recursive_const_get(classname)
|
507
|
+
end
|
508
|
+
else
|
509
|
+
run_cls = @run_class
|
510
|
+
end
|
511
|
+
|
512
|
+
run = run_cls.new(self).process_directory #NB this doesn't always return an object of class run_class - since the run may actually be from a different code
|
491
513
|
#trap(2, old_trap2)
|
492
514
|
#(eputs "Calling old interrupt #{Dir.pwd}"; Process.kill(2, 0)) if interrupted
|
493
515
|
rescue => err
|
@@ -934,9 +956,9 @@ Conditions contain a single = sign: #{conditions}
|
|
934
956
|
# pp @run_list.values.map{|run| run.instance_variables.map{|var| [var, run.instance_variable_get(var).class]}}
|
935
957
|
|
936
958
|
generate_combined_ids
|
937
|
-
@combined_run_list.each{|id, run| run.runner = nil}
|
959
|
+
@combined_run_list.each{|id, run| run.runner = nil; run.phantom_runs.each{|pr| pr.runner=nil} if run.phantom_runs}
|
938
960
|
File.open(@root_folder + "/.CODE_RUNNER_TEMP_RUN_LIST_CACHE", 'w'){|file| file.puts Marshal.dump @run_list}
|
939
|
-
@combined_run_list.each{|id, run| run.runner = self}
|
961
|
+
@combined_run_list.each{|id, run| run.runner = self; run.phantom_runs.each{|pr| pr.runner=self} if run.phantom_runs}
|
940
962
|
end
|
941
963
|
|
942
964
|
# Self-explanatory! Call CodeRunner::Run#process_directory for every run whose status is not either :Complete or :Failed. (Note, for historical reasons traverse_directories is called rather than CodeRunner::Run#process_directory directly but the effect is nearly the same).
|
data/lib/coderunner/run.rb
CHANGED
@@ -331,7 +331,7 @@ def results_file
|
|
331
331
|
# ID: #{@id}
|
332
332
|
|
333
333
|
# Results:
|
334
|
-
#{(rcp.results+rcp.run_info).inject({}){|hash, (var,type_co)| hash[var] = send(var); hash}.pretty_inspect}
|
334
|
+
#{(rcp.results+rcp.run_info - [:phantom_runs]).inject({}){|hash, (var,type_co)| hash[var] = send(var); hash}.pretty_inspect}
|
335
335
|
|
336
336
|
# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
337
337
|
EOF
|
@@ -359,6 +359,7 @@ def save
|
|
359
359
|
runner, @runner = @runner, nil
|
360
360
|
@system_triers, old_triers = nil, @system_triers
|
361
361
|
@phantom_runs.each{|run| run.runner = nil} if @phantom_runs
|
362
|
+
#@phantom_runs.each{|run| run.runner = nil} if @phantom_runs
|
362
363
|
# logi(self)
|
363
364
|
Dir.chdir(@directory){File.open(".code_runner_run_data", 'w'){|file| file.puts Marshal.dump(self)}}
|
364
365
|
@runner = runner
|
@@ -409,13 +410,15 @@ end
|
|
409
410
|
# Return the folder where the default defaults file is located.
|
410
411
|
|
411
412
|
def defaults_location
|
412
|
-
if @runner.defaults_file
|
413
|
+
#if @runner.defaults_file
|
413
414
|
location = [rcp.user_defaults_location, rcp.code_module_folder + "/defaults_files"].find{|folder| FileTest.exist? folder and Dir.entries(folder).include? defaults_file_name}
|
414
|
-
raise "Defaults file: #{defaults_file_name} not found" unless location
|
415
|
-
|
416
|
-
|
417
|
-
return
|
418
|
-
|
415
|
+
#raise "Defaults file: #{defaults_file_name} not found" unless location
|
416
|
+
raise "Can't find defaults_file #{defaults_file_name} in #{[rcp.user_defaults_location, rcp.code_module_folder + "/defaults_files"].join(',')}." unless location
|
417
|
+
location
|
418
|
+
#return location
|
419
|
+
#else
|
420
|
+
#location = [rcp.user_defaults_location, rcp.code_module_folder + "/defaults_files"].find{|folder| FileTest.exist? folder and Dir.entries(folder).include? defaults_file_name}
|
421
|
+
#end
|
419
422
|
end
|
420
423
|
|
421
424
|
# Return true if the run is completed, false otherwise
|
@@ -680,7 +683,7 @@ def info_file
|
|
680
683
|
# #{@job_no ? "Job_No: #{@job_no}" : ""}
|
681
684
|
|
682
685
|
# Parameters:
|
683
|
-
#{(rcp.variables + rcp.run_info + [:version, :code, :modlet, :sys]).inject({}){|hash, var| hash[var] = send(var) unless (!send(var) and send(var) == nil); hash}.pretty_inspect}
|
686
|
+
#{(rcp.variables + rcp.run_info + [:version, :code, :modlet, :sys] - [:phantom_runs]).inject({}){|hash, var| hash[var] = send(var) unless (!send(var) and send(var) == nil); hash}.pretty_inspect}
|
684
687
|
|
685
688
|
|
686
689
|
# Actual Command:
|
@@ -766,6 +769,19 @@ def self.check_and_update
|
|
766
769
|
end
|
767
770
|
|
768
771
|
@readout_list = (rcp.variables+rcp.results) unless rcp.readout_list
|
772
|
+
|
773
|
+
raise "
|
774
|
+
|
775
|
+
Please add the line
|
776
|
+
|
777
|
+
-----------------------------------------------------------
|
778
|
+
@code_module_folder = folder = File.dirname(File.expand_path(__FILE__)) # i.e. the directory this file is in
|
779
|
+
---------------------------------------------------------
|
780
|
+
|
781
|
+
to your code module.
|
782
|
+
|
783
|
+
" unless rcp.code_module_folder
|
784
|
+
|
769
785
|
# (variables+results).each{|v| const_get(:READOUT_LIST).push v} unless READOUT_LIST.size > 0
|
770
786
|
|
771
787
|
#if rcp.variables_0_5_0
|
data/lib/coderunner/version.rb
CHANGED
data/lib/cubecalccrmod.rb
CHANGED
@@ -1,106 +1 @@
|
|
1
|
-
|
2
|
-
class Cubecalc < Run
|
3
|
-
|
4
|
-
# @code = 'cubecalc'
|
5
|
-
|
6
|
-
@variables = [:calculate_sides, :width, :height, :depth, :area]
|
7
|
-
|
8
|
-
@naming_pars = [:width]
|
9
|
-
|
10
|
-
@results = [:volume, :sides]
|
11
|
-
|
12
|
-
# e.g. number of iterations
|
13
|
-
|
14
|
-
@run_info = [:phantom_run_description]
|
15
|
-
|
16
|
-
# @@executable_name = 'cubecalc'
|
17
|
-
|
18
|
-
@code_long = "Cube Volume Calculator"
|
19
|
-
|
20
|
-
@excluded_sub_folders = []
|
21
|
-
|
22
|
-
@defaults_file_name = "cubecalc_defaults.rb"
|
23
|
-
|
24
|
-
@modlet_required = true
|
25
|
-
|
26
|
-
@uses_mpi = false
|
27
|
-
|
28
|
-
def process_directory_code_specific
|
29
|
-
if @running
|
30
|
-
@status = :Incomplete
|
31
|
-
else
|
32
|
-
if FileTest.exist? 'results.txt'
|
33
|
-
@status = :Complete
|
34
|
-
@volume = File.readlines('results.txt')[0].scan(LongRegexen::FLOAT)[0][0].to_f
|
35
|
-
else
|
36
|
-
@status = :Failed
|
37
|
-
end
|
38
|
-
@sides = []
|
39
|
-
if FileTest.exist? 'sides.txt'
|
40
|
-
File.read('sides.txt').scan(Regexp.new("is\\s*" + LongRegexen::FLOAT.verbatim + "$")){@sides.push $~[:float].to_f}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def print_out_line
|
46
|
-
if @is_phantom
|
47
|
-
if @phantom_run_description == :area
|
48
|
-
return sprintf("%d:%d %30s %10s %f %s", @id, @job_no, @run_name, @status, (@volume or 0.0), @area.to_s)
|
49
|
-
else
|
50
|
-
raise 'there is only one phantom_run_description at the moment'
|
51
|
-
end
|
52
|
-
else
|
53
|
-
return sprintf("%d:%d %30s %10s %f %s", @id, @job_no, @run_name, @status, (@volume or 0.0), @sides.to_s)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def parameter_string
|
58
|
-
return sprintf("%d %s", @calculate_sides, 'edges.txt')
|
59
|
-
end
|
60
|
-
|
61
|
-
def generate_input_file
|
62
|
-
File.open('edges.txt', 'w') do |file|
|
63
|
-
file.puts @width
|
64
|
-
file.puts @height
|
65
|
-
file.puts @depth
|
66
|
-
end
|
67
|
-
end
|
68
|
-
# @run_class.variables.keys[0]
|
69
|
-
def parameter_transition(run)
|
70
|
-
end
|
71
|
-
|
72
|
-
def executable_location
|
73
|
-
@runner.script_folder + '/test_suite'
|
74
|
-
end
|
75
|
-
|
76
|
-
|
77
|
-
def generate_phantom_runs
|
78
|
-
return unless @sides
|
79
|
-
@sides.each do |area|
|
80
|
-
# puts 'creating phantom: ' + @run_name
|
81
|
-
phantom = create_phantom
|
82
|
-
phantom.area = area
|
83
|
-
phantom.phantom_run_description = :area
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def graphkit(name, options)
|
88
|
-
case name
|
89
|
-
when /sides/
|
90
|
-
# x = AxisKit.autocreate({data: ["'width'", "'depth'", "'height'"], name: 'Properties'})
|
91
|
-
x = GraphKit::AxisKit.autocreate({data: sides, title: "Areas of the Sides: #@run_name"})
|
92
|
-
# x.range = [0, x.data.max]
|
93
|
-
kit = GraphKit.autocreate({x: x})
|
94
|
-
kit.style = 'data histograms'
|
95
|
-
kit.file_name = 'inputs'
|
96
|
-
# kit.with = 'histogram clustered'
|
97
|
-
return kit
|
98
|
-
else
|
99
|
-
raise 'Unknown graph'
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
1
|
+
require 'cubecalccrmod/cubecalc'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class CodeRunner
|
2
|
+
class Cubecalc < Run
|
3
|
+
|
4
|
+
# @code = 'cubecalc'
|
5
|
+
|
6
|
+
@variables = [:calculate_sides, :width, :height, :depth, :area]
|
7
|
+
|
8
|
+
@naming_pars = [:width]
|
9
|
+
|
10
|
+
@results = [:volume, :sides]
|
11
|
+
|
12
|
+
# e.g. number of iterations
|
13
|
+
|
14
|
+
@run_info = [:phantom_run_description]
|
15
|
+
|
16
|
+
# @@executable_name = 'cubecalc'
|
17
|
+
|
18
|
+
@code_long = "Cube Volume Calculator"
|
19
|
+
|
20
|
+
@excluded_sub_folders = []
|
21
|
+
|
22
|
+
@defaults_file_name = "cubecalc_defaults.rb"
|
23
|
+
|
24
|
+
@modlet_required = true
|
25
|
+
|
26
|
+
@uses_mpi = false
|
27
|
+
|
28
|
+
@code_module_folder = folder = File.dirname(File.expand_path(__FILE__)) # i.e. the directory this file is in
|
29
|
+
|
30
|
+
def process_directory_code_specific
|
31
|
+
if @running
|
32
|
+
@status = :Incomplete
|
33
|
+
else
|
34
|
+
if FileTest.exist? 'results.txt'
|
35
|
+
@status = :Complete
|
36
|
+
@volume = File.readlines('results.txt')[0].scan(LongRegexen::FLOAT)[0][0].to_f
|
37
|
+
else
|
38
|
+
@status = :Failed
|
39
|
+
end
|
40
|
+
@sides = []
|
41
|
+
if FileTest.exist? 'sides.txt'
|
42
|
+
File.read('sides.txt').scan(Regexp.new("is\\s*" + LongRegexen::FLOAT.verbatim + "$")){@sides.push $~[:float].to_f}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def print_out_line
|
48
|
+
if @is_phantom
|
49
|
+
if @phantom_run_description == :area
|
50
|
+
return sprintf("%d:%d %30s %10s %f %s", @id, @job_no, @run_name, @status, (@volume or 0.0), @area.to_s)
|
51
|
+
else
|
52
|
+
raise 'there is only one phantom_run_description at the moment'
|
53
|
+
end
|
54
|
+
else
|
55
|
+
return sprintf("%d:%d %30s %10s %f %s", @id, @job_no, @run_name, @status, (@volume or 0.0), @sides.to_s)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def parameter_string
|
60
|
+
return sprintf("%d %s", @calculate_sides, 'edges.txt')
|
61
|
+
end
|
62
|
+
|
63
|
+
def generate_input_file
|
64
|
+
File.open('edges.txt', 'w') do |file|
|
65
|
+
file.puts @width
|
66
|
+
file.puts @height
|
67
|
+
file.puts @depth
|
68
|
+
end
|
69
|
+
end
|
70
|
+
# @run_class.variables.keys[0]
|
71
|
+
def parameter_transition(run)
|
72
|
+
end
|
73
|
+
|
74
|
+
#def executable_location
|
75
|
+
#@runner.script_folder + '/test_suite'
|
76
|
+
#end
|
77
|
+
|
78
|
+
|
79
|
+
def generate_phantom_runs
|
80
|
+
return unless @sides
|
81
|
+
@sides.each do |area|
|
82
|
+
# puts 'creating phantom: ' + @run_name
|
83
|
+
phantom = create_phantom
|
84
|
+
phantom.area = area
|
85
|
+
phantom.phantom_run_description = :area
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def graphkit(name, options)
|
90
|
+
case name
|
91
|
+
when /sides/
|
92
|
+
# x = AxisKit.autocreate({data: ["'width'", "'depth'", "'height'"], name: 'Properties'})
|
93
|
+
x = GraphKit::AxisKit.autocreate({data: sides, title: "Areas of the Sides: #@run_name"})
|
94
|
+
# x.range = [0, x.data.max]
|
95
|
+
kit = GraphKit.autocreate({x: x})
|
96
|
+
kit.style = 'data histograms'
|
97
|
+
kit.file_name = 'inputs'
|
98
|
+
# kit.with = 'histogram clustered'
|
99
|
+
return kit
|
100
|
+
else
|
101
|
+
raise 'Unknown graph'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
File without changes
|
data/test/old_test.rb
ADDED
@@ -0,0 +1,472 @@
|
|
1
|
+
require 'coderunner'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
module Test::Unit::Assertions
|
5
|
+
def assert_system(string)
|
6
|
+
assert(system(string), "System Command: '#{string}'")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
`g++ cubecalc.cc -o cubecalc`
|
11
|
+
|
12
|
+
|
13
|
+
ppipe = PPipe.new(10, false, redirect: true)
|
14
|
+
|
15
|
+
raise "Please Specify Tests" unless ARGV[-1]
|
16
|
+
|
17
|
+
# CodeRunner::SYS = (ENV['CODE_RUNNER_SYSTEM'] or 'genericlinux')
|
18
|
+
|
19
|
+
if ARGV[-1] =~ /0/
|
20
|
+
if FileTest.exist? 'results'
|
21
|
+
FileUtils.rm_r 'results'
|
22
|
+
end
|
23
|
+
FileUtils.makedirs 'results'
|
24
|
+
|
25
|
+
Dir.chdir('results') do
|
26
|
+
|
27
|
+
puts 'testing test submission'
|
28
|
+
exit unless system %[ruby ../lib/coderunner.rb submit -C cubecalc -m sleep -D sleep -X ../cubecalc -T]
|
29
|
+
raise "didn't find defaults" unless FileTest.exist? 'sleep_defaults.rb'
|
30
|
+
puts 'testing test submission complete'
|
31
|
+
|
32
|
+
puts 'testing job_no detection'
|
33
|
+
puts fork{system %[ruby ../lib/coderunner.rb sub -p "{sleep_time: 4}"]}
|
34
|
+
sleep 2
|
35
|
+
#exit unless system %[ps | grep cubecalc]
|
36
|
+
Process.waitall
|
37
|
+
puts 'testing job_no detection complete'
|
38
|
+
|
39
|
+
#exit
|
40
|
+
|
41
|
+
|
42
|
+
puts 'testing canceling a job (not deleting)'
|
43
|
+
fork{system %[ruby ../../coderunner.rb sub -p "{sleep_time: 900}"]}
|
44
|
+
sleep 3
|
45
|
+
fork{system %[ruby ../../coderunner.rb sub -p "{sleep_time: 900, height: 3.0}"]}
|
46
|
+
sleep 4
|
47
|
+
runner = CodeRunner.new(Dir.pwd).update
|
48
|
+
runner.print_out(0)
|
49
|
+
runner.print_out_size = 0
|
50
|
+
runner.cancel_job(2, no_confirm: true, delete: false)
|
51
|
+
#pipe = ppipe.fork do
|
52
|
+
#runner.cancel_job(2)
|
53
|
+
#end
|
54
|
+
##3.times{puts ppipe.gets}
|
55
|
+
#2.times{ppipe.puts(pipe, "")}
|
56
|
+
#puts 'confirming...'
|
57
|
+
## sleep 0.5
|
58
|
+
##2.times{puts ppipe.gets}
|
59
|
+
#puts 'about to say no'
|
60
|
+
#ppipe.puts(pipe, "n")
|
61
|
+
## 9.times{puts ppipe.gets}
|
62
|
+
|
63
|
+
#exit
|
64
|
+
|
65
|
+
puts 'testing cancelling with deleting'
|
66
|
+
|
67
|
+
runner.update
|
68
|
+
runner.print_out(0)
|
69
|
+
runner.print_out_size = 0
|
70
|
+
runner.cancel_job(3, no_confirm: true, delete: true)
|
71
|
+
#pipe = ppipe.fork do
|
72
|
+
#runner.cancel_job(3)
|
73
|
+
#end
|
74
|
+
## 2.times{puts ppipe.gets}
|
75
|
+
#puts 'confirming...'
|
76
|
+
#ppipe.puts(pipe, "")
|
77
|
+
## ppipe.puts(pipe, "\n")
|
78
|
+
## sleep 0.5
|
79
|
+
## 2.times{puts ppipe.gets}
|
80
|
+
#puts 'about to say yes'
|
81
|
+
#ppipe.puts(pipe, "y")
|
82
|
+
## 8.times{puts ppipe.gets}
|
83
|
+
|
84
|
+
puts 'testing canceling complete'
|
85
|
+
|
86
|
+
#exit
|
87
|
+
|
88
|
+
# exit
|
89
|
+
|
90
|
+
puts
|
91
|
+
puts 'testing parameter scan'
|
92
|
+
File.open('parameter_scan.rb', 'w') do |file|
|
93
|
+
file.puts [
|
94
|
+
[
|
95
|
+
['width', [0.3, 0.5]], ['height', [0.5, 4.3]]
|
96
|
+
],
|
97
|
+
[
|
98
|
+
['width', [7.2]], ['height', [3.6, 12.6]]
|
99
|
+
]
|
100
|
+
].inspect
|
101
|
+
end
|
102
|
+
exit unless system %[ruby ../../coderunner.rb ps parameter_scan.rb]
|
103
|
+
# # exit unless system %[ruby ../../coderunner.rb -UN -O "width height"]
|
104
|
+
runner.update
|
105
|
+
runner.print_out(0)
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
# exit
|
110
|
+
#
|
111
|
+
end
|
112
|
+
|
113
|
+
end # if ARGV[0] == 's'
|
114
|
+
|
115
|
+
# exit
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
if ARGV[-1] =~ /1/
|
120
|
+
FileUtils.rm_r 'results' if FileTest.exist? 'results'
|
121
|
+
FileUtils.makedirs 'results'
|
122
|
+
|
123
|
+
# CodeRunner::SYS = ENV['CODE_RUNNER_SYSTEM'] = 'genericlinux_testsystem' if CodeRunner::SYS == 'genericlinux'
|
124
|
+
|
125
|
+
Dir.chdir('results') do
|
126
|
+
|
127
|
+
|
128
|
+
exit unless system %[ruby ../../coderunner.rb submit -C cubecalc -m empty -X ../cubecalc -T]
|
129
|
+
|
130
|
+
defs = File.read('cubecalc_defaults.rb')
|
131
|
+
File.open('cubecalc_defaults.rb', 'w'){|f| f.puts defs.sub(/(sides\s+=\s+)0/, '\11')}
|
132
|
+
|
133
|
+
puts 'testing submission with -p flag'
|
134
|
+
|
135
|
+
exit unless system %[ruby ../../coderunner.rb submit -p "{width: 3.0, height: 8.0}"]
|
136
|
+
raise "didn't find defaults" unless FileTest.exist? 'cubecalc_defaults.rb'
|
137
|
+
puts 'testing submission with -p flag complete'
|
138
|
+
# exit
|
139
|
+
|
140
|
+
puts 'testing printing out status'
|
141
|
+
exit unless system %[ruby ../../coderunner.rb status -N]
|
142
|
+
puts 'that should have raised a TerminalError from print_out'
|
143
|
+
ENV['ROWS'] = Terminal.terminal_size[0].to_s
|
144
|
+
ENV['COLS'] = Terminal.terminal_size[1].to_s
|
145
|
+
puts ENV['ROWS'], ENV['COLS']
|
146
|
+
exit unless system %[ruby ../../coderunner.rb st -N]
|
147
|
+
runner = CodeRunner.new(Dir.pwd).update
|
148
|
+
runner.print_out(0)
|
149
|
+
puts 'testing printing out status complete'
|
150
|
+
|
151
|
+
puts 'testing using large cache'
|
152
|
+
%x[ruby ../../coderunner.rb sub -p "{width: 3.0, height: 6.0}"]
|
153
|
+
%x[ruby ../../coderunner.rb sub -p "{width: 3.0, height: 9.0}"]
|
154
|
+
puts "using large cache without updating"
|
155
|
+
runner.use_large_cache = true
|
156
|
+
runner.update.print_out(0)
|
157
|
+
puts 'using large cache after updating'
|
158
|
+
runner.update
|
159
|
+
runner.use_large_cache = true
|
160
|
+
runner.update.print_out(0)
|
161
|
+
puts 'testing using large cache complete'
|
162
|
+
|
163
|
+
puts 'testing sorting'
|
164
|
+
%x[ruby ../../coderunner.rb sub -p "{width: 12.0, height: 9.0}"]
|
165
|
+
%x[ruby ../../coderunner.rb sub -p "{width: 5.0, height: 6.0}"]
|
166
|
+
puts '----', 'unsorted'
|
167
|
+
exit unless system %[ruby ../../coderunner.rb st -N]
|
168
|
+
puts '----', 'sort by volume'
|
169
|
+
exit unless system %[ruby ../../coderunner.rb st -O "volume" -N]
|
170
|
+
puts '----','sort by width then by height'
|
171
|
+
exit unless system %[ruby ../../coderunner.rb st -O "width;height" -N]
|
172
|
+
puts 'testing sorting complete'
|
173
|
+
|
174
|
+
puts 'testing getting directory'
|
175
|
+
exit unless system %[ruby ../../coderunner.rb dir 3 -UN ]
|
176
|
+
puts 'testing getting directory complete'
|
177
|
+
|
178
|
+
puts 'testing filtering'
|
179
|
+
puts '----', 'height == 9.0'
|
180
|
+
exit unless system %[ruby ../../coderunner.rb st -UNf "height == 9.0"]
|
181
|
+
puts '----', 'id == 1 or width == 12.0'
|
182
|
+
exit unless system %[ruby ../../coderunner.rb st -UNf 'id == 1 or width == 12.0']
|
183
|
+
puts 'testing filtering complete'
|
184
|
+
|
185
|
+
# exit
|
186
|
+
|
187
|
+
puts 'testing phantom runs'
|
188
|
+
exit unless system %[ruby ../../coderunner.rb st -UN -h -O "volume;area"]
|
189
|
+
puts 'testing using both'
|
190
|
+
exit unless system %[ruby ../../coderunner.rb st -UN -h both -O "volume;id"]
|
191
|
+
puts 'testing phantom runs complete'
|
192
|
+
|
193
|
+
puts 'testing readout'
|
194
|
+
exit unless system %[ruby ../../coderunner.rb ro -UN -O "width;height"]
|
195
|
+
puts 'testing readout complete'
|
196
|
+
|
197
|
+
puts 'testing run eval'
|
198
|
+
exit unless system %[ruby ../../coderunner.rb rc "puts %[hello I am run \#\@run_name]" -U -f "id ==1" ]
|
199
|
+
puts 'testing run eval complete'
|
200
|
+
|
201
|
+
puts 'testing graph plotting'
|
202
|
+
exit unless system %[ruby ../../coderunner.rb sub -p "{width: 11.0, height: 9.0, depth: 2.0}"]
|
203
|
+
|
204
|
+
# IO.popen(%[ruby ../../coderunner.rb -U -g "width*height*depth:volume"]) do |pipe|
|
205
|
+
# sleep 1
|
206
|
+
# pipe.puts
|
207
|
+
# end
|
208
|
+
exit unless system %[ruby ../../coderunner.rb wg graph.ps -O volume -G "width*height*depth:volume"]
|
209
|
+
exit unless system %[ruby ../../coderunner.rb wg graph1.ps -U -O volume -G "width:height:depth:volume;;;height"]
|
210
|
+
exit unless system %[ruby ../../coderunner.rb wg "" -U -f "id==1 or id == 2" -g "sides"]
|
211
|
+
puts 'testing graph plotting complete'
|
212
|
+
|
213
|
+
puts 'testing max'
|
214
|
+
exit unless system %[ruby ../../coderunner.rb st -U -f "max(:volume)"]
|
215
|
+
exit unless system %[ruby ../../coderunner.rb st -U -f "width == 3.0 and smax(:volume, :height)"]
|
216
|
+
puts 'testing max complete'
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
#
|
225
|
+
# # puts 'testing interactive mode'
|
226
|
+
# # IO.popen(%[ruby ../../coderunner.rb -i]) do |pipe|
|
227
|
+
# # pipe.puts 'cr'
|
228
|
+
# # pipe.puts 'exit'
|
229
|
+
# # end
|
230
|
+
# # puts 'testing interactive mode'
|
231
|
+
|
232
|
+
end # Dir.chdir
|
233
|
+
|
234
|
+
end # if
|
235
|
+
|
236
|
+
p ARGV[-1] =~ /2/
|
237
|
+
|
238
|
+
if ARGV[-1] =~ /2/
|
239
|
+
|
240
|
+
FileUtils.rm_r 'results' if FileTest.exist? 'results'
|
241
|
+
FileUtils.makedirs 'results'
|
242
|
+
|
243
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', C: 'cubecalc', m: 'empty', X: '../cubecalc', T: true)
|
244
|
+
# exit
|
245
|
+
defs = File.read('results/cubecalc_defaults.rb')
|
246
|
+
File.open('results/cubecalc_defaults.rb', 'w'){|f| f.puts defs.sub(/\#(@calculate_sides\s+=\s+)0/, '\11')}
|
247
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 3.0, height: 8.0}")
|
248
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 3.0, height: 6.0}")
|
249
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 3.0, height: 9.0}")
|
250
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 12.0, height: 9.0}")
|
251
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 5.0, height: 6.0}")
|
252
|
+
CodeRunner.submit(Y: Dir.pwd + '/results', p: "{width: 11.0, height: 9.0, depth: 2.0}")
|
253
|
+
|
254
|
+
class TestCodeRunner < Test::Unit::TestCase
|
255
|
+
|
256
|
+
# Override this method as we want the tests to be run in the order they are defined
|
257
|
+
|
258
|
+
def self.test_methods
|
259
|
+
public_instance_methods(true).grep(/^test/).map { |m| m.to_s}
|
260
|
+
end
|
261
|
+
|
262
|
+
def setup
|
263
|
+
@runner = CodeRunner.fetch_runner(Y: Dir.pwd + '/results').update
|
264
|
+
end
|
265
|
+
|
266
|
+
def teardown
|
267
|
+
end
|
268
|
+
|
269
|
+
def cl(command)
|
270
|
+
Dir.chdir('results'){assert_system command}
|
271
|
+
end
|
272
|
+
|
273
|
+
def cl2(command)
|
274
|
+
Dir.chdir('results3'){assert_system command}
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
def cl3(command)
|
279
|
+
Dir.chdir('results3'){assert_system command}
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
#def test_remote_coderunner
|
284
|
+
#puts 'testing remote coderunner'
|
285
|
+
#rc = RemoteCodeRunner.new(ENV['USER'] + '@localhost', Dir.pwd + '/results', U: true, N: true).update
|
286
|
+
#assert_equal(@runner.ids.sort, rc.ids.sort)
|
287
|
+
#rc.print_out(0)
|
288
|
+
#wdvh = rc.graphkit("width:height:depth:volume;;;height")
|
289
|
+
#wdvh.gnuplot
|
290
|
+
#assert_equal(4, wdvh.naxes)
|
291
|
+
#assert_equal(1, wdvh.data.size)
|
292
|
+
#assert_equal([30.0, 18.0, 24.0, 108.0, 27.0, 198.0], wdvh.data[0].axes[:f].data)
|
293
|
+
#sds = rc.run_graphkit('sides;;[1,2].include? id')
|
294
|
+
## sds.gnuplot
|
295
|
+
#wdvh.close
|
296
|
+
#puts 'testing remote coderunner complete'
|
297
|
+
#end
|
298
|
+
|
299
|
+
#def test_run_eval_saving
|
300
|
+
#puts "\nTesting run command saving"
|
301
|
+
#cl(%[ruby ../../coderunner.rb rc '@test_var = :will_o_the_wisp' -U])
|
302
|
+
#@runner.update(false, true)
|
303
|
+
#assert_equal(:will_o_the_wisp, @runner.run_list[1].instance_variable_get(:@test_var))
|
304
|
+
#cl(%[ruby ../../coderunner.rb rc '@test_var2 = :will_o_the_wisps' -U -M 3])
|
305
|
+
|
306
|
+
#@runner.update(false, true)
|
307
|
+
#assert_equal(:will_o_the_wisps, @runner.run_list[1].instance_variable_get(:@test_var2))
|
308
|
+
#puts 'finished testing run command saving'
|
309
|
+
#end
|
310
|
+
|
311
|
+
#def test_relative_directory
|
312
|
+
#puts "\nTesting relative directory"
|
313
|
+
#@runner.recalc_all = true
|
314
|
+
#puts 'updating fully'
|
315
|
+
#@runner.update #(true, false)
|
316
|
+
#FileUtils.rm_r('results2') if FileTest.exist? 'results2'
|
317
|
+
#FileUtils.cp_r('results', 'results2')
|
318
|
+
#r = CodeRunner.fetch_runner(Y: 'results2', U: true)
|
319
|
+
#r.update(false)
|
320
|
+
#assert_equal(Dir.pwd + '/results', @runner.root_folder)
|
321
|
+
#assert_equal(Dir.pwd + '/results2', r.root_folder)
|
322
|
+
#assert_equal(@runner.run_list[1].directory.sub(File.expand_path(@runner.root_folder) + '/', ''), r.run_list[1].relative_directory)
|
323
|
+
#assert_equal(r.root_folder + '/' + r.run_list[1].relative_directory, r.run_list[1].directory)
|
324
|
+
#end
|
325
|
+
|
326
|
+
#def test_set_start_id
|
327
|
+
#eputs "\ntesting set_start_id"
|
328
|
+
#FileUtils.rm_r 'results3' if FileTest.exist?('results3')
|
329
|
+
#FileUtils.mkdir('results3')
|
330
|
+
#cl3('ruby ../../coderunner.rb st -C cubecalc -m empty -X ../cubecalc -T')
|
331
|
+
#cl3("ruby ../../coderunner.rb ev 'set_start_id(20)'")
|
332
|
+
#cl3('ruby ../../coderunner.rb sub -p "{width: 12.0, height: 9.0}"')
|
333
|
+
#@runner3 = CodeRunner.new(Dir.pwd + '/results3').update
|
334
|
+
#assert_equal(20, @runner3.start_id)
|
335
|
+
#assert_equal(21, @runner3.max_id)
|
336
|
+
#eputs "\ntesting set_start_id complete"
|
337
|
+
#end
|
338
|
+
|
339
|
+
#def test_merged_code_runner
|
340
|
+
#@runner3 = CodeRunner.new(Dir.pwd + '/results3').update
|
341
|
+
#assert_nothing_raised{@mrunner = CodeRunner::Merged.new(@runner, @runner3)}
|
342
|
+
#@mrunner.print_out(0)
|
343
|
+
#assert_equal(@runner.run_list.size + 1, @mrunner.run_list.size)
|
344
|
+
#@mrunner2 = @runner.merge(@runner3)
|
345
|
+
#assert_equal(@mrunner2.run_list.keys, @mrunner.run_list.keys)
|
346
|
+
#end
|
347
|
+
|
348
|
+
#def test_alter_ids
|
349
|
+
#FileUtils.rm_r('results4') if FileTest.exist? 'results4'
|
350
|
+
#FileUtils.cp_r('results', 'results4')
|
351
|
+
#@runner4 = CodeRunner.new(Dir.pwd + '/results4').update
|
352
|
+
#@runner4.alter_ids(40, no_confirm: true)
|
353
|
+
#@runner4a = CodeRunner.new(Dir.pwd + '/results4').update
|
354
|
+
#assert_equal(@runner.ids.map{|id| id + 40}.sort, @runner4.ids.sort)
|
355
|
+
#assert_equal(@runner4a.ids.sort, @runner4.ids.sort)
|
356
|
+
#@runner4.alter_ids(40, no_confirm: true)
|
357
|
+
#@runner4a.update
|
358
|
+
#assert_equal(@runner.ids.map{|id| id + 80}.sort, @runner4.ids.sort)
|
359
|
+
#assert_equal(@runner4a.ids.sort, @runner4.ids.sort)
|
360
|
+
#run = @runner4.run_list.values[0]
|
361
|
+
#assert(FileTest.exist?(run.directory), "Run directory exists")
|
362
|
+
#assert_equal(run.id, eval(File.read(run.directory + '/code_runner_info.rb'))[:id])
|
363
|
+
#end
|
364
|
+
|
365
|
+
#def test_submit_non_parallel_with_large_cache
|
366
|
+
#FileUtils.touch('results/submitting')
|
367
|
+
## fork{cl('ruby ../../coderunner.rb sub -p "{width: 1.887, height: 9.0}"')}
|
368
|
+
#fork{CodeRunner.submit(Y: 'results', p: "{width: 1.887, height: 9.0}", U: true)}
|
369
|
+
#sleep 1.0
|
370
|
+
#@runner.update(true, false)
|
371
|
+
#assert_equal(0, @runner.run_list.values.find_all{|run| run.width==1.887}.size)
|
372
|
+
#FileUtils.rm('results/submitting')
|
373
|
+
#i = 0
|
374
|
+
#Process.waitall
|
375
|
+
## (@runner.update(true, true); sleep 0.5; i+=1 ; flunk if i==20) until @runner.run_list.values.find{|run| run.width==1.887}
|
376
|
+
#@runner.update(true, true)
|
377
|
+
#assert_equal(1, @runner.run_list.values.find_all{|run| run.width==1.887}.size)
|
378
|
+
#@runner.conditions = "id==7"
|
379
|
+
#@runner.destroy(no_confirm: true)
|
380
|
+
#assert_equal(0, @runner.run_list.values.find_all{|run| run.width==1.887}.size)
|
381
|
+
#assert_raise(RuntimeError){CodeRunner.submit(Y: 'results', p: "{run_test_flags: {test_submit_error_handling: true}}", U: true)}
|
382
|
+
#assert(!FileTest.exist?('results/submitting'))
|
383
|
+
#end
|
384
|
+
|
385
|
+
def test_latex_graphkit
|
386
|
+
sds = @runner.run_graphkit('sides;;[1,2].include? id')
|
387
|
+
p sds
|
388
|
+
sds.ylabel = 'Hello'
|
389
|
+
sds.data.each_with_index{|dk,i| dk.title = i.to_s}
|
390
|
+
sds.xlabel = '\(\Gamma_{\epsilon}\)'
|
391
|
+
sds.title = 'Area of the Sides'
|
392
|
+
#pid1 = sds.gnuplot
|
393
|
+
|
394
|
+
sds.gnuplot_write('latgraph.eps', latex: true)
|
395
|
+
#pid = forkex "okular latgraph.eps"
|
396
|
+
sleep 3
|
397
|
+
#Process.kill 'TERM', pid
|
398
|
+
#Process.kill 'TERM', pid1
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_graphkit_multiplot
|
402
|
+
|
403
|
+
######################
|
404
|
+
# Make 3 random graphs
|
405
|
+
######################
|
406
|
+
|
407
|
+
|
408
|
+
# As usual, data can be an array or a GSL::Vector
|
409
|
+
kit1 = GraphKit.autocreate(x: {data: [0,2,4], title: 'A label with latex \(\Gamma_\epsilon \chi\)', units: '\(\nu e\)'}, y: {data: [3.3, 5.5, 10], title: 'Label with latex \(\beta\)', units: '\(v_{thi}\)'})
|
410
|
+
kit1.title = 'First Graph'
|
411
|
+
kit1.gp.label = '\'A label\' at 2,7' # This 'gp' syntax is new. You can set pretty much any gnuplot option like this - see gnuplot help set
|
412
|
+
kit1.data[0].title = 'A new title'
|
413
|
+
|
414
|
+
kit2 = GraphKit.autocreate(x: {data: [0,2,4], title: 'Stuff \(\Gamma_\epsilon \chi\)', units: '\(\nu e\)'}, y: {data: [2, -1, 2], title: 'Some \(\beta\)', units: '\(v_{thi}\)'})
|
415
|
+
kit2.title = 'Second Graph'
|
416
|
+
kit2.data[0].gp.with = 'lp linewidth 6' # See gnuplot help plot for data options
|
417
|
+
kit2.gp.key = 'off'
|
418
|
+
kit2.xlabel = 'A NEW XLABEL'
|
419
|
+
|
420
|
+
kit3 = GraphKit.autocreate(x: {data: [0,5,10], title: 'Mouse Height \(\Gamma_\epsilon \chi\)', units: '\(\nu e\)'}, y: {data: [4, 3, 4], title: 'Mouse weight \(\kappa\)', units: '\(v_{thi}\)'})
|
421
|
+
kit3.title = 'Mouse info'
|
422
|
+
kit3.data[0].gp.with = 'lp'
|
423
|
+
kit3.gp.key = 'off'
|
424
|
+
|
425
|
+
#####################
|
426
|
+
# Plot a single one
|
427
|
+
#####################
|
428
|
+
|
429
|
+
kit1.gnuplot_write('first_graph.eps', latex: true) #Just plot it by itself
|
430
|
+
|
431
|
+
###########################
|
432
|
+
# Plot multiple graphs
|
433
|
+
##########################
|
434
|
+
|
435
|
+
kit1.gnuplot_write('aname.eps', latex: true)
|
436
|
+
kit2.gnuplot_write('anothername.eps', latex: true)
|
437
|
+
kit3.gnuplot_write('athirdname.eps', latex: true, size: "2.0in,2.0in")
|
438
|
+
|
439
|
+
my_preamble = <<EOF
|
440
|
+
\\documentclass{article}
|
441
|
+
%\documentclass[aip,reprint]{}
|
442
|
+
\\usepackage{graphics,bm,overpic,subfigure,color}
|
443
|
+
|
444
|
+
\\pagestyle{empty}
|
445
|
+
\\begin{document}
|
446
|
+
\\begin{figure}
|
447
|
+
EOF
|
448
|
+
|
449
|
+
|
450
|
+
# Can use default preamble - just don't include preamble option in function call GraphKit.latex_multiplot('all_graphs.eps')
|
451
|
+
GraphKit.latex_multiplot('all_graphs.eps', preamble: my_preamble) do
|
452
|
+
<<EOF
|
453
|
+
\\subfigure{
|
454
|
+
\\includegraphics{aname}
|
455
|
+
}
|
456
|
+
\\subfigure{
|
457
|
+
\\begin{overpic}{anothername}
|
458
|
+
% The location is in percent of image width
|
459
|
+
\\put(44,22){\\includegraphics[scale=.45]
|
460
|
+
{athirdname}}
|
461
|
+
\\end{overpic}
|
462
|
+
}
|
463
|
+
EOF
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
|
468
|
+
end # def
|
469
|
+
|
470
|
+
end # class TestCodeRunner
|
471
|
+
|
472
|
+
end
|