ciat 0.4.8 → 0.4.9

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.
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