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.
- checksums.yaml +5 -13
- data/lib/assets_server.rb +37 -0
- data/lib/checker.rb +101 -0
- data/lib/expectations_hook.rb +8 -96
- data/lib/extensions/string.rb +17 -0
- data/lib/gobstones.rb +11 -0
- data/lib/gobstones/batch.rb +38 -0
- data/lib/gobstones/batch_parser.rb +68 -0
- data/lib/gobstones/error_builder.rb +6 -0
- data/lib/gobstones/example_code_builder.rb +35 -0
- data/lib/gobstones_runner.rb +17 -4
- data/lib/locales/en.yml +13 -0
- data/lib/locales/es.yml +13 -0
- data/lib/metadata_hook.rb +29 -7
- data/lib/multiple_executions_runner.rb +28 -0
- data/lib/precompile_hook.rb +30 -0
- data/lib/render/boards.html.erb +58 -0
- data/lib/render/editor/editor.css +12 -0
- data/lib/render/editor/editor.js +9 -0
- data/lib/render/html_board.rb +12 -0
- data/lib/render/html_renderer.rb +95 -0
- data/lib/render/with_renderer.rb +22 -0
- data/lib/test_hook.rb +8 -21
- metadata +66 -55
- data/lib/assets/boom.png +0 -0
- data/lib/stones_spec.rb +0 -21
- data/lib/stones_spec/error_message_parser.rb +0 -17
- data/lib/stones_spec/example.rb +0 -47
- data/lib/stones_spec/gobstones.rb +0 -55
- data/lib/stones_spec/hash.rb +0 -5
- data/lib/stones_spec/html_board_renderer.rb +0 -77
- data/lib/stones_spec/postcondition/expected_boom.rb +0 -55
- data/lib/stones_spec/postcondition/expected_final_board.rb +0 -56
- data/lib/stones_spec/postcondition/expected_return_value.rb +0 -44
- data/lib/stones_spec/postcondition/postcondition.rb +0 -35
- data/lib/stones_spec/precondition.rb +0 -26
- data/lib/stones_spec/runner.rb +0 -41
- data/lib/stones_spec/string.rb +0 -10
- data/lib/stones_spec/subject.rb +0 -80
- data/lib/stones_spec/version.rb +0 -3
- data/lib/stones_spec/with_command_line.rb +0 -7
- data/lib/stones_spec/with_gbb_html_rendering.rb +0 -60
- data/lib/stones_spec/with_gobstones_css.rb +0 -112
- data/lib/stones_spec/with_tempfile.rb +0 -13
- 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
|
data/lib/stones_spec/example.rb
DELETED
@@ -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
|
data/lib/stones_spec/hash.rb
DELETED
@@ -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
|