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.
@@ -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
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def init(n=1)
3
+ take size - n
4
+ end
5
+ end
@@ -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,8 @@
1
+ module Gobstones
2
+ module Spec
3
+ end
4
+ end
5
+
6
+ require_relative './spec/error_message_parser'
7
+ require_relative './spec/example'
8
+ require_relative './spec/runner'
@@ -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
@@ -0,0 +1,3 @@
1
+ module Gobstones
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ module Gobstones
2
+ module WithCommandLine
3
+ def run_command(command)
4
+ [%x{#{command}}, $?.success? ? :passed : :failed]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'tempfile'
2
+
3
+ module Gobstones
4
+ module WithTempfile
5
+
6
+ def write_tempfile(content, extension)
7
+ file = Tempfile.new %W(gobstones. .#{extension})
8
+ file.write content
9
+ file.close
10
+ file
11
+ end
12
+ end
13
+ 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: []