Skip to content

Commit

Permalink
More RCON tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Holiverh committed Dec 22, 2015
1 parent f4760b0 commit fed3679
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
10 changes: 9 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

import threading

try:
import mock
except ImportError:
import unittest.mock as mock
import pytest

import valve.source.a2s
Expand Down Expand Up @@ -92,7 +96,11 @@ def pytest_generate_tests(metafunc):


def pytest_namespace():
return {"srcds_functional": srcds_functional}
return {
"Mock": mock.Mock,
"MagicMock": mock.MagicMock,
"srcds_functional": srcds_functional,
}


@pytest.yield_fixture
Expand Down
87 changes: 87 additions & 0 deletions tests/test_rcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import (absolute_import,
unicode_literals, print_function, division)

import argparse
import textwrap

import pytest
Expand Down Expand Up @@ -434,3 +435,89 @@ def test_cvarlist_malformed(self, request, rcon_server):
rcon._authenticated = True
request.addfinalizer(rcon.close)
assert list(rcon.cvarlist()) == []


class TestExecute(object):

def test(self, rcon_server):
e1_request = rcon_server.expect(
0, valve.rcon.RCONMessage.Type.AUTH, b"password")
e1_request.respond(
0, valve.rcon.RCONMessage.Type.AUTH_RESPONSE, b"")
e2_request = rcon_server.expect(
0, valve.rcon.RCONMessage.Type.EXECCOMMAND, b"echo hello")
e2_request.respond(
0, valve.rcon.RCONMessage.Type.RESPONSE_VALUE, b"hello")
e2_request.respond_terminate_multi_part(0)
response = valve.rcon.execute(
rcon_server.server_address, "password", "echo hello")
assert response == "hello"
assert isinstance(response, six.text_type)


class TestConVar(object):

def test_repr(self):
assert repr(valve.rcon.ConVar(
"foo", "bar", frozenset(), "")) == "<ConVar 'foo' = 'bar'>"


class TestParseAddress(object):

def test(self):
assert valve.rcon._parse_address(
"localhost:9001") == ("localhost", 9001)

def test_port_default(self):
assert valve.rcon._parse_address("localhost") == ("localhost", 27015)

def test_port_not_a_number(self):
with pytest.raises(argparse.ArgumentTypeError):
valve.rcon._parse_address("localhost:asdf")

def test_port_too_small(self):
with pytest.raises(argparse.ArgumentTypeError):
valve.rcon._parse_address("localhost:0")

def test_port_too_big(self):
with pytest.raises(argparse.ArgumentTypeError):
valve.rcon._parse_address("localhost:65536")


class TestShell(object):

def test_address_and_password(self, monkeypatch):
monkeypatch.setattr(valve.rcon, "_RCONShell", pytest.Mock())
shell = valve.rcon._RCONShell.return_value
valve.rcon.shell(("localhost", "9001"), "password")
assert shell.onecmd.call_args[0] == (
"!connect localhost:9001 password",)
assert shell.cmdloop.called

def test_address_only(self, monkeypatch):
monkeypatch.setattr(valve.rcon, "_RCONShell", pytest.Mock())
shell = valve.rcon._RCONShell.return_value
valve.rcon.shell(("localhost", "9001"))
assert shell.onecmd.call_args[0] == ("!connect localhost:9001 ",)
assert shell.cmdloop.called

def test_no_address(self, monkeypatch):
monkeypatch.setattr(valve.rcon, "_RCONShell", pytest.Mock())
shell = valve.rcon._RCONShell.return_value
valve.rcon.shell()
assert not shell.onecmd.called
assert shell.cmdloop.called

def test_password_only(self, monkeypatch):
monkeypatch.setattr(valve.rcon, "_RCONShell", pytest.Mock())
shell = valve.rcon._RCONShell.return_value
valve.rcon.shell(password="password")
assert not shell.onecmd.called
assert shell.cmdloop.called

def test_ignore_interrupt(self, monkeypatch):
monkeypatch.setattr(valve.rcon, "_RCONShell", pytest.Mock())
shell = valve.rcon._RCONShell.return_value
shell.cmdloop.side_effect = KeyboardInterrupt
valve.rcon.shell()
assert shell.cmdloop.called
10 changes: 6 additions & 4 deletions valve/rcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -733,15 +733,17 @@ def shell(address=None, password=None):
"""A simple interactive RCON shell.
This will connect to the server identified by the given address using
the given password. If an address or password is not given then the shell
will prompt for it.
the given password. If a password is not given then the shell will
prompt for it. If no address is given, then no connection will be made
automatically and the user will have to do it manually using ``!connect``.
Once connected the shell simply dispatches commands and prints the
response to stdout.
:param address: a network address tuple containing the host and port
of the RCON server.
:param str password: the password for the server.
:param str password: the password for the server. This is ignored if
``address`` is not given.
"""
rcon_shell = _RCONShell()
try:
Expand Down Expand Up @@ -783,7 +785,7 @@ def _parse_address(address):
raise argparse.ArgumentTypeError(
"Could not parse address port "
"{!r} as a number".format(port_string))
if port < 0 or port > 65535:
if port <= 0 or port > 65535:
raise argparse.ArgumentTypeError(
"Port number must be in the range 1 to 65535")
return host, port
Expand Down

0 comments on commit fed3679

Please sign in to comment.