# -*- test-case-name: mv3d.test.test_ige -*- # Copyright (C) 2008-2012 Mortal Coil Games # See LICENSE for details. """ """ import os from cStringIO import StringIO from twisted.internet import defer from twisted.internet.defer import inlineCallbacks, Deferred from twisted.trial.unittest import TestCase from zope.interface import implements from mv3d.server.ige.server import ( Select as SelectServer, Move as MoveServer, Remove as RemoveServer, Add as AddServer, AssetSelector as AssetSelectorServer, Factory as FactoryServer, ) import sys try: from mv3d.client.ui.ige.client import ( Select as SelectClient, ISelectable, AssetSelector as AssetSelectorClient, Move as MoveClient, Add as AddClient, parseTuple, Factory as FactoryClient, StringInputWindow, FileSelector, absmax, ) noOgre = "" except ImportError: noOgre = "Ogre is not available." from mv3d.net.security import AccessDenied from mv3d.util.modifier import IModifiable, IModifier from mv3d.util.math3d import Quaternion from mv3d.util.classgen import ClassGenerator from mv3d.server.model.area import Area from mv3d.test.ui.test_layout import WithFakeUI, FakeText from mv3d.test.mixins import WithDocTests from mv3d.util.conductor import IConductor class FakeAsset: """ Faked out asset """ def __init__(self, aid): self.aid = aid self.name = "george" def getCG(self): """ return true """ return True def getName(self): """ return our name """ return self.name class FakeRenderer: """ a faker """ def __init__(self): self.rootSceneNode = self self.sceneManager = self self.camera = self def createChildSceneNode(self, _name): """ return self """ return self def addNode(self, _parent): """ do nothing """ class FakeSim: """ A fake sim service """ def __init__(self, items=None): self.parent = self self.items = {} if items is not None: for item in items: self.items[item.iid] = item def getItem(self, itm): return defer.succeed(self.items[itm]) def getLocalService(self, svc): return self def getService(self, svc): return defer.succeed(self) def getAsset(self, aid): return FakeAsset(aid) def getAreas(self): return self.items.values() def getRealm(self, rid): return self def returnID(self, iid): pass def remItem(self, itm): del self.items[itm] class FakeClient: """ A fake client """ user = "mike" readied = None def __init__(self): self.groups = [] def getUsername(self): return self.user def getGroups(self): return self.groups def readyClass(self, classes): """ just log """ self.readied = classes class FakeModifier: implements(IModifier) def __init__(self, name="move"): self.name = name def getMinimumPermissions(self): """ Return stuff """ return ["read", "modify"] class FakeItem: if not noOgre: implements(IModifiable, ISelectable) name = "putty" selected = 0 pos = 0 rot = 0 def __init__(self, iid=None, modifiers=None): self.iid = iid or (1, 23) self.modifiers = modifiers or [FakeModifier()] self.containers = [] self.areas = {} def checkPermissions(self, client, perm): if client.getUsername().startswith("mike"): return True return False def getID(self): return self.iid def getName(self): return self.name def getModifiers(self, type, conductor=None): return defer.succeed(self.modifiers) def deselect(self): self.selected -= 1 def select(self): self.selected += 1 def setPosition(self, pos): self.pos = pos def setRotation(self, rot): self.rot = rot def getPosition(self): return self.pos def getRotation(self): return self.rot def addContainedBy(self, c): self.containers.append(c) def listContainedBy(self): return [c.getID() for c in self.containers] def remContainedBy(self, c): self.containers.remove(c) def getMasterServers(self): return [1] def getSlaveServers(self): return [] class NoPermsItem(FakeItem): """ An item with no permissions """ def checkPermissions(self, client, perm): return False class FakeModifierUI: """ Faker """ def __init__(self, uint, parent): self.uint = uint self.parent = parent self.parent.uiinited = True def start(self): """ return tryue """ self.parent.uistarted = True return defer.succeed(True) class FakeSelectModifier: """ Just a faker """ uistarted = False uiinited = False def callRemote(self, f, *a, **kw): """ call local """ return defer.succeed(getattr(self, f)(*a, **kw)) def setSelection(self, selection): """ return it """ return selection def getModifiers(self): """ return stuff """ return ["1"] def getModifier(self, _name): """ return self """ return self def getUI(self): """ Return ourselves """ return ClassGenerator().setFrom(FakeModifierUI) class SelectServerTests(TestCase, WithDocTests): """ Test the select modifier """ def test_docs(self): """ Test the docs """ self.checkDocs(SelectServer) @inlineCallbacks def test_viewSetSelectionEmpty(self): """ Test setting the selection """ s = SelectServer(FakeSim()) r = yield s.view_setSelection(FakeClient(), []) self.assertEqual(r, []) @inlineCallbacks def test_viewSetSelectionSingle(self): """ Test setting the selection """ s = SelectServer(FakeSim([FakeItem()])) r = yield s.view_setSelection(FakeClient(), [(1, 23)]) self.assertEqual(r, [(1, 23)]) @inlineCallbacks def test_viewSetSelectionMulti(self): """ Test setting the selection """ s = SelectServer(FakeSim([FakeItem((1, 3)), FakeItem((1, 2))])) r = yield s.view_setSelection(FakeClient(), [(1, 2), (1, 3)]) self.assertEqual(r, [(1, 2), (1, 3)]) @inlineCallbacks def test_viewSetSelectionNoPerms(self): """ Test setting the selection """ s = SelectServer(FakeSim([FakeItem((1, 3)), NoPermsItem((1, 2))])) r = yield s.view_setSelection(FakeClient(), [(1, 2), (1, 3)]) self.assertEqual(r, [(1, 2), (1, 3)]) @inlineCallbacks def test_viewGetModifiersSingle(self): """ Test getting unique modifier names """ items = [FakeItem((1, 3))] s = SelectServer(FakeSim(items)) s.selection = items r = yield s.view_getModifiers(FakeClient()) self.assertEqual(r, ["move"]) @inlineCallbacks def test_viewGetModifiersDouble(self): """ Test getting unique modifier names """ items = [FakeItem((1, 3)), FakeItem((1, 4))] s = SelectServer(FakeSim(items)) s.selection = items r = yield s.view_getModifiers(FakeClient()) self.assertEqual(r, ["move"]) @inlineCallbacks def test_viewGetModifiersDoubleDifferent(self): """ Test getting unique modifier names """ items = [FakeItem((1, 3)), FakeItem((1, 4), modifiers=[FakeModifier("g")])] s = SelectServer(FakeSim(items)) s.selection = items r = yield s.view_getModifiers(FakeClient()) self.assertEqual(r, []) def test_viewGetObjectList(self): """ Test getting unique modifier names """ items = [FakeItem((1, 3)), FakeItem((1, 4))] s = SelectServer(FakeSim(items)) r = s.view_getObjectList(FakeClient()) self.assertEqual(r, [((1, 3), 'putty'), ((1, 4), 'putty')]) class SelectClientTests(WithFakeUI, WithDocTests): """ Tests of the select client """ if noOgre: skip = noOgre def test_docs(self): """ Test the docs """ self.checkDocs(SelectClient) def test_initialize(self): """ Test initializing the select client """ SelectClient(self.ui, None) self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/SelectModifier'), ('create', 'WindowsLook/Button', 'SelectModifier/SelectModifier/Select'), ('create', 'WindowsLook/Button', 'SelectModifier/SelectModifier/Lock'), ('create', 'WindowsLook/MultiColumnList', 'SelectModifier/SelectModifier/Selected'), ('create', 'WindowsLook/Button', 'SelectModifier/SelectModifier/Deselect'), ('create', 'WindowsLook/MultiColumnList', 'SelectModifier/SelectModifier/Modifiers'), ('create', 'WindowsLook/Button', 'SelectModifier/SelectModifier/Modify'), ('requestUICallback', 'EventCloseClicked', 'stop')]) def test_start(self): """ Test starting the select client """ sc = SelectClient(self.ui, None) sc.start() self.assertEqual(len(self.ui.callbacks), 4) self.assertEqual(len(self.ui.getInputContext().mouseCallbacks), 1) def test_stop(self): """ Test starting the select client """ sc = SelectClient(self.ui, None) sc.start() sc.stop() self.assertEqual(len(self.ui.callbacks), 0) self.assertEqual(len(self.ui.getInputContext().mouseCallbacks), 0) def test_parseTuple(self): """ Test parsing a tuple """ tests = [("(1,2)", (1, 2)), (" (1,2) ", (1, 2)), ("( 1, 2 )", (1, 2)), ("(2 ,1)", (2, 1))] sc = SelectClient(self.ui, None) for test, result in tests: self.assertEqual(parseTuple(test), result) def test_deselectItems(self): """ Test deselecting items """ sc = SelectClient(self.ui, None) self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} sc.selected = [(0, 1), (0, 2)] sc.deselectItems() self.assertEqual([i.selected for i in self.ui.items.values()], [ -1, -1]) def test_selectItems(self): """ Test selecting items """ sc = SelectClient(self.ui, None) self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} sc.selected = [(0, 1), (0, 2)] sc.selectItems() self.assertEqual([i.selected for i in self.ui.items.values()], [1, 1]) @inlineCallbacks def test_updateSelection(self): """ Test updating the selection """ sc = SelectClient(self.ui, FakeSelectModifier()) sc.selected = [(0, 1)] self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} yield sc.updateSelection([(0, 2)]) self.assertEqual([i.selected for i in self.ui.items.values()], [ -1, 1]) self.assertLog(['getColumnCount', 'addColumn ID: 0', "resetList", "Add row ['(0, 2)']"], sc.selectList.widget) self.assertLog(['getColumnCount', 'addColumn Name: 0', 'resetList', "Add row ['1']"], sc.modifierList.widget) def test_mouseClicked(self): """ Test clicking the mouse """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.selected = [(0, 1)] self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} scli.mouseClicked((1, 0, 0), (0.5, 0.5), None, [0, 0, 0]) self.assertEqual([i.selected for i in self.ui.items.values()], [-1, 0]) def test_rightMouseClicked(self): """ Test clicking the rmb brings up the context menu """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.selected = [(0, 1)] self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} scli.modifiers = ["hi", "two"] self.clearLog() scli.mouseClicked((0, 1, 0), (0.5, 0.5), None, [0, 0, 0]) self.assertNotIdentical(scli.contextMenu, None) self.assertLog([('create', 'WindowsLook/PopupMenu', 'Root/contextMenu'), ('create', 'WindowsLook/MenuItem', 'contextMenu/hi'), ('requestUICallback', 'EventClicked', 'runModifier'), ('create', 'WindowsLook/MenuItem', 'contextMenu/two'), ('requestUICallback', 'EventClicked', 'runModifier'), ('displayWindow', 'Root/contextMenu')]) def test_rightMouseClickedCloseContext(self): """ Test clicking the rmb closes the context menu if it is up """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.selected = [(0, 1)] self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} scli.modifiers = ["hi", "two"] scli.mouseClicked((0, 1, 0), (0.5, 0.5), None, [0, 0, 0]) self.clearLog() scli.mouseClicked((0, 1, 0), (0.5, 0.5), None, [0, 0, 0]) self.assertIdentical(scli.contextMenu, None) self.assertLog([('hideWindow', 'Root/contextMenu'), ('stopUICallback', 'call'), ('stopUICallback', 'call')]) def test_leftMouseClickedCloseContext(self): """ Test clicking the lmb closes the context menu if it is up """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.selected = [(0, 1)] self.ui.items = {(0, 1):FakeItem((0, 1)), (0, 2):FakeItem((0, 2))} scli.modifiers = ["hi", "two"] scli.mouseClicked((0, 1, 0), (0.5, 0.5), None, [0, 0, 0]) self.clearLog() scli.mouseClicked((1, 0, 0), (0.5, 0.5), None, [0, 0, 0]) self.assertIdentical(scli.contextMenu, None) self.assertLog([('hideWindow', 'Root/contextMenu'), ('stopUICallback', 'call'), ('stopUICallback', 'call')]) def test_showContextMenu(self): """ Test displaying the context menu """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.modifiers = ["one", "three"] self.clearLog() scli.showContextMenu((0.2, 0.2)) self.assertNotIdentical(scli.contextMenu, None) self.assertLog([('create', 'WindowsLook/PopupMenu', 'Root/contextMenu'), ('create', 'WindowsLook/MenuItem', 'contextMenu/one'), ('requestUICallback', 'EventClicked', 'runModifier'), ('create', 'WindowsLook/MenuItem', 'contextMenu/three'), ('requestUICallback', 'EventClicked', 'runModifier'), ('displayWindow', 'Root/contextMenu')]) def test_showContextMenuEmpty(self): """ Test displaying the context menu """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.modifiers = [] self.clearLog() scli.showContextMenu((0.2, 0.2)) self.assertIdentical(scli.contextMenu, None) self.assertLog([]) @inlineCallbacks def test_runModifier(self): """ Test actually opening a modifier """ scli = SelectClient(self.ui, FakeSelectModifier()) scli.start() yield scli.runModifier("test") self.assertEqual(scli.modifier.uiinited, True) self.assertEqual(scli.modifier.uistarted, True) class MoveServerTests(TestCase, WithDocTests): """ Tests for the server side of the move ige plugin """ def setUp(self): self.items = [FakeItem(x) for x in range(1, 10)] def test_docs(self): """ Test the docs """ self.checkDocs(MoveServer) def test_updateItemsSingle(self): """ Test updating the pos/rot of selected items """ m = MoveServer(self.items[0]) m.view_updateItems(FakeClient(), {1:(2, 3)}) self.assertEqual(self.items[0].pos, 2) self.assertEqual(self.items[0].rot, 3) def test_updateItemsMultiAll(self): """ Test updating the pos/rot of selected items """ m = MoveServer(self.items[0]) [m.addParent(p) for p in self.items[1:]] u = {} for x in range(1, 10): u[x] = (x, x + 1) m.view_updateItems(FakeClient(), u) for x in range(1, 10): self.assertEqual(self.items[x - 1].pos, x) self.assertEqual(self.items[x - 1].rot, x + 1) def test_updateItemsMultiSome(self): """ Test updating the pos/rot of selected items """ m = MoveServer(self.items[0]) [m.addParent(p) for p in self.items[1:]] u = {} for x in range(3, 5): u[x] = (x, x + 1) m.view_updateItems(FakeClient(), u) for x in range(3, 5): self.assertEqual(self.items[x - 1].pos, x) self.assertEqual(self.items[x - 1].rot, x + 1) for x in [1, 2, 5, 6, 7, 8, 9]: self.assertEqual(self.items[x - 1].pos, 0, str(x)) self.assertEqual(self.items[x - 1].rot, 0) def test_updateItemsBadOid(self): """ Test updating the pos/rot of selected items when the oid is invalid """ m = MoveServer(self.items[0]) self.assertRaises(ValueError, m.view_updateItems, FakeClient(), {2:(2, 3)}) def test_getSelection(self): """ Test getting the selection """ m = MoveServer(self.items[0]) self.assertEqual(m.view_getSelection(FakeClient()), [1]) [m.addParent(p) for p in self.items[1:]] self.assertEqual(m.view_getSelection(FakeClient()), range(1, 10)) class FakeMoveModifier: def callRemote(self, f, *a, **kw): return defer.succeed(getattr(self, f)(*a, **kw)) def getSelection(self): return [1] class MoveClientTests(WithFakeUI, WithDocTests): """ Test the move plugin on the client side """ if noOgre: skip = noOgre def test_docs(self): """ Test the docs """ self.checkDocs(MoveClient) def test_initialize(self): """ Test initializing the plugin """ sc = MoveClient(self.ui, None) self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/Move'), ('create', 'WindowsLook/Checkbox', 'Move/Relative'), ('requestUICallback', 'EventCheckStateChanged', 'relativeClicked'), ('create', 'WindowsLook/StaticText', 'Move/PosXLabel'), ('create', 'WindowsLook/Editbox', 'Move/PosXText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/StaticText', 'Move/PosYLabel'), ('create', 'WindowsLook/Editbox', 'Move/PosYText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/StaticText', 'Move/PosZLabel'), ('create', 'WindowsLook/Editbox', 'Move/PosZText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/StaticText', 'Move/RotXLabel'), ('create', 'WindowsLook/Editbox', 'Move/RotXText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/StaticText', 'Move/RotYLabel'), ('create', 'WindowsLook/Editbox', 'Move/RotYText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/StaticText', 'Move/RotZLabel'), ('create', 'WindowsLook/Editbox', 'Move/RotZText'), ('requestUICallback', 'EventTextAccepted', 'textEntered'), ('create', 'WindowsLook/Checkbox', 'Move/Grid'), ('create', 'WindowsLook/Button', 'Move/GridSetup'), ('create', 'WindowsLook/StaticText', 'Move/Lock'), ('create', 'WindowsLook/Checkbox', 'Move/LockX'), ('create', 'WindowsLook/Checkbox', 'Move/LockY'), ('create', 'WindowsLook/Checkbox', 'Move/LockZ'), ('create', 'WindowsLook/Checkbox', 'Move/LockRX'), ('create', 'WindowsLook/Checkbox', 'Move/LockRY'), ('create', 'WindowsLook/Checkbox', 'Move/LockRZ'), ('create', 'WindowsLook/StaticText', 'Move/Align'), ('create', 'WindowsLook/Checkbox', 'Move/AlignX'), ('create', 'WindowsLook/Checkbox', 'Move/AlignY'), ('create', 'WindowsLook/Checkbox', 'Move/AlignZ'), ('requestUICallback', 'EventCloseClicked', 'stop')]) def test_start(self): """ Test starting the move client """ self.ui.items = {1:FakeItem(1)} sc = MoveClient(self.ui, FakeMoveModifier()) sc.start() self.assertEqual(len(self.ui.callbacks), 8) self.assertEqual(len(self.ui.getInputContext().mouseCallbacks), 1) def test_stop(self): """ Test starting the move client """ self.ui.items = {1:FakeItem(1)} sc = MoveClient(self.ui, FakeMoveModifier()) defrd = sc.start() fired = [] def fire(_): """ Called when the deferred is fired """ fired.append(True) defrd.addCallback(fire) sc.stop() self.assertEqual(fired, [True]) self.assertEqual(len(self.ui.callbacks), 0) self.assertEqual(len(self.ui.getInputContext().mouseCallbacks), 0) def test_keyedMove(self): """ Test keyed move """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.keyedMove(1, 0, 0) self.assertEqual(self.ui.items[1].pos, (1, 0, 0)) self.assertEqual(self.ui.items[1].rot, (1, 0, 0, 0)) def test_keyedMoveShift(self): """ Test keyed move """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.mods = [self.ui.Shift] self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.keyedMove(1, 0, 0) self.assertEqual(tuple(self.ui.items[1].pos), (0.1, 0, 0)) self.assertEqual(self.ui.items[1].rot, (1, 0, 0, 0)) def test_keyedMoveAlt(self): """ Test keyed move with alt """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.mods = [self.ui.Alt] self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.keyedMove(1, 0, 0) self.assertEqual(tuple(self.ui.items[1].pos), (0, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (0.70738826916719977, 0.70682518110536596, 0.0, 0.0)) def test_keyedMoveCtrl(self): """ Test keyed move with ctrl """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.mods = [self.ui.Ctrl] self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.keyedMove(1, 0, 0) self.assertEqual(tuple(self.ui.items[1].pos), (1.0, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (1, 0, 0, 0)) def test_handleMovement(self): """ Test the handleMovement method """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.handleMovement([1, 0, 0], (1, 0, 0), (0, 0, 0)) self.assertEqual(tuple(self.ui.items[1].pos), (0.1, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (1, 0, 0, 0)) def test_handleMovementCtrl(self): """ Test the handleMovement method """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) self.ui.orientation = Quaternion().fromEuler(20, 40, 6) mc.selected = [self.ui.items[1]] mc.handleMovement([1, 0, 0], (1, 0, 0), (1, 0, 0)) self.assertEqual(tuple(self.ui.items[1].pos), (0.1, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (1, 0, 0, 0)) def test_handleMovementAlt(self): """ Test the handleMovement method """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.handleMovement([1, 0, 0], (1, 0, 0), (0, 1, 0)) self.assertEqual(tuple(self.ui.items[1].pos), (0, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (0.99998750002604164, 0.0, 0.0, 0.0049999791666927081)) def test_handleMovementShift(self): """ Test the handleMovement method """ mc = MoveClient(self.ui, FakeMoveModifier()) self.ui.items = {1:FakeItem(1)} self.ui.items[1].pos = (0, 0, 0) self.ui.items[1].rot = (1, 0, 0, 0) mc.selected = [self.ui.items[1]] mc.handleMovement([1, 0, 0], (1, 0, 0), (1, 0, 0)) self.assertEqual(tuple(self.ui.items[1].pos), (0.1, 0, 0)) self.assertEqual(tuple(self.ui.items[1].rot), (1, 0, 0, 0)) class FakeObject: def __init__(self, iid=3): self.iid = iid def getID(self): return self.iid def grantPermission(self, name, who): pass class FakeArea: """ Fake an area """ added = 0 name = "Area" def __init__(self, sim, iid): self.sim = sim self.iid = iid self.items = [] def newObject(self, cg): self.added += 1 return defer.succeed(FakeObject()) def getID(self): return self.iid def contain(self, item): self.items.append(item) def takeOut(self, item): self.items.remove(item) class AddServerTests(TestCase, WithDocTests): """ Test the Add object modifier for sim server / area """ def test_docs(self): """ Test the docs """ self.checkDocs(AddServer) def test_addObject(self): """ Test adding an actual object! """ s = FakeSim() ao = AddServer(s) a = FakeArea(s, 2) s.items[2] = a ao.view_addObject(FakeClient(), 1, 2) self.assertEqual(a.added, 1) def test_getAreas(self): """ Test retrieving the list of areas """ s = FakeSim() ao = AddServer(s) a = FakeArea(s, 2) s.items[2] = a areas = ao.view_getAreas(FakeClient()) self.assertEqual(areas, [dict(aid=2, name="Area")]) class FakeConductor: """ A faked out conductor """ implements(IConductor) def __init__(self): self.groups = {} self.badassets = [] self.uint = None self.parent = self def getUI(self): """ return the ui """ return self.uint def getLocalService(self, typ): return self def getGroupInfo(self, agid): return dict(agid=self.groups[agid].agid, name=self.groups[agid].name) def getAssetInfo(self, aid): if aid in self.badassets: return defer.fail(KeyError("Sorry dude")) return defer.succeed(dict(aid=aid, name="Assety", type="fluffer")) def acquireAsset(self, aid): """ just return a fake one """ return defer.succeed(FakeAsset(aid)) def listAssetGroups(self, _offset=0, _limit=0): """ Fake this out """ return [(group, "foo") for group in self.groups.keys()] def listAssets(self, agid, offset=0, limit=100): """ Fake this out """ assets = range(offset, offset + limit) for bad in self.badassets: if bad[1] in assets: assets.remove(bad[1]) return [((agid, asset), "foo", "bar") for asset in assets] class FakeAssetGroup: def __init__(self, agid=0, name="Test"): self.agid = agid self.name = name class AssetSelectorServerTests(TestCase, WithDocTests): """ Test the AssetSelector server interface """ def test_docs(self): """ Test the docs """ self.checkDocs(AssetSelectorServer) def test_getGroupsRestricted(self): """ Test getting the groups available """ c = FakeConductor() ass = AssetSelectorServer(c, None, [1, 2, 3]) result = yield ass.view_getGroups(FakeClient()) self.assertEqual(result, [1, 2, 3]) def test_getGroupsNone(self): """ Test getting the groups available """ c = FakeConductor() ass = AssetSelectorServer(c) result = yield ass.view_getGroups(FakeClient()) self.assertEqual(result, []) @inlineCallbacks def test_getGroupsSingle(self): """ Test getting the groups available """ c = FakeConductor() c.groups[0] = FakeAssetGroup() ass = AssetSelectorServer(c) result = yield ass.view_getGroups(FakeClient()) self.assertEqual(result, [dict(agid=0, name="Test")]) @inlineCallbacks def test_getGroupsMulti(self): """ Test getting the groups available """ c = FakeConductor() c.groups[0] = FakeAssetGroup() c.groups[1] = FakeAssetGroup(1, "Test1") ass = AssetSelectorServer(c) result = yield ass.view_getGroups(FakeClient()) self.assertEqual(result, [dict(agid=0, name="Test"), dict(agid=1, name="Test1")]) @inlineCallbacks def test_getAssetsBadGroup(self): """ Test getting the assets of a restricted group """ c = FakeConductor() ass = AssetSelectorServer(c, None, [1, 2]) try: yield ass.view_getAssets(FakeClient(), 3) except AccessDenied: pass else: self.fail("AccessDenied not raised!") @inlineCallbacks def test_getAssets(self): """ Test getting assets """ c = FakeConductor() c.groups[0] = FakeAssetGroup() ass = AssetSelectorServer(c) result = yield ass.view_getAssets(FakeClient(), 0) expect = [dict(aid=(0, aid), name="Assety", type="fluffer") for aid in range(20)] self.assertEqual(result, expect) @inlineCallbacks def test_getAssetsSomeBad(self): """ Test getting assets """ c = FakeConductor() c.badassets = [(0, 0), (0, 2), (0, 4), (0, 6), (0, 8), (0, 10), (0, 12), (0, 14), (0, 16), (0, 18)] c.groups[0] = FakeAssetGroup() ass = AssetSelectorServer(c) result = yield ass.view_getAssets(FakeClient(), 0) expect = [dict(aid=(0, aid), name="Assety", type="fluffer") for aid in range(1, 20, 2)] self.assertEqual(result, expect) self.flushLoggedErrors(KeyError) @inlineCallbacks def test_getAssetsOffsetLimit(self): """ Test getting assets """ c = FakeConductor() c.groups[0] = FakeAssetGroup() ass = AssetSelectorServer(c) result = yield ass.view_getAssets(FakeClient(), 0, offset=20, limit=5) expect = [dict(aid=(0, aid), name="Assety", type="fluffer") for aid in range(20, 25)] self.assertEqual(result, expect) class FakeAddModifier: """ Faked out """ def __init__(self, uint=None, modifier=None): self.uint = uint self.modifier = modifier def callRemote(self, f, *a, **kw): """ return local call """ return defer.succeed(getattr(self, f)(*a, **kw)) def selectAsset(self): """ return self """ return self def getUI(self): """ return the ui """ return ClassGenerator("mv3d.test.test_ige.FakeAddModifier") def initialize(self, ui, modifier): """ init the ui """ self.ui = ui self.modifier = modifier def start(self): """ start the ui """ self.started = True return defer.succeed(123) def getAreas(self): """ return some areas """ return dict() class AddClientTests(WithFakeUI, WithDocTests): """ Test the add client side """ if noOgre: skip = noOgre def test_docs(self): """ Test the docs """ self.checkDocs(AddClient) def test_initialize(self): """ Test initializing the uI """ ac = AddClient(self.ui, None) self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/add'), ('create', 'WindowsLook/StaticText', 'add/area'), ('create', 'WindowsLook/Combobox', 'add/areaSelect'), ('create', 'WindowsLook/StaticText', 'add/assetText'), ('create', 'WindowsLook/Editbox', 'add/asset'), ('create', 'WindowsLook/Button', 'add/select'), ('requestUICallback', 'EventClicked', 'selectAsset'), ('create', 'WindowsLook/Button', 'add/addButton'), ('requestUICallback', 'EventClicked', 'add'), ('create', 'WindowsLook/StaticText', 'add/status'), ('requestUICallback', 'EventCloseClicked', 'stop')]) @inlineCallbacks def test_selectAsset(self): """ Test selecting an asset """ ac = AddClient(self.ui, FakeAddModifier()) ac.start() yield ac.selectAsset() self.assertEqual(ac.asset.widget.texty, "123") class FakeAssetSelectorServer: """ Just fake it out! """ def callRemote(self, f, *a, **kw): return defer.succeed(getattr(self, f)(*a, **kw)) def getAssets(self, group, offset=0, limit=0): return [dict(aid=(group, 1), name="hi", type="george")] def getGroups(self, offset=0, limit=0): return [dict(agid=2, name="fred")] class AssetSelectorClientTests(WithFakeUI, WithDocTests): """ Test the client side fo the asset selector """ if noOgre: skip = noOgre def test_docs(self): """ Test the docs """ self.checkDocs(AssetSelectorClient) def test_initialize(self): """ Test initializing the uI """ AssetSelectorClient(self.ui, None) self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/assetSelector'), ('create', 'WindowsLook/StaticText', 'assetSelector/groupText'), ('create', 'WindowsLook/Combobox', 'assetSelector/group'), ('create', 'WindowsLook/StaticText', 'assetSelector/assetText'), ('create', 'WindowsLook/MultiColumnList', 'assetSelector/selectList'), ('create', 'WindowsLook/Button', 'assetSelector/select')]) @inlineCallbacks def test_updateGroupList(self): """ Test updating the group list """ ac = AssetSelectorClient(self.ui, FakeAssetSelectorServer()) yield ac.updateGroupList() self.assertLog([('setReadOnly', False), 'addItem 2: fred'], ac.groupCombo.widget) self.assertEqual(ac.groupCombo.widget.items, ["2: fred"]) @inlineCallbacks def test_updateList(self): """ Test updating the asset list """ ac = AssetSelectorClient(self.ui, FakeAssetSelectorServer()) yield ac.updateGroupList() yield ac.updateList() self.assertLog([ 'getColumnCount', 'addColumn ID 0', 'addColumn Type 1', 'addColumn Name 2', "resetList", "Add row ['(2, 1)', 'george', 'hi']"], ac.selectList.widget) class RemoveServerTests(TestCase, WithDocTests): """ Test the remove object server plugin """ def test_docs(self): """ Test the docs """ self.checkDocs(RemoveServer) def test_removeItemsSingle(self): """ Test removing actual items """ c = FakeConductor() s = FakeSim() f = FakeItem((1, 1)) f.parent = s s.items[1, 1] = f a = Area() a.parent = s a.iid = 2, 1 s.items[2, 1] = a a.contain((1, 1)) self.assertEqual(len(s.items), 2) ass = RemoveServer(f) ass.view_removeItems(FakeClient()) self.assertEqual(len(s.items), 1) @inlineCallbacks def test_removeItemsNoContainer(self): """ Test removing an item when it doesn't have a container. This is currently not possible. """ c = FakeConductor() s = FakeSim() f = FakeItem((1, 1)) f.parent = s s.items[1, 1] = f a = Area() a.parent = s a.iid = 2, 1 s.items[2, 1] = a self.assertEqual(len(s.items), 2) ass = RemoveServer(f) try: yield ass.view_removeItems(FakeClient()) self.fail("Did not raise an error!") except KeyError: self.assertEqual(len(s.items), 2) def test_removeItemsMulti(self): """ Test removing actual items """ c = FakeConductor() s = FakeSim() a = Area() a.parent = s a.iid = 2, 1 s.items[2, 1] = a def addItem(iid): f = FakeItem(iid) f.parent = s s.items[iid] = f a.contain(iid) return f items = [addItem((1, x)) for x in range(5)] self.assertEqual(len(s.items), 6) ass = RemoveServer(items[0]) for item in items[1:]: ass.addParent(item) ass.view_removeItems(FakeClient()) self.assertEqual(len(s.items), 1) def test_removeItemsMultiNotAll(self): """ Test removing actual items """ c = FakeConductor() s = FakeSim() a = Area() a.parent = s a.iid = 2, 1 s.items[2, 1] = a def addItem(iid): f = FakeItem(iid) f.parent = s s.items[iid] = f a.contain(iid) return f items = [addItem((1, x)) for x in range(5)] self.assertEqual(len(s.items), 6) ass = RemoveServer(items[0]) for item in items[1:4]: ass.addParent(item) ass.view_removeItems(FakeClient()) self.assertEqual(len(s.items), 2) self.assertIn((1, 4), s.items.keys()) class FactoryServerTests(TestCase, WithDocTests): """ Test the Factory server side modifier """ checkItems = (FactoryServer,) class StringInputWindowTests(WithFakeUI, WithDocTests): """ Test the string input window helper class """ if noOgre: skip = noOgre else: checkItems = (StringInputWindow,) def test_construct(self): """ Test building the ui """ StringInputWindow(self.ui, "test", "test") self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/StringInput'), ('create', 'WindowsLook/StaticText', 'StringInput/message'), ('create', 'WindowsLook/StaticText', 'StringInput/label'), ('create', 'WindowsLook/Editbox', 'StringInput/text'), ('create', 'WindowsLook/Button', 'StringInput/accept')]) class FileSelectorTests(WithFakeUI, WithDocTests): """ Test the file select helper class """ if noOgre: skip = noOgre else: checkItems = (FileSelector,) def setUp(self): """ Set up a fake directory and stuff """ self.directory = self.mktemp() os.makedirs(self.directory) file1 = open(os.path.join(self.directory, "test"), "w") file1.write("hello") file1.close() os.mkdir(os.path.join(self.directory, "testdir")) WithFakeUI.setUp(self) def test_construct(self): """ Test building the ui """ FileSelector(self.ui, "test", "test") self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/FileSelector'), ('create', 'WindowsLook/StaticText', 'FileSelector/pathText'), ('create', 'WindowsLook/Combobox', 'FileSelector/pathSelect'), ('create', 'WindowsLook/Button', 'FileSelector/backButton'), ('create', 'WindowsLook/Button', 'FileSelector/upButton'), ('create', 'WindowsLook/MultiColumnList', 'FileSelector/fileList'), ('create', 'WindowsLook/StaticText', 'FileSelector/fileText'), ('create', 'WindowsLook/Editbox', 'FileSelector/file'), ('create', 'WindowsLook/Button', 'FileSelector/openButton'), ('create', 'WindowsLook/StaticText', 'FileSelector/typeText'), ('create', 'WindowsLook/Combobox', 'FileSelector/fileType'), ('create', 'WindowsLook/Button', 'FileSelector/cancelButton')]) def test_start(self): """ Test starting up the file selector """ fsel = FileSelector(self.ui) self.clearLog() fsel.start() self.assertLog([('displayWindow', 'Root/FileSelector'), ('requestUICallback', 'EventClicked', 'open'), ('requestUICallback', 'EventClicked', 'cancel'), ('requestUICallback', 'EventListSelectionChanged', 'changePath'), ('requestUICallback', 'EventClicked', 'back'), ('requestUICallback', 'EventClicked', 'up'), ('requestUICallback', 'EventSelectionChanged', 'updateFile')]) def test_getFiles(self): """ Test adding directory contents to the listbox """ fsel = FileSelector(self.ui) fsel.pathSelect.text = self.directory self.clearLog(fsel.fileList.widget) fsel.getFiles() self.assertEqual(fsel.fileList.widget.log[0], "resetList") if sys.platform.startswith("win"): self.failUnless(fsel.fileList.widget.log[1 ].startswith("Add row ['', 'test', ")) self.failUnless(fsel.fileList.widget.log[2 ].startswith("Add row ['d', 'testdir', ")) else: self.failUnless(fsel.fileList.widget.log[2 ].startswith("Add row ['', 'test', ")) self.failUnless(fsel.fileList.widget.log[1 ].startswith("Add row ['d', 'testdir', ")) def test_openDir(self): """ Test the open function using a dir """ fsel = FileSelector(self.ui) fsel.pathSelect.text = self.directory fsel.file.text = "testDir" fsel.deferred = Deferred() fsel.open() if sys.platform.startswith("win"): self.assertEqual(fsel.pathSelect.text, os.path.join(self.directory, "testDir")) self.assertEqual(fsel.pathHistory, ['', os.path.join(self.directory, "testDir")]) else: # TODO: this is probably incorrect, but do we care? self.assertEqual(fsel.pathSelect.text, os.path.join(self.directory)) self.assertEqual(fsel.pathHistory, ['']) def test_updateFileNoSelection(self): """ Test updating the file when there isn't a selection """ fsel = FileSelector(self.ui) fsel.updateFile() self.assertEqual(fsel.file.text, "") def test_updateFilePath(self): """ Test the updateFile function with a path """ fsel = FileSelector(self.ui) fsel.pathSelect.text = self.directory fsel.fileList.widget.selection = [FakeText(""), FakeText("testDir")] fsel.updateFile() if sys.platform.startswith("win"): self.assertEqual(fsel.pathSelect.text, os.path.join(self.directory, "testDir")) self.assertEqual(fsel.pathHistory, ['', os.path.join(self.directory, "testDir")]) else: # TODO: this is probably wrong but do we really care? self.assertEqual(fsel.pathSelect.text, os.path.join(self.directory)) self.assertEqual(fsel.pathHistory, ['']) class FakeFactoryModifier: """ fake version """ factory = None produced = False template = None def __init__(self, inp=False): self.input = inp self.factoryUI = ClassGenerator("mv3d.test.test_ige.FakeFactoryUI") def callRemote(self, function, *args, **keys): """ call a local function """ return defer.succeed(getattr(self, function)(*args, **keys)) def setFactory(self, classgen): """ set it """ self.factory = classgen if classgen == "template": return self def setTemplate(self, template): """ set it """ self.template = template def requiresInput(self): """ just return it """ return self.input def getFactoryUI(self): """ return it """ return self.factoryUI def produce(self): """ record it """ self.produced = True return 1234 class FakeFactoryUI: """ Fake ui """ started = False def __init__(self, uint, factory): self.uint = uint self.factory = factory def start(self): """ set it """ self.started = True return defer.succeed(True) class FactoryClientTests(WithFakeUI, WithDocTests): """ Test the Factory client side interface """ if noOgre: skip = noOgre else: checkItems = (FactoryClient,) def test_construct(self): """ Construct the UI and make sure everything is created """ FactoryClient(self.ui, None) self.assertLog([('create', 'WindowsLook/FrameWindow', 'Root/Factory'), ('create', 'WindowsLook/MultiColumnList', 'Factory/selectList'), ('create', 'WindowsLook/Button', 'Factory/addAsset'), ('create', 'WindowsLook/Button', 'Factory/addClass'), ('create', 'WindowsLook/Button', 'Factory/addTemplate'), ('create', 'WindowsLook/Button', 'Factory/removeButton'), ('create', 'WindowsLook/Button', 'Factory/produceButton')]) def test_start(self): """ Start up the ui and make sure callbacks are registered """ factory = FactoryClient(self.ui, None) self.clearLog() factory.start() self.assertLog([('requestUICallback', 'EventClicked', 'addAsset'), ('requestUICallback', 'EventClicked', 'addClass'), ('requestUICallback', 'EventClicked', 'addTemplate'), ('requestUICallback', 'EventClicked', 'produce'), ('requestUICallback', 'EventCloseClicked', 'closed'), ('displayWindow', 'Root/Factory')]) def test_addItem(self): """ Test the addItem function """ factory = FactoryClient(self.ui, None) cgen = ClassGenerator("mv3d.test.Thingy") factory.addItem("Thingy", cgen) self.assertEqual(factory.selected, {"0: Thingy":cgen}) def test_addTwoItems(self): """ Test the addItem function running twice """ factory = FactoryClient(self.ui, None) cgen = ClassGenerator("mv3d.test.Thingy") factory.addItem("Thingy", cgen) cgen2 = ClassGenerator("mv3d.test.Thingy2") factory.addItem("NewThingy", cgen2) self.assertEqual(factory.selected, {"0: Thingy":cgen, "1: NewThingy":cgen2}) @inlineCallbacks def test_produceNoSelection(self): """ Test that calling produce with no selection does nothing """ factory = FactoryClient(self.ui, None) self.clearLog() result = yield factory.produce() self.assertIdentical(result, None) self.assertLog([]) @inlineCallbacks def test_produceSimple(self): """ Test producing when there is no need for a ui """ factory = FactoryClient(self.ui, FakeFactoryModifier()) self.clearLog() factory.selectList.widget.selection = [FakeText("0:blah")] factory.selected["0:blah"] = "hello" result = yield factory.produce() self.assertEqual(result, 1234) self.assertEqual(factory.modifier.produced, True) self.assertEqual(factory.factoryUI, None) self.assertEqual(factory.modifier.factory, "hello") self.assertLog([]) @inlineCallbacks def test_produceWithUI(self): """ Test producing when there is a ui """ factory = FactoryClient(self.ui, FakeFactoryModifier(True)) self.clearLog() factory.selectList.widget.selection = [FakeText("0:blah")] factory.selected["0:blah"] = "hello" result = yield factory.produce() self.assertEqual(result, 1234) self.assertEqual(factory.modifier.produced, True) self.failUnless(isinstance(factory.factoryUI, FakeFactoryUI)) self.failUnless(factory.factoryUI.started) self.assertEqual(factory.modifier.factory, "hello") self.assertLog([]) @inlineCallbacks def test_produceTemplate(self): """ Test producing when there is a template """ temp = self.mktemp() os.makedirs(temp) template = open(os.path.join(temp, "test"), "w") template.write("hello") template.close() factory = FactoryClient(self.ui, FakeFactoryModifier()) self.clearLog() factory.selectList.widget.selection = [FakeText("0:blah")] factory.selected["0:blah"] = ("template", os.path.join(temp, "test")) result = yield factory.produce() self.assertEqual(result, 1234) self.assertEqual(factory.modifier.produced, True) self.assertEqual(factory.factoryUI, None) self.assertEqual(factory.modifier.factory, "template") self.assertEqual(factory.modifier.template, "hello") self.assertLog([]) class MiscTests(TestCase): """ Test the functions in client """ if noOgre: skip = noOgre def test_absmax(self): """ Test the absmax function """ self.assertEqual(absmax(10, 5), 5) self.assertEqual(absmax(-10, 5), -5) self.assertEqual(absmax(2, 10), 2) self.assertEqual(absmax(-2, 10), -2) self.assertRaises(AssertionError, absmax, 2, 0) self.assertEqual(absmax(0, 4), 0)