1
0
mirror of https://github.com/gryf/fs-uae-wrapper.git synced 2025-12-19 20:38:06 +01:00

Adjust existing cd32 module for base class

Fix failing tests for small changes in utils and cd32/base modules
This commit is contained in:
2017-01-01 17:31:40 +01:00
parent 47787a3ab2
commit fa7afcb73b
4 changed files with 61 additions and 176 deletions

View File

@@ -8,28 +8,18 @@ used as a base for save state (it will append '_save.7z' to the archive file
name. name.
""" """
import os
import shutil
import sys import sys
import tempfile
from fs_uae_wrapper import utils from fs_uae_wrapper import base
class CD32(object): class CD32(base.Base):
""" """
Class for performing extracting archive, copying emulator files, and Class for performing extracting archive, copying emulator files, and
cleaning it back again cleaning it back again
""" """
def __init__(self):
self.dir = None
self.conf_file = None
self.save_filename = None
self.arch_filepath = None
self.all_options = None
self.fsuae_config = None
def run(self, conf_file, fs_uae_options, configuration): def run(self):
""" """
Main function which accepts configuration file for FS-UAE Main function which accepts configuration file for FS-UAE
It will do as follows: It will do as follows:
@@ -39,26 +29,12 @@ class CD32(object):
- [copy save if exists] - [copy save if exists]
- run the emulation - run the emulation
- archive save state - archive save state
Params:
conf_file: a relative path to provided configuration file
fs_uae_options: is an CmdOption object created out of command line
parameters
configuration: is config dictionary created out of config file
""" """
self.all_options = utils.merge_all_options(configuration, super(CD32, self).run()
fs_uae_options) if not self._validate_options():
if 'wrapper_archive' not in self.all_options:
sys.stderr.write("Configuration lacks of required "
"`wrapper_archive' option.\n")
return False return False
self.fsuae_config = configuration self._set_assets_paths()
self.conf_file = conf_file
self.dir = tempfile.mkdtemp()
self.set_assets_paths()
if not self._extract(): if not self._extract():
return False return False
@@ -66,131 +42,36 @@ class CD32(object):
if not method(): if not method():
return False return False
kick_opts = self.kickstart_option() kick_opts = self._kickstart_option()
if kick_opts: if kick_opts:
fs_uae_options.update(kick_opts) self.fsuae_options.update(kick_opts)
if self._run_game(fs_uae_options.list()): if self._run_emulator(self.fsuae_options.list()):
return self._save_save() return self._save_save()
return True return True
def clean(self): def _validate_options(self):
"""Remove temporary file""" validation_result = super(CD32, self)._validate_options()
if self.dir:
shutil.rmtree(self.dir)
return
def kickstart_option(self): validation_result = True
"""
This is kind of hack - since we potentially can have a relative path
to kickstart directory, there is a need for getting this option from
configuration files (which unfortunately can be spanned all over the
different places, see https://fs-uae.net/configuration-files) and
check whether or not one of 'kickstarts_dir', 'kickstart_file' or
'kickstart_ext_file' options are set. In either case if one of those
options are set and are relative, they should be set to absolute path,
so that kickstart files can be found by relocated configuration file.
"""
conf = utils.get_config(self.conf_file) if not super(CD32, self)._validate_options():
validation_result = False
kick = {} if 'wrapper_archive' not in self.all_options:
sys.stderr.write("Configuration lacks of required "
"`wrapper_archive' option.\n")
validation_result = False
for key in ('kickstart_file', 'kickstart_ext_file', 'kickstarts_dir'): return validation_result
val = conf.get(key)
if val:
if not os.path.isabs(val):
val = utils.interpolate_variables(val, self.conf_file)
kick[key] = os.path.abspath(val)
else:
kick[key] = val
return kick
def set_assets_paths(self):
"""
Set full paths for archive file (without extension) and for save state
archive file
"""
conf_abs_dir = os.path.dirname(os.path.abspath(self.conf_file))
conf_base = os.path.basename(self.conf_file)
conf_base = os.path.splitext(conf_base)[0]
arch = self.all_options['wrapper_archive']
if os.path.isabs(arch):
self.arch_filepath = arch
else:
self.arch_filepath = os.path.join(conf_abs_dir, arch)
self.save_filename = os.path.join(conf_abs_dir, conf_base + '_save.7z')
def _copy_conf(self):
"""copy provided configuration as Config.fs-uae"""
shutil.copy(self.conf_file, self.dir)
os.rename(os.path.join(self.dir, os.path.basename(self.conf_file)),
os.path.join(self.dir, 'Config.fs-uae'))
return True
def _extract(self):
"""Extract archive to temp dir"""
item = self.all_options.get('title')
if not item:
item = self.all_options['wrapper_archive']
curdir = os.path.abspath('.')
os.chdir(self.dir)
result = utils.extract_archive(self.arch_filepath,
self.all_options.get('wrapper_gui_msg'),
item)
os.chdir(curdir)
return result
def _run_game(self, fs_uae_options):
"""execute game in provided directory"""
curdir = os.path.abspath('.')
os.chdir(self.dir)
utils.run_command(['fs-uae'] + fs_uae_options)
os.chdir(curdir)
return True
def _save_save(self):
"""
Get the saves from emulator and store it where configuration is placed
"""
save_path = os.path.join(self.dir, 'fs-uae-save')
if not os.path.exists(save_path):
return True
if os.path.exists(self.save_filename):
os.unlink(self.save_filename)
if not utils.run_command(['7z', 'a', self.save_filename,
os.path.join(self.dir, 'fs-uae-save')]):
sys.stderr.write('Error: archiving save state failed\n')
return False
return True
def _load_save(self):
"""
Put the saves (if exists) to the temp directory.
"""
if not os.path.exists(self.save_filename):
return True
curdir = os.path.abspath('.')
os.chdir(self.dir)
utils.run_command(['7z', 'x', self.save_filename])
os.chdir(curdir)
return True
def run(config_file, fs_uae_options, configuration): def run(config_file, fsuae_options, configuration):
"""Run fs-uae with provided config file and options""" """Run fs-uae with provided config file and options"""
runner = CD32() runner = CD32(config_file, fsuae_options, configuration)
try: try:
return runner.run(config_file, fs_uae_options, configuration) return runner.run()
finally: finally:
runner.clean() runner.clean()

View File

@@ -68,7 +68,7 @@ def get_config_options(conf):
for key, val in parser.items(section)} for key, val in parser.items(section)}
def extract_archive(arch_name, show_gui_message, message_text): def extract_archive(arch_name, title=''):
""" """
Extract provided archive to current directory Extract provided archive to current directory
""" """
@@ -86,8 +86,8 @@ def extract_archive(arch_name, show_gui_message, message_text):
return False return False
msg = message.Message("Extracting files for `%s'. Please be " msg = message.Message("Extracting files for `%s'. Please be "
"patient" % message_text) "patient" % title)
if show_gui_message == '1': if title:
msg.show() msg.show()
try: try:

