Got VASSAL running inside the Docker container.

master
Pacman Ghost 4 years ago
parent ab1d3251d9
commit b22c714ec5
  1. 1
      .dockerignore
  2. 6
      Dockerfile
  3. 1
      docker/config/debug.cfg
  4. 20
      docker/config/logging.yaml
  5. 1
      docker/config/site.cfg
  6. 3
      docker/run.sh
  7. 90
      run-container.sh
  8. 3
      vasl_templates/webapp/snippets.py
  9. 10
      vasl_templates/webapp/tests/remote.py
  10. 102
      vasl_templates/webapp/tests/test_vassal.py
  11. 15
      vasl_templates/webapp/vassal.py

@ -3,5 +3,6 @@
! setup.py
! requirements*.txt
! vasl_templates/
! vassal-shim/release/
! docker/
! LICENSE.txt

@ -5,9 +5,10 @@
FROM centos:8 AS base
# update packages and install Python
# update packages and install Python and Java
RUN dnf -y upgrade-minimal && \
dnf install -y python36 && \
curl -s "https://download.java.net/java/GA/jdk15.0.1/51f4f36ad4ef43e39d0dfdbaf6549e32/9/GPL/openjdk-15.0.1_linux-x64_bin.tar.gz" | tar -C /usr/bin/ -xz && \
dnf clean all
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -40,12 +41,13 @@ RUN wget -qO- "https://download.mozilla.org/?product=firefox-latest-ssl&os=linux
echo "exclude=firefox" >> /etc/dnf/dnf.conf
# install geckodriver
RUN url=$( curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep -Eoh 'https.*linux64\.tar\.gz' ) && \
RUN url=$( curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep -Poh 'https.*linux64\.tar\.gz(?!\.)' ) && \
curl -sL "$url" | tar -C /usr/bin/ -xz
# install the application
WORKDIR /app
COPY vasl_templates vasl_templates
COPY vassal-shim/release/vassal-shim.jar vassal-shim/release/
COPY setup.py requirements.txt requirements-dev.txt LICENSE.txt ./
RUN pip install -e .

@ -1,4 +1,5 @@
[Debug]
TEST_VASSAL_ENGINES = /test-data/vassal/
TEST_VASL_MODS = /test-data/vasl-vmods/
TEST_VASL_EXTNS_DIR = /test-data/vasl-extensions/

@ -19,13 +19,25 @@ handlers:
loggers:
werkzeug:
level: "WARNING"
handlers: [ "console" ]
handlers: [ "file" ]
vasl_mod:
level: "WARNING"
handlers: [ "console", "file" ]
handlers: [ "file" ]
update_vsav:
level: "WARNING"
handlers: [ "console", "file" ]
handlers: [ "file" ]
analyze_vsav:
level: "WARNING"
handlers: [ "file" ]
analyze_vlog:
level: "WARNING"
handlers: [ "file" ]
webdriver:
level: "WARNING"
handlers: [ "file" ]
downloads:
level: "WARNING"
handlers: [ "file" ]
control_tests:
level: "DEBUG"
level: "INFO"
handlers: [ "console", "file" ]

@ -3,4 +3,5 @@
FLASK_HOST = 0.0.0.0
IS_CONTAINER = 1
JAVA_PATH = /usr/bin/jdk-15.0.1/bin/java
WEBDRIVER_PATH = /usr/bin/geckodriver

@ -1,7 +1,8 @@
#!/bin/sh
# set up the display (so we can run a webdriver)
# set up the display (so we can run VASSAL and a webdriver)
export ENV=10
export DISPLAY=:10.0
Xvfb :10 -ac 1>/tmp/xvfb.log 2>/tmp/xvfb.err &
# run the webapp server

