Skip to content

Commit

Permalink
Engine versioning (#190)
Browse files Browse the repository at this point in the history
* Engine versioning stubs

* Version tests

* Test fix

* Added simple version test.
  • Loading branch information
MuniuDev authored Dec 1, 2019
1 parent cca61fa commit 1d99d6c
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 65 deletions.
2 changes: 1 addition & 1 deletion PolyEngine/Scripts/common/docker_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def run_it_cmd(self, cmd):

def run_cmd(self, cmd):
subprocess.run("docker container run --rm -w /root/workspace -v {}:/root/workspace {} {}"\
.format(SCRIPT_ENV.repo_path, self._image_name, cmd), shell=False, check=True)
.format(SCRIPT_ENV.repo_path, self._image_name, cmd), shell=True, check=True)

class DockerFile():
def __init__(self, path):
Expand Down
10 changes: 9 additions & 1 deletion PolyEngine/Scripts/common/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
import logging
import sys
import platform
import json
import common.serialization

# Parameters
_COMMANDS_DIR_NAME = 'commands'
_RESOURCES_DIR_NAME = 'resources'
_TESTS_DIR_NAME = 'tests'
_THIRDPARTY_DIR_NAME = 'ThirdParty'
_LOG_LEVEL = 'DEBUG'

_ENGINE_VER_FILENAME = 'version.json'
_LOGGER_FORMAT = '[%(asctime)s] [%(levelname)s] [%(name)s]\t %(message)s'

# Constants
Expand Down Expand Up @@ -45,6 +47,12 @@ def is_cygwin(self):
def is_posix(self):
return self.is_linux() or self.is_macos() or self.is_cygwin()

def engine_ver(self):
with open(os.path.join(self.engine_path, _ENGINE_VER_FILENAME), 'r') as file:
version_obj = json.load(file, cls=common.serialization.JSONDecoder)
assert(isinstance(version_obj, common.version.Version))
return version_obj

@property
def scripts_path(self):
return self._scripts_path
Expand Down
2 changes: 1 addition & 1 deletion PolyEngine/Scripts/common/project_mgr/engine_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class EngineProject(ProjectBase):
def __init__(self, build_postfix=None):
ProjectBase.__init__(self, common.SCRIPT_ENV.engine_path, 'PolyEngine', common.Version(0, 0, 1), build_postfix)
ProjectBase.__init__(self, common.SCRIPT_ENV.engine_path, 'PolyEngine', build_postfix)
self._logger = common.SCRIPT_ENV.get_logger(name='EngineProject')

if not os.path.isdir(self._root_path):
Expand Down
14 changes: 13 additions & 1 deletion PolyEngine/Scripts/common/project_mgr/game_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self, project_root_path, project_name=None, create_if_absent=False,
self._logger.info('Deduced project name to be: [{}]'.format(self._project_name))

# Initialize base
ProjectBase.__init__(self, project_root_path, self._project_name, common.Version(0, 0, 1), build_postfix)
ProjectBase.__init__(self, project_root_path, self._project_name, build_postfix)

