ciat 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +96 -0
- data/README.rdoc +135 -0
- data/Rakefile +40 -0
- data/ciat.gemspec +53 -0
- data/lib/ciat.rb +22 -0
- data/lib/ciat/cargo.rb +55 -0
- data/lib/ciat/compilers/java.rb +54 -0
- data/lib/ciat/crate.rb +58 -0
- data/lib/ciat/differs/html_differ.rb +20 -0
- data/lib/ciat/erb_helpers.rb +83 -0
- data/lib/ciat/executors/java.rb +36 -0
- data/lib/ciat/executors/parrot.rb +51 -0
- data/lib/ciat/feedback/composite.rb +20 -0
- data/lib/ciat/feedback/feedback_counter.rb +45 -0
- data/lib/ciat/feedback/html_feedback.rb +40 -0
- data/lib/ciat/feedback/return_status.rb +23 -0
- data/lib/ciat/feedback/standard_output.rb +29 -0
- data/lib/ciat/processors/basic_processing.rb +64 -0
- data/lib/ciat/processors/compilation_interpreter.rb +18 -0
- data/lib/ciat/processors/compiler.rb +18 -0
- data/lib/ciat/processors/copy.rb +37 -0
- data/lib/ciat/processors/interpreter.rb +18 -0
- data/lib/ciat/rake_task.rb +56 -0
- data/lib/ciat/suite.rb +112 -0
- data/lib/ciat/test.rb +41 -0
- data/lib/ciat/test_element.rb +44 -0
- data/lib/ciat/traffic_light.rb +39 -0
- data/lib/ciat/version.rb +7 -0
- data/lib/data/ciat.css +40 -0
- data/lib/data/elements.yml +30 -0
- data/lib/data/prototype.js +4228 -0
- data/lib/templates/detail_row.html.erb +9 -0
- data/lib/templates/detail_row/elements.html.erb +3 -0
- data/lib/templates/elements/diff.html.erb +7 -0
- data/lib/templates/elements/plain.html.erb +8 -0
- data/lib/templates/group_header.html.erb +7 -0
- data/lib/templates/report.html.erb +38 -0
- data/lib/templates/summary_row.html.erb +12 -0
- data/lib/templates/test_numbers.html.erb +12 -0
- metadata +99 -0
data/lib/ciat/crate.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
class CIAT::Crate #:nodoc:all
|
2
|
+
attr_reader :test_file
|
3
|
+
attr_reader :stub
|
4
|
+
attr_reader :output_folder
|
5
|
+
|
6
|
+
def initialize(test_file, output_folder)
|
7
|
+
@test_file = test_file
|
8
|
+
@output_folder = output_folder
|
9
|
+
end
|
10
|
+
|
11
|
+
def stub
|
12
|
+
test_file.gsub(File.extname(test_file), "")
|
13
|
+
end
|
14
|
+
|
15
|
+
def filename(*modifiers)
|
16
|
+
File.join(output_folder, [stub, *modifiers].compact.join("_"))
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_test_file
|
20
|
+
File.readlines(test_file)
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_test_file #:nodoc:
|
24
|
+
elements = empty_elements_hash
|
25
|
+
split_test_file.each do |name, contents|
|
26
|
+
elements[name] = CIAT::TestElement.new(name, filename(name), contents)
|
27
|
+
end
|
28
|
+
elements
|
29
|
+
end
|
30
|
+
|
31
|
+
def split_test_file #:nodoc:
|
32
|
+
tag = :description
|
33
|
+
content = ""
|
34
|
+
raw_elements = {}
|
35
|
+
read_test_file.each do |line|
|
36
|
+
if line =~ /^==== ((\w|\s)+?)\W*$/
|
37
|
+
raw_elements[tag] = content
|
38
|
+
tag = $1.gsub(" ", "_").to_sym
|
39
|
+
content = ""
|
40
|
+
else
|
41
|
+
content += line
|
42
|
+
end
|
43
|
+
end
|
44
|
+
raw_elements[tag] = content
|
45
|
+
raw_elements
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Helpers
|
50
|
+
#
|
51
|
+
private
|
52
|
+
|
53
|
+
def empty_elements_hash
|
54
|
+
Hash.new do |hash, name|
|
55
|
+
hash[name] = CIAT::TestElement.new(name, filename(name), nil)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CIAT
|
2
|
+
module Differs
|
3
|
+
# Module for implementing the diff between two files.
|
4
|
+
# The output is in HTML table rows with the expected output on the left and
|
5
|
+
# the generated on the right.
|
6
|
+
module HtmlDiffer
|
7
|
+
def html_diff(expected_file, generated_file, diff_file)
|
8
|
+
system("diff #{diff_options} '#{expected_file}' '#{generated_file}' > '#{diff_file}'")
|
9
|
+
end
|
10
|
+
|
11
|
+
# TODO: it would be nice to have line numbers in the output
|
12
|
+
def diff_options
|
13
|
+
"--old-group-format='<tr><td>%df</td><td class=\"red\"><pre>%<</pre></td><td></td><td></td></tr>' " +
|
14
|
+
"--new-group-format='<tr><td></td><td></td><td>%dF</td><td class=\"red\"><pre>%></pre><td></tr>' " +
|
15
|
+
"--changed-group-format='<tr class=\"yellow\"><td>%df</td><td><pre>%<</pre></td><td>%dF</td><td><pre>%></pre></td></tr>' " +
|
16
|
+
"--unchanged-group-format='<tr class=\"green\"><td>%df</td><td><pre>%=</pre></td><td>%dF</td><td><pre>%=</pre></td></tr>'"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# If it were easy for you to write your own HTML templates, then the methods
|
2
|
+
# in this module would be useful.
|
3
|
+
#
|
4
|
+
# <em>I don't know if it's easy to write your own HTML template!</em>
|
5
|
+
module CIAT::ERBHelpers
|
6
|
+
# Turns a traffic light into a more "testing" word: "FAILURE",
|
7
|
+
# "ERROR", "passed", "n/a".
|
8
|
+
def light_to_word(light)
|
9
|
+
case
|
10
|
+
when light.red? then "FAILURE"
|
11
|
+
when light.yellow? then "ERROR"
|
12
|
+
when light.green? then "passed"
|
13
|
+
when light.unset? then "n/a"
|
14
|
+
else
|
15
|
+
raise "cannot turn #{light} into word"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Turns a traffic light in a sentence wrapped in a classed +span+.
|
20
|
+
def light_to_sentence(prefix, light)
|
21
|
+
"<span class=\"#{light.setting}\">#{prefix} " +
|
22
|
+
case
|
23
|
+
when light.red? then "failed"
|
24
|
+
when light.yellow? then "errored"
|
25
|
+
when light.green? then "passed"
|
26
|
+
when light.unset? then "not run"
|
27
|
+
else
|
28
|
+
raise "cannot turn #{light} into a sentence"
|
29
|
+
end +
|
30
|
+
".</span>"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Capitalizes string as a title.
|
34
|
+
def title(text)
|
35
|
+
text.gsub(/\b\w/){$&.upcase}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Replaces tabs with spaces because Firefox does _really_ wacky things with
|
39
|
+
# tabs in a +pre+ in a +table+.
|
40
|
+
def replace_tabs(string)
|
41
|
+
string.gsub("\t", " ")
|
42
|
+
end
|
43
|
+
|
44
|
+
def new_path?(result)
|
45
|
+
if @old_path == File.dirname(result.filename)
|
46
|
+
false
|
47
|
+
else
|
48
|
+
@old_path = File.dirname(result.filename)
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Recursively renders another template. If it's possible to write your own
|
54
|
+
# templates for reports, this will probably play a key role.
|
55
|
+
def render(file, locals)
|
56
|
+
ERB.new(read(file)).result(CIAT::TemplateBinder.new(locals).get_binding)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def read(file)
|
62
|
+
File.read(template_path(file))
|
63
|
+
end
|
64
|
+
|
65
|
+
def template_path(file)
|
66
|
+
File.join(File.dirname(__FILE__), '..', 'templates', file + ".html.erb")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Assists in binding local variables for a recursive render.
|
71
|
+
class CIAT::TemplateBinder
|
72
|
+
include CIAT::ERBHelpers
|
73
|
+
|
74
|
+
def initialize(locals)
|
75
|
+
locals.each do |variable, value|
|
76
|
+
self.class.send(:define_method, variable, Proc.new {value})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_binding
|
81
|
+
binding
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module CIAT
|
2
|
+
module Executors
|
3
|
+
# Executor class for Java interpreters.
|
4
|
+
#
|
5
|
+
class Java
|
6
|
+
include CIAT::Processors::BasicProcessing
|
7
|
+
include CIAT::Differs::HtmlDiffer
|
8
|
+
|
9
|
+
# Traffic light
|
10
|
+
attr :light, true
|
11
|
+
attr_reader :processor_kind
|
12
|
+
|
13
|
+
# Creates a Java executor.
|
14
|
+
#
|
15
|
+
# Possible options:
|
16
|
+
# * <code>:description</code> is the description used in the HTML report
|
17
|
+
# for this processor (default: <code>"Parrot virtual machine"</code>).
|
18
|
+
def initialize(classpath, interpreter_class, options={})
|
19
|
+
@processor_kind = options[:processor_kind] || CIAT::Processors::Interpreter.new
|
20
|
+
@classpath = classpath
|
21
|
+
@interpreter_class = interpreter_class
|
22
|
+
@description = options[:description] || "in-Java interpreter"
|
23
|
+
@light = CIAT::TrafficLight.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# Provides a description of the processor.
|
27
|
+
def describe
|
28
|
+
@description
|
29
|
+
end
|
30
|
+
|
31
|
+
def executable
|
32
|
+
"java -cp '#{@classpath}' #{@interpreter_class}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module CIAT
|
2
|
+
module Executors
|
3
|
+
# Executor class for Parrot programs. This will execute PIR or PASM code
|
4
|
+
# using the +parrot+ executable.
|
5
|
+
#
|
6
|
+
# The Parrot executor expects <code>compilation</code> and
|
7
|
+
# <code>execution</code> elements. The <code>compilation</code> element
|
8
|
+
# is used as input (and it actually pulls in the generated version, but it
|
9
|
+
# should be the same as the expected). <code>execution</code> is
|
10
|
+
# compared.
|
11
|
+
#
|
12
|
+
# The Parrot executor allows for a <code>command line</code> element. This
|
13
|
+
# specifies the command-line arguments when the <code>compilation</code>
|
14
|
+
# is executed.
|
15
|
+
# If none is provided, no command-line arguments are used.
|
16
|
+
class Parrot
|
17
|
+
include CIAT::Processors::BasicProcessing
|
18
|
+
include CIAT::Differs::HtmlDiffer
|
19
|
+
|
20
|
+
# Traffic light
|
21
|
+
attr :light, true
|
22
|
+
attr_reader :processor_kind
|
23
|
+
|
24
|
+
# Creates a Parrot executor.
|
25
|
+
#
|
26
|
+
# Possible options:
|
27
|
+
# * <code>:description</code> is the description used in the HTML report
|
28
|
+
# for this processor (default: <code>"Parrot virtual machine"</code>).
|
29
|
+
# * <code>:command_line</code> is the description used in the HTML
|
30
|
+
# report
|
31
|
+
# for the command-line arguments (if any) (default: "Command-line
|
32
|
+
# arguments").
|
33
|
+
def initialize(options={})
|
34
|
+
@processor_kind = options[:processor_kind] ||
|
35
|
+
CIAT::Processors::Interpreter.new
|
36
|
+
@description = options[:description] || "Parrot virtual machine"
|
37
|
+
@libraries = options[:libraries] || []
|
38
|
+
@light = CIAT::TrafficLight.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# Provides a description of the processor.
|
42
|
+
def describe
|
43
|
+
@description
|
44
|
+
end
|
45
|
+
|
46
|
+
def executable
|
47
|
+
(["parrot"] + @libraries.map { |l| "-L" + l }).join(" ")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# A feedback mechanism for compositing other feedbacks.
|
2
|
+
module CIAT::Feedback
|
3
|
+
class Composite
|
4
|
+
# Pass in instances of the feedbacks as arguments to the constructor.
|
5
|
+
def initialize(*feedbacks)
|
6
|
+
@feedbacks = feedbacks
|
7
|
+
end
|
8
|
+
|
9
|
+
def pre_tests(suite)
|
10
|
+
@feedbacks.each { |feedback| feedback.pre_tests(suite) }
|
11
|
+
end
|
12
|
+
def post_tests(suite)
|
13
|
+
@feedbacks.each { |feedback| feedback.post_tests(suite) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def processor_result(processor)
|
17
|
+
@feedbacks.each { |feedback| feedback.processor_result(processor) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module CIAT
|
2
|
+
module Feedback
|
3
|
+
# This feedback class sends some simple messages to the screen about the
|
4
|
+
# progress of a CIAT::Suite run.
|
5
|
+
class FeedbackCounter
|
6
|
+
def initialize
|
7
|
+
@error_count = 0
|
8
|
+
@failure_count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def error_count
|
12
|
+
@error_count
|
13
|
+
end
|
14
|
+
|
15
|
+
def failure_count
|
16
|
+
@failure_count
|
17
|
+
end
|
18
|
+
|
19
|
+
def increment_error_count
|
20
|
+
@error_count += 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def increment_failure_count
|
24
|
+
@failure_count += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def pre_tests(suite)
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def post_tests(suite)
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def processor_result(processor)
|
36
|
+
case processor.light.setting
|
37
|
+
when :red
|
38
|
+
increment_failure_count
|
39
|
+
when :yellow
|
40
|
+
increment_error_count
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'ciat/erb_helpers'
|
2
|
+
|
3
|
+
module CIAT::Feedback
|
4
|
+
class HtmlFeedback
|
5
|
+
include CIAT::ERBHelpers
|
6
|
+
|
7
|
+
def initialize(counter)
|
8
|
+
@counter = counter
|
9
|
+
end
|
10
|
+
|
11
|
+
def pre_tests(suite)
|
12
|
+
suite.cargo.copy_suite_data
|
13
|
+
end
|
14
|
+
|
15
|
+
def processor_result(processor)
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_tests(suite)
|
20
|
+
suite.cargo.write_file(
|
21
|
+
suite.cargo.report_filename,
|
22
|
+
generate_html(suite))
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_html(suite) #:nodoc:
|
26
|
+
processors = suite.processors
|
27
|
+
results = suite.results
|
28
|
+
report_title = suite.report_title
|
29
|
+
size = suite.size
|
30
|
+
counter = @counter
|
31
|
+
ERB.new(template).result(binding)
|
32
|
+
end
|
33
|
+
|
34
|
+
def template #:nodoc:
|
35
|
+
File.read(File.join(
|
36
|
+
File.dirname(__FILE__), "..", "..", "templates", "report.html.erb"
|
37
|
+
))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# A feedback mechanism for failing a task
|
2
|
+
module CIAT::Feedback
|
3
|
+
class ReturnStatus
|
4
|
+
def pre_tests(suite)
|
5
|
+
@failure = false
|
6
|
+
end
|
7
|
+
|
8
|
+
def post_tests(suite)
|
9
|
+
if failure?
|
10
|
+
fail "CIAT tests unsuccessful"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def processor_result(processor)
|
15
|
+
@failure ||= processor.light.yellow? || processor.light.red?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def failure?
|
20
|
+
@failure
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module CIAT
|
2
|
+
module Feedback
|
3
|
+
# This feedback class sends some simple messages to the screen about the
|
4
|
+
# progress of a CIAT::Suite run.
|
5
|
+
class StandardOutput
|
6
|
+
LIGHT_OUTPUTS = { :green => ".", :red => "F", :yellow => "E", :unset => "-" }
|
7
|
+
|
8
|
+
def initialize(counter)
|
9
|
+
@counter = counter
|
10
|
+
end
|
11
|
+
|
12
|
+
def pre_tests(suite)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_tests(suite)
|
17
|
+
print "\n"
|
18
|
+
print "#{suite.size} tests executed"
|
19
|
+
print ", #{@counter.failure_count} failures" if @counter.failure_count > 0
|
20
|
+
print ", #{@counter.error_count} errors" if @counter.error_count > 0
|
21
|
+
print ".\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def processor_result(processor)
|
25
|
+
putc LIGHT_OUTPUTS[processor.light.setting]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module CIAT::Processors
|
2
|
+
module BasicProcessing
|
3
|
+
# Produces a clone for an individual test.
|
4
|
+
def for_test
|
5
|
+
copy = clone
|
6
|
+
copy.light = light.clone
|
7
|
+
copy
|
8
|
+
end
|
9
|
+
|
10
|
+
# Executes the program, and diffs the output.
|
11
|
+
def process(test)
|
12
|
+
# TODO: verify required elements
|
13
|
+
# TODO: handle optional element
|
14
|
+
if execute(test)
|
15
|
+
if diff(test)
|
16
|
+
light.green!
|
17
|
+
else
|
18
|
+
light.red!
|
19
|
+
end
|
20
|
+
else
|
21
|
+
light.yellow!
|
22
|
+
end
|
23
|
+
test
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute(test)
|
27
|
+
system "#{executable} '#{input_file(test)}' #{command_line_args(test)} > '#{output_file(test)}' 2> '#{error_file(test)}'"
|
28
|
+
end
|
29
|
+
|
30
|
+
def command_line_args(test) #:nodoc:
|
31
|
+
test.element?(:command_line) ? test.element(:command_line).content.strip : ''
|
32
|
+
end
|
33
|
+
|
34
|
+
# Compares the expected and generated executions.
|
35
|
+
def diff(test)
|
36
|
+
html_diff(
|
37
|
+
test.element(processor_kind.output_name).as_file,
|
38
|
+
test.element(processor_kind.output_name, :generated).as_file,
|
39
|
+
test.element(processor_kind.output_name, :diff).as_file)
|
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]
|
50
|
+
end
|
51
|
+
|
52
|
+
def input_file(test)
|
53
|
+
test.element(processor_kind.input_name).as_file
|
54
|
+
end
|
55
|
+
|
56
|
+
def output_file(test)
|
57
|
+
test.element(processor_kind.output_name, :generated).as_file
|
58
|
+
end
|
59
|
+
|
60
|
+
def error_file(test)
|
61
|
+
test.element(processor_kind.output_name, :error).as_file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|