@ -5,21 +5,24 @@
function print_help {
echo "`basename "$0"` {options}"
echo " Build and launch the \"vasl-templates\" container."
echo
echo " -p --port Web server port number."
echo " -v --vasl-vmod Path to the VASL .vmod file."
echo " -e --vasl-extensions Path to the VASL extensions directory."
echo " -h --chapter-h Path to the Chapter H notes directory."
echo " -u --user-files Path to the user files directory."
echo
echo " -t --tag Docker tag."
echo " -d --detach Detach from the container and let it run in the background."
echo " --no-build Launch the container as-is (i.e. without rebuilding it first)."
echo " --build-network Docker network to use when building the container."
echo " --run-network Docker network to use when running the container."
echo
cat <<EOM
Build and launch the "vasl-templates" container.
-p --port Web server port number.
--vassal VASSAL installation directory.
-v --vasl-vmod Path to the VASL .vmod file.
-e --vasl-extensions Path to the VASL extensions directory.
--boards Path to the VASL boards.
--chapter-h Path to the Chapter H notes directory.
--user-files Path to the user files directory.
-k --template-pack Path to a user-defined template pack.
-t --tag Docker tag.
-d --detach Detach from the container and let it run in the background.
--no-build Launch the container as-is (i.e. without rebuilding it first).
--build-network Docker network to use when building the container.
--run-network Docker network to use when running the container.
NOTE: If the port the webapp server is listening on *inside* the container is different
to the port exposed *outside* the container, webdriver image generation (e.g. Shift-Click
on a snippet button, or Chapter H content as images) may not work properly. This is because
@ -36,12 +39,18 @@ EOM
# initialize
cd `dirname "$0"`
PORT=5010
VASSAL_LOCAL=
VASSAL=
VASL_MOD_LOCAL=
VASL_MOD=
VASL_BOARDS_LOCAL=
VASL_BOARDS=
VASL_EXTNS_LOCAL=
VASL_EXTNS=
CHAPTER_H_NOTES_LOCAL=
CHAPTER_H_NOTES=
TEMPLATE_PACK_LOCAL=
TEMPLATE_PACK=
USER_FILES_LOCAL=
USER_FILES=
TAG=latest
@ -55,7 +64,7 @@ if [ $# -eq 0 ]; then
print_help
exit 0
fi
params="$(getopt -o p:v:e:h:u:t:d -l port:,vasl-vmod:,vasl-extensions:,chapter-h:,user-files:,tag:,detach,no-build,build-network:,run-network:,help --name "$0" -- "$@")"
params="$(getopt -o p:v:e:k:t:d -l port:,vassal:,vasl-vmod:,vasl-extensions:,boards:,chapter-h:,user-files:,template-pack:,tag:,detach,no-build,build-network:,run-network:,help --name "$0" -- "$@")"
if [ $? -ne 0 ]; then exit 1; fi
eval set -- "$params"
while true; do
@ -63,18 +72,27 @@ while true; do
-p | --port)
PORT=$2
shift 2 ;;
--vassal)
VASSAL_LOCAL=$2
shift 2 ;;
-v | --vasl-vmod)
VASL_MOD_LOCAL=$2
shift 2 ;;
-e | --vasl-extensions)
VASL_EXTNS_LOCAL=$2
shift 2 ;;
-h | --chapter-h)
--boards)
VASL_BOARDS_LOCAL=$2
shift 2 ;;
--chapter-h)
CHAPTER_H_NOTES_LOCAL=$2
shift 2 ;;
-u | --user-files)
--user-files)
USER_FILES_LOCAL=$2
shift 2 ;;
-k | --template-pack)
TEMPLATE_PACK_LOCAL=$2
shift 2 ;;
-t | --tag)
TAG=$2
shift 2 ;;
@ -102,6 +120,17 @@ while true; do
esac
done
# check if a VASSAL directory has been specified
if [ -n "$VASSAL_LOCAL" ]; then
if [ ! -d "$VASSAL_LOCAL" ]; then
echo "Can't find the VASSAL directory: $VASSAL_LOCAL"
exit 1
fi
VASSAL=/data/vassal/
VASSAL_VOLUME="--volume `readlink -f "$VASSAL_LOCAL"`:$VASSAL"
VASSAL_ENV="--env VASSAL_DIR=$VASSAL"
fi
# check if a VASL .vmod file has been specified
if [ -n "$VASL_MOD_LOCAL" ]; then
if [ ! -f "$VASL_MOD_LOCAL" ]; then
@ -113,6 +142,17 @@ if [ -n "$VASL_MOD_LOCAL" ]; then
VASL_MOD_ENV="--env VASL_MOD=$VASL_MOD"
fi
# check if a VASL boards directory has been specified
if [ -n "$VASL_BOARDS_LOCAL" ]; then
if [ ! -d "$VASL_BOARDS_LOCAL" ]; then
echo "Can't find the VASL boards directory: $VASL_BOARDS_LOCAL"
exit 1
fi
VASL_BOARDS=/data/boards/
VASL_BOARDS_VOLUME="--volume `readlink -f "$VASL_BOARDS_LOCAL"`:$VASL_BOARDS"
VASL_BOARDS_ENV="--env VASL_BOARDS_DIR=$VASL_BOARDS"
fi
# check if a VASL extensions directory has been specified
if [ -n "$VASL_EXTNS_LOCAL" ]; then
if [ ! -d "$VASL_EXTNS_LOCAL" ]; then
@ -135,6 +175,18 @@ if [ -n "$CHAPTER_H_NOTES_LOCAL" ]; then
CHAPTER_H_NOTES_ENV="--env CHAPTER_H_NOTES_DIR=$CHAPTER_H_NOTES"
fi
# check if a template pack has been specified
if [ -n "$TEMPLATE_PACK_LOCAL" ]; then
# NOTE: The template pack can either be a file (ZIP) or a directory.
if ! ls "$TEMPLATE_PACK_LOCAL" >/dev/null 2>&1 ; then
echo "Can't find the template pack: $TEMPLATE_PACK_LOCAL"
exit 1
fi
TEMPLATE_PACK=/data/template-pack
TEMPLATE_PACK_VOLUME="--volume `readlink -f "$TEMPLATE_PACK_LOCAL"`:$TEMPLATE_PACK"
TEMPLATE_PACK_ENV="--env DEFAULT_TEMPLATE_PACK=$TEMPLATE_PACK"
fi
# check if a user files directory has been specified
if [ -n "$USER_FILES_LOCAL" ]; then
if [ ! -d "$USER_FILES_LOCAL" ]; then
@ -160,8 +212,8 @@ echo Launching the \"$TAG\" container...
docker run \
--publish $PORT:5010 \
--name vasl-templates \
$VASL_MOD_VOLUME $VASL_EXTNS_VOLUME $CHAPTER_H_NOTES_VOLUME $USER_FILES_VOLUME \
$VASL_MOD_ENV $VASL_EXTNS_ENV $CHAPTER_H_NOTES_ENV $USER_FILES_ENV \
$VASSAL_VOLUME $VASL_MOD_VOLUME $VASL_BOARDS_VOLUME $VASL_EXTNS_VOLUME $CHAPTER_H_NOTES_VOLUME $USER_FILES_VOLUME $TEMPLATE_PACK_VOLUME \
$VASSAL_ENV $VASL_MOD_ENV $VASL_BOARDS_ENV $VASL_EXTNS_ENV $CHAPTER_H_NOTES_ENV $USER_FILES_ENV $TEMPLATE_PACK_ENV \
$RUN_NETWORK $DETACH \
-it --rm \
vasl-templates:$TAG \

