gobstones-spec 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|