# -*- coding: utf-8 -*- import argparse import codecs import datetime import logging import os import lxml import mock from q3stats.lib.scripts import import_games, utils from q3stats.models import Game from q3stats.testing import BaseQ3StatsTestCase class FakeArgs(object): DEFAULTS = { 'stats_path': '/path/to/q3/stats', 'verbose': False, } def __init__(self, **update): args = dict(self.DEFAULTS) args.update(update) for k, v in args.items(): setattr(self, k, v) class Test_LibScriptsImportGames(BaseQ3StatsTestCase): @classmethod def setUpClass(cls): super(Test_LibScriptsImportGames, cls).setUpClass() cls._stats_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'fixtures', 'stats' ) cls._game_xml_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'fixtures', 'game.xml' ) def test_find_stats_files(self): result = import_games._find_stats_files(self._stats_path) assert len(result) == 4 unique_days = set() for path in result: assert path.startswith(self._stats_path) assert path.endswith('.xml') unique_days.add( os.path.dirname(path).replace(self._stats_path + '/', '') ) assert unique_days == set(['2017/02/20', '2017/02/21']) def test_read_match(self): result = import_games._read_match(self._game_xml_path) assert result is not None assert result.tag == 'match' def test_read_game(self): match = import_games._read_match(self._game_xml_path) result = import_games._read_game(match) assert result is not None assert result.uuid is not None assert result.map == 'Q3DM7' assert result.date == datetime.date(2017, 2, 20) assert result.time == datetime.time(14, 36, 26) assert result.attrs['type'] == 'FFA' assert result.attrs['team_game'] is False assert result.attrs['duration'] == 583 def test_read_scores(self): match = import_games._read_match(self._game_xml_path) result = import_games._read_scores(match) assert len(result) == 2 pl1_score, pl2_score = result[0] assert pl1_score.player == 'Player 1' assert pl1_score.score == 30 assert pl1_score.kills == 30 assert pl1_score.deaths == 21 assert pl1_score.suicides == 0 assert pl1_score.net == 9 assert pl1_score.damage_given == 4894 assert pl1_score.damage_taken == 4329 assert pl1_score.total_health == 925 assert pl1_score.total_armor == 1255 assert pl1_score.weapons['G']['hits'] == 1 assert pl1_score.weapons['G']['shots'] == 0 assert pl1_score.weapons['G']['kills'] == 1 assert pl1_score.weapons['MG']['hits'] == 82 assert pl1_score.weapons['MG']['shots'] == 325 assert pl1_score.weapons['MG']['kills'] == 1 assert pl1_score.weapons['SG']['hits'] == 29 assert pl1_score.weapons['SG']['shots'] == 192 assert pl1_score.weapons['SG']['kills'] == 2 assert pl1_score.weapons['RL']['hits'] == 51 assert pl1_score.weapons['RL']['shots'] == 140 assert pl1_score.weapons['RL']['kills'] == 21 assert pl1_score.weapons['RG']['hits'] == 9 assert pl1_score.weapons['RG']['shots'] == 34 assert pl1_score.weapons['RG']['kills'] == 4 assert pl1_score.weapons['PG']['hits'] == 14 assert pl1_score.weapons['PG']['shots'] == 117 assert pl1_score.weapons['PG']['kills'] == 1 assert pl1_score.items['MH'] == 3 assert pl1_score.items['RA'] == 5 assert pl1_score.items['YA'] == 5 assert pl1_score.items['GA'] == 0 assert pl1_score.powerups == {} assert pl2_score.player == 'Player 2' assert pl2_score.score == 27 assert pl2_score.kills == 28 assert pl2_score.deaths == 19 assert pl2_score.suicides == 1 assert pl2_score.net == 8 assert pl2_score.damage_given == 5822 assert pl2_score.damage_taken == 3792 assert pl2_score.total_health == 810 assert pl2_score.total_armor == 930 assert pl2_score.weapons['G']['hits'] == 1 assert pl2_score.weapons['G']['shots'] == 0 assert pl2_score.weapons['G']['kills'] == 1 assert pl2_score.weapons['MG']['hits'] == 56 assert pl2_score.weapons['MG']['shots'] == 244 assert pl2_score.weapons['MG']['kills'] == 1 assert pl2_score.weapons['SG']['hits'] == 55 assert pl2_score.weapons['SG']['shots'] == 256 assert pl2_score.weapons['SG']['kills'] == 3 assert pl2_score.weapons['RL']['hits'] == 70 assert pl2_score.weapons['RL']['shots'] == 163 assert pl2_score.weapons['RL']['kills'] == 19 assert pl2_score.weapons['RG']['hits'] == 6 assert pl2_score.weapons['RG']['shots'] == 19 assert pl2_score.weapons['RG']['kills'] == 1 assert pl2_score.weapons['PG']['hits'] == 18 assert pl2_score.weapons['PG']['shots'] == 173 assert pl2_score.weapons['PG']['kills'] == 3 assert pl2_score.items['MH'] == 1 assert pl2_score.items['RA'] == 1 assert pl2_score.items['YA'] == 7 assert pl2_score.items['GA'] == 0 assert pl2_score.powerups['Quad'] == [5, 51188] def test_read_stats_file(self): result = import_games._read_stats_file(self._game_xml_path) assert result is not None assert result.map == 'Q3DM7' assert len(result.scores) == 2 def test_get_argument_parser(self): new_argument_parser = mock.Mock(spec=argparse.ArgumentParser) with mock.patch.object(import_games, 'ArgumentParser', return_value=new_argument_parser): result = import_games._get_argument_parser() import_games.ArgumentParser.assert_called_with( description='Import Q3A stats' ) assert result == new_argument_parser result.add_argument.assert_any_call( 'stats_path', help='path to stats directory' ) result.add_argument.assert_any_call( '-v', '--verbose', action='store_true', default=False, help='be verbose' ) def test_script_main(self): new_argument_parser = mock.Mock(spec=argparse.ArgumentParser) new_logger = mock.Mock(spec=logging.Logger) with mock.patch.object(import_games, '_get_argument_parser', return_value=new_argument_parser): with mock.patch.object(import_games.utils, 'get_logger', return_value=new_logger): with mock.patch.object(import_games, '_find_stats_files', return_value=[self._game_xml_path]): result = import_games.script_main( None, config=self._config ) assert result == utils.RET_OK with utils.db_session(self._config) as session: games = session.query(Game).all() assert len(games) == 1 assert games[0].map == 'Q3DM7' assert len(games[0].scores) == 2