View File

@@ -10,6 +10,7 @@ except ImportError:
import mock import mock
from fs_uae_wrapper import cd32 from fs_uae_wrapper import cd32
from fs_uae_wrapper import utils
class TestCD32(TestCase): class TestCD32(TestCase):
@@ -38,7 +39,7 @@ class TestCD32(TestCase):
def test_clean(self): def test_clean(self):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.clean() acd32.clean()
self.assertTrue(os.path.exists(self.dirname)) self.assertTrue(os.path.exists(self.dirname))
@@ -49,46 +50,46 @@ class TestCD32(TestCase):
@mock.patch('fs_uae_wrapper.utils.get_config') @mock.patch('fs_uae_wrapper.utils.get_config')
def test_kickstart_option(self, get_config): def test_kickstart_option(self, get_config):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
get_config.return_value = {'foo': 'bar'} get_config.return_value = {'foo': 'bar'}
self.assertDictEqual(acd32.kickstart_option(), {}) self.assertDictEqual(acd32._kickstart_option(), {})
get_config.return_value = {'kickstarts_dir': '/some/path'} get_config.return_value = {'kickstarts_dir': '/some/path'}
self.assertDictEqual(acd32.kickstart_option(), self.assertDictEqual(acd32._kickstart_option(),
{'kickstarts_dir': '/some/path'}) {'kickstarts_dir': '/some/path'})
os.chdir(self.dirname) os.chdir(self.dirname)
get_config.return_value = {'kickstarts_dir': '../some/path'} get_config.return_value = {'kickstarts_dir': '../some/path'}
result = os.path.abspath(os.path.join(self.dirname, '../some/path')) result = os.path.abspath(os.path.join(self.dirname, '../some/path'))
self.assertDictEqual(acd32.kickstart_option(), self.assertDictEqual(acd32._kickstart_option(),
{'kickstarts_dir': result}) {'kickstarts_dir': result})
acd32.conf_file = os.path.join(self.dirname, 'Config.fs-uae') acd32.conf_file = os.path.join(self.dirname, 'Config.fs-uae')
get_config.return_value = {'kickstarts_dir': '$CONFIG/../path'} get_config.return_value = {'kickstarts_dir': '$CONFIG/../path'}
result = os.path.abspath(os.path.join(self.dirname, '../path')) result = os.path.abspath(os.path.join(self.dirname, '../path'))
self.assertDictEqual(acd32.kickstart_option(), self.assertDictEqual(acd32._kickstart_option(),
{'kickstarts_dir': result}) {'kickstarts_dir': result})
def test_set_assets_paths(self): def test_set_assets_paths(self):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
os.chdir(self.dirname) os.chdir(self.dirname)
acd32.conf_file = 'Config.fs-uae' acd32.conf_file = 'Config.fs-uae'
acd32.all_options = {'wrapper_archive': 'foo.7z'} acd32.all_options = {'wrapper_archive': 'foo.7z'}
acd32.set_assets_paths() acd32._set_assets_paths()
full_path = os.path.join(self.dirname, 'Config_save.7z') full_path = os.path.join(self.dirname, 'Config_save.7z')
self.assertEqual(acd32.save_filename, full_path) self.assertEqual(acd32.save_filename, full_path)
acd32.all_options = {'wrapper_archive': '/home/user/foo.7z'} acd32.all_options = {'wrapper_archive': '/home/user/foo.7z'}
acd32.set_assets_paths() acd32._set_assets_paths()
full_path = os.path.join(self.dirname, 'Config_save.7z') full_path = os.path.join(self.dirname, 'Config_save.7z')
self.assertEqual(acd32.save_filename, full_path) self.assertEqual(acd32.save_filename, full_path)
def test_copy_conf(self): def test_copy_conf(self):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.conf_file = self.fname acd32.conf_file = self.fname
acd32.dir = self.dirname acd32.dir = self.dirname
@@ -99,7 +100,7 @@ class TestCD32(TestCase):
@mock.patch('fs_uae_wrapper.utils.extract_archive') @mock.patch('fs_uae_wrapper.utils.extract_archive')
def test_extract(self, utils_extract): def test_extract(self, utils_extract):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.arch_filepath = self.fname acd32.arch_filepath = self.fname
acd32.dir = self.dirname acd32.dir = self.dirname
@@ -107,47 +108,52 @@ class TestCD32(TestCase):
# message for the gui is taken from title in fs-uae conf or, if there # message for the gui is taken from title in fs-uae conf or, if there
# is no such entry, use archive name, which is mandatory to provide # is no such entry, use archive name, which is mandatory to provide
acd32.all_options = {'title': 'foo_game'} acd32.all_options = {'title': 'foo_game',
'wrapper_gui_msg': '1'}
self.assertFalse(acd32._extract()) self.assertFalse(acd32._extract())
utils_extract.assert_called_once_with(self.fname, None, 'foo_game') utils_extract.assert_called_once_with(self.fname, 'foo_game')
utils_extract.reset_mock() utils_extract.reset_mock()
acd32.all_options = {'wrapper_archive': 'arch.7z'} acd32.all_options = {'wrapper_archive': 'arch.tar',
'wrapper_gui_msg': '1'}
self.assertFalse(acd32._extract()) self.assertFalse(acd32._extract())
utils_extract.assert_called_once_with(self.fname, None, 'arch.7z') utils_extract.assert_called_once_with(self.fname, 'arch.tar')
# lets pretend, the extracting has succeed. # lets pretend, the extracting has failed
utils_extract.reset_mock() utils_extract.reset_mock()
acd32.all_options['wrapper_gui_msg'] = '1' acd32.all_options = {'wrapper_gui_msg': '0'}
utils_extract.return_value = False utils_extract.return_value = False
self.assertFalse(acd32._extract()) self.assertFalse(acd32._extract())
utils_extract.assert_called_once_with(self.fname, '1', 'arch.7z') utils_extract.assert_called_once_with(self.fname, '')
@mock.patch('fs_uae_wrapper.utils.run_command') @mock.patch('fs_uae_wrapper.utils.run_command')
def test_run_game(self, run): def test_run_emulator(self, run):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.dir = self.dirname acd32.dir = self.dirname
self.assertTrue(acd32._run_game([])) self.assertTrue(acd32._run_emulator([]))
run.assert_called_once_with(['fs-uae']) run.assert_called_once_with(['fs-uae'])
# Errors from emulator are not fatal to wrappers # Errors from emulator are not fatal to wrappers
run.reset_mock() run.reset_mock()
run.return_value = False run.return_value = False
self.assertTrue(acd32._run_game([])) self.assertTrue(acd32._run_emulator([]))
run.assert_called_once_with(['fs-uae']) run.assert_called_once_with(['fs-uae'])
@mock.patch('fs_uae_wrapper.base.Base._get_saves_dir')
@mock.patch('fs_uae_wrapper.utils.run_command') @mock.patch('fs_uae_wrapper.utils.run_command')
def test_save_save(self, run): def test_save_save(self, run, saves_dir):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.dir = self.dirname acd32.dir = self.dirname
acd32.save_filename = "foobar_save.7z" acd32.save_filename = 'foobar_save.7z'
saves_dir.acd32.save_filenamereturn_value = None
run.return_value = True run.return_value = True
self.assertTrue(acd32._save_save()) self.assertTrue(acd32._save_save())
saves_dir.return_value = acd32.save_filename
os.chdir(self.confdir) os.chdir(self.confdir)
with open(acd32.save_filename, 'w') as fobj: with open(acd32.save_filename, 'w') as fobj:
fobj.write('asd') fobj.write('asd')
@@ -163,7 +169,7 @@ class TestCD32(TestCase):
@mock.patch('fs_uae_wrapper.utils.run_command') @mock.patch('fs_uae_wrapper.utils.run_command')
def test_load_save(self, run): def test_load_save(self, run):
acd32 = cd32.CD32() acd32 = cd32.CD32('Config.fs-uae', utils.CmdOption(), {})
acd32.dir = self.dirname acd32.dir = self.dirname
acd32.save_filename = "foobar_save.7z" acd32.save_filename = "foobar_save.7z"
run.return_value = 0 run.return_value = 0

