gobstones-spec 0.2.0
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.
- checksums.yaml +7 -0
- data/lib/extensions/array.rb +5 -0
- data/lib/gobstones.rb +11 -0
- data/lib/gobstones/board.rb +55 -0
- data/lib/gobstones/cell.rb +30 -0
- data/lib/gobstones/gbb_parser.rb +52 -0
- data/lib/gobstones/position.rb +22 -0
- data/lib/gobstones/spec.rb +8 -0
- data/lib/gobstones/spec/error_message_parser.rb +19 -0
- data/lib/gobstones/spec/example.rb +81 -0
- data/lib/gobstones/spec/runner.rb +50 -0
- data/lib/gobstones/version.rb +3 -0
- data/lib/gobstones/with_command_line.rb +7 -0
- data/lib/gobstones/with_tempfile.rb +13 -0
- metadata +115 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 8b3c5bb11b693ef447845a080987bf266ed91d49
|
|
4
|
+
data.tar.gz: 4ad74366f324d2280aba57682b946ee2e1989017
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7a8dec77ebcf4cfa31699442077bb7e0093c4539af95ae8e5419da9f89e5e838b8f29d1f81012131868ccca885260a265ce58db08b0a450d43b4ec53b53a91e7
|
|
7
|
+
data.tar.gz: 4eba581631c514205a2b2aa8e5d93600bedff21d09a89d89cba840bcf072265cf23265e1e87c26450c2089c2cb5d6ab9082bde5dcc28907e58a94d25dc9983c9
|
data/lib/gobstones.rb
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Gobstones
|
|
2
|
+
end
|
|
3
|
+
|
|
4
|
+
require_relative 'gobstones/board'
|
|
5
|
+
require_relative 'gobstones/cell'
|
|
6
|
+
require_relative 'gobstones/gbb_parser'
|
|
7
|
+
require_relative 'gobstones/position'
|
|
8
|
+
require_relative 'gobstones/with_tempfile'
|
|
9
|
+
require_relative 'gobstones/with_command_line'
|
|
10
|
+
require_relative 'gobstones/spec'
|
|
11
|
+
require_relative 'gobstones/version'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Gobstones
|
|
2
|
+
|
|
3
|
+
class OutOfBoardError < RuntimeError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class Board
|
|
7
|
+
attr_reader :size, :cells, :head_position
|
|
8
|
+
|
|
9
|
+
def initialize(x, y)
|
|
10
|
+
@size = [x, y]
|
|
11
|
+
@cells = Hash.new(Cell.new)
|
|
12
|
+
@head_position = Position.new(0, 0)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_cell(position, cell)
|
|
16
|
+
@cells[position] = cell
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def move_head_to(position)
|
|
21
|
+
check_is_within_bounds position
|
|
22
|
+
@head_position = position
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cell_at(position)
|
|
27
|
+
check_is_within_bounds position
|
|
28
|
+
@cells[position]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ==(other)
|
|
32
|
+
self.class === other &&
|
|
33
|
+
other.size == @size &&
|
|
34
|
+
all_cells_equal?(other)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def within_bounds?(position)
|
|
40
|
+
@size[0] > position.x && @size[1] > position.y
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def check_is_within_bounds(position)
|
|
44
|
+
raise OutOfBoardError unless within_bounds?(position)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def all_cells_equal?(other)
|
|
48
|
+
self.class.includes_cells?(self, other) && self.class.includes_cells?(other, self)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.includes_cells?(this, that)
|
|
52
|
+
this.cells.all? { |position, cell| that.cell_at(position) == cell }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Gobstones
|
|
2
|
+
class Cell
|
|
3
|
+
attr_accessor :red, :green, :blue, :black
|
|
4
|
+
|
|
5
|
+
def initialize(red: 0, green: 0, blue: 0, black: 0)
|
|
6
|
+
@red = red
|
|
7
|
+
@green = green
|
|
8
|
+
@blue = blue
|
|
9
|
+
@black = black
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def set(color, quantity)
|
|
13
|
+
send "#{color}=", quantity
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ==(other)
|
|
17
|
+
self.class === other &&
|
|
18
|
+
other.red == @red &&
|
|
19
|
+
other.green == @green &&
|
|
20
|
+
other.blue == @blue &&
|
|
21
|
+
other.black == @black
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
alias eql? ==
|
|
25
|
+
|
|
26
|
+
def hash
|
|
27
|
+
@red.hash ^ @green.hash ^ @blue.hash ^ @black.hash
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require_relative '../extensions/array.rb'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MatchData
|
|
5
|
+
def to_position
|
|
6
|
+
Gobstones::Position.new self[1].to_i, self[2].to_i
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Gobstones
|
|
11
|
+
class GbbParser
|
|
12
|
+
COLORS = {'Azul' => :blue, 'Negro' => :black, 'Rojo' => :red, 'Verde' => :green}
|
|
13
|
+
|
|
14
|
+
def from_string(gbb_string)
|
|
15
|
+
board = nil
|
|
16
|
+
|
|
17
|
+
lines = gbb_string.lines.reject { |it| it.start_with? 'GBB', '%%' }
|
|
18
|
+
|
|
19
|
+
/size (\d+) (\d+)/.match(lines[0]) { |match| board = Board.new(match[1].to_i, match[2].to_i) }
|
|
20
|
+
/head (\d+) (\d+)/.match(lines.last) { |match| board.move_head_to match.to_position }
|
|
21
|
+
|
|
22
|
+
lines.drop(1).init.each do |cell_line|
|
|
23
|
+
position = get_position_from cell_line
|
|
24
|
+
cell = create_cell_from cell_line
|
|
25
|
+
|
|
26
|
+
board.add_cell position, cell
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
board
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def get_position_from(cell_line)
|
|
35
|
+
/cell (\d+) (\d+)/.match(cell_line).to_position
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_cell_from(cell_line)
|
|
39
|
+
cell = Cell.new
|
|
40
|
+
|
|
41
|
+
cell_line.scan(/(Azul|Negro|Rojo|Verde) (\d+)/) do |match|
|
|
42
|
+
cell.set to_color(match[0]), match[1].to_i
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
cell
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_color(gbb_color_string)
|
|
49
|
+
COLORS[gbb_color_string]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Gobstones
|
|
2
|
+
class Position
|
|
3
|
+
attr_reader :x, :y
|
|
4
|
+
|
|
5
|
+
def initialize(x, y)
|
|
6
|
+
@x = x
|
|
7
|
+
@y = y
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def ==(other)
|
|
11
|
+
self.class === other &&
|
|
12
|
+
other.x == @x &&
|
|
13
|
+
other.y == @y
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias eql? ==
|
|
17
|
+
|
|
18
|
+
def hash
|
|
19
|
+
@x.hash ^ @y.hash
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Gobstones::Spec
|
|
2
|
+
class ErrorMessageParser
|
|
3
|
+
def remove_traceback (x)
|
|
4
|
+
x.take_while { |str| not str.start_with? 'Traceback' }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def remove_line_specification(x)
|
|
8
|
+
x.drop(3)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def remove_boom_line_specification(x)
|
|
12
|
+
x.take_while { |str| not str.strip.start_with? 'En:' }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def parse(result)
|
|
16
|
+
remove_boom_line_specification(remove_traceback(remove_line_specification(result.lines))).join.strip
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Gobstones::Spec
|
|
2
|
+
class Example
|
|
3
|
+
include Gobstones::WithTempfile
|
|
4
|
+
|
|
5
|
+
attr_reader :gobstones_path
|
|
6
|
+
|
|
7
|
+
def initialize(gobstones_path, check_head_position)
|
|
8
|
+
@gobstones_path = gobstones_path
|
|
9
|
+
@check_head_position = check_head_position
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def start!(source_file, initial_board, final_board)
|
|
13
|
+
@source_file = source_file
|
|
14
|
+
@expected_final_board_gbb = final_board
|
|
15
|
+
@expected_final_board = Gobstones::GbbParser.new.from_string final_board
|
|
16
|
+
|
|
17
|
+
@html_output_file = Tempfile.new %w(gobstones.output .html)
|
|
18
|
+
@actual_final_board_file = Tempfile.new %w(gobstones.output .gbb)
|
|
19
|
+
@initial_board_file = write_tempfile initial_board, 'gbb'
|
|
20
|
+
|
|
21
|
+
"#{run_on_gobstones @source_file, @initial_board_file, @actual_final_board_file} 2>&1 &&" +
|
|
22
|
+
"#{run_on_gobstones @source_file, @initial_board_file, @html_output_file}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def result
|
|
26
|
+
actual = Gobstones::GbbParser.new.from_string(@actual_final_board_file.read)
|
|
27
|
+
|
|
28
|
+
if matches_with_expected_board? actual
|
|
29
|
+
["<div>#{@html_output_file.read}</div>", :passed]
|
|
30
|
+
else
|
|
31
|
+
initial_board_html = get_html_board @initial_board_file.open.read
|
|
32
|
+
expected_board_html = get_html_board @expected_final_board_gbb
|
|
33
|
+
|
|
34
|
+
output =
|
|
35
|
+
"<div>
|
|
36
|
+
#{add_caption initial_board_html, 'Tablero inicial'}
|
|
37
|
+
#{add_caption @html_output_file.read, 'Tablero final obtenido'}
|
|
38
|
+
#{add_caption expected_board_html, 'Tablero final esperado'}
|
|
39
|
+
</div>"
|
|
40
|
+
|
|
41
|
+
[output, :failed]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def parse_error_message(result)
|
|
46
|
+
ErrorMessageParser.new.parse(result)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def stop!
|
|
50
|
+
[@html_output_file, @actual_final_board_file, @initial_board_file].each { |it| it.unlink }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def matches_with_expected_board?(actual_board)
|
|
56
|
+
actual_board == @expected_final_board && (!@check_head_position || actual_board.head_position == @expected_final_board.head_position)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def run_on_gobstones(source_file, initial_board_file, final_board_file)
|
|
60
|
+
"#{gobstones_path} #{source_file.path} --from #{initial_board_file.path} --to #{final_board_file.path}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_html_board(gbb_representation)
|
|
64
|
+
identity = write_tempfile 'program {}', '.gbs'
|
|
65
|
+
|
|
66
|
+
board = write_tempfile gbb_representation, '.gbb'
|
|
67
|
+
|
|
68
|
+
board_html = Tempfile.new %w(gobstones.board .html)
|
|
69
|
+
|
|
70
|
+
%x"#{run_on_gobstones(identity, board, board_html)}"
|
|
71
|
+
|
|
72
|
+
result = board_html.read
|
|
73
|
+
board_html.unlink
|
|
74
|
+
result
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def add_caption(board_html, caption)
|
|
78
|
+
board_html.sub '<table class="gbs_board">', "<table class=\"gbs_board\">\n<caption>#{caption}</caption>"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Gobstones::Spec
|
|
2
|
+
class Runner
|
|
3
|
+
include Gobstones::WithCommandLine
|
|
4
|
+
include Gobstones::WithTempfile
|
|
5
|
+
|
|
6
|
+
attr_reader :gobstones_path
|
|
7
|
+
|
|
8
|
+
def initialize(gobstones_path)
|
|
9
|
+
@gobstones_path = gobstones_path
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run!(test_definition)
|
|
13
|
+
source_file = write_tempfile test_definition[:source], 'gbs'
|
|
14
|
+
results = test_definition[:examples].map do |example_definition|
|
|
15
|
+
example_definition[:check_head_position] = test_definition[:check_head_position]
|
|
16
|
+
run_example!(example_definition, source_file)
|
|
17
|
+
end
|
|
18
|
+
aggregate_results(results)
|
|
19
|
+
ensure
|
|
20
|
+
source_file.unlink
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def run_example!(example_definition, source_file)
|
|
26
|
+
command = start_example(source_file, example_definition)
|
|
27
|
+
result, status = run_command command
|
|
28
|
+
post_process result, status
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def aggregate_results(results)
|
|
32
|
+
[results.map { |it| it[0] }.join("\n<hr>\n"), results.all? { |it| it[1] == :passed } ? :passed : :failed]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def post_process(result, status)
|
|
36
|
+
if status == :passed
|
|
37
|
+
@example.result
|
|
38
|
+
else
|
|
39
|
+
[@example.parse_error_message(result), status]
|
|
40
|
+
end
|
|
41
|
+
ensure
|
|
42
|
+
@example.stop!
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def start_example(source, example_definition)
|
|
46
|
+
@example = Gobstones::Spec::Example.new(gobstones_path, example_definition[:check_head_position])
|
|
47
|
+
@example.start!(source, example_definition[:initial_board], example_definition[:final_board])
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: gobstones-spec
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Federico Aloi
|
|
8
|
+
- Franco Bulgarelli
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2015-05-27 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: bundler
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - ~>
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '1.7'
|
|
21
|
+
type: :development
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - ~>
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '1.7'
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: rake
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - ~>
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '10.0'
|
|
35
|
+
type: :development
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ~>
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '10.0'
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: rspec
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ~>
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '2'
|
|
49
|
+
type: :development
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ~>
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '2'
|
|
56
|
+
- !ruby/object:Gem::Dependency
|
|
57
|
+
name: codeclimate-test-reporter
|
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - '>='
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - '>='
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
description: Write Gobstones specs within Ruby
|
|
71
|
+
email:
|
|
72
|
+
- federico.aloi@gmail.com
|
|
73
|
+
- flbulgarelli@yahoo.com.ar
|
|
74
|
+
executables: []
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files: []
|
|
77
|
+
files:
|
|
78
|
+
- lib/gobstones/with_command_line.rb
|
|
79
|
+
- lib/gobstones/with_tempfile.rb
|
|
80
|
+
- lib/gobstones/gbb_parser.rb
|
|
81
|
+
- lib/gobstones/position.rb
|
|
82
|
+
- lib/gobstones/spec/error_message_parser.rb
|
|
83
|
+
- lib/gobstones/spec/example.rb
|
|
84
|
+
- lib/gobstones/spec/runner.rb
|
|
85
|
+
- lib/gobstones/spec.rb
|
|
86
|
+
- lib/gobstones/version.rb
|
|
87
|
+
- lib/gobstones/cell.rb
|
|
88
|
+
- lib/gobstones/board.rb
|
|
89
|
+
- lib/gobstones.rb
|
|
90
|
+
- lib/extensions/array.rb
|
|
91
|
+
homepage: https://github.com/uqbar-project/gobstones-spec
|
|
92
|
+
licenses:
|
|
93
|
+
- MIT
|
|
94
|
+
metadata: {}
|
|
95
|
+
post_install_message:
|
|
96
|
+
rdoc_options: []
|
|
97
|
+
require_paths:
|
|
98
|
+
- lib
|
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - '>='
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - '>='
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0'
|
|
109
|
+
requirements: []
|
|
110
|
+
rubyforge_project:
|
|
111
|
+
rubygems_version: 2.0.14
|
|
112
|
+
signing_key:
|
|
113
|
+
specification_version: 4
|
|
114
|
+
summary: Minimal test framework for the Gobstones language
|
|
115
|
+
test_files: []
|