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. 106
      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,29 +5,32 @@
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
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
a web browser is launched internally with snippet HTML and a screenshot taken of it, but
the HTML will contain links to the webapp server that work from outside the container,
but if those links don't resolve from inside the container, you will get broken images.
In this case, you will need to make such links resolve from inside the container e.g. by
port-forwarding, or via DNS.
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
a web browser is launched internally with snippet HTML and a screenshot taken of it, but
the HTML will contain links to the webapp server that work from outside the container,
but if those links don't resolve from inside the container, you will get broken images.
In this case, you will need to make such links resolve from inside the container e.g. by
port-forwarding, or via DNS.
EOM
}
@ -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