@ -58,6 +58,9 @@ def load_default_template_pack(): #pylint: disable=too-many-locals
data["templates"]["extras/"+key] = val
# check if a default template pack has been configured
# NOTE: The Docker container configures this setting via an environment variable.
global default_template_pack
default_template_pack = os.environ.get( "DEFAULT_TEMPLATE_PACK", default_template_pack )
if default_template_pack:
dname = default_template_pack
data["_path_"] = dname

@ -19,7 +19,9 @@ import pytest
from vasl_templates.webapp import app, globvars
from vasl_templates.webapp.config.constants import DATA_DIR
from vasl_templates.webapp.vassal import VassalShim
from vasl_templates.webapp.vasl_mod import set_vasl_mod
from vasl_templates.webapp.utils import TempFile
from vasl_templates.webapp import main as webapp_main
from vasl_templates.webapp import snippets as webapp_snippets
from vasl_templates.webapp import scenarios as webapp_scenarios
@ -260,6 +262,14 @@ class ControlTests:
app.config["VASSAL_DIR"] = vengine
return self
def _get_vsav_dump( self, bin_data=None ): #pylint: disable=no-self-use
"""Dump a VSAV file."""
with TempFile( mode="wb" ) as temp_file:
temp_file.write( bin_data )
temp_file.close( delete=False )
vassal_shim = VassalShim()
return vassal_shim.dump_scenario( temp_file.name )
def _set_vo_notes_dir( self, dtype=None ):
"""Set the vehicle/ordnance notes directory."""
if dtype == "real":

