mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
* implemented 'get_workfile_info' in entities * removed 'prepare_asset_update_data' which is not used * disable settings and project manager if in v4 mode * prepared conversion helper functions for v4 entities * prepared conversion functions for hero versions * fix hero versions * implemented get_archived_representations * fix get latest versions * return prepared changes * handle archived representation * raise exception on failed json conversion * map archived to active properly * make sure default fields are added * fix conversion of hero version entity * fix conversion of archived representations * fix some conversions of representations and versions * changed active behavior in queries * fixed hero versions * implemented basic thumbnail caching * added raw variants of crud methods * implemented methods to get and create thumbnail * fix from flat dict * implemented some basic folder conversion for updates * fix thumbnail updates for version * implemented v4 thumbnail integrator * simplified data mapping * 'get_thumbnail' function also expect entity type and entity id for which is the thumbnail received * implemented 'get_thumbnail' for server * fix how thumbnail id is received from entity * removed unnecessary method 'get_thumbnail_id_from_source' * implemented thumbnail resolver for v4 * removed unnecessary print * move create and delete project directly to server api * disable local settings action too on v4 * OP-3521 - added method to check and download updated addons from v4 server * OP-3521 - added more descriptive error message for missing source * OP-3521 - added default implementation of addon downloader to import * OP-3521 - added check for dependency package zips WIP - server doesn't contain required endpoint. Testing only with mockup data for now. * OP-3521 - fixed parsing of DependencyItem Added Server Url type and ServerAddonDownloader - v4 server doesn't know its own DNS for static files so it is sending unique name and url must be created during runtime. * OP-3521 - fixed creation of targed directories * change nev keys to look for and don't set them automatically * fix task type conversion * implemented base of loading v4 addons in v3 * Refactored argument name in Downloaders * Updated parsing to DependencyItem according to current schema * Implemented downloading of package from server * Updated resolving of failures Uses Enum items. * Introduced passing of authorization token Better to inject it than to have it from env var. * Remove weird parsing of server_url Not necessary, endpoints have same prefix. * Fix doubling asset version name in addons folder Zip file should already contain `addonName_addonVersion` as first subfolder * Fix doubling asset version name in addons folder Zip file should already contain `addonName_addonVersion` as first subfolder * Made server_endpoint optional Argument should be better for testing, but for calling from separate methods it would be better to encapsulate it. Removed unwanted temporary productionPackage value * Use existing method to pull addon info from Server to load v4 version of addon * Raise exception when server doesn't have any production dependency package * added ability to specify v3 alias of addon name * expect v3_alias as uppered constant * Re-implemented method to get addon info Previous implementation wouldn't work in Python2 hosts. Will be refactored in the future. * fix '__getattr__' * added ayon api to pyproject.toml and lock file * use ayon api in common connection * added mapping for label * use ayon_api in client codebase * separated clearing cache of url and username * bump ayon api version * rename env 'OP4_TEST' to 'USE_AYON_SERVER' * Move and renamend get_addons_info to get_addons_info_as_dict in addon_distribution Should be moved to ayon_api later * Replaced requests calls with ayon_api * Replaced OP4_TEST_ENABLED with AYON_SERVER_ENABLED fixed endpoints * Hound * Hound * OP-3521 - fix wrong key in get_representation_parents parents overloads parents * OP-3521 - changes for v4 of SiteSync addon * OP-3521 - fix names * OP-3521 - remove storing project_name It should be safer to go thorug self.dbcon apparently * OP-3521 - remove unwanted "context["folder"]" can be only in dummy test data * OP-3521 - move site sync loaders to addon * Use only project instead of self.project * OP-3521 - added missed get_progress_for_repre * base of settings conversion script * simplified ayon functions in start.py * added loading of settings from ayon server * added a note about colors * fix global and local settings functions * AvalonMongoDB is not using mongo connection on ayon server enabled * 'get_dynamic_modules_dirs' is not checking system settings for paths in setting * log viewer is disabled when ayon server is enabled * basic logic of enabling/disabled addons * don't use mongo logging if ayon server is enabled * update ayon api * bump ayon api again * use ayon_api to get addons info in modules/base * update ayon api * moved helper functions to get addons and dependencies dir to common functions * Initialization of AddonInfo is not crashing on unkonwn sources * renamed 'DependencyDownloader' to 'AyonServerDownloader' * renamed function 'default_addon_downloader' to 'get_default_addon_downloader' * Added ability to convert 'WebAddonSource' to 'ServerResourceSorce' * missing dependency package on server won't cause crash * data sent to downloaders don't contain ayon specific headers * modified addon distribution to not duplicate 'ayon_api' functionality * fix doubled function defintioin * unzip client file to addon destination * formatting - unify quotes * disable usage of mongo connection if in ayon mode * renamed window.py to login_window.py * added webpublisher settings conversion * added maya conversion function * reuse variable * reuse variable (similar to previous commit) * fix ayon addons loading * fix typo 'AyonSettingsCahe' -> 'AyonSettingsCache' * fix enabled state changes * fix rr_path in royal render conversion * avoid mongo calls in AYON state * implemented custom AYON start script * fix formatting (after black) * ayon_start cleanup * 'get_addons_dir' and 'get_dependencies_dir' store value to environment variable * add docstrings to local dir functions * addon info has full name * fix modules enabled states * removed unused 'run_disk_mapping_commands' * removed ayon logic from 'start.py' * fix warning message * renamed 'openpype_common' to 'ayon_common' * removed unused import * don't import igniter * removed startup validations of third parties * change what's shown in version info * fix which keys are applied from ayon values * fix method name * get applications from attribs * Implemented UI basics to be able change user or logout * merged server.py and credentials.py * add more metadata to urls * implemented change token * implemented change user ui functionality * implemented change user ui * modify window to handle username and token value * pass username to add server * fix show UI cases * added loggin action to tray * update ayon api * added missing dependency * convert applications to config in a right way * initial implementation of 'nuke' settings conversion * removed few nuke comments * implemented hiero conversion * added imageio conversion * added run ayon tray script * fix few settings conversions * Renamed class of source classes as they are not just for addons * implemented objec to track source transfer progress * Implemented distribution item with multiple sources * Implemented ayon distribution wrapper to care about multiple things during distribution * added 'cleanup' method for downlaoders * download gets tranfer progress object * Change UploadState enum * added missing imports * use AyonDistribution in ayon_start.py * removed unused functions * removed implemented TODOs * fix import * fix key used for Web source * removed temp development fix * formatting fix * keep information if source require distribution * handle 'require_distribution' attribute in distribution process * added path attribute to server source * added option to pass addons infor to ayon distribution * fix tests * fix formatting * Fix typo * Fix typo * remove '_try_convert_to_server_source' * renamed attributes and methods to match their content * it is possible to pass dependency package info to AyonDistribution * fix called methods in tests * added public properties for error message and error detail * Added filename to WebSourceInfo Useful for GDrive sharable links where target file name is unknown/unparsable, it should be provided explicitly. * unify source conversion by adding 'convert_source' function * Fix error message Co-authored-by: Roy Nieterau <roy_nieterau@hotmail.com> * added docstring for 'transfer_progress' * don't create metadata file on read * added few docstrings * add default folder fields to folder/task queries * fix generators * add dependencies when runnign from code * add sys paths from distribution to pythonpath env * fix missing applications * added missing conversions for maya renderers * fix formatting * update ayon api * fix hashes in lock file * Use better exception Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> * Use Python 3 syntax Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> * apply some of sugested changes in ayon_start * added some docstrings and suggested modifications * copy create env from develop * fix rendersettings conversion * change code by suggestions * added missing args to docstring * added missing docstrings * separated downloader and download factory * fix ayon settings * added some basic file docstring to ayon_settings * join else conditions * fix project settings conversion * fix created at conversion * fix workfile info query * fix publisher UI * added utils function 'get_ayon_appdirs' * fix 'get_all_current_info' * fix server url assignment when url is set * updated ayon api * added utils functions to create local site id for ayon * added helper functions to create global connection * create global connection in ayon start to start use site id * use ayon site id in ayon mode * formatting cleanup * added header docstring * fixes after ayon_api update * load addons from ynput appdirs * fix function call * added docstring * update ayon pyton api * fix settings access * use ayon_api to get root overrides in Anatomy * bumbayon version to 0.1.13 * nuke: fixing settings keys from settings * fix burnins definitions * change v4 to AYON in thumbnail integrate * fix one more v4 information * Fixes after rebase * fix extract burnin conversion * additional fix of extract burnin * SiteSync:added missed loaders or v3 compatibility (#4587) * Added site sync loaders for v3 compatibility * Fix get_progress_for_repre * use 'files.name' instead of 'files.baseName' * update ayon api to 0.1.14 * add common to include files * change arguments for hero version creation * skip shotgrid settings conversion if different ayon addon is used * added ayon icons * fix labels of application variants * added option to show login window always on top * login window on invalid credentials is always on top * update ayon api * update ayon api * add entityType to project and folders * AYON: Editorial hierarchy creation (#4699) * disable extract hierarchy avalon when ayon mode is enabled * implemented extract hierarchy to AYON --------- Co-authored-by: Petr Kalis <petr.kalis@gmail.com> Co-authored-by: Roy Nieterau <roy_nieterau@hotmail.com> Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> Co-authored-by: Jakub Jezek <jakubjezek001@gmail.com>
475 lines
17 KiB
Python
475 lines
17 KiB
Python
"""Testing classes for module testing and publishing in hosts."""
|
|
import os
|
|
import sys
|
|
import six
|
|
import json
|
|
import pytest
|
|
import tempfile
|
|
import shutil
|
|
import glob
|
|
import platform
|
|
import requests
|
|
import re
|
|
|
|
from tests.lib.db_handler import DBHandler
|
|
from common.ayon_common.distribution.file_handler import RemoteFileHandler
|
|
from openpype.modules import ModulesManager
|
|
from openpype.settings import get_project_settings
|
|
|
|
|
|
class BaseTest:
|
|
"""Empty base test class"""
|
|
|
|
|
|
class ModuleUnitTest(BaseTest):
|
|
"""Generic test class for testing modules
|
|
|
|
Use PERSIST==True to keep temporary folder and DB prepared for
|
|
debugging or preparation of test files.
|
|
|
|
Implemented fixtures:
|
|
monkeypatch_session - fixture for env vars with session scope
|
|
project_settings - fixture for project settings with session scope
|
|
download_test_data - tmp folder with extracted data from GDrive
|
|
env_var - sets env vars from input file
|
|
db_setup - prepares avalon AND openpype DBs for testing from
|
|
binary dumps from input data
|
|
dbcon - returns DBConnection to AvalonDB
|
|
dbcon_openpype - returns DBConnection for OpenpypeMongoDB
|
|
|
|
"""
|
|
PERSIST = False # True to not purge temporary folder nor test DB
|
|
|
|
TEST_OPENPYPE_MONGO = "mongodb://localhost:27017"
|
|
TEST_DB_NAME = "avalon_tests"
|
|
TEST_PROJECT_NAME = "test_project"
|
|
TEST_OPENPYPE_NAME = "openpype_tests"
|
|
|
|
TEST_FILES = []
|
|
|
|
PROJECT = "test_project"
|
|
ASSET = "test_asset"
|
|
TASK = "test_task"
|
|
|
|
TEST_DATA_FOLDER = None
|
|
|
|
@pytest.fixture(scope='session')
|
|
def monkeypatch_session(self):
|
|
"""Monkeypatch couldn't be used with module or session fixtures."""
|
|
from _pytest.monkeypatch import MonkeyPatch
|
|
m = MonkeyPatch()
|
|
yield m
|
|
m.undo()
|
|
|
|
@pytest.fixture(scope='module')
|
|
def project_settings(self):
|
|
yield get_project_settings(
|
|
self.PROJECT
|
|
)
|
|
|
|
@pytest.fixture(scope="module")
|
|
def download_test_data(self, test_data_folder, persist, request):
|
|
test_data_folder = test_data_folder or self.TEST_DATA_FOLDER
|
|
if test_data_folder:
|
|
print("Using existing folder {}".format(test_data_folder))
|
|
yield test_data_folder
|
|
else:
|
|
tmpdir = tempfile.mkdtemp()
|
|
print("Temporary folder created:: {}".format(tmpdir))
|
|
for test_file in self.TEST_FILES:
|
|
file_id, file_name, md5 = test_file
|
|
|
|
f_name, ext = os.path.splitext(file_name)
|
|
|
|
RemoteFileHandler.download_file_from_google_drive(file_id,
|
|
str(tmpdir),
|
|
file_name)
|
|
|
|
if ext.lstrip('.') in RemoteFileHandler.IMPLEMENTED_ZIP_FORMATS: # noqa: E501
|
|
RemoteFileHandler.unzip(os.path.join(tmpdir, file_name))
|
|
yield tmpdir
|
|
|
|
persist = (persist or self.PERSIST or
|
|
self.is_test_failed(request))
|
|
if not persist:
|
|
print("Removing {}".format(tmpdir))
|
|
shutil.rmtree(tmpdir)
|
|
|
|
@pytest.fixture(scope="module")
|
|
def output_folder_url(self, download_test_data):
|
|
"""Returns location of published data, cleans it first if exists."""
|
|
path = os.path.join(download_test_data, "output")
|
|
if os.path.exists(path):
|
|
print("Purging {}".format(path))
|
|
shutil.rmtree(path)
|
|
yield path
|
|
|
|
@pytest.fixture(scope="module")
|
|
def env_var(self, monkeypatch_session, download_test_data):
|
|
"""Sets temporary env vars from json file."""
|
|
env_url = os.path.join(download_test_data, "input",
|
|
"env_vars", "env_var.json")
|
|
if not os.path.exists(env_url):
|
|
raise ValueError("Env variable file {} doesn't exist".
|
|
format(env_url))
|
|
|
|
env_dict = {}
|
|
try:
|
|
with open(env_url) as json_file:
|
|
env_dict = json.load(json_file)
|
|
except ValueError:
|
|
print("{} doesn't contain valid JSON")
|
|
six.reraise(*sys.exc_info())
|
|
|
|
for key, value in env_dict.items():
|
|
all_vars = globals()
|
|
all_vars.update(vars(ModuleUnitTest)) # TODO check
|
|
value = value.format(**all_vars)
|
|
print("Setting {}:{}".format(key, value))
|
|
monkeypatch_session.setenv(key, str(value))
|
|
|
|
#reset connection to openpype DB with new env var
|
|
import openpype.settings.lib as sett_lib
|
|
sett_lib._SETTINGS_HANDLER = None
|
|
sett_lib._LOCAL_SETTINGS_HANDLER = None
|
|
sett_lib.create_settings_handler()
|
|
sett_lib.create_local_settings_handler()
|
|
|
|
import openpype
|
|
openpype_root = os.path.dirname(os.path.dirname(openpype.__file__))
|
|
|
|
# ?? why 2 of those
|
|
monkeypatch_session.setenv("OPENPYPE_ROOT", openpype_root)
|
|
monkeypatch_session.setenv("OPENPYPE_REPOS_ROOT", openpype_root)
|
|
|
|
# for remapping purposes (currently in Nuke)
|
|
monkeypatch_session.setenv("TEST_SOURCE_FOLDER", download_test_data)
|
|
|
|
@pytest.fixture(scope="module")
|
|
def db_setup(self, download_test_data, env_var, monkeypatch_session,
|
|
request):
|
|
"""Restore prepared MongoDB dumps into selected DB."""
|
|
backup_dir = os.path.join(download_test_data, "input", "dumps")
|
|
|
|
uri = os.environ.get("OPENPYPE_MONGO")
|
|
db_handler = DBHandler(uri)
|
|
db_handler.setup_from_dump(self.TEST_DB_NAME, backup_dir,
|
|
overwrite=True,
|
|
db_name_out=self.TEST_DB_NAME)
|
|
|
|
db_handler.setup_from_dump(self.TEST_OPENPYPE_NAME, backup_dir,
|
|
overwrite=True,
|
|
db_name_out=self.TEST_OPENPYPE_NAME)
|
|
|
|
yield db_handler
|
|
|
|
persist = self.PERSIST or self.is_test_failed(request)
|
|
if not persist:
|
|
db_handler.teardown(self.TEST_DB_NAME)
|
|
db_handler.teardown(self.TEST_OPENPYPE_NAME)
|
|
|
|
@pytest.fixture(scope="module")
|
|
def dbcon(self, db_setup, output_folder_url):
|
|
"""Provide test database connection.
|
|
|
|
Database prepared from dumps with 'db_setup' fixture.
|
|
"""
|
|
from openpype.pipeline import AvalonMongoDB
|
|
dbcon = AvalonMongoDB()
|
|
dbcon.Session["AVALON_PROJECT"] = self.PROJECT
|
|
dbcon.Session["AVALON_ASSET"] = self.ASSET
|
|
dbcon.Session["AVALON_TASK"] = self.TASK
|
|
|
|
# set project root to temp folder
|
|
platform_str = platform.system().lower()
|
|
root_key = "config.roots.work.{}".format(platform_str)
|
|
dbcon.update_one(
|
|
{"type": "project"},
|
|
{"$set":
|
|
{
|
|
root_key: output_folder_url
|
|
}}
|
|
)
|
|
yield dbcon
|
|
|
|
@pytest.fixture(scope="module")
|
|
def dbcon_openpype(self, db_setup):
|
|
"""Provide test database connection for OP settings.
|
|
|
|
Database prepared from dumps with 'db_setup' fixture.
|
|
"""
|
|
from openpype.lib import OpenPypeMongoConnection
|
|
mongo_client = OpenPypeMongoConnection.get_mongo_client()
|
|
yield mongo_client[self.TEST_OPENPYPE_NAME]["settings"]
|
|
|
|
def is_test_failed(self, request):
|
|
# if request.node doesn't have rep_call, something failed
|
|
try:
|
|
return request.node.rep_call.failed
|
|
except AttributeError:
|
|
return True
|
|
|
|
|
|
class PublishTest(ModuleUnitTest):
|
|
"""Test class for publishing in hosts.
|
|
|
|
Implemented fixtures:
|
|
launched_app - launches APP with last_workfile_path
|
|
publish_finished - waits until publish is finished, host must
|
|
kill its process when finished publishing. Includes timeout
|
|
which raises ValueError
|
|
|
|
Not implemented:
|
|
last_workfile_path - returns path to testing workfile
|
|
startup_scripts - provide script for setup in host
|
|
|
|
Implemented tests:
|
|
test_folder_structure_same - compares published and expected
|
|
subfolders if they contain same files. Compares only on file
|
|
presence
|
|
|
|
TODO: implement test on file size, file content
|
|
"""
|
|
|
|
APP_GROUP = ""
|
|
|
|
TIMEOUT = 120 # publish timeout
|
|
|
|
# could be overwritten by command line arguments
|
|
# command line value takes precedence
|
|
|
|
# keep empty to locate latest installed variant or explicit
|
|
APP_VARIANT = ""
|
|
PERSIST = True # True - keep test_db, test_openpype, outputted test files
|
|
TEST_DATA_FOLDER = None # use specific folder of unzipped test file
|
|
|
|
SETUP_ONLY = False
|
|
|
|
@pytest.fixture(scope="module")
|
|
def app_name(self, app_variant):
|
|
"""Returns calculated value for ApplicationManager. Eg.(nuke/12-2)"""
|
|
from openpype.lib import ApplicationManager
|
|
app_variant = app_variant or self.APP_VARIANT
|
|
|
|
application_manager = ApplicationManager()
|
|
if not app_variant:
|
|
variant = (
|
|
application_manager.find_latest_available_variant_for_group(
|
|
self.APP_GROUP))
|
|
app_variant = variant.name
|
|
|
|
yield "{}/{}".format(self.APP_GROUP, app_variant)
|
|
|
|
@pytest.fixture(scope="module")
|
|
def app_args(self, download_test_data):
|
|
"""Returns additional application arguments from a test file.
|
|
|
|
Test zip file should contain file at:
|
|
FOLDER_DIR/input/app_args/app_args.json
|
|
containing a list of command line arguments (like '-x' etc.)
|
|
"""
|
|
app_args = []
|
|
args_url = os.path.join(download_test_data, "input",
|
|
"app_args", "app_args.json")
|
|
if not os.path.exists(args_url):
|
|
print("App argument file {} doesn't exist".format(args_url))
|
|
else:
|
|
try:
|
|
with open(args_url) as json_file:
|
|
app_args = json.load(json_file)
|
|
|
|
if not isinstance(app_args, list):
|
|
raise ValueError
|
|
except ValueError:
|
|
print("{} doesn't contain valid JSON".format(args_url))
|
|
six.reraise(*sys.exc_info())
|
|
|
|
yield app_args
|
|
|
|
@pytest.fixture(scope="module")
|
|
def launched_app(self, dbcon, download_test_data, last_workfile_path,
|
|
startup_scripts, app_args, app_name, output_folder_url,
|
|
setup_only):
|
|
"""Launch host app"""
|
|
if setup_only or self.SETUP_ONLY:
|
|
print("Creating only setup for test, not launching app")
|
|
yield
|
|
return
|
|
# set schema - for integrate_new
|
|
from openpype import PACKAGE_DIR
|
|
# Path to OpenPype's schema
|
|
schema_path = os.path.join(
|
|
os.path.dirname(PACKAGE_DIR),
|
|
"schema"
|
|
)
|
|
os.environ["AVALON_SCHEMA"] = schema_path
|
|
|
|
os.environ["OPENPYPE_EXECUTABLE"] = sys.executable
|
|
from openpype.lib import ApplicationManager
|
|
|
|
application_manager = ApplicationManager()
|
|
data = {
|
|
"last_workfile_path": last_workfile_path,
|
|
"start_last_workfile": True,
|
|
"project_name": self.PROJECT,
|
|
"asset_name": self.ASSET,
|
|
"task_name": self.TASK
|
|
}
|
|
if app_args:
|
|
data["app_args"] = app_args
|
|
|
|
app_process = application_manager.launch(app_name, **data)
|
|
yield app_process
|
|
|
|
@pytest.fixture(scope="module")
|
|
def publish_finished(self, dbcon, launched_app, download_test_data,
|
|
timeout, setup_only):
|
|
"""Dummy fixture waiting for publish to finish"""
|
|
if setup_only or self.SETUP_ONLY:
|
|
print("Creating only setup for test, not launching app")
|
|
yield False
|
|
return
|
|
import time
|
|
time_start = time.time()
|
|
timeout = timeout or self.TIMEOUT
|
|
timeout = float(timeout)
|
|
while launched_app.poll() is None:
|
|
time.sleep(0.5)
|
|
if time.time() - time_start > timeout:
|
|
launched_app.terminate()
|
|
raise ValueError("Timeout reached")
|
|
|
|
# some clean exit test possible?
|
|
print("Publish finished")
|
|
yield True
|
|
|
|
def test_folder_structure_same(self, dbcon, publish_finished,
|
|
download_test_data, output_folder_url,
|
|
skip_compare_folders,
|
|
setup_only):
|
|
"""Check if expected and published subfolders contain same files.
|
|
|
|
Compares only presence, not size nor content!
|
|
"""
|
|
if setup_only or self.SETUP_ONLY:
|
|
print("Creating only setup for test, not launching app")
|
|
return
|
|
|
|
published_dir_base = output_folder_url
|
|
expected_dir_base = os.path.join(download_test_data,
|
|
"expected")
|
|
|
|
print("Comparing published:'{}' : expected:'{}'".format(
|
|
published_dir_base, expected_dir_base))
|
|
published = set(f.replace(published_dir_base, '') for f in
|
|
glob.glob(published_dir_base + "\\**", recursive=True)
|
|
if f != published_dir_base and os.path.exists(f))
|
|
expected = set(f.replace(expected_dir_base, '') for f in
|
|
glob.glob(expected_dir_base + "\\**", recursive=True)
|
|
if f != expected_dir_base and os.path.exists(f))
|
|
|
|
filtered_published = self._filter_files(published,
|
|
skip_compare_folders)
|
|
|
|
# filter out temp files also in expected
|
|
# could be polluted by accident by copying 'output' to zip file
|
|
filtered_expected = self._filter_files(expected, skip_compare_folders)
|
|
|
|
not_mtched = filtered_expected.symmetric_difference(filtered_published)
|
|
if not_mtched:
|
|
raise AssertionError("Missing {} files".format(
|
|
"\n".join(sorted(not_mtched))))
|
|
|
|
def _filter_files(self, source_files, skip_compare_folders):
|
|
"""Filter list of files according to regex pattern."""
|
|
filtered = set()
|
|
for file_path in source_files:
|
|
if skip_compare_folders:
|
|
if not any([re.search(val, file_path)
|
|
for val in skip_compare_folders]):
|
|
filtered.add(file_path)
|
|
else:
|
|
filtered.add(file_path)
|
|
|
|
return filtered
|
|
|
|
|
|
class DeadlinePublishTest(PublishTest):
|
|
@pytest.fixture(scope="module")
|
|
def publish_finished(self, dbcon, launched_app, download_test_data,
|
|
timeout):
|
|
"""Dummy fixture waiting for publish to finish"""
|
|
import time
|
|
time_start = time.time()
|
|
timeout = timeout or self.TIMEOUT
|
|
timeout = float(timeout)
|
|
while launched_app.poll() is None:
|
|
time.sleep(0.5)
|
|
if time.time() - time_start > timeout:
|
|
launched_app.terminate()
|
|
raise ValueError("Timeout reached")
|
|
|
|
metadata_json = glob.glob(os.path.join(download_test_data,
|
|
"output",
|
|
"**/*_metadata.json"),
|
|
recursive=True)
|
|
if not metadata_json:
|
|
raise RuntimeError("No metadata file found. No job id.")
|
|
|
|
if len(metadata_json) > 1:
|
|
# depends on creation order of published jobs
|
|
metadata_json.sort(key=os.path.getmtime, reverse=True)
|
|
|
|
with open(metadata_json[0]) as fp:
|
|
job_info = json.load(fp)
|
|
|
|
deadline_job_id = job_info["deadline_publish_job_id"]
|
|
|
|
manager = ModulesManager()
|
|
deadline_module = manager.modules_by_name["deadline"]
|
|
deadline_url = deadline_module.deadline_urls["default"]
|
|
|
|
if not deadline_url:
|
|
raise ValueError("Must have default deadline url.")
|
|
|
|
url = "{}/api/jobs?JobId={}".format(deadline_url, deadline_job_id)
|
|
valid_date_finished = None
|
|
|
|
time_start = time.time()
|
|
while not valid_date_finished:
|
|
time.sleep(0.5)
|
|
if time.time() - time_start > timeout:
|
|
raise ValueError("Timeout for DL finish reached")
|
|
|
|
response = requests.get(url, timeout=10)
|
|
if not response.ok:
|
|
msg = "Couldn't connect to {}".format(deadline_url)
|
|
raise RuntimeError(msg)
|
|
|
|
if not response.json():
|
|
raise ValueError("Couldn't find {}".format(deadline_job_id))
|
|
|
|
# '0001-...' returned until job is finished
|
|
valid_date_finished = response.json()[0]["DateComp"][:4] != "0001"
|
|
|
|
# some clean exit test possible?
|
|
print("Publish finished")
|
|
yield True
|
|
|
|
|
|
class HostFixtures():
|
|
"""Host specific fixtures. Should be implemented once per host."""
|
|
@pytest.fixture(scope="module")
|
|
def last_workfile_path(self, download_test_data, output_folder_url):
|
|
"""Returns url of workfile"""
|
|
raise NotImplementedError
|
|
|
|
@pytest.fixture(scope="module")
|
|
def startup_scripts(self, monkeypatch_session, download_test_data):
|
|
""""Adds init scripts (like userSetup) to expected location"""
|
|
raise NotImplementedError
|
|
|
|
@pytest.fixture(scope="module")
|
|
def skip_compare_folders(self):
|
|
"""Use list of regexs to filter out published folders from comparing"""
|
|
raise NotImplementedError
|