pygo/gomill/gomill_tests/gtp_controller_tests.py

699 lines
30 KiB
Python
Raw Normal View History

"""Tests for gtp_controller.py"""
from __future__ import with_statement
import os
from gomill import gtp_controller
from gomill.gtp_controller import (
GtpChannelError, GtpProtocolError, GtpTransportError, GtpChannelClosed,
BadGtpResponse, Gtp_controller)
from gomill_tests import gomill_test_support
from gomill_tests import gtp_controller_test_support
from gomill_tests import gtp_engine_fixtures
from gomill_tests.test_framework import SupporterError
from gomill_tests.gtp_controller_test_support import Preprogrammed_gtp_channel
def make_tests(suite):
suite.addTests(gomill_test_support.make_simple_tests(globals()))
### Channel-level
def test_linebased_channel(tc):
channel = Preprogrammed_gtp_channel("=\n\n=\n\n")
tc.assertEqual(channel.get_command_stream(), "")
channel.send_command("play", ["b", "a3"])
tc.assertEqual(channel.get_command_stream(), "play b a3\n")
tc.assertEqual(channel.get_response(), (False, ""))
channel.send_command("quit", [])
tc.assertEqual(channel.get_command_stream(), "play b a3\nquit\n")
tc.assertEqual(channel.get_response(), (False, ""))
tc.assertRaisesRegexp(
GtpChannelClosed, "engine has closed the response channel",
channel.get_response)
channel.close()
def test_linebased_channel_responses(tc):
channel = Preprogrammed_gtp_channel(
"= 2\n\n"
# failure response
"? unknown command\n\n"
# final response with no newlines
"= ok")
channel.send_command("protocol_version", [])
tc.assertEqual(channel.get_response(), (False, "2"))
channel.send_command("xyzzy", ["1", "2"])
tc.assertEqual(channel.get_response(), (True, "unknown command"))
channel.send_command("quit", ["1", "2"])
tc.assertEqual(channel.get_response(), (False, "ok"))
def test_linebased_channel_response_cleaning(tc):
channel = Preprogrammed_gtp_channel(
# empty response
"=\n\n"
# whitespace-only response
"= \n\n"
# ignores CRs (GTP spec)
"= 1abc\rde\r\n\r\n"
# ignores extra blank lines (GTP spec)
"= 2abcde\n\n\n\n"
# strips control characters (GTP spec)
"= 3a\x7fbc\x00d\x07e\n\x01\n"
# converts tabs to spaces (GTP spec)
"= 4abc\tde\n\n"
# strips leading whitespace (channel docs)
"= \t 5abcde\n\n"
# strips trailing whitepace (channel docs)
"= 6abcde \t \n\n"
# doesn't strip whitespace in the middle of a multiline response
"= 7aaa \n bbb\tccc\nddd \t \n\n"
# passes high characters through
"= 8ab\xc3\xa7de\n\n"
# all this at once, in a failure response
"? a\raa \r\n b\rbb\tcc\x01c\nddd \t \n\n"
)
tc.assertEqual(channel.get_response(), (False, ""))
tc.assertEqual(channel.get_response(), (False, ""))
tc.assertEqual(channel.get_response(), (False, "1abcde"))
tc.assertEqual(channel.get_response(), (False, "2abcde"))
tc.assertEqual(channel.get_response(), (False, "3abcde"))
tc.assertEqual(channel.get_response(), (False, "4abc de"))
tc.assertEqual(channel.get_response(), (False, "5abcde"))
tc.assertEqual(channel.get_response(), (False, "6abcde"))
tc.assertEqual(channel.get_response(), (False, "7aaa \n bbb ccc\nddd"))
tc.assertEqual(channel.get_response(), (False, "8ab\xc3\xa7de"))
tc.assertEqual(channel.get_response(), (True, "aaa \n bbb ccc\nddd"))
def test_linebased_channel_invalid_responses(tc):
channel = Preprogrammed_gtp_channel(
# good response first, to get past the "isn't speaking GTP" checking
"=\n\n"
"ERROR\n\n"
"# comments not allowed in responses\n\n"
)
tc.assertEqual(channel.get_response(), (False, ""))
tc.assertRaisesRegexp(
GtpProtocolError, "^no success/failure indication from engine: "
"first line is `ERROR`$",
channel.get_response)
tc.assertRaisesRegexp(
GtpProtocolError, "^no success/failure indication from engine: "
"first line is `#",
channel.get_response)
def test_linebased_channel_without_response(tc):
channel = Preprogrammed_gtp_channel("")
channel.send_command("protocol_version", [])
tc.assertRaisesRegexp(
GtpChannelClosed, "^engine has closed the response channel$",
channel.get_response)
channel.close()
def test_linebased_channel_with_usage_message_response(tc):
channel = Preprogrammed_gtp_channel(
"Usage: randomprogram [options]\n\nOptions:\n"
"--help show this help message and exit\n")
channel.send_command("protocol_version", [])
tc.assertRaisesRegexp(
GtpProtocolError, "^engine isn't speaking GTP: first byte is 'U'$",
channel.get_response)
channel.close()
def test_linebased_channel_with_interactive_response(tc):
channel = Preprogrammed_gtp_channel("prompt> \n", hangs_before_eof=True)
channel.send_command("protocol_version", [])
tc.assertRaisesRegexp(
GtpProtocolError, "^engine isn't speaking GTP", channel.get_response)
channel.close()
def test_linebased_channel_hang(tc):
# Correct behaviour for a GTP controller here is to wait for a newline.
# (Would be nice to have a timeout.)
# This serves as a check that the hangs_before_eof modelling is working.
channel = Preprogrammed_gtp_channel("=prompt> ", hangs_before_eof=True)
channel.send_command("protocol_version", [])
tc.assertRaisesRegexp(
SupporterError, "this would hang", channel.get_response)
channel.close()
def test_linebased_channel_with_gmp_response(tc):
channel = Preprogrammed_gtp_channel("\x01\xa1\xa0\x80",
hangs_before_eof=True)
channel.send_command("protocol_version", [])
tc.assertRaisesRegexp(
GtpProtocolError, "appears to be speaking GMP", channel.get_response)
channel.close()
def test_linebased_channel_with_broken_command_pipe(tc):
channel = Preprogrammed_gtp_channel(
"Usage: randomprogram [options]\n\nOptions:\n"
"--help show this help message and exit\n")
channel.break_command_stream()
tc.assertRaisesRegexp(
GtpChannelClosed, "^engine has closed the command channel$",
channel.send_command, "protocol_version", [])
channel.close()
def test_linebased_channel_with_broken_response_pipe(tc):
channel = Preprogrammed_gtp_channel("= 2\n\n? unreached\n\n")
channel.send_command("protocol_version", [])
tc.assertEqual(channel.get_response(), (False, "2"))
channel.break_response_stream()
channel.send_command("list_commands", [])
tc.assertRaisesRegexp(
GtpChannelClosed, "^engine has closed the response channel$",
channel.get_response)
channel.close()
def test_channel_command_validation(tc):
channel = Preprogrammed_gtp_channel("\n\n")
# empty command
tc.assertRaises(ValueError, channel.send_command, "", [])
# space in command
tc.assertRaises(ValueError, channel.send_command, "play b a3", [])
# space after command
tc.assertRaises(ValueError, channel.send_command, "play ", ["b", "a3"])
# control character in command
tc.assertRaises(ValueError, channel.send_command, "pla\x01y", ["b", "a3"])
# unicode command
tc.assertRaises(ValueError, channel.send_command, u"protocol_version", [])
# space in argument
tc.assertRaises(ValueError, channel.send_command, "play", ["b a3"])
# unicode argument
tc.assertRaises(ValueError, channel.send_command, "play ", [u"b", "a3"])
# high characters
channel.send_command("pl\xc3\xa1y", ["b", "\xc3\xa13"])
tc.assertEqual(channel.get_command_stream(), "pl\xc3\xa1y b \xc3\xa13\n")
### Validating Testing_gtp_channel
def test_testing_gtp_channel(tc):
engine = gtp_engine_fixtures.get_test_engine()
channel = gtp_controller_test_support.Testing_gtp_channel(engine)
channel.send_command("play", ["b", "a3"])
tc.assertEqual(channel.get_response(), (True, "unknown command"))
channel.send_command("test", [])
tc.assertEqual(channel.get_response(), (False, "test response"))
channel.send_command("multiline", [])
tc.assertEqual(channel.get_response(),
(False, "first line \n second line\nthird line"))
channel.send_command("quit", [])
tc.assertEqual(channel.get_response(), (False, ""))
tc.assertRaisesRegexp(
GtpChannelClosed, "engine has closed the command channel",
channel.send_command, "quit", [])
channel.close()
def test_testing_gtp_channel_alt(tc):
engine = gtp_engine_fixtures.get_test_engine()
channel = gtp_controller_test_support.Testing_gtp_channel(engine)
channel.engine_exit_breaks_commands = False
channel.send_command("test", [])
tc.assertEqual(channel.get_response(), (False, "test response"))
channel.send_command("quit", [])
tc.assertEqual(channel.get_response(), (False, ""))
channel.send_command("test", [])
tc.assertRaisesRegexp(
GtpChannelClosed, "engine has closed the response channel",
channel.get_response)
channel.close()
def test_testing_gtp_channel_fatal_errors(tc):
engine = gtp_engine_fixtures.get_test_engine()
channel = gtp_controller_test_support.Testing_gtp_channel(engine)
channel.send_command("fatal", [])
tc.assertEqual(channel.get_response(), (True, "fatal error"))
tc.assertRaisesRegexp(
GtpChannelClosed, "engine has closed the response channel",
channel.get_response)
channel.close()
def test_testing_gtp_channel_sequencing(tc):
engine = gtp_engine_fixtures.get_test_engine()
channel = gtp_controller_test_support.Testing_gtp_channel(engine)
tc.assertRaisesRegexp(
SupporterError, "response request without command",
channel.get_response)
channel.send_command("test", [])
tc.assertRaisesRegexp(
SupporterError, "two commands in a row",
channel.send_command, "test", [])
def test_testing_gtp_force_error(tc):
engine = gtp_engine_fixtures.get_test_engine()
channel = gtp_controller_test_support.Testing_gtp_channel(engine)
channel.fail_next_command = True
tc.assertRaisesRegexp(
GtpTransportError, "forced failure for send_command_line",
channel.send_command, "test", [])
channel.send_command("test", [])
channel.fail_next_response = True
tc.assertRaisesRegexp(
GtpTransportError, "forced failure for get_response_line",
channel.get_response)
channel.force_next_response = "# error\n\n"
tc.assertRaisesRegexp(
GtpProtocolError,
"no success/failure indication from engine: first line is `# error`",
channel.get_response)
channel.fail_close = True
tc.assertRaisesRegexp(
GtpTransportError, "forced failure for close",
channel.close)
### Controller-level
def test_controller(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertEqual(controller.name, 'player test')
tc.assertIs(controller.channel, channel)
tc.assertFalse(controller.channel_is_bad)
tc.assertEqual(controller.do_command("test", "ab", "cd"), "args: ab cd")
with tc.assertRaises(BadGtpResponse) as ar:
controller.do_command("error")
tc.assertEqual(ar.exception.gtp_error_message, "normal error")
tc.assertEqual(ar.exception.gtp_command, "error")
tc.assertSequenceEqual(ar.exception.gtp_arguments, [])
tc.assertEqual(str(ar.exception),
"failure response from 'error' to player test:\n"
"normal error")
with tc.assertRaises(BadGtpResponse) as ar:
controller.do_command("fatal")
tc.assertFalse(controller.channel_is_bad)
with tc.assertRaises(GtpChannelClosed) as ar:
controller.do_command("test")
tc.assertEqual(str(ar.exception),
"error sending 'test' to player test:\n"
"engine has closed the command channel")
tc.assertTrue(controller.channel_is_bad)
controller.close()
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_alt_exit(tc):
channel = gtp_engine_fixtures.get_test_channel()
channel.engine_exit_breaks_commands = False
controller = Gtp_controller(channel, 'player test')
controller.do_command("quit")
tc.assertFalse(controller.channel_is_bad)
with tc.assertRaises(GtpChannelClosed) as ar:
controller.do_command("test")
tc.assertEqual(str(ar.exception),
"error reading response to 'test' from player test:\n"
"engine has closed the response channel")
tc.assertTrue(controller.channel_is_bad)
controller.close()
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_first_command_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
with tc.assertRaises(BadGtpResponse) as ar:
controller.do_command("error")
tc.assertEqual(
str(ar.exception),
"failure response from first command (error) to player test:\n"
"normal error")
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_command_transport_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertFalse(controller.channel_is_bad)
channel.fail_next_command = True
with tc.assertRaises(GtpTransportError) as ar:
controller.do_command("test")
tc.assertEqual(
str(ar.exception),
"transport error sending 'test' to player test:\n"
"forced failure for send_command_line")
tc.assertTrue(controller.channel_is_bad)
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_response_transport_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertFalse(controller.channel_is_bad)
channel.fail_next_response = True
with tc.assertRaises(GtpTransportError) as ar:
controller.do_command("test")
tc.assertEqual(
str(ar.exception),
"transport error reading response to first command (test) "
"from player test:\n"
"forced failure for get_response_line")
tc.assertTrue(controller.channel_is_bad)
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_response_protocol_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertFalse(controller.channel_is_bad)
channel.force_next_response = "# error\n\n"
with tc.assertRaises(GtpProtocolError) as ar:
controller.do_command("test")
tc.assertEqual(
str(ar.exception),
"GTP protocol error reading response to 'test' from player test:\n"
"no success/failure indication from engine: first line is `# error`")
tc.assertTrue(controller.channel_is_bad)
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_close(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertFalse(controller.channel_is_closed)
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertFalse(controller.channel_is_closed)
tc.assertFalse(controller.channel.is_closed)
controller.close()
tc.assertTrue(controller.channel_is_closed)
tc.assertTrue(controller.channel.is_closed)
tc.assertRaisesRegexp(StandardError, "^channel is closed$",
controller.do_command, "test")
tc.assertRaisesRegexp(StandardError, "^channel is closed$",
controller.close)
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_close_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
channel.fail_close = True
with tc.assertRaises(GtpTransportError) as ar:
controller.close()
tc.assertEqual(
str(ar.exception),
"error closing player test:\n"
"forced failure for close")
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_safe_close(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertFalse(controller.channel_is_closed)
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertFalse(controller.channel_is_closed)
tc.assertFalse(controller.channel.is_closed)
controller.safe_close()
tc.assertTrue(controller.channel_is_closed)
tc.assertTrue(controller.channel.is_closed)
tc.assertListEqual(channel.engine.commands_handled,
[('test', []), ('quit', [])])
# safe to call twice
controller.safe_close()
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_safe_close_after_error(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertFalse(controller.channel_is_bad)
channel.force_next_response = "# error\n\n"
with tc.assertRaises(GtpProtocolError) as ar:
controller.do_command("test")
tc.assertTrue(controller.channel_is_bad)
# doesn't send quit when channel_is_bad
controller.safe_close()
tc.assertTrue(controller.channel_is_closed)
tc.assertTrue(controller.channel.is_closed)
tc.assertListEqual(channel.engine.commands_handled,
[('test', []), ('test', [])])
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_controller_safe_close_with_error_from_quit(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
channel.force_next_response = "# error\n\n"
controller.safe_close()
tc.assertTrue(controller.channel_is_closed)
tc.assertTrue(controller.channel.is_closed)
tc.assertListEqual(channel.engine.commands_handled,
[('quit', [])])
tc.assertListEqual(
controller.retrieve_error_messages(),
["GTP protocol error reading response to first command (quit) "
"from player test:\n"
"no success/failure indication from engine: first line is `# error`"])
def test_controller_safe_close_with_failure_response_from_quit(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
channel.engine.force_error("quit")
controller.safe_close()
tc.assertTrue(controller.channel_is_closed)
tc.assertTrue(controller.channel.is_closed)
tc.assertListEqual(channel.engine.commands_handled,
[('quit', [])])
error_messages = controller.retrieve_error_messages()
tc.assertEqual(len(error_messages), 1)
tc.assertEqual(
error_messages[0],
"failure response from first command (quit) to player test:\n"
"handler forced to fail")
def test_controller_safe_close_with_error_from_close(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
channel.fail_close = True
controller.safe_close()
tc.assertTrue(controller.channel_is_closed)
tc.assertListEqual(channel.engine.commands_handled,
[('quit', [])])
tc.assertListEqual(
controller.retrieve_error_messages(),
["error closing player test:\n"
"forced failure for close"])
def test_safe_do_command(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
tc.assertEqual(controller.safe_do_command("test", "ab"), "args: ab")
with tc.assertRaises(BadGtpResponse) as ar:
controller.safe_do_command("error")
tc.assertFalse(controller.channel_is_bad)
channel.fail_next_response = True
tc.assertIsNone(controller.safe_do_command("test"))
tc.assertTrue(controller.channel_is_bad)
tc.assertIsNone(controller.safe_do_command("test"))
tc.assertListEqual(
controller.retrieve_error_messages(),
["transport error reading response to 'test' from player test:\n"
"forced failure for get_response_line"])
controller.safe_close()
# check that third 'test' wasn't sent, and nor was 'quit'
tc.assertListEqual(channel.engine.commands_handled,
[('test', ['ab']), ('error', []), ('test', [])])
def test_safe_do_command_closed_channel(tc):
# check it's ok to call safe_do_command() on a closed channel
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
controller.safe_close()
tc.assertIsNone(controller.safe_do_command("test"))
tc.assertListEqual(channel.engine.commands_handled,
[('quit', [])])
tc.assertListEqual(controller.retrieve_error_messages(), [])
def test_known_command(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'kc test')
tc.assertTrue(controller.known_command("test"))
tc.assertFalse(controller.known_command("nonesuch"))
tc.assertTrue(controller.known_command("test"))
tc.assertFalse(controller.known_command("nonesuch"))
def test_known_command_2(tc):
# Checking that known_command caches its responses
# and that it treats an error or unknown value the same as 'false'.
channel = Preprogrammed_gtp_channel(
"= true\n\n= absolutely not\n\n? error\n\n# unreached\n\n")
controller = Gtp_controller(channel, 'kc2 test')
tc.assertTrue(controller.known_command("one"))
tc.assertFalse(controller.known_command("two"))
tc.assertFalse(controller.known_command("three"))
tc.assertTrue(controller.known_command("one"))
tc.assertFalse(controller.known_command("two"))
tc.assertEqual(
channel.get_command_stream(),
"known_command one\nknown_command two\nknown_command three\n")
def test_check_protocol_version(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'pv test')
controller.check_protocol_version()
def test_check_protocol_version_2(tc):
channel = Preprogrammed_gtp_channel("= 1\n\n? error\n\n# unreached\n\n")
controller = Gtp_controller(channel, 'pv2 test')
with tc.assertRaises(BadGtpResponse) as ar:
controller.check_protocol_version()
tc.assertEqual(str(ar.exception), "pv2 test reports GTP protocol version 1")
tc.assertEqual(ar.exception.gtp_error_message, None)
# check error is not treated as a check failure
controller.check_protocol_version()
def test_list_commands(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'lc test')
channel.engine.add_command("xyzzy", None)
channel.engine.add_command("pl ugh", None)
tc.assertListEqual(
controller.list_commands(),
['error', 'fatal', 'known_command', 'list_commands',
'multiline', 'protocol_version', 'quit', 'test', 'xyzzy'])
def test_gtp_aliases(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'alias test')
controller.set_gtp_aliases({
'aliased' : 'test',
'aliased2' : 'nonesuch',
})
tc.assertIs(controller.known_command("test"), True)
tc.assertIs(controller.known_command("aliased"), True)
tc.assertIs(controller.known_command("nonesuch"), False)
tc.assertIs(controller.known_command("test"), True)
tc.assertIs(controller.known_command("aliased"), True)
tc.assertIs(controller.known_command("nonesuch"), False)
tc.assertEqual(controller.do_command("test"), "test response")
tc.assertEqual(controller.do_command("aliased"), "test response")
with tc.assertRaises(BadGtpResponse) as ar:
controller.do_command("aliased2")
tc.assertEqual(ar.exception.gtp_error_message, "unknown command")
tc.assertEqual(ar.exception.gtp_command, "nonesuch")
def test_gtp_aliases_safe(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'alias test')
controller.set_gtp_aliases({
'aliased' : 'test',
'aliased2' : 'nonesuch',
})
tc.assertIs(controller.safe_known_command("test"), True)
tc.assertIs(controller.safe_known_command("aliased"), True)
tc.assertIs(controller.safe_known_command("nonesuch"), False)
tc.assertIs(controller.safe_known_command("test"), True)
tc.assertIs(controller.safe_known_command("aliased"), True)
tc.assertIs(controller.safe_known_command("nonesuch"), False)
tc.assertEqual(controller.safe_do_command("test"), "test response")
tc.assertEqual(controller.safe_do_command("aliased"), "test response")
with tc.assertRaises(BadGtpResponse) as ar:
controller.safe_do_command("aliased2")
tc.assertEqual(ar.exception.gtp_error_message, "unknown command")
tc.assertEqual(ar.exception.gtp_command, "nonesuch")
def test_fix_version(tc):
fv = gtp_controller._fix_version
tc.assertEqual(fv("foo", "bar"), "bar")
tc.assertEqual(fv("foo", "FOO bar"), "bar")
tc.assertEqual(fv("foo", "asd " * 16), "asd " * 16)
tc.assertEqual(fv("foo", "asd " * 17), "asd")
tc.assertEqual(
fv("MoGo", "MoGo release 1. Please read http://www.lri.fr/~gelly/MoGo.htm for more information. That is NOT an official developpement MoGo version, but it is a public release. Its strength highly depends on your hardware and the time settings."),
"release 1")
tc.assertEqual(
fv("Pachi UCT Engine", "8.99 (Hakugen-devel): I'm playing UCT. When I'm losing, I will resign, if I think I win, I play until you pass. Anyone can send me 'winrate' in private chat to get my assessment of the position."),
"8.99 (Hakugen-devel)")
def test_describe_engine(tc):
channel = gtp_engine_fixtures.get_test_channel()
controller = Gtp_controller(channel, 'player test')
short_s, long_s = gtp_controller.describe_engine(controller)
tc.assertEqual(short_s, "unknown")
tc.assertEqual(long_s, "unknown")
channel = gtp_engine_fixtures.get_test_channel()
channel.engine.add_command('name', lambda args:"test engine")
controller = Gtp_controller(channel, 'player test')
short_s, long_s = gtp_controller.describe_engine(controller)
tc.assertEqual(short_s, "test engine")
tc.assertEqual(long_s, "test engine")
channel = gtp_engine_fixtures.get_test_channel()
channel.engine.add_command('name', lambda args:"test engine")
channel.engine.add_command('version', lambda args:"1.2.3")
controller = Gtp_controller(channel, 'player test')
short_s, long_s = gtp_controller.describe_engine(controller)
tc.assertEqual(short_s, "test engine:1.2.3")
tc.assertEqual(long_s, "test engine:1.2.3")
channel = gtp_engine_fixtures.get_test_channel()
channel.engine.add_command('name', lambda args:"test engine")
channel.engine.add_command('version', lambda args:"1.2.3")
channel.engine.add_command(
'gomill-describe_engine',
lambda args:"test engine (v1.2.3):\n pl\xc3\xa1yer \xa3")
controller = Gtp_controller(channel, 'player test')
short_s, long_s = gtp_controller.describe_engine(controller)
tc.assertEqual(short_s, "test engine:1.2.3")
tc.assertEqual(long_s, "test engine (v1.2.3):\n pl\xc3\xa1yer ?")
channel = gtp_engine_fixtures.get_test_channel()
channel.engine.add_command('name', lambda args:"test engine")
channel.engine.add_command('version', lambda args:"test engine v1.2.3")
controller = Gtp_controller(channel, 'player test')
short_s, long_s = gtp_controller.describe_engine(controller)
tc.assertEqual(short_s, "test engine:v1.2.3")
tc.assertEqual(long_s, "test engine:v1.2.3")
### Subprocess-specific
def test_subprocess_channel(tc):
# This tests that Subprocess_gtp_channel really launches a subprocess.
# It also checks that the 'stderr', 'env' and 'cwd' parameters work.
# This test relies on there being a 'python' executable on the PATH
# (doesn't have to be the same version as is running the testsuite).
fx = gtp_engine_fixtures.State_reporter_fixture(tc)
rd, wr = os.pipe()
try:
channel = gtp_controller.Subprocess_gtp_channel(
fx.cmd,
stderr=wr,
env={'GOMILL_TEST' : "from_gtp_controller_tests"},
cwd="/")
tc.assertEqual(os.read(rd, 256), "subprocess_state_reporter: testing\n")
finally:
os.close(wr)
os.close(rd)
tc.assertIsNone(channel.exit_status)
tc.assertIsNone(channel.resource_usage)
channel.send_command("tell", [])
tc.assertEqual(channel.get_response(),
(False, "cwd: /\nGOMILL_TEST:from_gtp_controller_tests"))
channel.close()
tc.assertEqual(channel.exit_status, 0)
rusage = channel.resource_usage
tc.assertTrue(hasattr(rusage, 'ru_utime'))
tc.assertTrue(hasattr(rusage, 'ru_stime'))
def test_subprocess_channel_nonexistent_program(tc):
with tc.assertRaises(GtpChannelError) as ar:
gtp_controller.Subprocess_gtp_channel(["/nonexistent/program"])
tc.assertIn("[Errno 2] No such file or directory", str(ar.exception))
def test_subprocess_channel_with_controller(tc):
# Also tests that leaving 'env' and 'cwd' unset works
fx = gtp_engine_fixtures.State_reporter_fixture(tc)
channel = gtp_controller.Subprocess_gtp_channel(fx.cmd, stderr=fx.devnull)
controller = Gtp_controller(channel, 'subprocess test')
tc.assertEqual(controller.do_command("tell"),
"cwd: %s\nGOMILL_TEST:None" % os.getcwd())
controller.close()
tc.assertEqual(channel.exit_status, 0)
rusage = channel.resource_usage
tc.assertTrue(hasattr(rusage, 'ru_utime'))