View File

@@ -77,21 +77,19 @@ class TestUtils(TestCase):
os.chdir(self.dirname) os.chdir(self.dirname)
# No config # No config
self.assertFalse(utils.extract_archive('non-existend.7z', False, '')) self.assertFalse(utils.extract_archive('non-existend.7z'))
# Archive type not known # Archive type not known
with open('unsupported-archive.ace', 'w') as fobj: with open('unsupported-archive.ace', 'w') as fobj:
fobj.write("\n") fobj.write("\n")
self.assertFalse(utils.extract_archive('unsupported-archive.ace', self.assertFalse(utils.extract_archive('unsupported-archive.ace'))
False, ''))
# archive is known, but extraction will fail - we have an empty # archive is known, but extraction will fail - we have an empty
# archive and there is no guarantee, that 7z exists on system where # archive and there is no guarantee, that 7z exists on system where
# test will run # test will run
with open('supported-archive.7z', 'w') as fobj: with open('supported-archive.7z', 'w') as fobj:
fobj.write("\n") fobj.write("\n")
self.assertFalse(utils.extract_archive('supported-archive.7z', self.assertFalse(utils.extract_archive('supported-archive.7z'))
False, ''))
@mock.patch('subprocess.check_call') @mock.patch('subprocess.check_call')
def test_extract_archive_positive(self, sp_check_call): def test_extract_archive_positive(self, sp_check_call):
@@ -101,7 +99,7 @@ class TestUtils(TestCase):
arch_name = 'archive.7z' arch_name = 'archive.7z'
with open(arch_name, 'w') as fobj: with open(arch_name, 'w') as fobj:
fobj.write("\n") fobj.write("\n")
self.assertTrue(utils.extract_archive(arch_name, False, '')) self.assertTrue(utils.extract_archive(arch_name))
sp_check_call.assert_called_once_with(utils.ARCHIVERS['.7z'] + sp_check_call.assert_called_once_with(utils.ARCHIVERS['.7z'] +
[arch_name]) [arch_name])