@ -9,10 +9,8 @@ import typing.re #pylint: disable=import-error
import pytest
from vasl_templates.webapp.vassal import VassalShim
from vasl_templates.webapp.vasl_mod import compare_version_strings
from vasl_templates.webapp.utils import TempFile, change_extn
from vasl_templates.webapp import globvars
from vasl_templates.webapp.tests.utils import \
init_webapp, refresh_webapp, select_menu_option, get_stored_msg, set_stored_msg, set_stored_msg_marker, wait_for, \
new_scenario, set_player
@ -21,13 +19,6 @@ from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario,
# ---------------------------------------------------------------------
class DummyVaslMod:
"""Dummy VaslMod class that lets us run the VASSAL shim locally (to dump scenarios)."""
def __init__( self, fname ):
self.filename = fname
# ---------------------------------------------------------------------
@pytest.mark.skipif( not pytest.config.option.vasl_mods, reason="--vasl-mods not specified" ) #pylint: disable=no-member
@pytest.mark.skipif( not pytest.config.option.vassal, reason="--vassal not specified" ) #pylint: disable=no-member
@pytest.mark.skipif( pytest.config.option.short_tests, reason="--short-tests specified" ) #pylint: disable=no-member
@ -114,7 +105,7 @@ def test_full_update( webapp, webdriver ):
# NOTE: We could arguably only do this once, but updating scenarios is the key functionality of the VASSAL shim,
# and so it's worth checking that every VASSAL+VASL combination understands its input correctly.
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/full.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
_check_vsav_dump( vsav_dump, {
"scenario": "Somewhere",
"players": re.compile( r"American:.*Belgian:" ),
@ -150,7 +141,7 @@ def test_full_update( webapp, webdriver ):
# check the results
temp_file.write( updated_vsav_data )
temp_file.close( delete=False )
updated_vsav_dump = _dump_vsav( temp_file.name )
updated_vsav_dump = _dump_vsav( control_tests, temp_file.name )
expected = {
"scenario": "Modified scenario name (<>{}\"'\\)",
"players": re.compile( r"American:.*Belgian:" ),
@ -234,12 +225,14 @@ def test_latw_autocreate( webapp, webdriver ):
# check the VASL scenario
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/empty.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
_check_vsav_dump( vsav_dump, {}, ignore_labels )
# update the scenario (German/Russian, no date)
load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "" } } )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3 }
)
_check_vsav_dump( updated_vsav_dump, {
# nb: no LATW labels should have been created
}, ignore_labels )
@ -248,7 +241,9 @@ def test_latw_autocreate( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "10/01/1943" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 4 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 4 }
)
_check_vsav_dump( updated_vsav_dump, {
"german/pf": "Panzerfaust",
}, ignore_labels )
@ -257,14 +252,18 @@ def test_latw_autocreate( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "01/01/1944" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 5 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 5 }
)
_check_vsav_dump( updated_vsav_dump, {
"german/pf": "Panzerfaust", "german/atmm": "ATMM check:",
}, ignore_labels )
# update the scenario (British/American, no date)
load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "" } } )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3 }
)
_check_vsav_dump( updated_vsav_dump, {
# nb: no LATW labels should have been created
}, ignore_labels )
@ -273,7 +272,9 @@ def test_latw_autocreate( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1945" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3 }
)
_check_vsav_dump( updated_vsav_dump, {
# nb: no LATW labels should have been created
}, ignore_labels )
@ -304,7 +305,7 @@ def test_latw_update( webapp, webdriver ):
# check the VASL scenario
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/latw.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
_check_vsav_dump( vsav_dump, {
"german/psk": "Panzerschrek", "german/atmm": "ATMM check:", # nb: the PF label has no snippet ID
"russian/mol-p": "TH#", # nb: the MOL label has no snippet ID
@ -317,7 +318,9 @@ def test_latw_update( webapp, webdriver ):
# NOTE: We changed the MOL-P template (to add custom list bullets), so the snippet is different
# to when this test was originally written, and so #updated changed from 2 to 3.
# NOTE: Same thing happened when we factored out the common CSS into common.css :-/ Sigh...
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 5 }
)
_check_vsav_dump( updated_vsav_dump, {
"german/pf": "Panzerfaust", # nb: the PF label now has a snippet ID
"german/psk": "Panzerschrek", "german/atmm": "ATMM check:",
@ -330,7 +333,9 @@ def test_latw_update( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1943" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 2 }
)
_check_vsav_dump( updated_vsav_dump, {
# NOTE: We used to delete the PSK/ATMM/MOL-P labels, but this no longer happens with player-owned labels.
"german/psk": "Panzerschrek", "german/atmm": "ATMM check:",
@ -360,7 +365,7 @@ def test_dump_vsav( webapp, webdriver ):
# dump the VASL scenario
fname = os.path.join( os.path.split(__file__)[0], "fixtures/dump-vsav/labels.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
# check the result
fname = change_extn( fname, ".txt" )
@ -392,7 +397,7 @@ def test_update_legacy_labels( webapp, webdriver ):
# dump the VASL scenario
# NOTE: We implemented snippet ID's in v0.5, this scenario is the "Hill 621" example from v0.4.
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/hill621-legacy.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
labels = _get_vsav_labels( vsav_dump )
assert len( [ lbl for lbl in labels if "vasl-templates:id" not in lbl ] ) == 20
assert len( [ lbl for lbl in labels if "vasl-templates:id" in lbl ] ) == 0 #pylint: disable=len-as-condition
@ -402,7 +407,9 @@ def test_update_legacy_labels( webapp, webdriver ):
saved_scenario = json.load( open( fname2, "r" ) )
load_scenario( saved_scenario )
expected = 5 if enable_vo_notes else 1
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": expected, "updated": 20 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": expected, "updated": 20 }
)
# check the results
# nb: the update process should create 1 new label (the "Download from MMP" scenario note)
@ -474,7 +481,7 @@ def test_update_legacy_latw_labels( webapp, webdriver ):
# dump the VASL scenario
# NOTE: This scenario contains LATW labels created using v0.4 i.e. they have no snippet ID's.
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/latw-legacy.vsav" )
vsav_dump = _dump_vsav( fname )
vsav_dump = _dump_vsav( control_tests, fname )
labels = _get_vsav_labels( vsav_dump )
assert len( [ lbl for lbl in labels if "vasl-templates:id" not in lbl ] ) == 8
assert len( [ lbl for lbl in labels if "vasl-templates:id" in lbl ] ) == 0 #pylint: disable=len-as-condition
@ -486,7 +493,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "12/31/1945" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 5 }
)
_check_vsav_dump( updated_vsav_dump, {
"german/pf": "Panzerfaust", "german/psk": "Panzerschrek", "german/atmm": "ATMM check:",
"russian/mol": "Kindling Attempt:", "russian/mol-p": "TH#",
@ -499,7 +508,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ):
load_scenario_params( {
"scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "12/31/1945" }
} )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 2 }
)
_check_vsav_dump( updated_vsav_dump, {
"british/piat": "PIAT",
"american/baz": "Bazooka ('45)",
@ -510,7 +521,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ):
# update the VSAV (some LATW are active)
load_scenario_params( { "scenario": { "PLAYER_1": "german", "PLAYER_2": "russian", "SCENARIO_DATE": "" } } )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 5 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 5 }
)
_check_vsav_dump( updated_vsav_dump, {
"german/pf": "Panzerfaust", "german/psk": "Panzerschrek", "german/atmm": "ATMM check:",
"russian/mol": "Kindling Attempt:", "russian/mol-p": "TH#",
@ -521,7 +534,9 @@ def test_update_legacy_latw_labels( webapp, webdriver ):
# update the VSAV (some LATW are active)
load_scenario_params( { "scenario": { "PLAYER_1": "british", "PLAYER_2": "american", "SCENARIO_DATE": "" } } )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 3, "updated": 2 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 3, "updated": 2 }
)
_check_vsav_dump( updated_vsav_dump, {
"british/piat": "PIAT",
"american/baz": "Bazooka",
@ -566,7 +581,9 @@ def test_player_owned_labels( webapp, webdriver ):
# - scenario (timestamp)
# - players (new American player)
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/player-owned-labels-legacy.vsav" )
updated_vsav_dump = _update_vsav_and_dump( fname, { "updated": 4 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "updated": 4 }
)
_check_vsav_dump( updated_vsav_dump , {
"german/ob_setup_1.1": "german setup #1",
"american/ob_setup_2.1": "american setup #1",
@ -580,7 +597,9 @@ def test_player_owned_labels( webapp, webdriver ):
# - players (new American player)
# The existing Russian OB setup label should be ignored and left in-place.
fname = os.path.join( os.path.split(__file__)[0], "fixtures/update-vsav/player-owned-labels.vsav" )
updated_vsav_dump = _update_vsav_and_dump( fname, { "created": 1, "updated": 2 } )
updated_vsav_dump = _update_vsav_and_dump( control_tests, fname,
{ "created": 1, "updated": 2 }
)
_check_vsav_dump( updated_vsav_dump , {
"german/ob_setup_1.1": "german setup #1",
"american/ob_setup_2.1": "american setup #1",
@ -819,13 +838,6 @@ def run_vassal_tests( control_tests, func, test_all, min_vasl_version=None ):
else:
assert False, "Can't find a valid combination of VASSAL and VASL."
# FUDGE! If we are running the tests against a remote server, we still need to be able to run
# the VASSAL shim locally (to dump VASSAL save files), so we need to set up things up enough
# for this to work.
if control_tests.server_url:
vasl_mods_local = control_tests._do_get_vasl_mods() #pylint: disable=protected-access
globvars.vasl_mod = DummyVaslMod( random.choice( vasl_mods_local ) )
# run the test for each VASSAL+VASL
for vassal_engine in vassal_engines:
control_tests.set_vassal_engine( vengine=vassal_engine )
@ -836,9 +848,9 @@ def run_vassal_tests( control_tests, func, test_all, min_vasl_version=None ):
vasl_version = mo.group()
if min_vasl_version and compare_version_strings( vasl_version, min_vasl_version ) < 0:
continue
control_tests.set_vasl_mod( vmod=vasl_mod )
if not is_valid_combo( vassal_engine, vasl_mod ):
continue
control_tests.set_vasl_mod( vmod=vasl_mod )
func()
# ---------------------------------------------------------------------
@ -878,25 +890,25 @@ def _update_vsav( fname, expected ):
return updated_vsav_data
def _update_vsav_and_dump( fname, expected ):
def _update_vsav_and_dump( control_tests, fname, expected ):
"""Update a VASL scenario and dump the result."""
# update the VASL
# update the VSAV
updated_vsav_data = _update_vsav( fname, expected )
# dump the updated VSAV
with TempFile() as temp_file:
temp_file.write( updated_vsav_data )
temp_file.close( delete=False )
return _dump_vsav( temp_file.name )
return _dump_vsav( control_tests, temp_file.name )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def _dump_vsav( fname ):
def _dump_vsav( control_tests, fname ):
"""Dump a VASL scenario file."""
# NOTE: This is run locally, even if we're running the tests against a remote server.
vassal_shim = VassalShim()
return vassal_shim.dump_scenario( fname )
with open( fname, "rb" ) as fp:
vsav_data = fp.read()
return control_tests.get_vsav_dump( bin_data=vsav_data )
def _check_vsav_dump( vsav_dump, expected, ignore=None ):
""""Check that a VASL scenario dump contains what we expect."""

@ -289,7 +289,7 @@ class VassalShim:
def __init__( self ): #pylint: disable=too-many-branches
# locate the VASSAL engine
vassal_dir = app.config.get( "VASSAL_DIR" )
vassal_dir = self._get_vassal_dir()
if not vassal_dir:
raise SimpleError( "The VASSAL installation directory has not been configured." )
self.vengine_jar = None
@ -323,7 +323,7 @@ class VassalShim:
@staticmethod
def get_version():
"""Get the VASSAL version."""
vassal_dir = app.config.get( "VASSAL_DIR" )
vassal_dir = VassalShim._get_vassal_dir()
if not vassal_dir:
return None
# FUDGE! We can't capture the output on Windows, get the result in a temp file instead :-/
@ -471,7 +471,8 @@ class VassalShim:
@staticmethod
def get_boards_dir():
"""Get the configured boards directory."""
boards_dir = app.config.get( "BOARDS_DIR" )
# NOTE: The Docker container configures this setting via an environment variable.
boards_dir = app.config.get( "BOARDS_DIR", os.environ.get("VASL_BOARDS_DIR") )
if not boards_dir:
raise SimpleError( "The VASL boards directory has not been configured." )
if not os.path.isdir( boards_dir ):
@ -513,7 +514,7 @@ class VassalShim:
@staticmethod
def check_vassal_version( msg_store ):
"""Check the version of VASSAL."""
if not app.config.get( "VASSAL_DIR" ) or not msg_store:
if not VassalShim._get_vassal_dir() or not msg_store:
return
try:
version = VassalShim.get_version()
@ -528,6 +529,12 @@ class VassalShim:
version
)
@staticmethod
def _get_vassal_dir():
"""Get the VASSAL installation directory."""
# NOTE: The Docker container configures this setting via an environment variable.
return app.config.get( "VASSAL_DIR", os.environ.get("VASSAL_DIR") )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class VassalShimError( Exception ):

Loading…
Cancel
Save