This commit is contained in:
annatisch 2017-05-09 09:38:06 -07:00
Родитель 76bcf03f00
Коммит 75855cea9b
14 изменённых файлов: 445 добавлений и 1747 удалений

Просмотреть файл

@ -36,6 +36,7 @@ import pkgutil
import inspect
import importlib
import tempfile
import pathlib
from Queue import Queue
from api import MayaAPI as maya
@ -74,8 +75,8 @@ class AzureBatchAssets(object):
self.ui = AssetsUI(self, frame)
self.frame = frame
callback.after_new(self._callback_refresh)
callback.after_read(self._callback_refresh)
#callback.after_new(self._callback_refresh)
#callback.after_read(self._callback_refresh)
def _callback_refresh(self, *args):
"""Called by Maya when a new scene file is loaded, so we reset
@ -131,6 +132,7 @@ class AzureBatchAssets(object):
SYS_SEARCHPATHS.append(maya.workspace(query=True, directory=True))
SYS_SEARCHPATHS.append(os.getcwd())
SYS_SEARCHPATHS = list(set(SYS_SEARCHPATHS))
return SYS_SEARCHPATHS
def _configure_renderer(self):
"""Configure the renderer-specific asset collection according
@ -624,7 +626,7 @@ class Asset(object):
"""Check whether this file is already represented in the current
asset list.
"""
return any(f.path == self.path for f in files) #TODO: Check if this is accurate
return any(pathlib.Path(f.path) == pathlib.Path(self.path) for f in files)
def restore_label(self):
"""Restore the original UI display label after the file has been

Просмотреть файл

@ -44,7 +44,15 @@ MAYA_IMAGES = {
'offer': 'autodesk-maya-arnold-win2016-preview',
'sku': 'maya2017',
'version': 'latest'
}
},
'Batch CentOS Preview':
{
'node_sku_id': 'batch.node.centos 7',
'publisher': 'batch',
'offer': 'autodesk-maya-arnold-centos73-preview',
'sku': 'maya2017',
'version': 'latest'
},
}
LICENSES = [
{'label': 'Maya', 'id': 'maya', 'plugin': None },
@ -71,8 +79,8 @@ class AzureBatchEnvironment(object):
self.skus = self._load_skus()
self.ui = EnvironmentUI(self, frame, MAYA_IMAGES.keys(), self.skus, self.licenses)
self.refresh()
callback.after_new(self.ui.refresh)
callback.after_read(self.ui.refresh)
#callback.after_new(self.ui.refresh)
#callback.after_read(self.ui.refresh)
def _load_skus(self):
"""Populate the list of availablke hardware SKUs."""

Просмотреть файл

@ -67,8 +67,8 @@ class AzureBatchSubmission(object):
self.env_manager = None
self.batch = None
callback.after_new(self.ui.refresh)
callback.after_open(self.ui.refresh)
#callback.after_new(self.ui.refresh)
#callback.after_open(self.ui.refresh)
def _collect_modules(self):
"""Collect the renderer-specific submission modules. This is where

Просмотреть файл

@ -1,9 +1,9 @@
# coding=utf-8
# --------------------------------------------------------------------------
#!/usr/bin/env python
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import os
import sys

Просмотреть файл

