mumuki-gobstones-runner 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +5 -13
  2. data/lib/assets_server.rb +37 -0
  3. data/lib/checker.rb +101 -0
  4. data/lib/expectations_hook.rb +8 -96
  5. data/lib/extensions/string.rb +17 -0
  6. data/lib/gobstones.rb +11 -0
  7. data/lib/gobstones/batch.rb +38 -0
  8. data/lib/gobstones/batch_parser.rb +68 -0
  9. data/lib/gobstones/error_builder.rb +6 -0
  10. data/lib/gobstones/example_code_builder.rb +35 -0
  11. data/lib/gobstones_runner.rb +17 -4
  12. data/lib/locales/en.yml +13 -0
  13. data/lib/locales/es.yml +13 -0
  14. data/lib/metadata_hook.rb +29 -7
  15. data/lib/multiple_executions_runner.rb +28 -0
  16. data/lib/precompile_hook.rb +30 -0
  17. data/lib/render/boards.html.erb +58 -0
  18. data/lib/render/editor/editor.css +12 -0
  19. data/lib/render/editor/editor.js +9 -0
  20. data/lib/render/html_board.rb +12 -0
  21. data/lib/render/html_renderer.rb +95 -0
  22. data/lib/render/with_renderer.rb +22 -0
  23. data/lib/test_hook.rb +8 -21
  24. metadata +66 -55
  25. data/lib/assets/boom.png +0 -0
  26. data/lib/stones_spec.rb +0 -21
  27. data/lib/stones_spec/error_message_parser.rb +0 -17
  28. data/lib/stones_spec/example.rb +0 -47
  29. data/lib/stones_spec/gobstones.rb +0 -55
  30. data/lib/stones_spec/hash.rb +0 -5
  31. data/lib/stones_spec/html_board_renderer.rb +0 -77
  32. data/lib/stones_spec/postcondition/expected_boom.rb +0 -55
  33. data/lib/stones_spec/postcondition/expected_final_board.rb +0 -56
  34. data/lib/stones_spec/postcondition/expected_return_value.rb +0 -44
  35. data/lib/stones_spec/postcondition/postcondition.rb +0 -35
  36. data/lib/stones_spec/precondition.rb +0 -26
  37. data/lib/stones_spec/runner.rb +0 -41
  38. data/lib/stones_spec/string.rb +0 -10
  39. data/lib/stones_spec/subject.rb +0 -80
  40. data/lib/stones_spec/version.rb +0 -3
  41. data/lib/stones_spec/with_command_line.rb +0 -7
  42. data/lib/stones_spec/with_gbb_html_rendering.rb +0 -60
  43. data/lib/stones_spec/with_gobstones_css.rb +0 -112
  44. data/lib/stones_spec/with_tempfile.rb +0 -13
  45. data/lib/with_test_parser.rb +0 -8
