ciat 0.4.8 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -4
- data/lib/ciat.rb +3 -5
- data/lib/ciat/differs/html_differ.rb +3 -4
- data/lib/ciat/erb_helpers.rb +6 -4
- data/lib/ciat/feedback/composite.rb +2 -2
- data/lib/ciat/feedback/feedback_counter.rb +2 -2
- data/lib/ciat/feedback/html_feedback.rb +25 -8
- data/lib/ciat/feedback/html_feedback_builder.rb +28 -0
- data/lib/ciat/feedback/return_status.rb +1 -1
- data/lib/ciat/feedback/standard_output.rb +1 -1
- data/lib/ciat/io.rb +17 -0
- data/lib/ciat/processors/basic_processing.rb +21 -30
- data/lib/ciat/{executors → processors}/java.rb +7 -8
- data/lib/ciat/{executors → processors}/parrot.rb +9 -10
- data/lib/ciat/rake_task.rb +1 -1
- data/lib/ciat/subresult.rb +20 -0
- data/lib/ciat/suite.rb +27 -38
- data/lib/ciat/suite_builder.rb +54 -0
- data/lib/ciat/test.rb +32 -18
- data/lib/ciat/test_element.rb +7 -2
- data/lib/ciat/{crate.rb → test_file.rb} +24 -16
- data/lib/ciat/test_result.rb +24 -0
- data/lib/ciat/traffic_light.rb +6 -0
- data/lib/templates/detail_row.html.erb +5 -4
- data/lib/templates/group_header.html.erb +2 -2
- data/lib/templates/report.html.erb +1 -1
- data/lib/templates/summary_row.html.erb +4 -4
- data/spec/ciat/erb_helpers_spec.rb +71 -0
- data/spec/ciat/feedback/composite_spec.rb +28 -0
- data/spec/ciat/feedback/feedback_counter_spec.rb +91 -0
- data/spec/ciat/feedback/html_feedback_spec.rb +48 -0
- data/spec/ciat/feedback/return_status_spec.rb +90 -0
- data/spec/ciat/feedback/standard_output_spec.rb +109 -0
- data/spec/ciat/processors/basic_processing_spec.rb +146 -0
- data/spec/ciat/processors/java_spec.rb +31 -0
- data/spec/ciat/processors/parrot_spec.rb +40 -0
- data/spec/ciat/subresult_spec.rb +40 -0
- data/spec/ciat/suite_builder_spec.rb +70 -0
- data/spec/ciat/suite_spec.rb +64 -0
- data/spec/ciat/test_element_spec.rb +78 -0
- data/spec/ciat/test_file_spec.rb +96 -0
- data/spec/ciat/test_spec.rb +127 -0
- data/spec/ciat/traffic_light_spec.rb +41 -0
- data/spec/ciat_spec.rb +2 -0
- data/spec/spec_helper.rb +134 -0
- data/spec/templates/detail_row/elements_html_erb_spec.rb +60 -0
- data/spec/templates/detail_row_html_erb_spec.rb +73 -0
- data/spec/templates/elements/diff_html_erb_spec.rb +28 -0
- data/spec/templates/elements/plain_element_html_erb_spec.rb +36 -0
- data/spec/templates/report_html_erb_spec.rb +85 -0
- data/spec/templates/summary_row_html_erb_spec.rb +93 -0
- data/spec/templates/test_numbers_html_erb_spec.rb +82 -0
- metadata +54 -32
- data/History.txt +0 -96
- data/Rakefile +0 -40
- data/ciat.gemspec +0 -53
- data/lib/ciat/cargo.rb +0 -55
- data/lib/ciat/compilers/java.rb +0 -54
- data/lib/ciat/processors/copy.rb +0 -37
- data/lib/ciat/version.rb +0 -7
data/README.rdoc
CHANGED
@@ -69,8 +69,8 @@ When the "Parrot executor" is run on the compilation, it'll also pass in <code>8
|
|
69
69
|
This sample +Rakefile+ will pull everything together:
|
70
70
|
|
71
71
|
require 'ciat'
|
72
|
-
require 'ciat/
|
73
|
-
require 'ciat/
|
72
|
+
require 'ciat/processors/java'
|
73
|
+
require 'ciat/processors/parrot'
|
74
74
|
|
75
75
|
def compiler
|
76
76
|
classpath = Dir.glob('../lib/*.jar').join(':') + ":../bin"
|
@@ -78,7 +78,7 @@ This sample +Rakefile+ will pull everything together:
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def executor
|
81
|
-
CIAT::
|
81
|
+
CIAT::Processors::Parrot.new
|
82
82
|
end
|
83
83
|
|
84
84
|
CIAT::RakeTask.new do |t|
|
@@ -97,7 +97,7 @@ documentation for CIAT::RakeTask for more information.
|
|
97
97
|
|
98
98
|
* Pronounce "CIAT" as "dog". (See this funny video[http://www.youtube.com/watch?v=tyQvjKqXA0Y].)
|
99
99
|
* Must have +diff+ executable.
|
100
|
-
* You have to provide your own target-code
|
100
|
+
* You have to provide your own target-code processors (e.g., +parrot+ for the
|
101
101
|
Parrot Virtual Machine, +spim+ for MIPS emulation, etc.)
|
102
102
|
|
103
103
|
|
data/lib/ciat.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__)) unless
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
|
-
# Loads in the basic files needed to use CIAT.
|
5
|
-
#
|
6
|
-
# at.
|
4
|
+
# Loads in the basic files needed to use CIAT. Processors have to be required
|
5
|
+
# separately. CIAT::Suite is the class you really want to look at.
|
7
6
|
module CIAT; end
|
8
7
|
|
9
8
|
require 'ciat/rake_task'
|
@@ -11,8 +10,7 @@ require 'ciat/traffic_light'
|
|
11
10
|
require 'ciat/suite'
|
12
11
|
require 'ciat/test'
|
13
12
|
require 'ciat/test_element'
|
14
|
-
require 'ciat/
|
15
|
-
require 'ciat/crate'
|
13
|
+
require 'ciat/test_file'
|
16
14
|
require 'ciat/feedback/standard_output'
|
17
15
|
require 'ciat/feedback/html_feedback'
|
18
16
|
require 'ciat/differs/html_differ'
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module CIAT
|
2
2
|
module Differs
|
3
|
-
# Module for implementing the diff between two files.
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# Module for implementing the diff between two files. The output is in
|
4
|
+
# HTML table rows with the expected output on the left and the generated
|
5
|
+
# on the right.
|
6
6
|
module HtmlDiffer
|
7
7
|
def html_diff(expected_file, generated_file, diff_file)
|
8
8
|
system("diff #{diff_options} '#{expected_file}' '#{generated_file}' > '#{diff_file}'")
|
9
9
|
end
|
10
10
|
|
11
|
-
# TODO: it would be nice to have line numbers in the output
|
12
11
|
def diff_options
|
13
12
|
"--old-group-format='<tr><td>%df</td><td class=\"red\"><pre>%<</pre></td><td></td><td></td></tr>' " +
|
14
13
|
"--new-group-format='<tr><td></td><td></td><td>%dF</td><td class=\"red\"><pre>%></pre><td></tr>' " +
|
data/lib/ciat/erb_helpers.rb
CHANGED
@@ -41,11 +41,11 @@ module CIAT::ERBHelpers
|
|
41
41
|
string.gsub("\t", " ")
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
45
|
-
if @
|
44
|
+
def new_grouping?(result)
|
45
|
+
if @old_grouping == result.grouping
|
46
46
|
false
|
47
47
|
else
|
48
|
-
@
|
48
|
+
@old_grouping = result.grouping
|
49
49
|
true
|
50
50
|
end
|
51
51
|
end
|
@@ -53,7 +53,9 @@ module CIAT::ERBHelpers
|
|
53
53
|
# Recursively renders another template. If it's possible to write your own
|
54
54
|
# templates for reports, this will probably play a key role.
|
55
55
|
def render(file, locals)
|
56
|
-
ERB.new(read(file))
|
56
|
+
erb = ERB.new(read(file))
|
57
|
+
erb.filename = file
|
58
|
+
erb.result(CIAT::TemplateBinder.new(locals).get_binding)
|
57
59
|
end
|
58
60
|
|
59
61
|
private
|
@@ -13,8 +13,8 @@ module CIAT::Feedback
|
|
13
13
|
@feedbacks.each { |feedback| feedback.post_tests(suite) }
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
@feedbacks.each { |feedback| feedback.
|
16
|
+
def report_subresult(subresult)
|
17
|
+
@feedbacks.each { |feedback| feedback.report_subresult(subresult) }
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -1,34 +1,51 @@
|
|
1
1
|
require 'ciat/erb_helpers'
|
2
|
+
require 'ciat/feedback/html_feedback_builder'
|
3
|
+
require 'ciat/io'
|
2
4
|
|
3
5
|
module CIAT::Feedback
|
4
6
|
class HtmlFeedback
|
5
7
|
include CIAT::ERBHelpers
|
8
|
+
include CIAT::IO
|
6
9
|
|
7
|
-
|
10
|
+
attr_reader :report_title
|
11
|
+
attr_reader :report_filename
|
12
|
+
|
13
|
+
def initialize(counter, options)
|
8
14
|
@counter = counter
|
15
|
+
builder = CIAT::Feedback::HtmlFeedbackBuilder.new(options)
|
16
|
+
@report_title = builder.build_report_title
|
17
|
+
@report_filename = builder.build_report_filename
|
9
18
|
end
|
10
19
|
|
11
20
|
def pre_tests(suite)
|
12
|
-
suite.
|
21
|
+
FileUtils.mkdir_p(suite.output_folder)
|
22
|
+
FileUtils.cp(File.join(File.dirname(__FILE__), "..", "..", "data", "ciat.css"), suite.output_folder)
|
23
|
+
FileUtils.cp(File.join(File.dirname(__FILE__), "..", "..", "data", "prototype.js"), suite.output_folder)
|
13
24
|
end
|
14
25
|
|
15
|
-
def
|
26
|
+
def report_subresult(processor)
|
16
27
|
nil
|
17
28
|
end
|
18
29
|
|
19
30
|
def post_tests(suite)
|
20
|
-
|
21
|
-
|
22
|
-
generate_html(suite)
|
31
|
+
write_file(
|
32
|
+
report_filename,
|
33
|
+
generate_html(suite)
|
34
|
+
)
|
23
35
|
end
|
24
36
|
|
25
37
|
def generate_html(suite) #:nodoc:
|
26
38
|
processors = suite.processors
|
27
39
|
results = suite.results
|
28
|
-
report_title = suite.report_title
|
29
40
|
size = suite.size
|
30
41
|
counter = @counter
|
31
|
-
|
42
|
+
build_erb.result(binding)
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_erb
|
46
|
+
e = ERB.new(template)
|
47
|
+
e.filename = "report.html.erb"
|
48
|
+
e
|
32
49
|
end
|
33
50
|
|
34
51
|
def template #:nodoc:
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'ciat/io'
|
2
|
+
|
3
|
+
class CIAT::Feedback::HtmlFeedbackBuilder
|
4
|
+
include CIAT::IO
|
5
|
+
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_output_folder
|
13
|
+
options[:output_folder] || OUTPUT_FOLDER
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_report_filename
|
17
|
+
File.join(build_output_folder, options[:report_filename] || REPORT_FILENAME)
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_report_title
|
21
|
+
if options[:report_title]
|
22
|
+
"CIAT Report: " + options[:report_title]
|
23
|
+
else
|
24
|
+
"CIAT Report"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/ciat/io.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module CIAT::IO
|
2
|
+
|
3
|
+
OUTPUT_FOLDER = "temp"
|
4
|
+
REPORT_FILENAME = "report.html"
|
5
|
+
|
6
|
+
def write_file(filename, content)
|
7
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
8
|
+
File.open(filename, "w") do |file|
|
9
|
+
file.write content
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def read_file(filename)
|
14
|
+
File.read(filename)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -1,30 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Produces a clone for an individual test.
|
4
|
-
def for_test
|
5
|
-
copy = clone
|
6
|
-
copy.light = light.clone
|
7
|
-
copy
|
8
|
-
end
|
1
|
+
require 'rake'
|
2
|
+
require 'ciat/differs/html_differ'
|
9
3
|
|
4
|
+
module CIAT::Processors
|
5
|
+
module BasicProcessing
|
6
|
+
include CIAT::Differs::HtmlDiffer
|
7
|
+
|
10
8
|
# Executes the program, and diffs the output.
|
11
9
|
def process(test)
|
12
10
|
# TODO: verify required elements
|
13
11
|
# TODO: handle optional element
|
14
12
|
if execute(test)
|
15
13
|
if diff(test)
|
16
|
-
|
14
|
+
CIAT::TrafficLight::GREEN
|
17
15
|
else
|
18
|
-
|
16
|
+
CIAT::TrafficLight::RED
|
19
17
|
end
|
20
18
|
else
|
21
|
-
|
19
|
+
CIAT::TrafficLight::YELLOW
|
22
20
|
end
|
23
|
-
test
|
24
21
|
end
|
25
|
-
|
22
|
+
|
26
23
|
def execute(test)
|
27
|
-
|
24
|
+
RakeFileUtils.verbose(false) do
|
25
|
+
sh "#{executable} '#{input_file(test)}' #{command_line_args(test)} > '#{output_file(test)}' 2> '#{error_file(test)}'" do |ok, result|
|
26
|
+
return ok
|
27
|
+
end
|
28
|
+
end
|
28
29
|
end
|
29
30
|
|
30
31
|
def command_line_args(test) #:nodoc:
|
@@ -34,31 +35,21 @@ module CIAT::Processors
|
|
34
35
|
# Compares the expected and generated executions.
|
35
36
|
def diff(test)
|
36
37
|
html_diff(
|
37
|
-
test.element(
|
38
|
-
test.element(
|
39
|
-
test.element(
|
40
|
-
end
|
41
|
-
|
42
|
-
def relevant_elements(test)
|
43
|
-
relevant_element_names.
|
44
|
-
select { |name| test.element?(name) }.
|
45
|
-
map { |name| test.element(name) }
|
46
|
-
end
|
47
|
-
|
48
|
-
def relevant_element_names
|
49
|
-
processor_kind.element_name_hash[light.setting]
|
38
|
+
test.element(kind.output_name).as_file,
|
39
|
+
test.element(kind.output_name, :generated).as_file,
|
40
|
+
test.element(kind.output_name, :diff).as_file)
|
50
41
|
end
|
51
42
|
|
52
43
|
def input_file(test)
|
53
|
-
test.element(
|
44
|
+
test.element(kind.input_name).as_file
|
54
45
|
end
|
55
46
|
|
56
47
|
def output_file(test)
|
57
|
-
test.element(
|
48
|
+
test.element(kind.output_name, :generated).as_file
|
58
49
|
end
|
59
50
|
|
60
51
|
def error_file(test)
|
61
|
-
test.element(
|
52
|
+
test.element(kind.output_name, :error).as_file
|
62
53
|
end
|
63
54
|
end
|
64
55
|
end
|
@@ -1,26 +1,25 @@
|
|
1
1
|
module CIAT
|
2
|
-
module
|
2
|
+
module Processors
|
3
3
|
# Executor class for Java interpreters.
|
4
4
|
#
|
5
5
|
class Java
|
6
6
|
include CIAT::Processors::BasicProcessing
|
7
|
-
include CIAT::Differs::HtmlDiffer
|
8
7
|
|
9
8
|
# Traffic light
|
10
|
-
|
11
|
-
|
9
|
+
attr_accessor :kind
|
10
|
+
attr_accessor :description
|
12
11
|
|
13
12
|
# Creates a Java executor.
|
14
13
|
#
|
15
14
|
# Possible options:
|
16
15
|
# * <code>:description</code> is the description used in the HTML report
|
17
16
|
# for this processor (default: <code>"Parrot virtual machine"</code>).
|
18
|
-
def initialize(classpath, interpreter_class
|
19
|
-
@processor_kind = options[:processor_kind] || CIAT::Processors::Interpreter.new
|
17
|
+
def initialize(classpath, interpreter_class)
|
20
18
|
@classpath = classpath
|
21
19
|
@interpreter_class = interpreter_class
|
22
|
-
|
23
|
-
|
20
|
+
self.kind = CIAT::Processors::Interpreter.new
|
21
|
+
self.description = "in-Java interpreter"
|
22
|
+
yield self if block_given?
|
24
23
|
end
|
25
24
|
|
26
25
|
# Provides a description of the processor.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module CIAT
|
2
|
-
module
|
2
|
+
module Processors
|
3
3
|
# Executor class for Parrot programs. This will execute PIR or PASM code
|
4
4
|
# using the +parrot+ executable.
|
5
5
|
#
|
@@ -17,9 +17,9 @@ module CIAT
|
|
17
17
|
include CIAT::Processors::BasicProcessing
|
18
18
|
include CIAT::Differs::HtmlDiffer
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
attr_accessor :kind
|
21
|
+
attr_accessor :description
|
22
|
+
attr_accessor :libraries
|
23
23
|
|
24
24
|
# Creates a Parrot executor.
|
25
25
|
#
|
@@ -30,12 +30,11 @@ module CIAT
|
|
30
30
|
# report
|
31
31
|
# for the command-line arguments (if any) (default: "Command-line
|
32
32
|
# arguments").
|
33
|
-
def initialize(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@light = CIAT::TrafficLight.new
|
33
|
+
def initialize()
|
34
|
+
self.kind = CIAT::Processors::Interpreter.new
|
35
|
+
self.description = "Parrot virtual machine"
|
36
|
+
self.libraries = []
|
37
|
+
yield self if block_given?
|
39
38
|
end
|
40
39
|
|
41
40
|
# Provides a description of the processor.
|
data/lib/ciat/rake_task.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
class CIAT::Subresult
|
2
|
+
attr_reader :light
|
3
|
+
attr_reader :processor
|
4
|
+
|
5
|
+
def initialize(elements, light, processor)
|
6
|
+
@elements = elements
|
7
|
+
@light = light
|
8
|
+
@processor = processor
|
9
|
+
end
|
10
|
+
|
11
|
+
def relevant_elements
|
12
|
+
relevant_element_names.
|
13
|
+
select { |name| @elements.element?(name) }.
|
14
|
+
map { |name| @elements.element(name) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def relevant_element_names
|
18
|
+
@processor.kind.element_name_hash[@light.setting]
|
19
|
+
end
|
20
|
+
end
|
data/lib/ciat/suite.rb
CHANGED
@@ -2,6 +2,7 @@ require 'erb'
|
|
2
2
|
require 'ciat/feedback/composite'
|
3
3
|
require 'ciat/feedback/feedback_counter'
|
4
4
|
require 'ciat/feedback/return_status'
|
5
|
+
require 'ciat/suite_builder'
|
5
6
|
|
6
7
|
# = A Suite of Tests
|
7
8
|
#
|
@@ -46,67 +47,55 @@ require 'ciat/feedback/return_status'
|
|
46
47
|
#
|
47
48
|
# You can create your own processors. Each processor needs to specify which
|
48
49
|
# test elements it wants or will accept, which files it wants checked, and how
|
49
|
-
# it should be executed. See CIAT::
|
50
|
-
# CIAT::
|
50
|
+
# it should be executed. See CIAT::Processors::Java and
|
51
|
+
# CIAT::Processors::Parrot (to learn how to use them and how to write others).
|
51
52
|
#
|
52
53
|
# == Test File
|
53
54
|
#
|
54
55
|
# See the README for details on the format of a test file.
|
55
56
|
#
|
56
57
|
class CIAT::Suite
|
57
|
-
|
58
|
-
attr_reader :results
|
58
|
+
|
59
59
|
attr_reader :processors
|
60
|
-
attr_reader :
|
60
|
+
attr_reader :output_folder
|
61
|
+
attr_reader :test_files
|
62
|
+
attr_reader :results
|
61
63
|
|
62
|
-
#
|
64
|
+
# Builds a suite of CIAT tests. See the instructions above for possible
|
63
65
|
# values for the +options+.
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
@feedback = options[:feedback] || default_feedback
|
72
|
-
@feedback = CIAT::Feedback::Composite.new(
|
73
|
-
@feedback, CIAT::Feedback::ReturnStatus.new
|
74
|
-
)
|
66
|
+
def self.build(options = {})
|
67
|
+
builder = CIAT::SuiteBuilder.new(options)
|
68
|
+
CIAT::Suite.new(
|
69
|
+
builder.build_processors,
|
70
|
+
builder.build_output_folder,
|
71
|
+
builder.build_test_files,
|
72
|
+
builder.build_feedback)
|
75
73
|
end
|
76
74
|
|
75
|
+
def initialize(processors, output_folder, test_files, feedback)
|
76
|
+
@processors = processors
|
77
|
+
@output_folder = output_folder
|
78
|
+
@test_files = test_files
|
79
|
+
@feedback = feedback
|
80
|
+
end
|
81
|
+
|
77
82
|
# Returns the number of tests in the suite.
|
78
83
|
def size
|
79
|
-
|
84
|
+
test_files.size
|
80
85
|
end
|
81
86
|
|
82
87
|
# Runs all of the tests in the suite, and returns the results. The results
|
83
88
|
# are also available through #results.
|
84
89
|
def run
|
85
90
|
@feedback.pre_tests(self)
|
86
|
-
@results =
|
87
|
-
map { |
|
91
|
+
@results = test_files.
|
92
|
+
map { |test_file| create_test(test_file) }.
|
88
93
|
map { |test| test.run }
|
89
94
|
@feedback.post_tests(self)
|
90
95
|
@results
|
91
96
|
end
|
92
97
|
|
93
|
-
def create_test(
|
94
|
-
CIAT::Test.new(
|
95
|
-
crate.process_test_file,
|
96
|
-
:processors => test_processors,
|
97
|
-
:feedback => @feedback)
|
98
|
-
end
|
99
|
-
|
100
|
-
def test_processors #:nodoc:
|
101
|
-
@processors.map { |processor| processor.for_test }
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
def default_feedback
|
106
|
-
counter = CIAT::Feedback::FeedbackCounter.new
|
107
|
-
CIAT::Feedback::Composite.new(counter,
|
108
|
-
CIAT::Feedback::StandardOutput.new(counter),
|
109
|
-
CIAT::Feedback::HtmlFeedback.new(counter)
|
110
|
-
)
|
98
|
+
def create_test(test_file)
|
99
|
+
CIAT::Test.new(test_file, @processors, @feedback)
|
111
100
|
end
|
112
101
|
end
|