ciat 0.4.8 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/README.rdoc +4 -4
  2. data/lib/ciat.rb +3 -5
  3. data/lib/ciat/differs/html_differ.rb +3 -4
  4. data/lib/ciat/erb_helpers.rb +6 -4
  5. data/lib/ciat/feedback/composite.rb +2 -2
  6. data/lib/ciat/feedback/feedback_counter.rb +2 -2
  7. data/lib/ciat/feedback/html_feedback.rb +25 -8
  8. data/lib/ciat/feedback/html_feedback_builder.rb +28 -0
  9. data/lib/ciat/feedback/return_status.rb +1 -1
  10. data/lib/ciat/feedback/standard_output.rb +1 -1
  11. data/lib/ciat/io.rb +17 -0
  12. data/lib/ciat/processors/basic_processing.rb +21 -30
  13. data/lib/ciat/{executors → processors}/java.rb +7 -8
  14. data/lib/ciat/{executors → processors}/parrot.rb +9 -10
  15. data/lib/ciat/rake_task.rb +1 -1
  16. data/lib/ciat/subresult.rb +20 -0
  17. data/lib/ciat/suite.rb +27 -38
  18. data/lib/ciat/suite_builder.rb +54 -0
  19. data/lib/ciat/test.rb +32 -18
  20. data/lib/ciat/test_element.rb +7 -2
  21. data/lib/ciat/{crate.rb → test_file.rb} +24 -16
  22. data/lib/ciat/test_result.rb +24 -0
  23. data/lib/ciat/traffic_light.rb +6 -0
  24. data/lib/templates/detail_row.html.erb +5 -4
  25. data/lib/templates/group_header.html.erb +2 -2
  26. data/lib/templates/report.html.erb +1 -1
  27. data/lib/templates/summary_row.html.erb +4 -4
  28. data/spec/ciat/erb_helpers_spec.rb +71 -0
  29. data/spec/ciat/feedback/composite_spec.rb +28 -0
  30. data/spec/ciat/feedback/feedback_counter_spec.rb +91 -0
  31. data/spec/ciat/feedback/html_feedback_spec.rb +48 -0
  32. data/spec/ciat/feedback/return_status_spec.rb +90 -0
  33. data/spec/ciat/feedback/standard_output_spec.rb +109 -0
  34. data/spec/ciat/processors/basic_processing_spec.rb +146 -0
  35. data/spec/ciat/processors/java_spec.rb +31 -0
  36. data/spec/ciat/processors/parrot_spec.rb +40 -0
  37. data/spec/ciat/subresult_spec.rb +40 -0
  38. data/spec/ciat/suite_builder_spec.rb +70 -0
  39. data/spec/ciat/suite_spec.rb +64 -0
  40. data/spec/ciat/test_element_spec.rb +78 -0
  41. data/spec/ciat/test_file_spec.rb +96 -0
  42. data/spec/ciat/test_spec.rb +127 -0
  43. data/spec/ciat/traffic_light_spec.rb +41 -0
  44. data/spec/ciat_spec.rb +2 -0
  45. data/spec/spec_helper.rb +134 -0
  46. data/spec/templates/detail_row/elements_html_erb_spec.rb +60 -0
  47. data/spec/templates/detail_row_html_erb_spec.rb +73 -0
  48. data/spec/templates/elements/diff_html_erb_spec.rb +28 -0
  49. data/spec/templates/elements/plain_element_html_erb_spec.rb +36 -0
  50. data/spec/templates/report_html_erb_spec.rb +85 -0
  51. data/spec/templates/summary_row_html_erb_spec.rb +93 -0
  52. data/spec/templates/test_numbers_html_erb_spec.rb +82 -0
  53. metadata +54 -32
  54. data/History.txt +0 -96
  55. data/Rakefile +0 -40
  56. data/ciat.gemspec +0 -53
  57. data/lib/ciat/cargo.rb +0 -55
  58. data/lib/ciat/compilers/java.rb +0 -54
  59. data/lib/ciat/processors/copy.rb +0 -37
  60. 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/compilers/java'