data/lib/assets/boom.png DELETED
Binary file
data/lib/stones_spec.rb DELETED
@@ -1,21 +0,0 @@
1
- module StonesSpec
2
- end
3
-
4
- require 'stones'
5
-
6
- require_relative 'stones_spec/string'
7
- require_relative 'stones_spec/hash'
8
-
9
- require_relative 'stones_spec/with_tempfile'
10
- require_relative 'stones_spec/with_command_line'
11
- require_relative 'stones_spec/with_gbb_html_rendering'
12
- require_relative 'stones_spec/version'
13
-
14
- require_relative 'stones_spec/precondition'
15
- require_relative 'stones_spec/postcondition/postcondition'
16
- require_relative 'stones_spec/error_message_parser'
17
- require_relative 'stones_spec/gobstones'
18
- require_relative 'stones_spec/example'
19
- require_relative 'stones_spec/subject'
20
- require_relative 'stones_spec/runner'
21
- require_relative 'stones_spec/html_board_renderer'
@@ -1,17 +0,0 @@
1
- module StonesSpec
2
- module ErrorMessageParser
3
- def self.parse(result)
4
- remove_boom_line_specification(remove_line_specification(result.lines)).join.strip
5
- end
6
-
7
- private
8
-
9
- def self.remove_line_specification(x)
10
- x.drop_while { |str| !str.include_any? ['cerca de', 'Error de Gobstones'] }
11
- end
12
-
13
- def self.remove_boom_line_specification(x)
14
- x.take_while { |str| not str.strip.start_with? 'En:' }
15
- end
16
- end
17
- end
@@ -1,47 +0,0 @@
1
- require 'ostruct'
2
-
3
- module StonesSpec
4
- class Example < OpenStruct
5
- include Mumukit::WithCommandLine
6
-
7
- def initialize(subject, attributes)
8
- super attributes
9
- @title = attributes[:title]
10
- @subject = subject
11
- @precondition = Precondition.from_example(self)
12
- end
13
-
14
- def execution_data(source)
15
- { source: @subject.test_program(source, @precondition.arguments),
16
- initial_board: @precondition.initial_board_gbb }
17
- end
18
-
19
- def execute!(files)
20
- result, status = run_command "#{Gobstones.run(files[:source], files[:initial_board], files[:final_board])} 2>&1"
21
- { result: result, status: status }
22
- end
23
-
24
- def result(files, execution, postcondition)
25
- if execution[:status] == :aborted
26
- raise Gobstones::AbortedError, execution[:result]
27
- end
28
-
29
- if execution[:status] == :failed
30
- error_message = Gobstones.parse_error_message execution[:result]
31
- Gobstones.ensure_no_syntax_error! error_message
32
- end
33
-
34
- postcondition.validate(files[:initial_board].open.read, files[:final_board].open.read, execution[:result], execution[:status])
35
- end
36
-
37
- def title
38
- @title || default_title
39
- end
40
-
41
- private
42
-
43
- def default_title
44
- @subject.default_title @precondition.arguments
45
- end
46
- end
47
- end
@@ -1,55 +0,0 @@
1
- module StonesSpec
2
- module Gobstones
3
- def self.configure
4
- @config ||= OpenStruct.new
5
- yield @config
6
- end
7
-
8
- def self.config
9
- @config
10
- end
11
-
12
- def self.run(source_file, initial_board_file, final_board_file)
13
- "#{config.gbs_command} #{source_file.path} --from #{initial_board_file.path} --to #{final_board_file.path} --no-print-board --silent"
14
- end
15
-
16
- def self.parse_error_message(result)
17
- "<pre>#{ErrorMessageParser.parse result}</pre>"
18
- end
19
-
20
- def self.runtime_error?(result)
21
- result.include_any? ['Error en tiempo de ejecución', 'Error en el programa']
22
- end
23
-
24
- def self.syntax_error?(result)
25
- result.include? 'Error de sintaxis'
26
- end
27
-
28
- def self.source_code_extension
29
- 'gbs'
30
- end
31
-
32
- def self.board_extension
33
- 'gbb'
34
- end
35
-
36
- def self.ensure_no_syntax_error!(error_message)
37
- raise SyntaxError, error_message if syntax_error? error_message
38
- end
39
-
40
- class Error < Exception
41
- end
42
-
43
- class SyntaxError < Error
44
- def status
45
- :errored
46
- end
47
- end
48
-
49
- class AbortedError < Error
50
- def status
51
- :aborted
52
- end
53
- end
54
- end
55
- end
@@ -1,5 +0,0 @@
1
- class Hash
2
- def map_values(&block)
3
- Hash[self.map {|k, v| [k, block.call(k,v)] }]
4
- end
5
- end
@@ -1,77 +0,0 @@
1
- require_relative './with_gobstones_css'
2
-
3
- module StonesSpec
4
- class HtmlBoardRenderer
5
- include StonesSpec::WithGobstonesCSS
6
-
7
- def initialize(options = {})
8
- @options = options
9
- end
10
-
11
- def render(board)
12
- "<style type=\"text/css\">
13
- #{render_css}</style>
14
-
15
- #{render_html board}"
16
- end
17
-
18
- def method_missing(name)
19
- @options[name]
20
- end
21
-
22
- def render_html(board)
23
- width, height = board.size
24
-
25
- "#{table_title}
26
- #{html_row_titles width, 'top'}
27
- #{(0...height).to_a.reverse.map {|y| html_row(board, y)}.join}#{html_row_titles width, 'bottom'}
28
- </table>
29
- "
30
- end
31
-
32
- def render_css
33
- gobstones_css '9pt', 30
34
- end
35
-
36
- private
37
-
38
- def table_title
39
- base = "<table class=\"gbs_board\">"
40
- caption ? base + "\n<caption>#{caption}</caption>" : base
41
- end
42
-
43
- def html_row(board, y)
44
- " <tr>
45
- <td class=\"lv\">#{y}</td>
46
- #{(0...board.size[0]).map {|x| html_cell board, [x, y] }.join "\n"}
47
- <td class=\"lv\">#{y}</td>
48
- </tr>
49
- "
50
- end
51
-
52
- def html_cell(board, position)
53
- cell = board.cell_at position
54
-
55
- " <td class=\"gc#{board.head_position == position ? ' gh' : ''}\">
56
- <table>
57
- <tr>#{html_stone cell, :black}#{html_stone cell, :blue}</tr>
58
- <tr>#{html_stone cell, :red}#{html_stone cell, :green}</tr>
59
- </table>
60
- </td>"
61
- end
62
-
63
- def html_stone(cell, color)
64
- quantity = cell[color]
65
-
66
- if cell[color] == 0
67
- '<td><div class="O"></div></td>'
68
- else
69
- "<td><div class=\"gbs_stone #{Stones::Color.all_with_names.invert[color][0]}\"><span>#{quantity}</span></div></td>"
70
- end
71
- end
72
-
73
- def html_row_titles(width, caption)
74
- "<tr><td class=\"lx #{caption}_left\"></td>#{(0...width).map {|x| "<td class=\"lh\">#{x}</td>"}.join}<td class=\"lx #{caption}_right\"></td></tr>"
75
- end
76
- end
77
- end
@@ -1,55 +0,0 @@
1
- module StonesSpec
2
- module Postcondition
3
- class ExpectedBoom
4
- include StonesSpec::WithGbbHtmlRendering
5
-
6
- attr_reader :example, :error_type
7
-
8
- def initialize(example)
9
- @example = example
10
- @error_type = known_error_types[example.error.to_sym]
11
- end
12
-
13
- def validate(initial_board_gbb, actual_final_board_gbb, result, status)
14
- if status == :failed
15
- check_right_error_type initial_board_gbb, result
16
- else
17
- boards = [['Tablero inicial', initial_board_gbb], ['Tablero final', actual_final_board_gbb]]
18
- make_boards_output example.title, boards, :failed, failure_message
19
- end
20
- end
21
-
22
- private
23
-
24
- def check_right_error_type(initial_board_gbb, result)
25
- if error_type_matches? result
26
- [example.title, :passed, make_error_output(result, initial_board_gbb)]
27
- else
28
- [example.title, :failed, "#{invalid_boom_type_message}\n#{make_error_output(result, initial_board_gbb)}"]
29
- end
30
- end
31
-
32
- def error_type_matches?(result)
33
- error_type[:matcher] =~ result
34
- end
35
-
36
- def known_error_types
37
- {
38
- out_of_board: { matcher: /La posición cae afuera del tablero/, friendly_message: 'caer fuera del tablero' },
39
- no_stones: { matcher: /No hay bolitas de ese color/, friendly_message: 'no haber bolitas' },
40
- unassigned_variable: { matcher: /podría no tener asignado ningún valor/, friendly_message: 'tener una variable sin asignar' },
41
- wrong_argument_type: { matcher: /El argumento de .+ debería ser/, friendly_message: 'tipo erróneo de un argumento' },
42
- wrong_arguments_quantity: { matcher: /Esperaba \d+ argumentos (.|\n)* Recibió \d+/, friendly_message: 'cantidad inválida de argumentos' }
43
- }
44
- end
45
-
46
- def failure_message
47
- 'Se esperaba que el programa hiciera BOOM pero se obtuvo un tablero final.'
48
- end
49
-
50
- def invalid_boom_type_message
51
- "<p>Se esperaba que el programa hiciera BOOM por #{error_type[:friendly_message]}.</p>"
52
- end
53
- end
54
- end
55
- end
@@ -1,56 +0,0 @@
1
- module StonesSpec
2
- module Postcondition
3
- class ExpectedFinalBoard < ExpectedResult
4
- attr_reader :check_head_position, :show_initial_board
5
-
6
- def initialize(example, check_head_position, show_initial_board)
7
- super example
8
- @check_head_position = check_head_position
9
- @show_initial_board = show_initial_board
10
- end
11
-
12
- def validate_expected_result(initial_board_gbb, actual_final_board_gbb, _result)
13
- if matches_with_expected_board? Stones::Gbb.read actual_final_board_gbb
14
- passed_result initial_board_gbb, actual_final_board_gbb
15
- else
16
- failed_result initial_board_gbb, example.final_board, actual_final_board_gbb
17
- end
18
- end
19
-
20
- private
21
-
22
- def failed_result(initial_board_gbb, expected_board_gbb, actual_board_gbb)
23
- boards = [
24
- ['Tablero final esperado', expected_board_gbb],
25
- ['Tablero final obtenido', actual_board_gbb]
26
- ]
27
-
28
- boards.unshift ['Tablero inicial', initial_board_gbb] if show_initial_board
29
-
30
- make_boards_output example.title, boards, :failed
31
- end
32
-
33
- def passed_result(initial_board_gbb, actual_board_gbb)
34
- boards = [
35
- ['Tablero final', actual_board_gbb]
36
- ]
37
-
38
- boards.unshift ['Tablero inicial', initial_board_gbb] if show_initial_board
39
-
40
- make_boards_output example.title, boards, :passed
41
- end
42
-
43
- def matches_with_expected_board?(actual_board)
44
- if check_head_position
45
- actual_board == final_board
46
- else
47
- actual_board.cells_equal? final_board
48
- end
49
- end
50
-
51
- def final_board
52
- Stones::Gbb.read example.final_board
53
- end
54
- end
55
- end
56
- end
@@ -1,44 +0,0 @@
1
- module StonesSpec
2
- module Postcondition
3
- class ExpectedReturnValue < ExpectedResult
4
- def initialize(example, show_initial_board)
5
- super example
6
- @show_initial_board = show_initial_board
7
- end
8
-
9
- def validate_expected_result(initial_board_gbb, _actual_final_board_gbb, result)
10
- normalized_actual_return = parse_success_output(result).strip
11
-
12
- if normalized_actual_return == return_value
13
- make_result(:passed, initial_board_gbb)
14
- else
15
- make_result(:failed, initial_board_gbb, "Se esperaba <b>#{return_value}</b> pero se obtuvo <b>#{normalized_actual_return}</b>")
16
- end
17
- end
18
-
19
- private
20
-
21
- def parse_success_output(result)
22
- first_return_value result || ''
23
- end
24
-
25
- def first_return_value(result)
26
- result[/#1 -> (.+)/, 1]
27
- end
28
-
29
- def make_result(status, initial_board_gbb, output='')
30
- title = "#{example.title} -> #{return_value}"
31
-
32
- if @show_initial_board
33
- make_boards_output title, [['Tablero inicial', initial_board_gbb]], status, output
34
- else
35
- [title, status, output]
36
- end
37
- end
38
-
39
- def return_value
40
- example.return.to_s
41
- end
42
- end
43
- end
44
- end
@@ -1,35 +0,0 @@
1
- module StonesSpec
2
- module Postcondition
3
- def self.from(example, check_head_position, show_initial_board)
4
- if example.final_board
5
- ExpectedFinalBoard.new(example, check_head_position, show_initial_board)
6
- elsif example.return
7
- ExpectedReturnValue.new(example, show_initial_board)
8
- else
9
- ExpectedBoom.new(example)
10
- end
11
- end
12
-
13
- class ExpectedResult
14
- include StonesSpec::WithGbbHtmlRendering
15
-
16
- attr_reader :example
17
-
18
- def initialize(example)
19
- @example = example
20
- end
21
-
22
- def validate(initial_board_gbb, actual_final_board_gbb, result, status)
23
- if status == :failed
24
- [example.title, :failed, make_error_output(result, initial_board_gbb)]
25
- else
26
- validate_expected_result(initial_board_gbb, actual_final_board_gbb, result)
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- require_relative './expected_boom'
34
- require_relative './expected_final_board'
35
- require_relative './expected_return_value'
@@ -1,26 +0,0 @@
1
- module StonesSpec
2
- class Precondition
3
- attr_reader :initial_board_gbb
4
-
5
- def self.from_example(example)
6
- self.new example.initial_board, example.arguments
7
- end
8
-
9
- def initialize(initial_board, arguments)
10
- @initial_board_gbb = initial_board || default_initial_board
11
- @arguments = arguments
12
- end
13
-
14
- def arguments
15
- @arguments || []
16
- end
17
-
18
- private
19
-
20
- def default_initial_board
21
- 'GBB/1.0
22
- size 4 4
23
- head 0 0'
24
- end
25
- end
26
- end