@ -15,8 +15,6 @@ import re
batch_client = None
storage_client = None
is_thumnail = re.compile("framethumb_[\d\-]+.png")
is_log = re.compile("frame_[\d\-]+.log")
def header(header):
@ -40,6 +38,7 @@ def _check_valid_dir(directory):
except (TypeError, EnvironmentError) as exp:
raise RuntimeError(exp)
def _download_output(container, blob_name, output_path, size):
def progress(data, total):
try:
@ -54,73 +53,61 @@ def _download_output(container, blob_name, output_path, size):
storage_client.get_blob_to_path(container, blob_name, output_path, progress_callback=progress)
print(" Output download successful.\n")
def _track_completed_tasks(container, dwnld_dir):
try:
job_outputs = storage_client.list_blobs(container)
for output in job_outputs:
if output.name.startswith('thumbs/'):
continue
elif is_log.match(output.name):
output_file = os.path.join(dwnld_dir, "logs", output.name)
else:
output_file = os.path.join(dwnld_dir, output.name)
if not os.path.isfile(output_file):
_download_output(container, output.name, output_file, output.properties.content_length)
except (TypeError, AttributeError, KeyError) as exp:
raise RuntimeError("Failed {0}".format(exp))
def _track_completed_outputs(container, dwnld_dir):
job_outputs = storage_client.list_blobs(container)
for output in job_outputs:
if output.name.startswith('thumbs/'):
continue
else:
output_file = os.path.normpath(os.path.join(dwnld_dir, output.name))
if not os.path.isfile(output_file):
if not os.path.isdir(os.path.dirname(output_file)):
os.makedirs(os.path.dirname(output_file))
_download_output(container, output.name, output_file, output.properties.content_length)
def _check_job_stopped(job):
"""Checks job for failure or completion.
:returns: A boolean indicating True if the job completed, or False if still in
progress.
:raises: RuntimeError if the job has failed, or been cancelled.
"""
Checks job for failure or completion.
:Args:
- job (:class:`batchapps.SubmittedJob`): an instance of the current
SubmittedJob object.
:Returns:
- A boolean indicating True if the job completed, or False if still in
progress.
:Raises:
- RuntimeError if the job has failed, or been cancelled.
"""
from azure.batch.models import JobState
stopped_status = [
batch.models.JobState.disabling,
batch.models.JobState.disabled,
batch.models.JobState.terminating,
batch.models.JobState.deleting
]
JobState.disabling,
JobState.disabled,
JobState.terminating,
JobState.deleting
]
running_status = [
batch.models.JobState.active,
batch.models.JobState.enabling
]
JobState.active,
JobState.enabling
]
try:
if job.state in stopped_status:
print(header("Job has stopped"))
print("Job status: {0}".format(job.state))
raise RuntimeError("Job is no longer running. Status: {0}".format(job.state))
elif job.state == batch.models.JobState.completed:
elif job.state == JobState.completed:
print(header("Job has completed"))
return True
elif job.state in running_status:
return False
else:
raise RuntimeError("Job state invalid: {}".format(job.state))
except AttributeError as exp:
raise RuntimeError(exp)
def track_job_progress(id, container, dwnld_dir):
from azure.batch.models import TaskState
print("Tracking job with ID: {0}".format(id))
try:
job = batch_client.job.get(id)
tasks = [t for t in batch_client.task.list(id)]
while True:
completed_tasks = [t for t in tasks if t.state == batch.models.TaskState.completed]
completed_tasks = [t for t in tasks if t.state == TaskState.completed]
errored_tasks = [t for t in completed_tasks if t.execution_info.exit_code != 0]
if len(tasks) == 0:
percentage = 0
@ -130,19 +117,17 @@ def track_job_progress(id, container, dwnld_dir):
if errored_tasks:
print(" - Warning: some tasks have completed with a non-zero exit code.")
_track_completed_tasks(container, dwnld_dir)
_track_completed_outputs(container, dwnld_dir)
if _check_job_stopped(job):
return # Job complete
time.sleep(10)
job = batch_client.job.get(id)
tasks = [t for t in batch_client.task.list(id)]
except (TypeError, AttributeError) as exp:
raise RuntimeError("Error occured: {0}".format(exp))
except KeyboardInterrupt:
raise RuntimeError("Monitoring aborted.")
def _authenticate(cfg_path):
global batch_client, storage_client
cfg = ConfigParser.ConfigParser()
@ -160,6 +145,7 @@ def _authenticate(cfg_path):
except (EnvironmentError, ConfigParser.NoOptionError, ConfigParser.NoSectionError) as exp:
raise ValueError("Failed to authenticate using Maya configuration {0}".format(cfg_path))
if __name__ == "__main__":
try:
sys.path.append(sys.argv[5])

Просмотреть файл

@ -36,6 +36,12 @@
"description": "The SAS URL to a pre-render asset path redirection script"
}
},
"thumbScript": {
"type": "string",
"metadata": {
"description": "The SAS URL to the thumbnail generation script"
}
},
"frameStart": {
"type": "int",
"metadata": {
@ -72,6 +78,10 @@
{
"blobSource": "[parameters('assetScript')]",
"filePath": "scripts/renderPrep.mel"
},
{
"blobSource": "[parameters('thumbScript')]",
"filePath": "thumbnail.py"
}
],
"commandLine": "dir"
@ -87,7 +97,7 @@
],
"repeatTask": {
"displayName": "Frame {0}",
"commandLine": "mkdir /X;mount -rbind $AZ_BATCH_JOB_PREP_WORKING_DIR/assets /X;render -renderer \"[parameters('renderer')]\" -verb -preRender \"renderPrep\" -rd \"$AZ_BATCH_TASK_WORKING_DIR/images\" -s {0} -e {0} \"[parameters('sceneFile')]\"",
"commandLine": "mkdir /X;mount -rbind $AZ_BATCH_JOB_PREP_WORKING_DIR/assets /X;render -renderer [parameters('renderer')] -verb -preRender renderPrep -rd \"$AZ_BATCH_TASK_WORKING_DIR/images\" -s {0} -e {0} \"[parameters('sceneFile')]\";err=$?;$AZ_BATCH_JOB_PREP_WORKING_DIR/thumbnail.py $err;exit $err",
"environmentSettings": [
{
"name": "MAYA_SCRIPT_PATH",
@ -110,6 +120,18 @@
"uploadCondition": "taskSuccess"
}
},
{
"filePattern": "thumbs/*.png",
"destination": {
"autoStorage": {
"fileGroup": "[parameters('outputs')]",
"path": "thumbs"
}
},
"uploadOptions": {
"uploadCondition": "taskSuccess"
}
},
{
"filePattern": "../stdout.txt",
"destination": {

Просмотреть файл

@ -1,5 +1,6 @@
pathlib==1.0.1
azure-mgmt-batch==4.0.0
azure-mgmt-batch==3.0.0
azure-mgmt-storage==1.0.0rc1
azure-batch==3.0.0
azure-batch==2.0.1
azure-storage==0.32.0
mock=2.0.0

Просмотреть файл

@ -1,6 +1,6 @@
#-------------------------------------------------------------------------
#
# Batch Apps Maya Plugin
# Azure Batch Maya Plugin
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#

Просмотреть файл

@ -1,6 +1,6 @@
#-------------------------------------------------------------------------
#
# Batch Apps Maya Plugin
# Azure Batch Maya Plugin
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
@ -31,6 +31,7 @@ import sys
import os
import logging
import json
from Queue import Queue
try:
import unittest2 as unittest
@ -41,6 +42,8 @@ try:
except ImportError:
import mock
import batch_extensions
from ui_assets import AssetsUI
from assets import Asset, Assets, AzureBatchAssets
from exception import FileUploadException
@ -50,53 +53,53 @@ class TestAsset(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(Asset)
self.mock_file = mock.create_autospec(UserFile)
self.mock_file.path = "/my/test_path"
self.mock_file = "/my/local/test_path"
self.mock_self.batch = mock.create_autospec(batch_extensions.BatchExtensionsClient)
self.mock_self.batch.file = mock.create_autospec(batch_extensions.operations.ExtendedFileOperations)
self.mock_self.log = logging.getLogger('batch-maya-asset-tests')
return super(TestAsset, self).setUp()
def test_create_asset(self):
self.mock_file._exist = True
self.mock_file.__bool__.return_value = True
test_asset = Asset(self.mock_file, None)
def test_asset_create(self):
test_asset = Asset(self.mock_file, "parent", "batch")
self.assertEqual(test_asset.label, " test_path")
self.assertEqual(test_asset.path, "/my/test_path")
self.assertEqual(test_asset.note, "Can't find /my/test_path")
self.assertEqual(test_asset.path, "\\my\\local\\test_path")
self.assertEqual(test_asset.note, "Can't find \\my\\local\\test_path")
self.assertFalse(test_asset.exists)
self.mock_file.__bool__.return_value = True
test_asset = Asset(self.mock_file, None)
#self.assertEqual(test_asset.note, "/test_path")
with mock.patch.object(os.path, 'exists') as exist:
with mock.patch.object(os.path, 'getmtime') as mod:
with mock.patch.object(os.path, 'getsize'):
exist.return_value = True
mod.return_value = 1453766301
test_asset = Asset(self.mock_file, "parent", "batch")
self.assertEqual(test_asset.note, "\\my\\local\\test_path")
self.assertTrue(test_asset.exists)
self.assertEqual(test_asset.pathmap['\\my\\local']('Linux'), 'my/local')
@mock.patch("assets.maya")
def test_display(self, mock_api):
self.mock_self.file = self.mock_file
def test_asset_display(self, mock_api):
self.mock_self.path = "\\my\\local\\test_path"
self.mock_self.label = "label"
self.mock_self.note = "note"
self.mock_self.exists = False
Asset.display(self.mock_self, "ui", "layout", "scroll")
mock_api.symbol_button.assert_called_with(image="fpe_someBrokenPaths.png",
parent="layout",
command=mock.ANY,
height=17,
annotation="Add search path")
mock_api.symbol_button.assert_called_with(
image="fpe_someBrokenPaths.png", parent="layout", command=mock.ANY,
height=17, annotation="Add search path")
mock_api.text.assert_called_with("label", parent="layout", enable=False, annotation="note", align="left")
self.assertEqual(self.mock_self.scroll_layout, "scroll")
self.assertEqual(self.mock_self.frame, "ui")
self.mock_self.file = None
self.mock_self.exists = True
Asset.display(self.mock_self, "ui", "layout", "scroll")
mock_api.symbol_button.assert_called_with(image='fpe_someBrokenPaths.png',
parent="layout",
command=mock.ANY,
height=17,
annotation="Add search path")
mock_api.symbol_check_box.assert_called_with(
annotation='Click to remove asset from submission', offCommand=mock.ANY,
onCommand=mock.ANY, parent='layout', value=True)
@mock.patch("assets.maya")
def test_included(self, mock_api):
self.mock_self.file = self.mock_file
def test_asset_included(self, mock_api):
self.mock_self.exists = False
self.mock_self.check_box = None
val = Asset.included(self.mock_self)
@ -106,13 +109,12 @@ class TestAsset(unittest.TestCase):
val = Asset.included(self.mock_self)
self.assertFalse(val)
self.mock_self.file = "True"
self.mock_self.exists = True
val = Asset.included(self.mock_self)
mock_api.symbol_check_box.assert_called_with(1, query=True, value=True)
@mock.patch("assets.maya")
def test_include(self, mock_api):
def test_asset_include(self, mock_api):
self.mock_self.check_box = 1
self.mock_self.parent_list = []
Asset.include(self.mock_self)
@ -124,9 +126,8 @@ class TestAsset(unittest.TestCase):
mock_api.symbol_check_box.assert_called_with(1, edit=True, annotation="Click to remove asset from submission")
@mock.patch("assets.maya")
def test_search(self, mock_api):
def test_asset_search(self, mock_api):
from assets import USR_SEARCHPATHS
self.mock_self.frame = mock.create_autospec(AssetsUI)
mock_api.file_select.return_value = None
Asset.search(self.mock_self)
@ -144,8 +145,7 @@ class TestAsset(unittest.TestCase):
self.mock_self.frame.refresh.assert_called_with()
@mock.patch("assets.maya")
def test_exclude(self, mock_api):
def test_asset_exclude(self, mock_api):
self.mock_self.check_box = 1
self.mock_self.parent_list = []
Asset.exclude(self.mock_self)
@ -163,8 +163,7 @@ class TestAsset(unittest.TestCase):
mock_api.symbol_check_box.assert_called_with(1, edit=True, annotation="Click to include asset in submission")
@mock.patch("assets.maya")
def test_delete(self, mock_api):
def test_asset_delete(self, mock_api):
self.mock_self.parent_list = []
self.mock_self.check_box = 1
@ -177,9 +176,8 @@ class TestAsset(unittest.TestCase):
mock_api.delete_ui.assert_called_with(1, control=True)
self.assertEqual(self.mock_self.parent_list, [])
def test_check(self):
new_file = mock.create_autospec(UserFile)
def test_asset_check(self):
new_file = mock.create_autospec(Asset)
new_file.path = "C:\\TEST_file\\WeiRD_path"
self.mock_self.path = "c:\\test_file\\Weird_path"
@ -191,8 +189,7 @@ class TestAsset(unittest.TestCase):
self.assertFalse(check)
@mock.patch("assets.maya")
def test_make_visible(self, mock_maya):
def test_asset_make_visible(self, mock_maya):
mock_maya.text.return_value = 17
self.mock_self.scroll_layout = "layout"
self.mock_self.display_text = "text"
@ -202,10 +199,8 @@ class TestAsset(unittest.TestCase):
self.called += 1
if kwargs.get("query") and self.mock_self.scroll_layout == "layout":
return [4,0]
elif kwargs.get("query"):
return [0,0]
else:
self.assertEqual(kwargs.get("scrollPage"), "up")
self.mock_self.scroll_layout = "scrolled"
@ -223,29 +218,29 @@ class TestAsset(unittest.TestCase):
self.assertEqual(self.called, 4)
@mock.patch("assets.maya")
def test_upload(self, mock_maya):
def test_asset_upload(self, mock_maya):
queue = Queue()
self.mock_self.path = "/my/test/path/file.txt"
self.mock_self.display_text = "display"
self.mock_self.file = mock.create_autospec(UserFile)
self.mock_self.file.upload.return_value = mock.Mock(success=True)
self.mock_self.included.return_value = False
self.mock_self.storage_path = "my/test/path/file.txt"
self.mock_self.size = 10
prog = mock.create_autospec(ProgressBar)
prog.done = False
Asset.upload(self.mock_self, 0, prog, True)
self.mock_self.file.upload.assert_called_with(force=True, callback=mock.ANY, block=100000)
self.assertEqual(mock_maya.text.call_count, 0)
Asset.upload(self.mock_self, 0, prog, queue, "container")
self.mock_self.batch.file.upload.assert_called_with(
"/my/test/path/file.txt", "container", "my/test/path/file.txt", progress_callback=mock.ANY)
self.assertEqual(queue.qsize(), 7)
self.mock_self.file.upload.return_value = mock.Mock(success=False)
with self.assertRaises(FileUploadException):
Asset.upload(self.mock_self, 0, prog, True)
self.mock_self.batch.file.upload.side_effect = ValueError('boom')
Asset.upload(self.mock_self, 0, prog, queue, "container")
self.assertEqual(queue.qsize(), 13)
Asset.upload(self.mock_self, 0, prog, False)
mock_maya.text.assert_called_with("display", edit=True, label=" Skipped file.txt")
self.mock_self.included.return_value = True
Asset.upload(self.mock_self, 0, prog, False)
mock_maya.text.assert_called_with("display", edit=True, label=" Already uploaded file.txt")
prog.done = True
Asset.upload(self.mock_self, 0, prog, queue, "container")
self.assertEqual(queue.qsize(), 14)
class TestAssets(unittest.TestCase):
@ -253,111 +248,102 @@ class TestAssets(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(Assets)
self.mock_self._log = logging.getLogger("TestAssets")
self.mock_self.batch = mock.create_autospec(batch_extensions.BatchExtensionsClient)
return super(TestAssets, self).setUp()
def test_create_assets(self):
test_assets = Assets()
self.assertIsNone(test_assets.manager)
self.assertEqual(test_assets.refs, {'Additional':[]})
def test_assets_create(self):
test_assets = Assets('batch')
self.assertEqual(test_assets.batch, 'batch')
self.assertEqual(test_assets.refs, [])
@mock.patch("assets.SYS_SEARCHPATHS")
@mock.patch("assets.USR_SEARCHPATHS")
@mock.patch("assets.glob")
@mock.patch("assets.os.path.exists")
def test_search_path(self, mock_exists, mock_glob, mock_sys, mock_usr):
def test_assets_search_path(self, mock_exists, mock_glob, mock_sys, mock_usr):
mock_sys = []
mock_usr = []
self.mock_self.pathmaps = []
self.mock_self.pathmaps = {}
mock_exists.return_value = True
path = Assets.search_path(self.mock_self, "testpath\\testfile")
path = Assets._search_path(self.mock_self, "testpath\\testfile")
self.assertEqual(path, ["testpath\\testfile"])
mock_exists.assert_called_once_with("testpath\\testfile")
mock_exists.call_count = 0
self.assertEqual(mock_glob.glob.call_count, 0)
mock_exists.return_value = False
path = Assets.search_path(self.mock_self, "testpath\\testfile")
path = Assets._search_path(self.mock_self, "testpath\\testfile")
self.assertEqual(path, ["testpath\\testfile"])
mock_exists.assert_called_once_with("testpath\\testfile")
self.assertEqual(mock_glob.glob.call_count, 0)
mock_glob.glob.return_value = [1,2,3]
path = Assets.search_path(self.mock_self, "testpath\\*\\testfile")
path = Assets._search_path(self.mock_self, "testpath\\*\\testfile")
mock_glob.glob.assert_called_with("testpath\\*\\testfile")
self.assertEqual(path, [1,2,3])
mock_glob.glob.return_value = []
path = Assets.search_path(self.mock_self, "testpath\\[0-9]testfile")
path = Assets._search_path(self.mock_self, "testpath\\[0-9]testfile")
mock_glob.glob.assert_any_call("testpath\\[0-9]testfile")
self.assertEqual(path, ["testpath\\[0-9]testfile"])
def test_assets_gather(self):
self.mock_self.refs = []
self.mock_self._get_textures.return_value = ['a']
self.mock_self._get_caches.return_value = ['b']
self.mock_self._get_references.return_value = ['c']
def test_gather(self):
self.mock_self.refs = {}
self.mock_self.get_textures.return_value = {'a':1}
self.mock_self.get_caches.return_value = {'b':2}
self.mock_self.get_references.return_value = {'c':3}
Assets.gather(self.mock_self, "manager")
self.assertEqual(self.mock_self.refs, {'a':1, 'b':2, 'c':3, 'Additional':[]})
self.assertEqual(self.mock_self.manager, "manager")
self.assertEqual(self.mock_self.get_textures.call_count, 1)
self.assertEqual(self.mock_self.get_caches.call_count, 1)
self.assertEqual(self.mock_self.get_references.call_count, 1)
Assets.gather(self.mock_self)
self.assertEqual(self.mock_self.refs, ['a', 'b', 'c'])
self.assertEqual(self.mock_self._get_textures.call_count, 1)
self.assertEqual(self.mock_self._get_caches.call_count, 1)
self.assertEqual(self.mock_self._get_references.call_count, 1)
@mock.patch("assets.Asset")
def test_extend(self, mock_asset):
self.mock_self.refs = {}
self.mock_self.manager = mock.create_autospec(FileManager)
def test_assets_extend(self, mock_asset):
self.mock_self.refs = []
mock_asset.return_value = mock.create_autospec(Asset)
mock_asset.return_value.is_duplicate.return_value = True
self.mock_self.manager.file_from_path.return_value = "UserFile"
self.mock_self.search_path.return_value = ["a"]
self.mock_self._search_path.return_value = ["a"]
Assets.extend(self.mock_self, {"new_path":["/test_path/test_file"]})
mock_asset.assert_called_with("UserFile", [])
self.assertEqual(self.mock_self.refs, {"new_path": []})
Assets.extend(self.mock_self, ["/test_path/test_file"])
mock_asset.assert_called_with("a", [], self.mock_self.batch, self.mock_self._log)
self.assertEqual(self.mock_self.refs, [])
mock_asset.return_value.is_duplicate.return_value = False
Assets.extend(self.mock_self, {"new_path":["/test_path/test_file"]})
self.assertEqual(self.mock_self.refs, {"new_path": [mock.ANY]})
Assets.extend(self.mock_self, ["/test_path/test_file"])
self.assertEqual(self.mock_self.refs, [mock.ANY])
self.mock_self.refs = []
mock_asset.side_effect = Exception("error!")
Assets.extend(self.mock_self, {"new_path":["/test_path/test_file"]})
self.assertEqual(self.mock_self.refs, {"new_path": []})
Assets.extend(self.mock_self, ["/test_path/test_file"])
self.assertEqual(self.mock_self.refs, [])
def test_collect(self):
self.mock_self.refs = {}
def test_assets_collect(self):
self.mock_self.refs = []
files = Assets.collect(self.mock_self)
self.assertEqual(files, [])
test_file = mock.create_autospec(Asset)
test_file.file = "my_test_file"
self.mock_self.refs["Test1"] = [test_file]
test_file.included.return_value = True
self.mock_self.refs = [test_file]
files = Assets.collect(self.mock_self)
test_file.included.assert_called_once_with()
self.assertEqual(files, ["my_test_file"])
self.assertEqual(files, [test_file])
test_file.included.return_value = False
files = Assets.collect(self.mock_self)
self.assertEqual(files, [])
@mock.patch("assets.Asset")
@mock.patch("assets.maya")
def test_get_textures(self, mock_maya, mock_asset):
self.mock_self.manager = mock.create_autospec(FileManager)
def test_assets_get_textures(self, mock_maya, mock_asset):
mock_asset.return_value = mock.create_autospec(Asset)
mock_asset.return_value.is_duplicate.return_value = True
self.mock_self.manager.file_from_path.return_value = "UserFile"
self.mock_self.search_path.return_value = ["a"]
self.mock_self._search_path.return_value = ["a"]
class TestIter(object):
def __init__(self):
self.current = None
self.itr = iter(range(0,5))
@ -373,364 +359,194 @@ class TestAssets(unittest.TestCase):
return ["dir1/1", "dir2/2", "dir3/3"]
mock_maya.dependency_nodes.return_value = TestIter()
tex = Assets.get_textures(self.mock_self)
self.assertEqual(tex, {'Files': []})
tex = Assets._get_textures(self.mock_self)
self.assertEqual(tex, [])
self.assertEqual(mock_asset.call_count, 15)
mock_asset.assert_called_with("UserFile", [])
mock_asset.assert_called_with("a", [], self.mock_self.batch, self.mock_self._log)
mock_asset.return_value.is_duplicate.return_value = False
mock_maya.dependency_nodes.return_value = TestIter()
tex = Assets.get_textures(self.mock_self)
self.assertEqual(len(tex['Files']), 15)
tex = Assets._get_textures(self.mock_self)
self.assertEqual(len(tex), 15)
@mock.patch("assets.Asset")
@mock.patch("assets.maya")
def test_get_references(self, mock_maya, mock_asset):
self.mock_self.manager = mock.create_autospec(FileManager)
def test_assets_get_references(self, mock_maya, mock_asset):
mock_asset.return_value = mock.create_autospec(Asset)
mock_asset.return_value.is_duplicate.return_value = True
self.mock_self.manager.file_from_path.return_value = "UserFile"
self.mock_self.pathmaps = []
self.mock_self.refs = {'Files':[]}
self.mock_self.refs = []
refs = Assets.get_references(self.mock_self)
self.assertEqual(refs, {'References':[]})
refs = Assets._get_references(self.mock_self)
self.assertEqual(refs, [])
mock_maya.get_list.return_value = ["1", "2", "3"]
mock_maya.reference.return_value = "c:\\file\\ref"
refs = Assets.get_references(self.mock_self)
self.assertEqual(refs, {'References':[]})
self.assertEqual(set(self.mock_self.pathmaps), set(["c:\\file"]))
refs = Assets._get_references(self.mock_self)
self.assertEqual(refs, [])
mock_asset.return_value.is_duplicate.return_value = False
refs = Assets.get_references(self.mock_self)
self.assertEqual(refs, {'References':[mock.ANY]})
refs = Assets._get_references(self.mock_self)
self.assertEqual(refs, [mock.ANY])
@mock.patch("assets.Asset")
@mock.patch("assets.maya")
@mock.patch("assets.glob")
def test_get_caches(self, mock_glob, mock_maya, mock_asset):
def test_assets_get_caches(self, mock_glob, mock_maya, mock_asset):
def get_attr(node):
if node.endswith("cachePath"):
return "/test_path"
else:
return "test_file"
self.mock_self.pathmaps = []
self.mock_self.manager = mock.create_autospec(FileManager)
mock_asset.return_value = mock.create_autospec(Asset)
mock_maya.get_list.return_value = ["1", "2", "3"]
mock_maya.get_attr = get_attr
mock_glob.glob.return_value = ["pathA"]
self.mock_self.manager.file_from_path.return_value = "UserFile"
caches = Assets.get_caches(self.mock_self)
self.assertEqual(caches, {'Caches': [mock.ANY, mock.ANY, mock.ANY]})
self.assertEqual(set(self.mock_self.pathmaps), set(["/test_path"]))
caches = Assets._get_caches(self.mock_self)
self.assertEqual(caches, [mock.ANY, mock.ANY, mock.ANY])
@mock.patch("assets.Asset")
def test_add_asset(self, mock_asset):
self.mock_self.pathmaps = []
self.mock_self.refs = {'Additional':[]}
self.mock_self.manager = mock.create_autospec(FileManager)
def test_assets_add_asset(self, mock_asset):
self.mock_self.refs = []
mock_asset.return_value = mock.create_autospec(Asset)
mock_asset.return_value.is_duplicate.return_value = True
self.mock_self.manager.file_from_path.return_value = "UserFile"
Assets.add_asset(self.mock_self, "/test_path/my_asset", "ui", ("layout", "scroll"))
self.assertEqual(self.mock_self.pathmaps, ["/test_path"])
self.assertEqual(self.mock_self.refs, {'Additional':[]})
Assets.add_asset(self.mock_self, "/test_path/my_asset", "ui", "layout", "scroll")
self.assertEqual(self.mock_self.refs, [])
mock_asset.return_value.is_duplicate.assert_called_once_with([])
mock_asset.assert_called_once_with("UserFile", [])
mock_asset.assert_called_once_with("/test_path/my_asset", [], self.mock_self.batch, self.mock_self._log)
mock_asset.return_value.is_duplicate.return_value = False
Assets.add_asset(self.mock_self, "/test_path/my_asset", "ui", ("layout", "scroll"))
self.assertEqual(self.mock_self.refs, {'Additional':[mock.ANY]})
Assets.add_asset(self.mock_self, "/test_path/my_asset", "ui", "layout", "scroll")
self.assertEqual(self.mock_self.refs, [mock.ANY])
mock_asset.return_value.display.assert_called_with("ui", "layout", "scroll")
def test_get_pathmaps(self):
self.mock_self.pathmaps = []
maps = Assets.get_pathmaps(self.mock_self)
self.assertEqual(maps, {"PathMaps": []})
self.mock_self.pathmaps = ["test", "", "test", None, 0, 5, "", "test"]
maps = Assets.get_pathmaps(self.mock_self)
self.assertEqual(maps, {"PathMaps": ["test", "5"]})
class TestBatchAppsAssets(unittest.TestCase):
class TestAzureBatchAssets(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(BatchAppsAssets)
self.mock_self = mock.create_autospec(AzureBatchAssets)
self.mock_self._log = logging.getLogger("TestAssets")
return super(TestBatchAppsAssets, self).setUp()
self.mock_self.batch = mock.create_autospec(batch_extensions.BatchExtensionsClient)
test_dir = os.path.dirname(__file__)
top_dir = os.path.dirname(test_dir)
src_dir = os.path.join(top_dir, 'azure_batch_maya', 'scripts')
mod_dir = os.path.join(test_dir, 'data', 'modules')
ui_dir = os.path.join(src_dir, 'ui')
tools_dir = os.path.join(src_dir, 'tools')
os.environ["AZUREBATCH_ICONS"] = os.path.join(top_dir, 'azure_batch_maya', 'icons')
os.environ["AZUREBATCH_TEMPLATES"] = os.path.join(top_dir, 'azure_batch_maya', 'templates')
os.environ["AZUREBATCH_MODULES"] = mod_dir
os.environ["AZUREBATCH_SCRIPTS"] = "{0};{1};{2}".format(src_dir, ui_dir, tools_dir)
return super(TestAzureBatchAssets, self).setUp()
@mock.patch.object(BatchAppsAssets, "collect_modules")
@mock.patch.object(AzureBatchAssets, "_collect_modules")
@mock.patch("assets.callback")
@mock.patch("assets.AssetsUI")
def test_create_batchappsassets(self, mock_ui, mock_call, mock_collect):
assets = BatchAppsAssets("frame", "call")
def test_batchassets_create(self, mock_ui, mock_call, mock_collect):
assets = AzureBatchAssets("frame", "call")
mock_ui.assert_called_with(assets, "frame")
mock_collect.assert_called_with()
mock_call.after_new.assert_called_with(assets.callback_refresh)
mock_call.after_read.assert_called_with(assets.callback_refresh)
def test_callback_refresh(self):
#mock_call.after_new.assert_called_with(assets.callback_refresh)
#mock_call.after_read.assert_called_with(assets.callback_refresh)
def test_batchassets_callback_refresh(self):
self.mock_self.ui = mock.create_autospec(AssetsUI)
self.mock_self.frame = mock.Mock()
self.mock_self.frame.selected_tab = lambda: 1
self.mock_self.ui.ready = False
BatchAppsAssets.callback_refresh(self.mock_self)
AzureBatchAssets._callback_refresh(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 0)
self.assertFalse(self.mock_self.ui.ready)
self.mock_self.ui.ready = True
BatchAppsAssets.callback_refresh(self.mock_self)
AzureBatchAssets._callback_refresh(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 0)
self.assertFalse(self.mock_self.ui.ready)
self.mock_self.frame.selected_tab = lambda: 3
BatchAppsAssets.callback_refresh(self.mock_self)
AzureBatchAssets._callback_refresh(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 1)
@mock.patch("assets.Assets")
@mock.patch("assets.FileManager")
def test_configure(self, mock_mgr, mock_assets):
def test_batchassets_configure(self, mock_assets):
session = mock.Mock(batch="batch")
AzureBatchAssets.configure(self.mock_self, session)
mock_assets.assert_called_with("batch")
self.assertEqual(self.mock_self._set_searchpaths.call_count, 1)
session = mock.Mock(credentials="creds", config="conf")
BatchAppsAssets.configure(self.mock_self, session)
mock_mgr.assert_called_with("creds", "conf")
mock_assets.assert_called_with()
self.assertEqual(self.mock_self.set_searchpaths.call_count, 1)
def test_collect_modules(self):
mods = BatchAppsAssets.collect_modules(self.mock_self)
def test_batchassets_collect_modules(self):
mods = AzureBatchAssets._collect_modules(self.mock_self)
self.assertEqual(len(mods), 4)
@mock.patch("assets.BatchAppsRenderAssets")
@mock.patch("assets.AzureBatchRenderAssets")
@mock.patch("assets.maya")
def test_configure_renderer(self, mock_maya, mock_default):
def test_batchassets_configure_renderer(self, mock_maya, mock_default):
mock_default.return_value = mock.Mock(render_engine = "default")
mock_maya.mel.return_value = "test_renderer"
mock_maya.get_attr.return_value = "test_renderer"
renderer = mock.Mock(render_engine = "my_renderer")
self.mock_self.modules = [renderer, "test", None]
BatchAppsAssets.configure_renderer(self.mock_self)
AzureBatchAssets._configure_renderer(self.mock_self)
self.assertEqual(self.mock_self.renderer, mock_default.return_value)
renderer = mock.Mock(render_engine = "test_renderer")
self.mock_self.modules.append(renderer)
BatchAppsAssets.configure_renderer(self.mock_self)
AzureBatchAssets._configure_renderer(self.mock_self)
self.assertEqual(self.mock_self.renderer, renderer)
def test_set_assets(self):
self.mock_self.manager = "manager"
def test_batchassets_set_assets(self):
self.mock_self.renderer = mock.Mock()
self.mock_self.assets = mock.create_autospec(Assets)
BatchAppsAssets.set_assets(self.mock_self)
self.mock_self._assets = mock.create_autospec(Assets)
AzureBatchAssets.set_assets(self.mock_self)
self.mock_self._configure_renderer.assert_called_with()
self.mock_self._assets.gather.assert_called_with()
self.mock_self._assets.extend.assert_called_with(mock.ANY)
self.mock_self.configure_renderer.assert_called_with()
self.mock_self.assets.gather.assert_called_with("manager")
def test_asset_categories(self):
self.mock_self.assets = mock.create_autospec(Assets)
self.mock_self.assets.refs = {'Additional':[], 'Caches':[], 'Textures':[]}
cats = BatchAppsAssets.asset_categories(self.mock_self)
self.assertEqual(sorted(cats), ['Caches', 'Textures'])
self.mock_self.assets.refs = {'Caches':[], 'Textures':[]}
cats = BatchAppsAssets.asset_categories(self.mock_self)
self.assertEqual(sorted(cats), ['Caches', 'Textures'])
def test_collect_assets(self):
self.mock_self.ui = mock.create_autospec(AssetsUI)
self.mock_self.ui.ready = True
self.mock_self.assets = mock.create_autospec(Assets)
self.mock_self.manager = mock.create_autospec(FileManager)
self.mock_self.assets.refs = {'Additional':[]}
self.mock_self.assets.get_pathmaps.return_value = ['/test_path', "c:\\test_path"]
self.mock_self.manager.file_from_path.return_value = mock.create_autospec(UserFile)
self.mock_self.manager.create_file_set.return_value = mock.create_autospec(FileCollection)
collection = BatchAppsAssets.collect_assets(self.mock_self, ['/test_path/file1', "c:\\test_path\\file2"])
self.assertTrue('pathmaps' in collection)
self.assertTrue('assets' in collection)
self.mock_self.assets.collect.assert_called_with()
self.assertEqual(self.mock_self.ui.prepare.call_count, 0)
self.mock_self.ui.ready = False
collection = BatchAppsAssets.collect_assets(self.mock_self, ['/test_path/file1', "c:\\test_path\\file2"])
self.mock_self.ui.prepare.assert_called_with()
def test_get_assets(self):
self.mock_self.assets = mock.create_autospec(Assets)
self.mock_self.assets.refs = {'Test':["file1", "file2"]}
assets = BatchAppsAssets.get_assets(self.mock_self, "Nothing")
self.assertEqual(assets, [])
assets = BatchAppsAssets.get_assets(self.mock_self, "Test")
def test_batchassets_get_assets(self):
self.mock_self._assets = mock.create_autospec(Assets)
self.mock_self._assets.refs = ["file1", "file2"]
assets = AzureBatchAssets.get_assets(self.mock_self)
self.assertEqual(assets, ["file1", "file2"])
@mock.patch("assets.SYS_SEARCHPATHS")
@mock.patch("assets.maya")
def test_set_searchpaths(self, mock_maya, mock_syspaths):
def test_batchassets_set_searchpaths(self, mock_maya, mock_syspaths):
mock_maya.file.return_value = "testscene.mb"
mock_maya.workspace.return_value = "/test/directory"
mock_syspaths = ["a", "b", "c"]
paths = BatchAppsAssets.set_searchpaths(self.mock_self)
paths = AzureBatchAssets._set_searchpaths(self.mock_self)
self.assertEqual(sorted(paths), ["/test/directory", "/test/directory\\sourceimages", os.getcwd()])
def test_add_files(self):
def test_batchassets_add_files(self):
self.mock_self.ui = mock.Mock()
self.mock_self.assets = mock.create_autospec(Assets)
BatchAppsAssets.add_files(self.mock_self, ["a", "b"], "layout")
self.mock_self.assets.add_asset.assert_any_call("a", self.mock_self.ui, "layout")
self.mock_self.assets.add_asset.assert_any_call("b", self.mock_self.ui, "layout")
def test_add_dir(self):
self.mock_self._assets = mock.create_autospec(Assets)
AzureBatchAssets.add_files(self.mock_self, ["a", "b"], "layout", "scroll")
self.mock_self._assets.add_asset.assert_any_call("a", self.mock_self.ui, "layout", "scroll")
self.mock_self._assets.add_asset.assert_any_call("b", self.mock_self.ui, "layout", "scroll")
def test_batchassets_add_dir(self):
test_dir = os.path.join(os.path.dirname(__file__), "data")
self.mock_self.assets = mock.create_autospec(Assets)
self.mock_self._assets = mock.create_autospec(Assets)
self.mock_self.ui = mock.Mock()
AzureBatchAssets.add_dir(self.mock_self, [test_dir], "layout", "scroll")
self.mock_self._assets.add_asset.assert_any_call(os.path.join(test_dir, "modules", "default.py"),
self.mock_self.ui, "layout", "scroll")
self.assertTrue(self.mock_self._assets.add_asset.call_count >= 4)
BatchAppsAssets.add_dir(self.mock_self, [test_dir], "layout")
self.mock_self.assets.add_asset.assert_any_call(os.path.join(test_dir, "modules", "default.py"), self.mock_self.ui, "layout")
self.assertTrue(self.mock_self.assets.add_asset.call_count >= 4)
def test_upload_items(self):
mock_file1 = mock.Mock()
mock_file2 = mock.Mock()
to_upload = [mock_file1]
self.mock_self.assets = mock.create_autospec(Assets)
self.mock_self.assets.refs = {'Test':[mock_file1, mock_file2]}
prog = mock.create_autospec(ProgressBar)
prog.is_cancelled.return_value = False
c = BatchAppsAssets.upload_items(self.mock_self, to_upload, prog, 1234)
self.assertFalse(c)
prog.is_cancelled.return_value = True
c = BatchAppsAssets.upload_items(self.mock_self, to_upload, prog, 1234)
self.assertTrue(c)
@mock.patch("assets.Asset")
@mock.patch("assets.ProgressBar")
@mock.patch("assets.maya")
def test_upload(self, mock_maya, mock_prog):
def test_batchassets_upload(self, mock_maya, mock_prog, mock_asset):
# TODO
self.mock_self.ui = mock.create_autospec(AssetsUI)
self.mock_self.ui.upload_button = mock.create_autospec(ProcButton)
self.mock_self.assets = mock.create_autospec(Assets)
BatchAppsAssets.upload(self.mock_self)
class TestAssetsCombined(unittest.TestCase):
@mock.patch("assets.callback")
@mock.patch("ui_assets.utils")
@mock.patch("ui_assets.maya")
@mock.patch("assets.maya")
def test_assets(self, *args):
mock_maya = args[0]
mock_maya.file.return_value = "/test_path/test_scene.mb"
mock_maya.workspace.return_value = "/test/project"
mock_uimaya = args[1]
mock_uimaya.file_select.return_value = [os.path.join(os.path.dirname(__file__), "data", "star.png")]
def add_tab(tab):
self.assertFalse(tab.ready)
def call(func, *args, **kwargs):
self.assertTrue(hasattr(func, '__call__'))
return func()
layout = mock.Mock(add_tab=add_tab)
assets = BatchAppsAssets(layout, call)
self.assertEqual(len(assets.modules), 4)
creds = mock.create_autospec(Credentials)
conf = mock.create_autospec(Configuration)
session = mock.Mock(credentials=creds, config=conf)
assets.configure(session)
#self.assertEqual(assets.scene, "")
mock_maya.file.return_value = os.path.join(os.path.dirname(__file__), "data", "empty.mb")
assets.configure(session)
#self.assertTrue(assets.scene.endswith("empty.mb"))
assets.ui.prepare()
self.assertTrue(assets.ui.ready)
self.assertEqual(assets.assets.refs, {'Additional':[],
'Caches':[],
'Files':[],
'References':[]})
files = assets.get_assets("Caches")
self.assertEqual(files, [])
assets.ui.add_asset()
files = assets.get_assets("Additional")
self.assertEqual(len(files), 1)
asset = files[0]
self.assertTrue(asset.included())
self.assertTrue(asset in asset.parent_list)
asset.exclude()
self.assertFalse(asset in asset.parent_list)
check_path = mock.Mock(path=mock_uimaya.file_select.return_value[0])
self.assertTrue(asset.is_duplicate([check_path]))
check_path.path = "/test_file"
self.assertFalse(asset.is_duplicate([check_path]))
asset.delete()
files = assets.get_assets("Additional")
self.assertEqual(len(files), 0)
self.assertEqual(len(assets.assets.pathmaps), 1)
assets.ui.add_asset()
files = assets.get_assets("Additional")
self.assertEqual(len(files), 1)
self.assertEqual(len(assets.assets.pathmaps), 2)
collected = assets.collect_assets([])
self.assertTrue(collected.get('assets'))
self.assertTrue(collected.get('pathmaps'))
decoded = collected.get('pathmaps')['PathMaps']
self.assertEqual(len(decoded), 1)
assets.ui.refresh()
files = assets.get_assets("Additional")
self.assertEqual(len(files), 0)
self.assertEqual(len(assets.assets.pathmaps), 0)
self.mock_self._assets = mock.create_autospec(Assets)
AzureBatchAssets.upload(self.mock_self)
if __name__ == '__main__':

Просмотреть файл

@ -1,337 +0,0 @@
#-------------------------------------------------------------------------
#
# Batch Apps Maya Plugin
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#--------------------------------------------------------------------------
import sys
import os
import logging
import json
try:
import unittest2 as unittest
except ImportError:
import unittest
try:
from unittest import mock
except ImportError:
import mock
from ui_environment import EnvironmentUI
from environment import BatchAppsEnvironment, BatchPlugin
class TestPlugin(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(BatchPlugin)
return super(TestPlugin, self).setUp()
@mock.patch.object(BatchPlugin, "create_checkbox")
def test_create(self, mock_checkbox):
plugin = BatchPlugin("base", "plugin", "False", [])
mock_checkbox.assert_called_with()
with self.assertRaises(AttributeError):
v = plugin.license_var
self.assertEqual(plugin.label, "plugin")
self.assertFalse(plugin.license)
self.assertFalse(plugin.supported)
plugin = BatchPlugin("base", "plugin", "False", [{"name":"My Plugin", "license":False}])
self.assertEqual(plugin.label, "My Plugin")
self.assertFalse(plugin.license)
self.assertTrue(plugin.supported)
self.assertEqual(plugin.license_var, {})
@mock.patch("environment.maya")
def test_create_checkbox(self, mock_maya):
self.mock_self.license = False
self.mock_self.base = mock.create_autospec(BatchAppsEnvironment)
self.mock_self.base.ui = mock.create_autospec(EnvironmentUI)
self.mock_self.base.ui.plugin_layout = "layout"
self.mock_self.supported = False
self.mock_self.label = "plugin"
self.mock_self.contents = []
BatchPlugin.create_checkbox(self.mock_self)
self.assertEqual(len(self.mock_self.contents), 2)
mock_maya.check_box.assert_called_with(label="Unsupported: plugin", value=False, onCommand=self.mock_self.include,
offCommand=self.mock_self.exclude, parent="layout", enable=False)
mock_maya.text.assert_called_with(label="", parent="layout")
self.mock_self.license = True
self.mock_self.contents = []
BatchPlugin.create_checkbox(self.mock_self)
self.assertEqual(len(self.mock_self.contents), 4)
@mock.patch("environment.maya")
def test_is_used(self, mock_maya):
used = ["plugin_A", "plugin_B"]
self.mock_self.base = mock.create_autospec(BatchAppsEnvironment)
self.mock_self.base.plugins = []
self.mock_self.base.warnings = []
self.mock_self.plugin = "plugin_C.py"
self.mock_self.label = "plugin"
self.mock_self.supported = False
self.mock_self.loaded = False
self.mock_self.license = False
self.mock_self.checkbox = "checkbox"
self.mock_self.license_check = "license"
BatchPlugin.is_used(self.mock_self, used)
self.assertFalse(self.mock_self.used)
self.assertEqual(self.mock_self.base.plugins, [])
self.assertEqual(self.mock_self.base.warnings, [])
self.mock_self.loaded = True
BatchPlugin.is_used(self.mock_self, used)
self.assertFalse(self.mock_self.used)
self.assertEqual(self.mock_self.base.plugins, [])
self.assertEqual(self.mock_self.base.warnings, [])
self.mock_self.plugin = "plugin_A.py"
BatchPlugin.is_used(self.mock_self, used)
self.assertTrue(self.mock_self.used)
self.assertEqual(mock_maya.check_box.call_count, 0)
self.assertEqual(self.mock_self.base.plugins, [])
self.assertEqual(self.mock_self.base.warnings, ["plugin_A.py"])
self.mock_self.supported = True
self.mock_self.base.warnings = []
BatchPlugin.is_used(self.mock_self, used)
self.assertTrue(self.mock_self.used)
mock_maya.check_box.assert_called_with("checkbox", edit=True, value=True)
self.assertEqual(self.mock_self.base.plugins, ["plugin"])
self.assertEqual(self.mock_self.base.warnings, [])
self.mock_self.license = True
BatchPlugin.is_used(self.mock_self, used)
mock_maya.check_box.assert_called_with("license", edit=True, enable=True)
@mock.patch("environment.maya")
def test_use_license(self, mock_maya):
self.mock_self.license = False
self.mock_self.custom_license_endp = "endp"
self.mock_self.custom_license_port = "port"
BatchPlugin.use_license(self.mock_self, True)
self.assertEqual(mock_maya.text_field.call_count, 0)
self.mock_self.license = True
BatchPlugin.use_license(self.mock_self, True)
self.assertEqual(mock_maya.text_field.call_count, 2)
mock_maya.text_field.assert_called_with("port", edit=True, enable=True)
@mock.patch("environment.maya")
def test_include(self, mock_maya):
self.mock_self.base = mock.create_autospec(BatchAppsEnvironment)
self.mock_self.base.plugins = []
self.mock_self.label = "My Plugin"
self.mock_self.license = False
self.mock_self.license_check = "check"
BatchPlugin.include(self.mock_self)
self.assertEqual(self.mock_self.base.plugins, ["My Plugin"])
self.assertEqual(mock_maya.check_box.call_count, 0)
self.mock_self.license = True
BatchPlugin.include(self.mock_self)
self.assertEqual(self.mock_self.base.plugins, ["My Plugin", "My Plugin"])
mock_maya.check_box.assert_called_with("check", edit=True, enable=True)
@mock.patch("environment.maya")
def test_exclude(self, mock_maya):
self.mock_self.base = mock.create_autospec(BatchAppsEnvironment)
self.mock_self.base.plugins = ["My Plugin"]
self.mock_self.label = "My Plugin"
self.mock_self.license = False
self.mock_self.license_check = "check"
self.mock_self.used = False
BatchPlugin.exclude(self.mock_self)
self.assertEqual(mock_maya.warning.call_count, 0)
self.assertEqual(mock_maya.check_box.call_count, 0)
self.assertEqual(self.mock_self.base.plugins, [])
self.mock_self.license = True
BatchPlugin.exclude(self.mock_self)
self.assertEqual(mock_maya.warning.call_count, 0)
mock_maya.check_box.assert_called_with("check", edit=True, enable=False)
self.assertEqual(self.mock_self.base.plugins, [])
self.mock_self.used = True
BatchPlugin.exclude(self.mock_self)
mock_maya.warning.assert_called_with(mock.ANY)
@mock.patch("environment.maya")
def test_delete(self, mock_maya):
self.mock_self.contents = ["a"]
BatchPlugin.delete(self.mock_self)
mock_maya.delete_ui.assert_called_with("a", control=True)
@mock.patch("environment.maya")
def test_get_vaiables(self, mock_maya):
mock_maya.check_box.return_value = True
self.mock_self.license = False
self.mock_self.license_check = "check"
self.mock_self.license_var = {"key":"solidangle_LICENSE", "value":"{port}@{host}"}
self.mock_self.custom_license_endp = "host"
self.mock_self.custom_license_port = "port"
vars = BatchPlugin.get_variables(self.mock_self)
self.assertEqual(vars, {})
self.assertEqual(mock_maya.text_field.call_count, 0)
self.mock_self.license = True
mock_maya.text_field.return_value = "blah"
vars = BatchPlugin.get_variables(self.mock_self)
self.assertEqual(vars, {"solidangle_LICENSE":"blah@blah"})
self.assertEqual(mock_maya.text_field.call_count, 2)
class TestBatchAppsEnvironment(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(BatchAppsEnvironment)
self.mock_self._log = logging.getLogger("TestEnvironment")
self.mock_self._server_plugins = []
self.mock_self.warnings = []
self.mock_self._plugins = []
self.mock_self._version = "2017"
return super(TestBatchAppsEnvironment, self).setUp()
@mock.patch.object(BatchAppsEnvironment, "refresh")
@mock.patch("environment.EnvironmentUI")
@mock.patch("environment.callback")
def test_create(self, mock_call, mock_ui, mock_refresh):
env = BatchAppsEnvironment("frame", "call")
mock_ui.assert_called_with(env, "frame", ["Maya I/O PR55"])
mock_call.after_new.assert_called_with(mock.ANY)
mock_call.after_read.assert_called_with(mock.ANY)
mock_refresh.assert_called_with()
self.assertEqual(env.plugins, [])
self.assertEqual(env.version, "2017")
lic = env.license
env.ui.get_license_server.assert_called_with()
vars = env.environment_variables
env.ui.get_env_vars.assert_called_with()
def test_configure(self):
BatchAppsEnvironment.configure(self.mock_self, "session")
self.assertEqual(self.mock_self._session, "session")
@mock.patch("environment.BatchPlugin")
@mock.patch("environment.maya")
def test_get_plugins(self, mock_maya, mock_plugin):
mock_maya.plugins.return_value = ["mtoa.mll", "b", "c"]
self.mock_self.search_for_plugins.return_value = ["Mayatomr.mll", "mtoa.mll", "c", "d", "e"]
mock_plugin.return_value = mock.create_autospec(BatchPlugin)
plugins = BatchAppsEnvironment.get_plugins(self.mock_self)
mock_maya.plugins.assert_any_call('e', query=True, loaded=True)
self.mock_self.search_for_plugins.assert_called_with()
mock_plugin.assert_any_call(mock.ANY, "mtoa.mll", ["mtoa.mll", "b", "c"],
[{"name": "Arnold", "plugin": "mtoa.", "license": True, "license_var": {"key":"solidangle_LICENSE", "value":"{port}@{host}"}}])
mock_plugin.assert_any_call(mock.ANY, "e", ["mtoa.mll", "b", "c"], [])
mock_plugin.assert_any_call(mock.ANY, "Mayatomr.mll", ["mtoa.mll", "b", "c"],
[{"name": "MentalRay", "plugin": "Mayatomr.", "license": False}])
mock_plugin.return_value.is_used.assert_called_with(["mtoa.mll", "b", "c"])
self.assertEqual(len(plugins), 5)
self.mock_self.warnings = ["a","b","c"]
plugins = BatchAppsEnvironment.get_plugins(self.mock_self)
mock_maya.warning.assert_called_with("The following plug-ins are used in the scene, but not yet supported.\nRendering may be affected.\na\nb\nc\n")
@mock.patch("environment.os")
def test_search_for_plugins(self, mock_os):
self.mock_self.is_default = lambda a: BatchAppsEnvironment.is_default(self.mock_self, a)
mock_os.path.splitext = os.path.splitext
mock_os.environ = {"MAYA_PLUG_IN_PATH":"dir1;dir2;dir3"}
mock_os.pathsep = ';'
mock_os.path.isdir.return_value = True
mock_os.listdir.return_value = ["a","b","test.mll","test.mll","plugin.py", "xgenMR.py", "fbxmaya.mll"]
plugins = BatchAppsEnvironment.search_for_plugins(self.mock_self)
self.assertEqual(sorted(plugins), sorted(["test.mll", "plugin.py"]))
def test_set_version(self):
BatchAppsEnvironment.set_version(self.mock_self, "Maya 2015")
self.assertEqual(self.mock_self._version, "2017")
BatchAppsEnvironment.set_version(self.mock_self, "test")
self.assertEqual(self.mock_self._version, "2017")
def test_refresh(self):
self.mock_self._server_plugins = [1,2,3]
self.mock_self.warnings = [4,5,6]
mock_plugin = mock.create_autospec(BatchPlugin)
self.mock_self._plugins = [mock_plugin]
BatchAppsEnvironment.refresh(self.mock_self)
self.assertEqual(self.mock_self._server_plugins, [])
self.assertEqual(self.mock_self.warnings, [])
self.mock_self.get_plugins.assert_called_with()
mock_plugin.delete.assert_called_with()
class TestEnvironmentCombined(unittest.TestCase):
@mock.patch("ui_environment.utils")
@mock.patch("ui_environment.maya")
@mock.patch("environment.callback")
@mock.patch("environment.maya")
def test_environment(self, *args):
os.environ["MAYA_PLUG_IN_PATH"] = os.path.join(os.path.dirname(__file__), "data", "modules")
def add_tab(tab):
self.assertFalse(tab.ready)
def call(func, *args, **kwargs):
self.assertTrue(hasattr(func, '__call__'))
return func(*args, **kwargs)
layout = mock.Mock(add_tab=add_tab)
env = BatchAppsEnvironment(layout, call)
env.configure("session")
self.assertEqual(env.plugins, [])
if __name__ == '__main__':
unittest.main()

Просмотреть файл

@ -1,510 +0,0 @@
#-------------------------------------------------------------------------
#
# Batch Apps Maya Plugin
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#--------------------------------------------------------------------------
import sys
import os
import logging
import datetime
try:
import unittest2 as unittest
except ImportError:
import unittest
try:
from unittest import mock
except ImportError:
import mock
from ui_history import HistoryUI, BatchAppsJobInfo
from history import BatchAppsHistory
from batchapps import JobManager, Configuration, Credentials
from batchapps.job import SubmittedJob, JobSubmission, Task
from batchapps.exceptions import FileDownloadException
from utils import ProcButton
class TestBatchAppsHistory(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(BatchAppsHistory)
self.mock_self._log = logging.getLogger("TestHistory")
self.mock_self.index = 0
self.mock_self.per_call = 5
self.mock_self.min = True
self.mock_self.max = False
return super(TestBatchAppsHistory, self).setUp()
@mock.patch("history.HistoryUI")
def test_create_batchappshistory(self, mock_ui):
history = BatchAppsHistory("frame", "call")
mock_ui.assert_called_with(history, "frame")
@mock.patch("history.JobManager")
def test_configure(self, mock_mgr):
session = mock.Mock(credentials="creds", config="conf")
BatchAppsHistory.configure(self.mock_self, session)
mock_mgr.assert_called_with("creds", "conf")
self.assertEqual(session, self.mock_self._session)
def test_get_history(self):
mgr = mock.create_autospec(JobManager)
mgr.get_jobs.return_value = [mock.Mock(name="test_job")]
mgr.__len__.return_value = 1
def call(func, arg_a, arg_b):
self.assertEqual(func, mgr.get_jobs)
self.assertEqual(arg_a, 0)
self.assertEqual(arg_b, 5)
return func()
self.mock_self.manager = mgr
self.mock_self._call = call
self.mock_self.ui = mock.create_autospec(HistoryUI)
self.mock_self.ui.create_job_entry.return_value = "job_entry"
displayed = BatchAppsHistory.get_history(self.mock_self)
self.assertEqual(displayed, ["job_entry"])
self.assertEqual(len(self.mock_self.jobs), 1)
def test_set_num_jobs(self):
self.mock_self.ui = mock.create_autospec(HistoryUI)
self.mock_self.count = 8
BatchAppsHistory.set_num_jobs(self.mock_self)
self.assertEqual(self.mock_self.ui.num_jobs, "1 - 5 of 8")
self.mock_self.count = 3
BatchAppsHistory.set_num_jobs(self.mock_self)
self.assertEqual(self.mock_self.ui.num_jobs, "1 - 3 of 3")
self.mock_self.index = 5
BatchAppsHistory.set_num_jobs(self.mock_self)
self.assertEqual(self.mock_self.ui.num_jobs, "3 - 3 of 3")
self.mock_self.count = 20
BatchAppsHistory.set_num_jobs(self.mock_self)
self.assertEqual(self.mock_self.ui.num_jobs, "6 - 10 of 20")
def test_set_min_max(self):
self.mock_self.ui = mock.create_autospec(HistoryUI)
self.mock_self.count = 4
BatchAppsHistory.set_min_max(self.mock_self)
self.assertTrue(self.mock_self.min)
self.assertTrue(self.mock_self.max)
self.mock_self.index = 2
BatchAppsHistory.set_min_max(self.mock_self)
self.assertTrue(self.mock_self.max)
self.assertFalse(self.mock_self.min)
self.mock_self.count = 20
BatchAppsHistory.set_min_max(self.mock_self)
self.assertFalse(self.mock_self.max)
self.assertFalse(self.mock_self.min)
self.mock_self.count = 5
BatchAppsHistory.set_min_max(self.mock_self)
self.assertTrue(self.mock_self.max)
self.assertFalse(self.mock_self.min)
self.mock_self.count = 6
BatchAppsHistory.set_min_max(self.mock_self)
self.assertFalse(self.mock_self.max)
self.assertFalse(self.mock_self.min)
def test_next_jobs(self):
self.mock_self.count = 12
BatchAppsHistory.show_next_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 5)
BatchAppsHistory.show_next_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 10)
BatchAppsHistory.show_next_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 12)
def test_prev_jobs(self):
self.mock_self.count = 9
BatchAppsHistory.show_prev_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 0)
self.mock_self.index = 4
BatchAppsHistory.show_prev_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 0)
self.mock_self.index = 8
BatchAppsHistory.show_prev_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 3)
def test_first_jobs(self):
BatchAppsHistory.show_first_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 0)
self.mock_self.index = 8
BatchAppsHistory.show_first_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 0)
def test_last_jobs(self):
self.mock_self.count = 11
BatchAppsHistory.show_last_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 10)
self.mock_self.count = 15
BatchAppsHistory.show_last_jobs(self.mock_self)
self.assertEqual(self.mock_self.index, 10)
def test_job_selected(self):
ui_job = mock.create_autospec(BatchAppsJobInfo)
ui_job.index = 0
self.mock_self.selected_job = None
BatchAppsHistory.job_selected(self.mock_self, None)
BatchAppsHistory.job_selected(self.mock_self, ui_job)
self.assertEqual(self.mock_self.selected_job, ui_job)
self.mock_self.update_job.assert_called_with(0)
BatchAppsHistory.job_selected(self.mock_self, ui_job)
ui_job.collapse.assert_called_with()
self.mock_self.selected_job = None
self.mock_self.jobs = []
BatchAppsHistory.job_selected(self.mock_self, ui_job)
ui_job.collapse.assert_called_with()
@mock.patch("history.maya")
def test_update_job(self, mock_maya):
job = mock.create_autospec(SubmittedJob)
job.status = "Running"
job.percentage = "10%"
job.time_submitted = "today"
job.number_tasks = "500"
job.id = "12345"
job.pool_id = "67890"
job.name = "Test Job"
self.mock_self.jobs = [job]
ui_job = mock.create_autospec(BatchAppsJobInfo)
ui_job.index = 0
self.mock_self.selected_job = ui_job
def call(func):
self.assertTrue(hasattr(func, '__call__'))
self.mock_self._call = call
BatchAppsHistory.update_job(self.mock_self, 0)
ui_job.set_thumbnail.assert_called_with(os.path.join(
os.environ["BATCHAPPS_ICONS"], "loading_preview.png"), 24)
ui_job.set_status.assert_called_with("Running")
def test_get_thumb(self):
job = mock.create_autospec(SubmittedJob)
job.status = "Running"
job.get_tasks.return_value = [1,2,3]
self.mock_self.jobs = [job]
ui_job = mock.create_autospec(BatchAppsJobInfo)
ui_job.index = 0
def call(func):
self.assertTrue(hasattr(func, '__call__'))
return func()
self.mock_self._call = call
self.mock_self.selected_job = ui_job
BatchAppsHistory.get_thumb(self.mock_self)
self.mock_self.get_task_thumb.assert_called_with(job, [1,2,3])
job.status = "Complete"
BatchAppsHistory.get_thumb(self.mock_self)
self.mock_self.get_job_thumb.assert_called_with(job)
self.mock_self.jobs = []
BatchAppsHistory.get_thumb(self.mock_self)
ui_job.set_thumbnail.assert_called_with(os.path.join(os.environ["BATCHAPPS_ICONS"], "no_preview.png"), 24)
self.mock_self.selected_job = None
BatchAppsHistory.get_thumb(self.mock_self)
@mock.patch("history.glob")
@mock.patch("history.maya")
def test_task_thumb(self, mock_maya, mock_glob):
star = os.path.join(os.path.dirname(__file__), "data", "star.png")
mock_glob.glob.return_value = []
job = mock.create_autospec(SubmittedJob)
job.id = "12345"
task1 = mock.create_autospec(Task)
task1.id = "abc"
task1.get_thumbnail.side_effect = FileDownloadException("Broken!")
task2 = mock.create_autospec(Task)
task2.id = "abc"
task2.get_thumbnail.return_value = star
def call(func, dir, thumb, over):
self.assertTrue(hasattr(func, '__call__'))
self.assertTrue(over)
self.assertTrue(thumb.startswith("12345.abc"))
return func()
self.mock_self.temp_name = lambda a: BatchAppsHistory.temp_name(self.mock_self, a)
self.mock_self._call = call
self.mock_self.selected_job = mock.create_autospec(BatchAppsJobInfo)
BatchAppsHistory.get_task_thumb(self.mock_self, job, [task2, task1])
self.mock_self.selected_job.set_thumbnail.assert_called_with(star, mock.ANY)
mock_glob.glob.assert_called_with(mock.ANY)
self.assertEqual(task2.get_thumbnail.call_count, 1)
task2.get_thumbnail.call_count = 0
mock_glob.glob.return_value = [star]
BatchAppsHistory.get_task_thumb(self.mock_self, job, [task2, task1])
self.assertEqual(task2.get_thumbnail.call_count, 0)
mock_glob.glob.return_value = []
task2.get_thumbnail.side_effect = FileDownloadException("Broken!")
BatchAppsHistory.get_task_thumb(self.mock_self, job, [task2, task1])
self.mock_self.selected_job.set_thumbnail.assert_called_with(
os.path.join(os.environ["BATCHAPPS_ICONS"], "no_preview.png"), mock.ANY)
@mock.patch("history.glob")
@mock.patch("history.maya")
def test_job_thumb(self, mock_maya, mock_glob):
star = os.path.join(os.path.dirname(__file__), "data", "star.png")
mock_glob.glob.return_value = []
job = mock.create_autospec(SubmittedJob)
job.id = "12345"
job.get_thumbnail.side_effect = FileDownloadException("Broken!")
def call(func, dir, thumb, over):
self.assertTrue(hasattr(func, '__call__'))
self.assertTrue(over)
self.assertTrue(thumb.startswith("12345.job."))
return func()
self.mock_self.temp_name = lambda a: BatchAppsHistory.temp_name(self.mock_self, a)
self.mock_self._call = call
self.mock_self.selected_job = mock.create_autospec(BatchAppsJobInfo)
BatchAppsHistory.get_job_thumb(self.mock_self, job)
self.mock_self.selected_job.set_thumbnail.assert_called_with(
os.path.join(os.environ["BATCHAPPS_ICONS"], "no_preview.png"), mock.ANY)
job.get_thumbnail.call_count = 0
mock_glob.glob.return_value = [star]
BatchAppsHistory.get_job_thumb(self.mock_self, job)
self.mock_self.selected_job.set_thumbnail.assert_called_with(star, mock.ANY)
self.assertEqual(job.get_thumbnail.call_count, 0)
mock_glob.glob.return_value = []
job.get_thumbnail.side_effect = None
job.get_thumbnail.return_value = star
BatchAppsHistory.get_job_thumb(self.mock_self, job)
self.mock_self.selected_job.set_thumbnail.assert_called_with(star, mock.ANY)
self.assertEqual(job.get_thumbnail.call_count, 1)
def test_cancel_job(self):
job = mock.create_autospec(SubmittedJob)
job.cancel.return_value = True
def call(func):
self.assertTrue(hasattr(func, '__call__'))
return func()
self.mock_self.jobs = [job]
self.mock_self._call = call
self.mock_self.selected_job = mock.create_autospec(BatchAppsJobInfo)
self.mock_self.selected_job.index = 0
BatchAppsHistory.cancel_job(self.mock_self)
job.cancel.assert_called_with()
job.cancel.call_count = 0
self.mock_self.jobs = []
BatchAppsHistory.cancel_job(self.mock_self)
self.assertEqual(job.cancel.call_count, 0)
@mock.patch("history.os")
@mock.patch("history.tempfile")
@mock.patch("history.shutil")
@mock.patch("history.maya")
def test_download_output(self, mock_maya, mock_util, mock_temp, mock_os):
data_dir = os.path.join(os.path.dirname(__file__), "data")
mock_temp.mkdtemp.return_value = data_dir
mock_os.path.exists.return_value = False
selected_file = os.path.join(os.path.dirname(__file__), "my_output.zip")
job = mock.create_autospec(SubmittedJob)
def call(func, dir, overwrite):
self.assertTrue(hasattr(func, '__call__'))
self.assertEqual(dir, data_dir)
self.assertTrue(overwrite)
func(dir, overwrite)
return os.path.join(data_dir, "output.zip")
self.mock_self.ui = mock.create_autospec(HistoryUI)
self.mock_self.ui.refresh_button = mock.create_autospec(ProcButton)
self.mock_self.jobs = [job]
self.mock_self._call = call
self.mock_self.selected_job = mock.create_autospec(BatchAppsJobInfo)
self.mock_self.selected_job.index = 0
BatchAppsHistory.download_output(self.mock_self, selected_file)
job.get_output.assert_called_with(data_dir, overwrite=True, callback=mock.ANY, block=100000)
job.get_output.side_effect = FileDownloadException("Failed!")
BatchAppsHistory.download_output(self.mock_self, selected_file)
self.mock_self.ui.refresh_button.finish.assert_called_with()
job.get_output.call_count = 0
job.get_output.side_effect = None
mock_os.path.exists.return_value = True
BatchAppsHistory.download_output(self.mock_self, selected_file)
mock_os.remove.assert_called_with(selected_file)
mock_util.move_assert_called_with(os.path.join(data_dir, "output.zip"), selected_file)
mock_util.rmtree.assert_called_with(data_dir)
mock_os.remove.side_effect = EnvironmentError("Couldn't delete...")
BatchAppsHistory.download_output(self.mock_self, selected_file)
self.mock_self.ui.refresh_button.finish.assert_called_with()
self.assertEqual(job.get_output.call_count, 1)
mock_util.rmtree.side_effect = Exception("Couldn't move to new location")
BatchAppsHistory.download_output(self.mock_self, selected_file)
self.mock_self.ui.refresh_button.finish.assert_called_with()
mock_util.rmtree.assert_called_with(data_dir)
def test_image_height(self):
image = os.path.join(os.path.dirname(__file__), "data", "star.png")
height = BatchAppsHistory.get_image_height(self.mock_self, image)
self.assertEqual(height, 405)
class TestHistoryCombined(unittest.TestCase):
@mock.patch("ui_history.utils")
@mock.patch("ui_history.maya")
@mock.patch("history.maya")
def test_history(self, *args):
def add_tab(tab):
self.assertFalse(tab.ready)
def call(func, *args, **kwargs):
self.assertTrue(hasattr(func, '__call__'))
return func(*args, **kwargs)
layout = mock.Mock(add_tab=add_tab)
history = BatchAppsHistory(layout, call)
creds = mock.create_autospec(Credentials)
conf = mock.create_autospec(Configuration)
session = mock.Mock(credentials=creds, config=conf)
history.configure(session)
history.manager = mock.create_autospec(JobManager)
job1 = mock.create_autospec(SubmittedJob)
job1.name = "Job1"
job1.status = "Complete"
job1.percentage = "100%"
job1.time_submitted = str(datetime.datetime.now()).replace(' ', 'T')
job1.number_tasks = "10"
job1.id = "12345"
job1.pool_id = "pool"
job2 = mock.create_autospec(SubmittedJob)
job2.name = "Job2"
history.manager.get_jobs.return_value = [job1, job2]
history.manager.__len__.return_value = 2
history.ui.prepare()
self.assertTrue(history.ui.ready)
self.assertTrue(history.min)
self.assertTrue(history.max)
history.ui.show_next_jobs()
self.assertEqual(history.index, 2)
self.assertFalse(history.min)
self.assertTrue(history.max)
history.ui.show_last_jobs()
self.assertEqual(history.index, 0)
self.assertTrue(history.min)
self.assertTrue(history.max)
history.ui.show_prev_jobs()
self.assertEqual(history.index, 0)
self.assertTrue(history.min)
self.assertTrue(history.max)
history.ui.show_first_jobs()
self.assertEqual(history.index, 0)
self.assertTrue(history.min)
self.assertTrue(history.max)
history.ui.jobs_displayed[0].on_expand()
self.assertEqual(history.ui.jobs_displayed[0], history.selected_job)
history.selected_job.collapse()
self.assertIsNone(history.selected_job)
history.ui.jobs_displayed[1].on_expand()
self.assertIsNone(history.selected_job)
mock_maya = args[1]
mock_maya.file_select.return_value = os.path.join(os.path.dirname(__file__), "data", "my_output.zip")
history.ui.jobs_displayed[0].download_output()
self.assertEqual(job1.get_output.call_count, 0)
history.ui.jobs_displayed[0].on_expand()
history.ui.jobs_displayed[0].download_output()
self.assertEqual(job1.get_output.call_count, 1)

Просмотреть файл

@ -8,223 +8,70 @@ try:
except ImportError:
import mock
import os, sys
import os
import sys
from collections import namedtuple
from batch_extensions import models
from batchapps import (
JobManager,
Configuration)
from batchapps.job import (
SubmittedJob,
Task,
JobSubmission)
from batchapps.exceptions import (
RestCallException,
AuthenticationException,
InvalidConfigException)
CWD = os.path.dirname(os.path.abspath(__file__))
top_dir = os.path.dirname(CWD)
src_dir = os.path.join(top_dir, 'azure_batch_maya', 'scripts')
tools_dir = os.path.join(src_dir, 'tools')
sys.path.extend([src_dir, tools_dir])
with mock.patch.object(sys, "argv"):
import job_watcher as client
class TestBlob(object):
def __init__(self, name):
self.name = name
self.properties = object
class TestJobWatcher(unittest.TestCase):
def setUp(self):
self.cwd = os.path.dirname(os.path.abspath(__file__))
return super(TestJobWatcher, self).setUp()
def test_check_valid_dir(self):
def test_watcher_check_valid_dir(self):
with self.assertRaises(RuntimeError):
client._check_valid_dir(None)
with self.assertRaises(RuntimeError):
client._check_valid_dir("test")
client._check_valid_dir("//test")
with self.assertRaises(RuntimeError):
client._check_valid_dir(1)
self.assertEqual(client._check_valid_dir(CWD), CWD)
self.assertEqual(client._check_valid_dir(self.cwd), self.cwd)
@mock.patch.object(client, 'storage_client')
@mock.patch.object(client, '_download_output')
def test_watcher_track_completed_outputs(self, mock_download, mock_storage):
blob = namedtuple("Blob", "name, properties")
mock_storage.list_blobs.return_value = [
blob("job_output.exr", mock.Mock(content_length=1)),
blob("subdir/job_output.png", mock.Mock(content_length=1)),
blob("thumbs/0.png", mock.Mock(content_length=1)),
blob("logs/frame_0.log", mock.Mock(content_length=1)),
blob("logs/frame_0_error.log", mock.Mock(content_length=1))]
@mock.patch.object(client, "_check_valid_dir")
@mock.patch('job_watcher.os')
def test_download_tasks_outputs(self, mock_os, mock_check_valid_dir):
client._download_task_outputs(None, [], None)
self.assertFalse(mock_os.path.join.called, "Output list is empty")
mock_task = mock.create_autospec(Task)
mock_outputs = [{'type': 'TaskOutput', 'name': 'test.png'}]
mock_check_valid_dir.return_value = "test_dir"
mock_os.path.isfile.return_value = False
client._download_task_outputs(mock_task, mock_outputs, "test_dir")
mock_os.path.join.assert_called_with("test_dir", "test.png")
mock_task.get_output.assert_called_with({'type': 'TaskOutput', 'name': 'test.png'}, "test_dir",
callback=mock.ANY, block=100000)
@mock.patch.object(client, '_download_task_outputs')
def test_track_completed_tasks(self, mock_download_task_outputs):
mock_job = mock.create_autospec(SubmittedJob)
mock_job.get_tasks.side_effect = RestCallException("RestCallException", "RestCallExceptionRaised", None)
client._track_completed_outputs("container", "\\test_dir")
mock_storage.list_blobs.assert_called_with("container")
self.assertEqual(mock_download.call_count, 4)
mock_download.assert_any_call('container', 'job_output.exr', '\\test_dir\\job_output.exr', 1)
mock_download.assert_any_call('container', 'subdir/job_output.png', '\\test_dir\\subdir\\job_output.png', 1)
mock_download.assert_any_call('container', 'logs/frame_0.log', '\\test_dir\\logs\\frame_0.log', 1)
mock_download.assert_any_call('container', 'logs/frame_0_error.log', '\\test_dir\\logs\\frame_0_error.log', 1)
def test_watcher_check_job_stopped(self):
mock_job = mock.create_autospec(models.CloudJob)
with self.assertRaises(RuntimeError):
client._track_completed_tasks(mock_job, "test_dir")
mock_job.get_tasks.side_effect = None
mock_job.get_tasks.return_value = [1, 2, 3]
with self.assertRaises(RuntimeError):
client._track_completed_tasks(mock_job, "test_dir")
mock_task1 = mock.create_autospec(Task)
mock_task1.status = "Complete"
mock_task1.id = 1
mock_task1.outputs = []
mock_task2 = mock.create_autospec(Task)
mock_task2.status = "Complete"
mock_task2.id = 2
mock_task2.outputs = []
mock_job.number_tasks = 3
mock_job.get_tasks.return_value = [mock_task1, mock_task2]
client._track_completed_tasks(mock_job, "test_dir")
def test_retrieve_logs(self):
mock_job = mock.create_autospec(SubmittedJob)
client._retrieve_logs(mock_job)
mock_job.get_logs.side_effect = RestCallException("RestCallException", "RestCalleExceptionRaised", None)
with self.assertRaises(RuntimeError):
client._retrieve_logs(mock_job)
mock_job.get_logs.side_effect = None
mock_job.get_logs.return_value = {}
self.assertIsNone(client._retrieve_logs(mock_job))
mock_job.get_logs.return_value = {'upTo': None}
with self.assertRaises(RuntimeError):
client._retrieve_logs(mock_job)
mock_job.get_logs.return_value = {'upTo': None,
'messages': [{'timestamp': '1800-09-23bla',
'text': 'This is a test message',
'taskId': 2}]}
self.assertTrue(mock_job.get_logs()['messages'])
@mock.patch.object(client, "_retrieve_logs")
def test_check_job_stopped(self, mock_retrieve_logs):
mock_job = mock.create_autospec(SubmittedJob)
client._check_job_stopped(mock_job)
mock_job.state = "test"
with self.assertRaises(RuntimeError):
client._check_job_stopped(mock_job)
mock_job.status = "test"
client._check_job_stopped(mock_job)
mock_job.status = "Error"
with self.assertRaises(RuntimeError):
client._check_job_stopped(mock_job)
self.assertTrue(mock_retrieve_logs.called)
mock_job.status = "OnHold"
mock_job.state = models.JobState.disabled
with self.assertRaises(RuntimeError):
client._check_job_stopped(mock_job)
mock_job.status = "Complete"
mock_job.state = models.JobState.completed
self.assertTrue(client._check_job_stopped(mock_job))
mock_job.status = "NotStarted"
mock_job.state = models.JobState.active
self.assertFalse(client._check_job_stopped(mock_job))
mock_job.status = "InProgress"
self.assertFalse(client._check_job_stopped(mock_job))
@mock.patch.object(client, "_check_job_stopped")
@mock.patch.object(client, "_track_completed_tasks")
def test_track_job_progress(self, mock_track_completed_tasks, mock_check_job_stopped):
mock_job_manager = mock.create_autospec(JobManager)
mock_id = "test_id"
mock_dwnld_dir = "test_dir"
mock_job = mock.create_autospec(SubmittedJob)
mock_job.status = "test"
mock_job_manager.get_job.return_value = mock_job
with self.assertRaises(RuntimeError):
client.track_job_progress(mock_job_manager, mock_id, mock_dwnld_dir)
mock_job.status = "Error"
mock_job.percentage = "30"
mock_check_job_stopped.side_effect = RuntimeError("RuntimeError", "RuntimeError raised", None)
with self.assertRaises(RuntimeError):
client.track_job_progress(mock_job_manager, mock_id, mock_dwnld_dir)
mock_job.status = "InProgress"
mock_check_job_stopped.side_effect = [False, True]
self.assertFalse(client.track_job_progress(mock_job_manager, mock_id, mock_dwnld_dir))
self.assertEqual(mock_job.update.call_count, 1)
mock_job.status = "Complete"
mock_check_job_stopped.side_effect = None
self.assertIsNone(client.track_job_progress(mock_job_manager, mock_id, mock_dwnld_dir), "track_job_progress returned None unexpectedly.")
@mock.patch("job_watcher.webbrowser")
@mock.patch("job_watcher.AzureOAuth")
def test_authentication(self, mock_azureoauth, mock_webbrowser):
mock_azureoauth.get_unattended_session.return_value = "Auth"
auth = client.authentication("test")
self.assertEqual("Auth", auth)
self.assertFalse(mock_azureoauth.get_session.called)
mock_azureoauth.get_unattended_session.side_effect = InvalidConfigException("InvalidConfigException", "InvalidConfigException raised", None)
client.authentication("test")
self.assertTrue(mock_azureoauth.get_session.called)
mock_azureoauth.get_session.return_value = "Done!"
auth = client.authentication("test")
self.assertEqual("Done!", auth)
mock_azureoauth.get_session.called_with(config="test")
mock_azureoauth.get_session.side_effect = InvalidConfigException("InvalidConfigException", "InvalidConfigException raised", None)
with self.assertRaises(RuntimeError):
client.authentication("test")
mock_azureoauth.get_authorization_token.side_effect = InvalidConfigException("InvalidConfigException", "InvalidConfigExceptio Raised", None)
with self.assertRaises(RuntimeError):
client.authentication("test")
mock_azureoauth.get_session.side_effect = AuthenticationException("AuthenticationException", "AuthenticationException raised", None)
@mock.patch("job_watcher.Configuration")
def test_generate_config(self, mock_cfg):
mock_data_path = "test"
with self.assertRaises(EnvironmentError):
client.generate_config(mock_data_path)
mock_cfg.side_effect = InvalidConfigException("InvalidConfigException", "InvalidConfigException Raised", None)
mock_data_path = os.path.dirname(os.path.normpath(__file__))
with self.assertRaises(ValueError):
client.generate_config(mock_data_path)
mock_cfg.side_effect = None
self.assertEqual(client.generate_config(mock_data_path), mock_cfg())

Просмотреть файл

@ -1,6 +1,6 @@
#-------------------------------------------------------------------------
#
# Batch Apps Maya Plugin
# Azure Batch Maya Plugin
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
@ -44,6 +44,7 @@ except ImportError:
from ui_pools import PoolsUI, AzureBatchPoolInfo
from pools import AzureBatchPools
from environment import AzureBatchEnvironment
import batch_extensions as batch
from batch_extensions import models
@ -53,6 +54,9 @@ class AzureTestBatchPools(unittest.TestCase):
def setUp(self):
self.mock_self = mock.create_autospec(AzureBatchPools)
self.mock_self._log = logging.getLogger("TestPools")
self.mock_self.batch = mock.create_autospec(batch.BatchExtensionsClient)
self.mock_self.batch.pool = mock.create_autospec(batch.operations.ExtendedPoolOperations)
self.mock_self.environment = mock.create_autospec(AzureBatchEnvironment)
return super(AzureTestBatchPools, self).setUp()
@mock.patch("pools.PoolsUI")
@ -62,7 +66,7 @@ class AzureTestBatchPools(unittest.TestCase):
def test_pools_configure(self):
session = mock.Mock(batch="batch")
AzureBatchPools.configure(self.mock_self, session)
AzureBatchPools.configure(self.mock_self, session, "env_manager")
self.assertEqual("batch", self.mock_self.batch)
def test_pools_list_pools(self):
@ -77,7 +81,13 @@ class AzureTestBatchPools(unittest.TestCase):
self.mock_self._call = lambda x: [pool1, pool2]
ids = AzureBatchPools.list_pools(self.mock_self)
self.assertEqual(ids, ['67890', '12345'])
self.assertEqual(ids, [])
self.assertEqual(len(self.mock_self.pools), 0)
pool1.id = "Maya_Pool_A"
pool2.id = "Maya_Auto_Pool_B"
ids = AzureBatchPools.list_pools(self.mock_self)
self.assertEqual(ids, ["Maya_Pool_A"])
self.assertEqual(len(self.mock_self.pools), 2)
def test_pools_get_pools(self):
@ -111,6 +121,7 @@ class AzureTestBatchPools(unittest.TestCase):
self.mock_self.batch.pool = mock.Mock(get="get")
self.mock_self.batch.compute_node = mock.Mock(list="list")
pool = mock.create_autospec(models.CloudPool)
pool.application_licenses = ["maya", "arnold"]
pool.display_name = "name"
pool.current_dedicated_nodes = 3
pool.target_dedicated_nodes = 5
@ -119,6 +130,7 @@ class AzureTestBatchPools(unittest.TestCase):
pool.max_tasks_per_node = 1
pool.allocation_state = mock.Mock(value="allocating")
pool.creation_time = datetime.datetime.now()
pool.vm_size = "Standard_A1"
self.mock_self.pools = [pool]
pool_ui = mock.create_autospec(AzureBatchPoolInfo)
pool_ui.index = 0
@ -144,177 +156,99 @@ class AzureTestBatchPools(unittest.TestCase):
def test_pools_auto_pool(self):
self.mock_self.pools = [mock.Mock(id='Maya_Pool_123'), mock.Mock(id='Maya_Auto_Pool_123')]
self.mock_self.selected_pool = mock.Mock(index=0)
self.mock_self.selected_pool = mock.Mock(index=1)
self.assertTrue(AzureBatchPools.is_auto_pool(self.mock_self))
self.mock_self.selected_pool = mock.Mock(index=1)
self.mock_self.selected_pool = mock.Mock(index=0)
self.assertFalse(AzureBatchPools.is_auto_pool(self.mock_self))
self.mock_self.selected_pool = mock.Mock(index=2)
self.assertFalse(AzureBatchPools.is_auto_pool(self.mock_self))
def test_get_pool_size(self):
def test_pools_get_size(self):
self.mock_self.pools = [mock.Mock(target_size=5),
mock.Mock(target_size="8"),
mock.Mock(target_size=None)]
self.mock_self.pools = [mock.Mock(target_dedicated_nodes=5),
mock.Mock(target_dedicated_nodes="8"),
mock.Mock(target_dedicated_nodes=None)]
self.mock_self.selected_pool = mock.Mock(index=0)
self.assertEqual(BatchAppsPools.get_pool_size(self.mock_self), 5)
self.assertEqual(AzureBatchPools.get_pool_size(self.mock_self), 5)
self.mock_self.selected_pool = mock.Mock(index=1)
self.assertEqual(BatchAppsPools.get_pool_size(self.mock_self), 8)
self.assertEqual(AzureBatchPools.get_pool_size(self.mock_self), 8)
self.mock_self.selected_pool = mock.Mock(index=2)
self.assertEqual(BatchAppsPools.get_pool_size(self.mock_self), 0)
self.assertEqual(AzureBatchPools.get_pool_size(self.mock_self), 0)
self.mock_self.selected_pool = mock.Mock(index=3)
self.assertEqual(BatchAppsPools.get_pool_size(self.mock_self), 0)
self.assertEqual(AzureBatchPools.get_pool_size(self.mock_self), 0)
def test_delete_pool(self):
def test_pools_delete(self):
mock_pool = mock.create_autospec(Pool)
mock_pool.delete.return_value = None
mock_pool = mock.create_autospec(models.CloudPool)
mock_pool.id = "pool id"
self.mock_self.pools = [mock_pool]
def call(func):
self.assertTrue(hasattr(func, "__call__"))
return func()
self.mock_self._call = call
self.mock_self.selected_pool = mock.Mock(index=0)
self.mock_self.ui = mock.create_autospec(PoolsUI)
BatchAppsPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 1)
mock_pool.delete.return_value = 1
BatchAppsPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 2)
self.mock_self.selected_pool.index = 1
BatchAppsPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 2)
def test_create_pool(self):
def call(func, **kwargs):
self.assertTrue(hasattr(func, "__call__"))
self.assertEqual(kwargs.get("target_size"), 5)
return func(**kwargs)
self.mock_self._call = call
self.mock_self.manager = mock.create_autospec(PoolManager)
BatchAppsPools.create_pool(self.mock_self, 5)
self.mock_self.manager.create.assert_called_with(target_size=5)
@mock.patch("pools.maya")
def test_resize_pool(self, mock_maya):
def call(func, *args):
self.assertTrue(hasattr(func, "__call__"))
self.assertEqual(args[0], 5)
self.assertTrue(callable(func))
return func(*args)
mock_pool = mock.create_autospec(Pool)
mock_pool.delete.return_value = None
self.mock_self._call = call
self.mock_self.selected_pool = mock.Mock(index=0)
self.mock_self.ui = mock.create_autospec(PoolsUI)
AzureBatchPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 1)
self.mock_self.batch.pool.delete.assert_called_with("pool id")
self.mock_self.batch.pool.delete.side_effect = AttributeError("boom")
AzureBatchPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 2)
self.mock_self.batch.pool.delete.assert_called_with("pool id")
self.mock_self.selected_pool.index = 1
AzureBatchPools.delete_pool(self.mock_self)
self.assertEqual(self.mock_self.ui.refresh.call_count, 3)
self.assertEqual(self.mock_self.batch.pool.delete.call_count, 2)
def test_pools_create(self):
pool_obj = None
def call(func, new_pool):
self.assertTrue(callable(func))
pool_obj = new_pool
self.assertEqual(new_pool.target_dedicated_nodes, 5)
self.assertEqual(new_pool.display_name, "Maya Pool for test job")
self.assertEqual(new_pool.application_licenses, ['maya'])
self.assertEqual(new_pool.virtual_machine_configuration.node_agent_sku_id, 'sku_id')
self.assertEqual(new_pool.virtual_machine_configuration.image_reference.publisher, 'foo')
return func(new_pool)
self.mock_self._call = call
self.mock_self.environment.get_application_licenses.return_value = ['maya']
self.mock_self.environment.get_image.return_value = {
'publisher': 'foo', 'sku': 'bar', 'offer': 'baz', 'node_sku_id':'sku_id'}
AzureBatchPools.create_pool(self.mock_self, 5, "test job")
self.mock_self.batch.pool.add.assert_called_with(pool_obj)
@mock.patch("pools.maya")
def test_pools_resize(self, mock_maya):
def call(func, *args):
self.assertTrue(callable(func))
self.assertEqual(args[1]['target_dedicated_nodes'], 5)
return func(*args)
mock_pool = mock.create_autospec(models.CloudPool)
mock_pool.id = "pool id"
self.mock_self.pools = [mock_pool]
self.mock_self._call = call
self.mock_self.selected_pool = mock.Mock(index=0)
self.mock_self.ui = mock.create_autospec(PoolsUI)
BatchAppsPools.resize_pool(self.mock_self, 5)
AzureBatchPools.resize_pool(self.mock_self, 5)
self.assertFalse(self.mock_self.ui.refresh.call_count)
BatchAppsPools.resize_pool(self.mock_self, "5")
AzureBatchPools.resize_pool(self.mock_self, "5")
self.assertFalse(self.mock_self.ui.refresh.call_count)
BatchAppsPools.resize_pool(self.mock_self, None)
AzureBatchPools.resize_pool(self.mock_self, None)
self.assertEqual(self.mock_self.ui.refresh.call_count, 1)
class TestPoolsCombined(unittest.TestCase):
@mock.patch("ui_pools.utils")
@mock.patch("ui_pools.maya")
@mock.patch("pools.maya")
def test_pools(self, *args):
def add_tab(tab):
self.assertFalse(tab.ready)
def call(func, *args, **kwargs):
self.assertTrue(hasattr(func, '__call__'))
return func(*args, **kwargs)
layout = mock.Mock(add_tab=add_tab)
pools = BatchAppsPools(layout, call)
creds = mock.create_autospec(Credentials)
conf = mock.create_autospec(Configuration)
session = mock.Mock(credentials=creds, config=conf)
pools.configure(session)
pools.manager = mock.create_autospec(PoolManager)
pool1 = mock.create_autospec(Pool)
pool1.current_size = "3"
pool1.target_size = "5"
pool1.auto = False
pool1.state = "500"
pool1.id = "12345"
pool1.max_tasks = "2"
pool1.allocation_state = "allocating"
pool1.created = "now"
pool2 = mock.create_autospec(Pool)
pool2.id = "67890"
pool2.auto = True
pools.manager.get_pools.return_value = []
pools.manager.__len__.return_value = 0
pools.ui.prepare()
self.assertIsNone(pools.selected_pool)
self.assertEqual(pools.pools, [])
self.assertTrue(pools.ui.ready)
pools.manager.get_pools.return_value = [pool1, pool2]
pools.manager.__len__.return_value = 2
pools.ui.refresh()
self.assertIsNone(pools.selected_pool)
self.assertEqual(pools.pools, [pool1, pool2])
self.assertEqual(len(pools.ui.pools_displayed), 2)
self.assertEqual(pools.ui.pools_displayed[0].index, 0)
pools.ui.pools_displayed[0].on_expand()
self.assertIsNone(pools.selected_pool)
pool1.created = str(datetime.datetime.now()).replace(' ', 'T')
pools.ui.pools_displayed[0].on_expand()
self.assertEqual(pools.ui.pools_displayed[0], pools.selected_pool)
pools.ui.pools_displayed[1].on_expand()
self.assertIsNone(pools.selected_pool)
pools.ui.pools_displayed[0].on_expand()
self.assertEqual(pools.get_pool_size(), 5)
self.assertFalse(pools.is_auto_pool())
pools.resize_pool(10)
pool1.resize.assert_called_with(10)
pool1.resize.side_effect = Exception("failed!")
pools.resize_pool(8)
self.assertIsNone(pools.selected_pool)
pools.ui.pools_displayed[0].on_expand()
pools.ui.pools_displayed[0].collapse()
self.assertIsNone(pools.selected_pool)
pools.ui.pools_displayed[0].on_expand()
pools.delete_pool()
pool1.delete.assert_called_with()
self.assertIsNone(pools.selected_pool)

Просмотреть файл

@ -46,11 +46,18 @@ from submission import AzureBatchSubmission, AzureBatchRenderJob
from assets import AzureBatchAssets
from pools import AzureBatchPools
from environment import AzureBatchEnvironment
from shared import AzureBatchSettings
from exception import CancellationException
from batch_extensions import BatchExtensionsClient
from batch_extensions.batch_auth import SharedKeyCredentials
from batch_extensions import operations
from batch_extensions import models
from azure.storage.blob import BlockBlobService
LIVE = True
def print_status(status):
print(status)
@ -88,8 +95,8 @@ class TestBatchSubmission(unittest.TestCase):
submission = AzureBatchSubmission("frame", "call")
mock_mods.assert_called_with()
mock_ui.assert_called_with(submission, "frame")
mock_call.after_new.assert_called_with(mock.ANY)
mock_call.after_open.assert_called_with(mock.ANY)
#mock_call.after_new.assert_called_with(mock.ANY)
#mock_call.after_open.assert_called_with(mock.ANY)
@mock.patch("submission.maya")
def test_submission_start(self, mock_maya):
@ -97,7 +104,7 @@ class TestBatchSubmission(unittest.TestCase):
self.mock_self.ui = mock.create_autospec(SubmissionUI)
self.mock_self.ui.render_module = "module"
self.mock_self.renderer = mock.Mock()
AzureBatchSubmission.start(self.mock_self, session, "assets", "pools")
AzureBatchSubmission.start(self.mock_self, session, "assets", "pools", "env")
self.mock_self.renderer.delete.assert_called_with()
self.mock_self._configure_renderer.assert_called_with()
self.mock_self.renderer.display.assert_called_with("module")
@ -143,17 +150,17 @@ class TestBatchSubmission(unittest.TestCase):
@mock.patch("submission.utils")
@mock.patch("submission.maya")
def test_submission_submit(self, mock_maya, mock_utils):
def call(func):
self.assertTrue(hasattr(func, '__call__'))
return func()
def call(func, *args, **kwargs):
self.assertTrue(callable(func))
return func(*args, **kwargs)
mock_prog = mock.create_autospec(ProgressBar)
mock_prog.is_cancelled.return_value = False
mock_utils.ProgressBar.return_value = mock_prog
self.mock_self._configure_pool = AzureBatchSubmission._configure_pool
self.mock_self._check_outputs = AzureBatchSubmission._check_outputs
mock_utils.format_scene_path.return_value = "test_file_path"
self.mock_self._configure_pool = lambda t: AzureBatchSubmission._configure_pool(self.mock_self, t)
self.mock_self._check_plugins.return_value = []
self.mock_self.asset_manager.upload.return_value = ("a", "b", mock_prog)
self.mock_self._get_os_flavor.return_value = 'Windows'
self.mock_self.pool_manager.create_auto_pool.return_value = {'autoPool': 'auto-pool'}
self.mock_self.pool_manager.create_pool.return_value = {'poolId': 'new-pool'}
self.mock_self.renderer = mock.Mock()
@ -161,154 +168,76 @@ class TestBatchSubmission(unittest.TestCase):
self.mock_self.renderer.get_params.return_value = {"foo": "bar"}
self.mock_self.renderer.get_title.return_value = "job name"
self.mock_self._call = call
mock_job = mock.create_autospec(models.ExtendedJobParameter)
self.mock_self.batch.job.jobparameter_from_json.return_value = mock_job
self.mock_self.ui.get_pool.return_value = {1:"pool"}
self.mock_self.asset_manager.upload.return_value = ("files", "maps", mock_prog)
self.mock_self.asset_manager.upload.return_value = ("files", "maps", "thumbs", mock_prog)
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 1)
self.mock_self.renderer.disable.assert_called_with(True)
self.mock_self.ui.get_pool.return_value = {1:4}
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 1)
self.mock_self.renderer.disable.assert_called_with(True)
self.mock_self.pool_manager.create_auto_pool.assert_called_with(4, "job name")
self.mock_self.batch.job.add.assert_called_with(mock_job)
self.mock_self.batch.job.jobparameter_from_json.assert_called_with(
{'poolInfo': {'autoPool': 'auto-pool'},
'displayName': 'job name',
'id': mock.ANY,
'applicationTemplateInfo': {
'parameters': {'sceneFile': 'test_file_path', 'outputs': mock.ANY, 'assetScript': 'maps', 'foo': 'bar', 'projectData': 'files', 'thumbScript': 'thumbs'},
'filePath': os.path.join(os.environ['AZUREBATCH_TEMPLATES'], 'arnold-basic-windows.json')},
'metadata': [{'name': 'JobType', 'value': 'Maya'}]})
job.submit.assert_called_with()
self.assertEqual(job.instances, 4)
self.mock_self.ui.get_pool.return_value = {2:4}
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 1)
self.mock_self.renderer.disable.assert_called_with(True)
self.mock_self.batch.job.add.assert_called_with(mock_job)
self.mock_self.batch.job.jobparameter_from_json.assert_called_with(
{'poolInfo': {'poolId': '4'},
'displayName': 'job name',
'id': mock.ANY,
'applicationTemplateInfo': {
'parameters': {'sceneFile': 'test_file_path', 'outputs': mock.ANY, 'assetScript': 'maps', 'foo': 'bar', 'projectData': 'files', 'thumbScript': 'thumbs'},
'filePath': os.path.join(os.environ['AZUREBATCH_TEMPLATES'], 'arnold-basic-windows.json')},
'metadata': [{'name': 'JobType', 'value': 'Maya'}]})
job.submit.assert_called_with()
self.assertEqual(job.pool, '4')
self.mock_self.check_outputs.side_effect = ValueError("No camera")
self.mock_self._check_outputs.side_effect = ValueError("No camera")
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 2)
self.mock_self.check_outputs.side_effect = None
self.mock_self._check_outputs.side_effect = None
self.mock_self.ui.get_pool.return_value = {3: 4}
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 2)
self.mock_self.renderer.disable.assert_called_with(True)
job.submit.assert_called_with()
job.submit.call_count = 0
self.mock_self.pool_manager.create_pool.assert_called_with(4)
self.mock_self.batch.job.add.assert_called_with(mock_job)
self.mock_self.batch.job.add.call_count = 0
self.mock_self.pool_manager.create_pool.assert_called_with(4, 'job name')
mock_prog.is_cancelled.return_value = True
mock_prog.is_cancelled.side_effect = CancellationException("cancelled")
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.info.call_count, 4)
self.mock_self.renderer.disable.assert_called_with(True)
self.assertEqual(job.submit.call_count, 0)
self.assertEqual(self.mock_self.batch.job.add.call_count, 0)
mock_prog.is_cancelled.return_value = False
mock_prog.is_cancelled.side_effect = None
self.mock_self.pool_manager.create_pool.side_effect = Exception("Logged out!")
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 2)
self.mock_self.renderer.disable.assert_called_with(True)
self.assertEqual(self.mock_self.batch.job.add.call_count, 0)
self.mock_self.pool_manager.create_pool.side_effect = ValueError("Bad data")
AzureBatchSubmission.submit(self.mock_self)
self.assertEqual(mock_maya.error.call_count, 3)
self.mock_self.renderer.disable.assert_called_with(True)
self.assertEqual(job.submit.call_count, 0)
class TestSubmissionCombined(unittest.TestCase):
@mock.patch("submission.utils")
@mock.patch("ui_submission.utils")
@mock.patch("ui_submission.maya")
@mock.patch("submission.callback")
@mock.patch("submission.maya")
def test_submission(self, *args):
mock_callback = args[1]
mock_maya = args[0]
mock_maya.mel.return_value = "Renderer"
mock_maya.get_list.return_value = ["1","2","3"]
mock_maya.get_attr.return_value = True
ui_maya = args[2]
ui_maya.radio_group.return_value = 2
ui_maya.menu.return_value = "12345"
ui_maya.int_slider.return_value = 6
def add_tab(tab):
pass
def call(func, *args, **kwargs):
self.assertTrue(hasattr(func, '__call__'))
return func()
mock_utils = args[4]
mock_prog = mock.create_autospec(ProgressBar)
mock_prog.is_cancelled.return_value = False
mock_utils.ProgressBar.return_value = mock_prog
layout = mock.Mock(add_tab=add_tab)
sub = AzureBatchSubmission(layout, call)
self.assertEqual(len(sub.modules), 4)
self.assertTrue(mock_callback.after_new.called)
self.assertTrue(mock_callback.after_open.called)
creds = mock.create_autospec(Credentials)
conf = mock.create_autospec(Configuration)
session = mock.Mock(credentials=creds, config=conf)
assets = mock.create_autospec(BatchAppsAssets)
pools = mock.create_autospec(BatchAppsPools)
env = mock.create_autospec(BatchAppsEnvironment)
env.license = {"license":"test"}
env.environment_variables = {"env":"val"}
env.plugins = {"plugins":"test"}
sub.start(session, assets, pools, env)
mock_maya.mel.return_value = "Renderer_A"
sub.ui.refresh()
sub.asset_manager.upload.return_value = (["abc"], {}, mock_prog)
sub.asset_manager.collect_assets.return_value = {'assets':['abc'],
'pathmaps':'mapping'}
sub.job_manager = mock.create_autospec(JobManager)
job = mock.create_autospec(JobSubmission)
job.required_files = mock.Mock()
job.required_files.upload.return_value = []
sub.job_manager.create_job.return_value = job
sub.submit()
self.assertEqual(mock_maya.error.call_count, 0)
self.assertEqual(sub.pool_manager.create_pool.call_count, 0)
job.submit.assert_called_with()
self.assertEqual(job.params, {"setting_A":1, "setting_B":2})
job.add_file_collection.assert_called_with(["abc"])
self.assertEqual(job.pool, "12345")
mock_maya.get_attr.return_value = False
sub.submit()
mock_maya.error.assert_called_with(mock.ANY)
mock_maya.error.call_count = 0
mock_maya.get_attr.return_value = True
ui_maya.menu.return_value = None
sub.submit()
mock_maya.error.assert_called_with("No pool selected.")
mock_maya.error.call_count = 0
ui_maya.radio_group.return_value = 1
sub.submit()
self.assertEqual(mock_maya.error.call_count, 0)
self.assertEqual(sub.pool_manager.create_pool.call_count, 0)
job.submit.assert_called_with()
self.assertEqual(job.instances, 6)
ui_maya.radio_group.return_value = 3
sub.submit()
self.assertEqual(mock_maya.error.call_count, 0)
sub.pool_manager.create_pool.assert_called_with(6)
job.submit.assert_called_with()
sub.asset_manager.upload.return_value = [("failed", Exception("boom"))]
sub.submit()
self.assertEqual(mock_maya.error.call_count, 1)
self.assertEqual(self.mock_self.batch.job.add.call_count, 0)