Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some tests for game #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ GEM
remote: https://rubygems.org/
specs:
SgfParser (2.0.0)
ray (0.2.1)

PLATFORMS
java
ruby

DEPENDENCIES
SgfParser
ray
1 change: 1 addition & 0 deletions lib/weiqi.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require_relative "weiqi/board"
require_relative "weiqi/gnu_go"
require_relative "weiqi/scheduler"
require_relative "weiqi/game"
18 changes: 6 additions & 12 deletions lib/weiqi/game.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
require "thread"

module Weiqi
class Game
def initialize(engine)
def initialize(engine, scheduler=Weiqi::AsyncScheduler.new)
self.engine = engine
self.observers = []
self.history = []
self.mutex = Mutex.new
self.scheduler = scheduler
end

def observe(&block)
Expand All @@ -27,17 +25,13 @@ def quit

private

attr_accessor :engine, :observers, :history, :mutex
attr_accessor :engine, :observers, :history, :scheduler

def move
return if mutex.locked?

Thread.new do
mutex.synchronize do
notify_observers(yield)
scheduler.run do
notify_observers(yield)

notify_observers(engine.play_white)
end
notify_observers(engine.play_white)
end
end

Expand Down
21 changes: 21 additions & 0 deletions lib/weiqi/scheduler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require "thread"

module Weiqi
class SequentialScheduler
def run
yield
end
end

class AsyncScheduler
def initialize
@mutex = Mutex.new
end

def run(&block)
return if @mutex.locked?

@mutex.synchronize { yield }
end
end
end
42 changes: 42 additions & 0 deletions test/game_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require "minitest/autorun"
require "mocha/mini_test"

require_relative "../lib/weiqi"
require_relative "helpers/game_session"

describe "Game" do
let(:engine) { mock("Engine") }
let(:game) { Weiqi::Game.new(engine, Weiqi::SequentialScheduler.new) }
let(:session) { GameSession.new(engine, game) }
let(:transcript) { [] }

it "must be able to end game end by passing" do
assert_output "PASS!\nGame over. Final score 0\n" do
session.black_passes
.white_passes
.final_score(0)
.game_ends
end
end

it "must be able to end game by resignation" do
assert_output "PASS!\nYou win! The computer resigned\n" do
session.black_passes
.white_resigns
.game_ends
end
end

it "must be able to notify observers of moves" do
moves = []
game.observe { |board| moves << board.last_move }

session.black_plays(3,3)
.white_plays(3,4)
.black_plays(4,4)
.white_plays(5,5)
.verify_results

moves.must_equal([[3,3],[3,4],[4,4],[5,5]])
end
end
69 changes: 69 additions & 0 deletions test/helpers/game_session.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class GameSession
def initialize(mock_engine, game)
@moves = Mocha::Sequence.new('moves')
@engine = mock_engine
@game = game

@actions = []
end

def black_passes
@engine.expects(:pass_black).in_sequence(@moves).returns(move("PASS"))

@actions << lambda { @game.pass }

self
end

def black_plays(x,y)
@engine.expects(:play_black).in_sequence(@moves).returns(move([x,y]))

@actions << lambda { @game.play(x, y) }

self
end

def white_plays(x,y)
@engine.expects(:play_white).in_sequence(@moves).returns(move([x,y]))

self
end

def white_passes
@engine.expects(:play_white).in_sequence(@moves).returns(move("PASS"))

self
end

def white_resigns
@engine.expects(:play_white).in_sequence(@moves).returns(move("resign"))

self
end

def final_score(num)
@engine.expects(:final_score).returns(num)

self
end

def game_ends
@engine.expects(:quit)

verify_results

self
end

def verify_results
@actions.each { |a| a.call }

self
end

private

def move(data)
Struct.new(:last_move).new(data)
end
end