"""Tests for allplayalls.py""" from __future__ import with_statement from textwrap import dedent import cPickle as pickle from gomill import competitions from gomill import allplayalls from gomill.gtp_games import Game_result from gomill.game_jobs import Game_job, Game_job_result from gomill.competitions import ( Player_config, NoGameAvailable, CompetitionError, ControlFileError) from gomill.allplayalls import Competitor_config from gomill_tests import competition_test_support from gomill_tests import gomill_test_support from gomill_tests import test_framework from gomill_tests.competition_test_support import ( fake_response, check_screen_report) def make_tests(suite): suite.addTests(gomill_test_support.make_simple_tests(globals())) def check_short_report(tc, comp, expected_grid, expected_matchups, expected_players, competition_name="testcomp"): """Check that an allplayall's short report is as expected.""" expected = ("allplayall: %s\n\n%s\n%s\n%s\n" % (competition_name, expected_grid, expected_matchups, expected_players)) tc.assertMultiLineEqual(competition_test_support.get_short_report(comp), expected) class Allplayall_fixture(test_framework.Fixture): """Fixture setting up a Allplayall. attributes: comp -- Allplayall """ def __init__(self, tc, config=None): if config is None: config = default_config() self.tc = tc self.comp = allplayalls.Allplayall('testcomp') self.comp.initialise_from_control_file(config) self.comp.set_clean_status() def check_screen_report(self, expected): """Check that the screen report is as expected.""" check_screen_report(self.tc, self.comp, expected) def check_short_report(self, *args, **kwargs): """Check that the short report is as expected.""" check_short_report(self.tc, self.comp, *args, **kwargs) def default_config(): return { 'players' : { 't1' : Player_config("test1"), 't2' : Player_config("test2"), 't3' : Player_config("test3"), }, 'board_size' : 13, 'komi' : 7.5, 'competitors' : [ Competitor_config('t1'), Competitor_config('t2'), 't3', ], } def test_default_config(tc): comp = allplayalls.Allplayall('test') config = default_config() comp.initialise_from_control_file(config) comp.set_clean_status() tr = comp.get_tournament_results() tc.assertListEqual(tr.get_matchup_ids(), ['AvB', 'AvC', 'BvC']) mBvC = tr.get_matchup('BvC') tc.assertEqual(mBvC.player_1, 't2') tc.assertEqual(mBvC.player_2, 't3') tc.assertEqual(mBvC.board_size, 13) tc.assertEqual(mBvC.komi, 7.5) tc.assertEqual(mBvC.move_limit, 1000) tc.assertEqual(mBvC.scorer, 'players') tc.assertEqual(mBvC.internal_scorer_handicap_compensation, 'full') tc.assertEqual(mBvC.number_of_games, None) tc.assertIs(mBvC.alternating, True) tc.assertIs(mBvC.handicap, None) tc.assertEqual(mBvC.handicap_style, 'fixed') def test_basic_config(tc): comp = allplayalls.Allplayall('test') config = default_config() config['description'] = "default\nconfig" config['board_size'] = 9 config['komi'] = 0.5 config['move_limit'] = 200 config['scorer'] = 'internal' config['internal_scorer_handicap_compensation'] = 'short' config['rounds'] = 20 comp.initialise_from_control_file(config) tc.assertEqual(comp.description, "default\nconfig") comp.set_clean_status() mBvC = comp.get_tournament_results().get_matchup('BvC') tc.assertEqual(mBvC.player_1, 't2') tc.assertEqual(mBvC.player_2, 't3') tc.assertEqual(mBvC.board_size, 9) tc.assertEqual(mBvC.komi, 0.5) tc.assertEqual(mBvC.move_limit, 200) tc.assertEqual(mBvC.scorer, 'internal') tc.assertEqual(mBvC.internal_scorer_handicap_compensation, 'short') tc.assertEqual(mBvC.number_of_games, 20) tc.assertIs(mBvC.alternating, True) tc.assertIs(mBvC.handicap, None) tc.assertEqual(mBvC.handicap_style, 'fixed') def test_unknown_player(tc): comp = allplayalls.Allplayall('test') config = default_config() config['competitors'].append('nonex') tc.assertRaisesRegexp( ControlFileError, "competitor nonex: unknown player", comp.initialise_from_control_file, config) def test_duplicate_player(tc): comp = allplayalls.Allplayall('test') config = default_config() config['competitors'].append('t2') tc.assertRaisesRegexp( ControlFileError, "duplicate competitor: t2", comp.initialise_from_control_file, config) def test_game_id_format(tc): config = default_config() config['rounds'] = 1000 fx = Allplayall_fixture(tc, config) tc.assertEqual(fx.comp.get_game().game_id, 'AvB_000') def test_get_player_checks(tc): fx = Allplayall_fixture(tc) checks = fx.comp.get_player_checks() tc.assertEqual(len(checks), 3) tc.assertEqual(checks[0].board_size, 13) tc.assertEqual(checks[0].komi, 7.5) tc.assertEqual(checks[0].player.code, "t1") tc.assertEqual(checks[0].player.cmd_args, ['test1']) tc.assertEqual(checks[1].player.code, "t2") tc.assertEqual(checks[1].player.cmd_args, ['test2']) tc.assertEqual(checks[2].player.code, "t3") tc.assertEqual(checks[2].player.cmd_args, ['test3']) def test_play(tc): fx = Allplayall_fixture(tc) tc.assertIsNone(fx.comp.description) job1 = fx.comp.get_game() tc.assertIsInstance(job1, Game_job) tc.assertEqual(job1.game_id, 'AvB_0') tc.assertEqual(job1.player_b.code, 't1') tc.assertEqual(job1.player_w.code, 't2') tc.assertEqual(job1.board_size, 13) tc.assertEqual(job1.komi, 7.5) tc.assertEqual(job1.move_limit, 1000) tc.assertIs(job1.use_internal_scorer, False) tc.assertEqual(job1.internal_scorer_handicap_compensation, 'full') tc.assertEqual(job1.game_data, ('AvB', 0)) tc.assertIsNone(job1.sgf_filename) tc.assertIsNone(job1.sgf_dirname) tc.assertIsNone(job1.void_sgf_dirname) tc.assertEqual(job1.sgf_event, 'testcomp') tc.assertIsNone(job1.gtp_log_pathname) job2 = fx.comp.get_game() tc.assertIsInstance(job2, Game_job) tc.assertEqual(job2.game_id, 'AvC_0') tc.assertEqual(job2.player_b.code, 't1') tc.assertEqual(job2.player_w.code, 't3') response1 = fake_response(job1, 'b') fx.comp.process_game_result(response1) response2 = fake_response(job2, None) fx.comp.process_game_result(response2) expected_grid = dedent("""\ 2 games played A B C A t1 1-0 0.5-0.5 B t2 0-1 0-0 C t3 0.5-0.5 0-0 """) expected_matchups = dedent("""\ t1 v t2 (1 games) board size: 13 komi: 7.5 wins t1 1 100.00% (black) t2 0 0.00% (white) t1 v t3 (1 games) board size: 13 komi: 7.5 wins t1 0.5 50.00% (black) t3 0.5 50.00% (white) """) expected_players = dedent("""\ player t1: t1 engine:v1.2.3 player t2: t2 engine testdescription player t3: t3 engine testdescription """) fx.check_screen_report(expected_grid) fx.check_short_report(expected_grid, expected_matchups, expected_players) avb_results = fx.comp.get_tournament_results().get_matchup_results('AvB') tc.assertEqual(avb_results, [response1.game_result]) def test_play_many(tc): config = default_config() config['rounds'] = 30 fx = Allplayall_fixture(tc, config) jobs = [fx.comp.get_game() for _ in xrange(57)] for i in xrange(57): response = fake_response(jobs[i], 'b') fx.comp.process_game_result(response) fx.check_screen_report(dedent("""\ 57/90 games played A B C A t1 10-9 10-9 B t2 9-10 10-9 C t3 9-10 9-10 """)) tc.assertEqual( len(fx.comp.get_tournament_results().get_matchup_results('AvB')), 19) comp2 = competition_test_support.check_round_trip(tc, fx.comp, config) jobs2 = [comp2.get_game() for _ in range(4)] tc.assertListEqual([job.game_id for job in jobs2], ['AvB_19', 'AvC_19', 'BvC_19', 'AvB_20']) tr = comp2.get_tournament_results() tc.assertEqual(len(tr.get_matchup_results('AvB')), 19) ms = tr.get_matchup_stats('AvB') tc.assertEqual(ms.total, 19) tc.assertEqual(ms.wins_1, 10) tc.assertIs(ms.alternating, True) def test_competitor_change(tc): fx = Allplayall_fixture(tc) status = pickle.loads(pickle.dumps(fx.comp.get_status())) config2 = default_config() del config2['competitors'][2] comp2 = allplayalls.Allplayall('testcomp') comp2.initialise_from_control_file(config2) with tc.assertRaises(CompetitionError) as ar: comp2.set_status(status) tc.assertEqual( str(ar.exception), "competitor has been removed from control file") config3 = default_config() config3['players']['t4'] = Player_config("test4") config3['competitors'][2] = 't4' comp3 = allplayalls.Allplayall('testcomp') comp3.initialise_from_control_file(config3) with tc.assertRaises(CompetitionError) as ar: comp3.set_status(status) tc.assertEqual( str(ar.exception), "competitors have changed in the control file") config4 = default_config() config4['players']['t4'] = Player_config("test4") config4['competitors'].append('t4') comp4 = allplayalls.Allplayall('testcomp') comp4.initialise_from_control_file(config4) comp4.set_status(status)