self._project_path = os.path.join(self._root_path, self._project_name)
self._project_resources_path = os.path.join(self._project_path, PROJECT_RESOURCES_DIR_NAME)
Expand All @@ -78,10 +78,22 @@ def __init__(self, project_root_path, project_name=None, create_if_absent=False,
raise ValueError('Project [{}] cannot be created when create_if_absent=False.'.format(self._project_name))
self._create()

if os.path.isfile(self._project_file_path):
self._parse_proj_file()

assert(os.path.isfile(self._project_file_path))
assert(self._engine_ver is not None)

def bump_ver(self, version):
if version <= self._engine_ver:
raise ValueError('Engine version can only go up! Current: [{}] Requested: [{}]'.format(self._engine_ver, version))
self._engine_ver = version
self._save()

def _create(self):
# Setup engine version
self._engine_ver = common.SCRIPT_ENV.engine_ver()

# Ensure all necessary folders are present
os.makedirs(self._root_path, exist_ok=True)
os.makedirs(self._project_path, exist_ok=True)
Expand Down
7 changes: 1 addition & 6 deletions PolyEngine/Scripts/common/project_mgr/project_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
DIST_DIR_NAME = 'Dist'

class ProjectBase():
def __init__(self, project_root_path, project_name, engine_ver, build_postfix=None):
def __init__(self, project_root_path, project_name, build_postfix=None):
self._root_path = project_root_path

build_dir_fullname = BUILD_DIR_NAME + '_' + build_postfix if build_postfix else BUILD_DIR_NAME
Expand All @@ -15,7 +15,6 @@ def __init__(self, project_root_path, project_name, engine_ver, build_postfix=No
self._build_postfix = build_postfix
self._dist_path = os.path.join(project_root_path, dist_dir_fullname)
self._project_name = project_name
self._engine_ver = engine_ver


def update(self):
Expand All @@ -34,10 +33,6 @@ def save(self):
def name(self):
return self._project_name

@property
def engine_ver(self):
return self._engine_ver

# Abstract API
def _before_cmake_gen(self):
pass
Expand Down
39 changes: 35 additions & 4 deletions PolyEngine/Scripts/common/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ def __init__(self, major, minor, fix):
self.minor = minor
self.fix = fix

def supports(self, other):
'''
This method returns true when self is a newer version that is backwards compatible with other
'''

if not isinstance(other, Version):
raise TypeError('Cannot check for backwards compatibility with object of type: {}'.format(type(other)))
return self.major == other.major and self.minor >= other.minor

def __repr__(self):
return 'Version(major={}, minor={}, fix={})'.format(self.major, self.minor, self.fix)

Expand All @@ -34,7 +43,29 @@ def __eq__(self, other):
raise TypeError('Cannot compare version with object of type: {}'.format(type(other)))
return self.major == other.major and self.minor == other.minor and self.fix == other.fix

def is_backwards_compatible_with(self, other):
if not isinstance(other, Version):
raise TypeError('Cannot check for backwards compatibility with object of type: {}'.format(type(other)))
return self.major == other.major and self.minor <= other.minor
def __lt__(self, other):
if self.major < other.major:
return True
elif self.major == other.major:
if self.minor < other.minor:
return True
elif self.minor == other.minor and self.fix < other.fix:
return True
return False

def __gt__(self, other):
if self.major > other.major:
return True
elif self.major == other.major:
if self.minor > other.minor:
return True
elif self.minor == other.minor and self.fix > other.fix:
return True
return False

def __le__(self, other):
return self == other or self < other

def __ge__(self, other):
return self == other or self > other

106 changes: 55 additions & 51 deletions PolyEngine/Scripts/tests/common/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,58 @@
import common

class Test(unittest.TestCase):
def setUp(self):
pass

def tearDown(self):
pass

def test_environment_exists(self):
env = common.SCRIPT_ENV

self.assertTrue(os.path.isdir(env.scripts_path))
self.assertTrue(os.path.isdir(env.script_commands_path))
self.assertTrue(os.path.isdir(env.engine_path))
self.assertTrue(os.path.isdir(env.repo_path))
self.assertTrue(os.path.isdir(env.script_resources_path))
self.assertTrue(os.path.isdir(env.script_tests_path))

def test_env_logger(self):
TEST_LOGGER_NAME = 'TestLogger'
logger = common.SCRIPT_ENV.get_logger(TEST_LOGGER_NAME)

self.assertIsNotNone(logger)
self.assertEqual(logger.name, TEST_LOGGER_NAME)

def test_env_os(self):
is_windows = common.SCRIPT_ENV.is_windows()
is_linux = common.SCRIPT_ENV.is_linux()
is_macos = common.SCRIPT_ENV.is_macos()
is_cygwin = common.SCRIPT_ENV.is_cygwin()
is_posix = common.SCRIPT_ENV.is_posix()

if is_windows:
self.assertFalse(is_linux)
self.assertFalse(is_macos)
self.assertFalse(is_cygwin)
self.assertFalse(is_posix)
elif is_linux:
self.assertFalse(is_windows)
self.assertFalse(is_macos)
self.assertFalse(is_cygwin)
self.assertTrue(is_posix)
elif is_macos:
self.assertFalse(is_windows)
self.assertFalse(is_linux)
self.assertFalse(is_cygwin)
self.assertTrue(is_posix)
else:
self.assertFalse(is_windows)
self.assertFalse(is_linux)
self.assertFalse(is_macos)
self.assertTrue(is_cygwin)
self.assertTrue(is_posix)
def setUp(self):
pass

def tearDown(self):
pass

def test_engine_version(self):
version = common.SCRIPT_ENV.engine_ver()
self.assertIsNotNone(version)

def test_environment_exists(self):
env = common.SCRIPT_ENV

self.assertTrue(os.path.isdir(env.scripts_path))
self.assertTrue(os.path.isdir(env.script_commands_path))
self.assertTrue(os.path.isdir(env.engine_path))
self.assertTrue(os.path.isdir(env.repo_path))
self.assertTrue(os.path.isdir(env.script_resources_path))
self.assertTrue(os.path.isdir(env.script_tests_path))

def test_env_logger(self):
TEST_LOGGER_NAME = 'TestLogger'
logger = common.SCRIPT_ENV.get_logger(TEST_LOGGER_NAME)

self.assertIsNotNone(logger)
self.assertEqual(logger.name, TEST_LOGGER_NAME)

def test_env_os(self):
is_windows = common.SCRIPT_ENV.is_windows()
is_linux = common.SCRIPT_ENV.is_linux()
is_macos = common.SCRIPT_ENV.is_macos()
is_cygwin = common.SCRIPT_ENV.is_cygwin()
is_posix = common.SCRIPT_ENV.is_posix()

if is_windows:
self.assertFalse(is_linux)
self.assertFalse(is_macos)
self.assertFalse(is_cygwin)
self.assertFalse(is_posix)
elif is_linux:
self.assertFalse(is_windows)
self.assertFalse(is_macos)
self.assertFalse(is_cygwin)
self.assertTrue(is_posix)
elif is_macos:
self.assertFalse(is_windows)
self.assertFalse(is_linux)
self.assertFalse(is_cygwin)
self.assertTrue(is_posix)
else:
self.assertFalse(is_windows)
self.assertFalse(is_linux)
self.assertFalse(is_macos)
self.assertTrue(is_cygwin)
self.assertTrue(is_posix)
109 changes: 109 additions & 0 deletions PolyEngine/Scripts/tests/common/test_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import unittest
import os
import json

import common.serialization
from common.version import Version

class Test(unittest.TestCase):
def setUp(self):
pass

def tearDown(self):
pass

def test_valid_construction(self):
ver = Version(1, 2, 3)
self.assertEqual(ver.major, 1)
self.assertEqual(ver.minor, 2)
self.assertEqual(ver.fix, 3)

def test_invalid_construction(self):
with self.assertRaises(TypeError):
Version(1.0, 2, 3)

with self.assertRaises(TypeError):
Version(1, 2.0, 3)

with self.assertRaises(TypeError):
Version(1, 2, 'a')

def test_supports(self):
ver = Version(5, 6, 7)
ver_compat_fix1 = Version(5, 6, 1)
ver_compat_fix2 = Version(5, 6, 9)
ver_compat_min = Version(5, 4, 1)
ver_compat_max = Version(5, 6, 7)

ver_noncompat_min = Version(5, 8, 1)
ver_noncompat_max1 = Version(3, 1, 1)
ver_noncompat_max2 = Version(6, 1, 1)

self.assertTrue(ver.supports(ver))

self.assertTrue(ver.supports(ver_compat_fix1))
self.assertTrue(ver.supports(ver_compat_fix2))

self.assertTrue(ver.supports(ver_compat_min))
self.assertTrue(ver.supports(ver_compat_max))

self.assertFalse(ver.supports(ver_noncompat_min))
self.assertFalse(ver.supports(ver_noncompat_max1))
self.assertFalse(ver.supports(ver_noncompat_max2))

def test_eq(self):
ver1 = Version(1, 2, 3)
ver2 = Version(1, 2, 3)
ver3 = Version(4, 5, 6)

self.assertEqual(ver1, ver2)
self.assertEqual(ver2, ver1)

self.assertNotEqual(ver1, ver3)
self.assertNotEqual(ver3, ver1)

self.assertNotEqual(ver2, ver3)
self.assertNotEqual(ver3, ver2)

def test_lt(self):
ver = Version(5, 6, 7)
ver_fix_l = Version(5, 6, 6)
ver_fix_h = Version(5, 6, 8)
ver_min_l = Version(5, 5, 9)
ver_min_h = Version(5, 7, 1)
ver_maj_l = Version(4, 9, 9)
ver_maj_h = Version(6, 1, 1)

self.assertLess(ver_fix_l, ver)
self.assertLess(ver, ver_fix_h)

self.assertLess(ver_min_l, ver)
self.assertLess(ver, ver_min_h)

self.assertLess(ver_maj_l, ver)
self.assertLess(ver, ver_maj_h)

def test_gt(self):
ver = Version(5, 6, 7)
ver_fix_l = Version(5, 6, 6)
ver_fix_h = Version(5, 6, 8)
ver_min_l = Version(5, 5, 9)
ver_min_h = Version(5, 7, 1)
ver_maj_l = Version(4, 9, 9)
ver_maj_h = Version(6, 1, 1)

self.assertGreater(ver_fix_h, ver)
self.assertGreater(ver, ver_fix_l)

self.assertGreater(ver_min_h, ver)
self.assertGreater(ver, ver_min_l)

self.assertGreater(ver_maj_h, ver)
self.assertGreater(ver, ver_maj_l)

def test_serialization(self):
ver1 = Version(1, 2, 3)
ver_str = json.dumps(ver1, cls=common.serialization.JSONEncoder)
ver2 = json.loads(ver_str, cls=common.serialization.JSONDecoder)

self.assertEqual(ver1, ver2)
1 change: 1 addition & 0 deletions PolyEngine/version.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Major": 0, "Minor": 0, "Fix": 1, "@type": "Version"}

0 comments on commit 1d99d6c

Please sign in to comment.