73
- require 'ciat/executors/parrot'
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::Executors::Parrot.new
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 executors (e.g., +parrot+ for the
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. Compilers and Executors have
5
- # to be required separately. CIAT::Suite is the class you really want to look
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/cargo'
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
- # The output is in HTML table rows with the expected output on the left and
5
- # the generated on the right.
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>' " +
@@ -41,11 +41,11 @@ module CIAT::ERBHelpers
41
41
  string.gsub("\t", " ")
42
42
  end
43
43
 
44
- def new_path?(result)
45
- if @old_path == File.dirname(result.filename)
44
+ def new_grouping?(result)
45
+ if @old_grouping == result.grouping
46
46
  false
47
47
  else
48
- @old_path = File.dirname(result.filename)
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)).result(CIAT::TemplateBinder.new(locals).get_binding)
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 processor_result(processor)
17
- @feedbacks.each { |feedback| feedback.processor_result(processor) }
16
+ def report_subresult(subresult)
17
+ @feedbacks.each { |feedback| feedback.report_subresult(subresult) }
18
18
  end
19
19
  end
20
20
  end
@@ -32,8 +32,8 @@ module CIAT
32
32
  nil
33
33
  end
34
34
 
35
- def processor_result(processor)
36
- case processor.light.setting
35
+ def report_subresult(subresult)
36
+ case subresult.light.setting
37
37
  when :red
38
38
  increment_failure_count
39
39
  when :yellow
@@ -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
- def initialize(counter)
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.cargo.copy_suite_data
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 processor_result(processor)
26
+ def report_subresult(processor)
16
27
  nil
17
28
  end
18
29
 
19
30
  def post_tests(suite)
20
- suite.cargo.write_file(
21
- suite.cargo.report_filename,
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
- ERB.new(template).result(binding)
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
@@ -11,7 +11,7 @@ module CIAT::Feedback
11
11
  end
12
12
  end
13
13
 
14
- def processor_result(processor)
14
+ def report_subresult(processor)
15
15
  @failure ||= processor.light.yellow? || processor.light.red?
16
16
  end
17
17
 
@@ -21,7 +21,7 @@ module CIAT
21
21
  print ".\n"
22
22
  end
23
23
 
24
- def processor_result(processor)
24
+ def report_subresult(processor)
25
25
  putc LIGHT_OUTPUTS[processor.light.setting]
26
26
  end
27
27
  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
- 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
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
- light.green!
14
+ CIAT::TrafficLight::GREEN
17
15
  else
18
- light.red!
16
+ CIAT::TrafficLight::RED
19
17
  end
20
18
  else
21
- light.yellow!
19
+ CIAT::TrafficLight::YELLOW
22
20
  end
23
- test
24
21
  end
25
-
22
+
26
23
  def execute(test)
27
- system "#{executable} '#{input_file(test)}' #{command_line_args(test)} > '#{output_file(test)}' 2> '#{error_file(test)}'"
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(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]
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(processor_kind.input_name).as_file
44
+ test.element(kind.input_name).as_file
54
45
  end
55
46
 
56
47
  def output_file(test)
57
- test.element(processor_kind.output_name, :generated).as_file
48
+ test.element(kind.output_name, :generated).as_file
58
49
  end
59
50
 
60
51
  def error_file(test)
61
- test.element(processor_kind.output_name, :error).as_file
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 Executors
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
- attr :light, true
11
- attr_reader :processor_kind
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, options={})
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
- @description = options[:description] || "in-Java interpreter"
23
- @light = CIAT::TrafficLight.new
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 Executors
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
- # Traffic light
21
- attr :light, true
22
- attr_reader :processor_kind
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(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
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.
@@ -42,7 +42,7 @@ class CIAT::RakeTask
42
42
  def define
43
43
  desc "Run CIAT tests" + (@name==:test ? "" : ", #{@name}")
44
44
  task @name do
45
- suite = CIAT::Suite.new(
45
+ suite = CIAT::Suite.build(
46
46
  :processors => @processors,
47
47
  :files => @files,
48
48
  :feedback => @feedback,
@@ -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::Compilers::Java and
50
- # CIAT::Executors::Parrot (to learn how to use them and how to write others).
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
- attr_reader :cargo
58
- attr_reader :results
58
+
59
59
  attr_reader :processors
60
- attr_reader :report_title
60
+ attr_reader :output_folder
61
+ attr_reader :test_files
62
+ attr_reader :results
61
63
 
62
- # Constructs a suite of CIAT tests. See the instructions above for possible
64
+ # Builds a suite of CIAT tests. See the instructions above for possible
63
65
  # values for the +options+.
64
- def initialize(options = {})
65
- @processors = options[:processors]
66
- @cargo = options[:cargo] || CIAT::Cargo.new(options)
67
- @report_title = "CIAT Report"
68
- if options[:report_title]
69
- @report_title = @report_title + ": " + options[:report_title]
70
- end
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
- cargo.size
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 = cargo.crates.
87
- map { |crate| create_test(crate) }.
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(crate)
94
- CIAT::Test.new(crate.test_file,
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