coderunner 0.12.7 → 0.12.8
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/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
|