Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/addontests.py7
-rw-r--r--tests/constraintstests.py42
-rw-r--r--tests/enginetests.py182
-rw-r--r--tests/linear_creatortests.py79
-rw-r--r--tests/probetests.py84
-rw-r--r--tests/propertiestests.py56
-rw-r--r--tests/translatortests.py131
7 files changed, 457 insertions, 124 deletions
diff --git a/tests/addontests.py b/tests/addontests.py
index ceaee2b..5a48e42 100644
--- a/tests/addontests.py
+++ b/tests/addontests.py
@@ -47,4 +47,9 @@ class AddonTest(unittest.TestCase):
def test_get_addon_meta(self):
addon._cache = None
meta = addon.get_addon_meta("BubbleMessage")
- assert set(meta.keys()) == set(['type', 'mandatory_props', 'class', 'display_name', 'name', 'icon',])
+ keys = meta.keys()
+ assert 'mandatory_props' in keys
+ assert 'class' in keys
+ assert 'display_name' in keys
+ assert 'name' in keys
+ assert 'icon' in keys
diff --git a/tests/constraintstests.py b/tests/constraintstests.py
index 4e19a92..a5ccf26 100644
--- a/tests/constraintstests.py
+++ b/tests/constraintstests.py
@@ -240,5 +240,47 @@ class FileConstraintTest(unittest.TestCase):
except FileConstraintError:
pass
+class ResourceConstraintTest(unittest.TestCase):
+ def test_valid_names(self):
+ name1 = "file_" + unicode(uuid.uuid1()) + ".png"
+ name2 = unicode(uuid.uuid1()) + "_" + unicode(uuid.uuid1()) + ".extension"
+ name3 = "/home/user/.sugar/_random/new_image1231_" + unicode(uuid.uuid1()).upper() + ".mp3"
+ name4 = "a_" + unicode(uuid.uuid1())
+ name5 = ""
+
+ cons = ResourceConstraint()
+
+ # All of those names should pass without exceptions
+ cons.validate(name1)
+ cons.validate(name2)
+ cons.validate(name3)
+ cons.validate(name4)
+ cons.validate(name5)
+
+ def test_invalid_names(self):
+ bad_name1 = ".jpg"
+ bad_name2 = "_.jpg"
+ bad_name3 = "_" + unicode(uuid.uuid1())
+
+ cons = ResourceConstraint()
+
+ try:
+ cons.validate(bad_name1)
+ assert False, "%s should not be a valid resource name" % bad_name1
+ except ResourceConstraintError:
+ pass
+
+ try:
+ cons.validate(bad_name2)
+ assert False, "%s should not be a valid resource name" % bad_name2
+ except ResourceConstraintError:
+ pass
+
+ try:
+ cons.validate(bad_name3)
+ assert False, "%s should not be a valid resource name" % bad_name3
+ except ResourceConstraintError:
+ pass
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/enginetests.py b/tests/enginetests.py
index 30d68de..1723954 100644
--- a/tests/enginetests.py
+++ b/tests/enginetests.py
@@ -25,37 +25,98 @@ and event filters. Those are in their separate test module
"""
import unittest
+from functools import partial
+from uuid import uuid1
from sugar.tutorius.tutorial import Tutorial
from sugar.tutorius.engine import TutorialRunner
+import sugar.tutorius.engine as engine
+from sugar.tutorius.actions import Action
from sugar.tutorius.filters import EventFilter
from actiontests import CountAction
+class MockProbeMgrMultiAddons(object):
+ def __init__(self):
+ self.action_dict = {}
+ self.event_dict = {}
+ self.event_cb_dict = {}
+
+ self._action_installed_cb_list = []
+ self._install_error_cb_list = []
+ self._event_subscribed_cb_list = []
+ self._subscribe_error_cb_list = []
+
+ currentActivity = property(fget=lambda s:s, fset=lambda s, v: v)
+
+ def run_install_cb(self, action_number, action):
+ self._action_installed_cb_list[action_number](str(uuid1()))
+
+ def run_install_error_cb(self, action_number):
+ self._install_error_cb_list[action_number](Exception("Could not install action..."))
+
+ def run_subscribe_cb(self, event_number):
+ self._event_subscribed_cb_list[event_number](str(uuid1()))
+
+ def run_subscribe_error(self, event_number):
+ self._subscribe_error_cb_list[event_number](Exception("Could not subscribe to event"))
+
+ def install(self, action, action_installed_cb, error_cb):
+ action_address = str(uuid1())
+ self.action_dict[action_address] = action
+ self._action_installed_cb_list.append(action_installed_cb)
+ self._install_error_cb_list.append(error_cb)
+
+ def update(self, action_address, new_action):
+ self.action_dict[action_address] = new_action
+
+ def uninstall(self, action_address):
+ del self.action_dict[action_address]
+
+ def subscribe(self, event, notif_cb, subscribe_cb, error_cb):
+ event_address = str(uuid1())
+ self.event_dict[event_address] = event
+ self.event_cb_dict[event_address] = notif_cb
+ self._event_subscribed_cb_list.append(subscribe_cb)
+ self._subscribe_error_cb_list.append(error_cb)
+
+ def unsubscribe(self, address):
+ for (event_address, other_event) in self.event_dict.values():
+ if event == other_event:
+ del self.event_dict[address]
+ break
class MockProbeMgr(object):
def __init__(self):
self.action = None
self.event = None
self.cB = None
+
+ self._action_installed_cb = None
+ self._install_error_cb = None
def doCB(self):
self.cB(self.event)
currentActivity = property(fget=lambda s:s, fset=lambda s, v: v)
- def install(self, action, block=False):
+ def install(self, action, action_installed_cb, error_cb):
self.action = action
+ self._action_installed_cb = action_installed_cb
+ self._install_error_cb = partial(error_cb, action)
- def update(self, action, newaction, block=False):
+ def update(self, action_address, newaction):
self.action = newaction
- def uninstall(self, action, block=False):
+ def uninstall(self, action_address):
self.action = None
- def subscribe(self, event, callback):
+ def subscribe(self, event, notif_cb, event_sub_cb, error_cb):
self.event = event
- self.cB = callback
- self.event.install_handlers(callback)
+ self.cB = notif_cb
+ self.event.install_handlers(notif_cb)
+ # Save the callbacks for this action
+ self.event_sub_cB = event_sub_cb
+ self._subscribe_error_cb = error_cb
return str(event)
def unsubscribe(self, address):
@@ -63,9 +124,104 @@ class MockProbeMgr(object):
class MockEvent(EventFilter):
pass
+
+class TestRunnerStates(unittest.TestCase):
+ def setUp(self):
+ self.pM = MockProbeMgr()
+ self.tutorial = Tutorial("TutorialRunner")
+ self.state_name = self.tutorial.add_state()
+ self.tutorial.update_transition(Tutorial.INITIAL_TRANSITION_NAME,
+ None, self.state_name)
+ self.action = CountAction()
+ self.tutorial.add_action(self.state_name, self.action)
+ self.event = MockEvent()
+ self.tutorial.add_transition(self.state_name, (self.event, Tutorial.END))
+
+ self.runner = TutorialRunner(self.tutorial, self.pM)
+
+ def test_setup_states(self):
+ assert self.runner._runner_state == engine.RUNNER_STATE_IDLE, "Idle should be the initial state for the runner"
+
+ self.runner.start()
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_ACTIONS, "Setup Actions State should be entered after start"
+ self.pM._action_installed_cb('action1')
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "State should be Setup Events after all actions are installed"
+
+ self.pM.event_sub_cB('event1')
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_AWAITING_NOTIFICATIONS, "State should be Awaiting Notifications once all events are installed"
+
+ def test_setup_actions_errors(self):
+ self.runner.start()
+
+ self.pM._install_error_cb(Exception("Fake Exception"))
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "Setup Events should be reached after error on action installation"
+
+ self.pM._subscribe_error_cb(Exception("Fake Exception"))
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_AWAITING_NOTIFICATIONS, "State Awaiting Notifications should be reached after event subscribe error"
+
+ def test_stop_in_actions(self):
+ self.runner.start()
+
+ self.runner.stop()
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_ACTIONS, "Stop state should not be reached"
+
+ self.pM._action_installed_cb('action1')
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_IDLE
+
+ def test_stop_in_events(self):
+ self.runner.start()
+ self.pM._action_installed_cb('action1')
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "Setup events state should be reached after all actions installed"
+
+ self.runner.stop()
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "Tutorial should not be stopped until all events have been confirmed"
+ self.pM.event_sub_cB('event1')
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_IDLE, "Tutorial should have been stopped right after the last event was confirmed"
+
+class TestInstallationStates(unittest.TestCase):
+ def setUp(self):
+ self.pM = MockProbeMgrMultiAddons()
+ self.tutorial = Tutorial("TutorialRunner")
+ self.state_name = self.tutorial.add_state()
+ self.tutorial.update_transition(Tutorial.INITIAL_TRANSITION_NAME,
+ None, self.state_name)
+ self.action1 = CountAction()
+ self.tutorial.add_action(self.state_name, self.action1)
+ self.action2 = CountAction()
+ self.tutorial.add_action(self.state_name, self.action2)
+
+ self.event = MockEvent()
+ self.tutorial.add_transition(self.state_name, (self.event, Tutorial.END))
+ self.event2 = MockEvent()
+ self.tutorial.add_transition(self.state_name, (self.event2, Tutorial.INIT))
+
+ self.runner = TutorialRunner(self.tutorial, self.pM)
+
+ def test_multiple_actions(self):
+ self.runner.start()
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_ACTIONS, "Runner should be in Setup Actions state"
+
+ self.pM.run_install_cb(1, self.action2)
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_ACTIONS, "Runner should still be in Setup Actions state after a single action confirmation callback"
+
+ self.pM.run_install_cb(0, self.action1)
+
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "Runner should be in Setup Events state after all actions are installed"
+ self.pM.run_subscribe_cb(1)
+ assert self.runner._runner_state == engine.RUNNER_STATE_SETUP_EVENTS, "Runner should still be in Setup Events state when not all event installations are confirmed"
-
class TutorialRunnerTest(unittest.TestCase):
"""
This class needs to test the TutorialRunner
@@ -73,7 +229,6 @@ class TutorialRunnerTest(unittest.TestCase):
def setUp(self):
self.pM = MockProbeMgr()
-
def tearDown(self):
self.pM = None
@@ -87,19 +242,20 @@ class TutorialRunnerTest(unittest.TestCase):
tutorial.add_transition(state_name, (event, Tutorial.END))
runner = TutorialRunner(tutorial, self.pM)
+
runner.start()
+ self.pM.event_sub_cB('event1')
- assert runner._state == state_name, "Current state is: %s"%runner._state
+ assert runner._state == state_name, "Current tutorial state is: %s"%runner._state
assert self.pM.action == None
assert self.pM.event == event
-
+
event.do_callback()
- assert runner._state == Tutorial.END, "Current state is: %s"%runner._state
+
+ assert runner._state == Tutorial.END, "Current tutorial state is: %s"%runner._state
assert self.pM.action == None, "Current action is %s"%str(self.pM.action)
assert self.pM.event == None, "Current event is %s"%str(self.pM.event)
-
-
# Limit cases
def testEmptyTutorial(self):
tutorial = Tutorial("TutorialRunner")
diff --git a/tests/linear_creatortests.py b/tests/linear_creatortests.py
deleted file mode 100644
index e3c30c1..0000000
--- a/tests/linear_creatortests.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright (C) 2009, Tutorius.org
-# Greatly influenced by sugar/activity/namingalert.py
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-from sugar.tutorius.core import *
-from sugar.tutorius.actions import *
-from sugar.tutorius.filters import *
-from sugar.tutorius.linear_creator import *
-from sugar.tutorius.addons.triggereventfilter import *
-from actiontests import CountAction
-import unittest
-
-class CreatorTests(unittest.TestCase):
-
- def test_simple_usage(self):
- creator = LinearCreator()
- fsm_name = "SimpleUsageTest"
-
- creator.set_name(fsm_name)
-
- # Generate an FSM using the steps
- creator.action(CountAction())
- creator.action(CountAction())
-
- creator.event(TriggerEventFilter())
-
- creator.action(CountAction())
-
- creator.event(TriggerEventFilter())
-
- fsm = creator.generate_fsm()
-
- # Make sure everything worked!
- assert fsm.name == fsm_name, "Name was not set properly"
-
- init_state = fsm.get_state_by_name("INIT")
-
- assert len(init_state.get_action_list()) == 2, "Creator did not insert all the actions"
-
- assert init_state.get_event_filter_list()[0][1] == "State 1" , "expected next state to be 'State 1' but got %s" % init_state.get_event_filter_list()[0][1]
-
- state1 = fsm.get_state_by_name("State 1")
-
- assert len(state1.get_action_list()) == 1, "Creator did not insert all the actions"
-
- assert state1.get_event_filter_list()[0][1] == "State 2"
-
- # Make sure we have the final state and that it's empty
- state2 = fsm.get_state_by_name("State2")
-
- assert len(state2.get_action_list()) == 0, "Creator inserted extra actions on wrong state"
-
- assert len(state2.get_event_filter_list()) == 0, "Creator assigner events to the final state"
-
- creator.action(CountAction())
-
- fsm = creator.generate_fsm()
-
- state2 = fsm.get_state_by_name("State2")
-
- assert len(state2.get_action_list()) == 1, "Creator did not add the action"
-
- assert len(state2.get_event_filter_list()) == 0, "Creator assigner events to the final state"
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/probetests.py b/tests/probetests.py
index 59072e5..37748d8 100644
--- a/tests/probetests.py
+++ b/tests/probetests.py
@@ -85,40 +85,43 @@ class MockProbeProxy(object):
@param activityName unique activity id. Must be a valid dbus bus name.
"""
self.MockAction = None
+ self.MockActionName = None
self.MockActionUpdate = None
self.MockEvent = None
self.MockCB = None
self.MockAlive = True
self.MockEventAddr = None
+ self.MockAddressCallback = None
def isAlive(self):
return self.MockAlive
- def install(self, action, block=False):
+ def install(self, action, action_installed_cb, error_cb):
self.MockAction = action
+ self.MockAddressCallback_install = action_installed_cb
+ self.MockInstallErrorCallback = error_cb
self.MockActionUpdate = None
return None
- def update(self, action, newaction, block=False):
- self.MockAction = action
+ def update(self, action_address, newaction, block=False):
+ self.MockActionAddress = action_address
self.MockActionUpdate = newaction
return None
- def uninstall(self, action, block=False):
+ def uninstall(self, action_address):
self.MockAction = None
self.MockActionUpdate = None
return None
- def subscribe(self, event, callback, block=True):
+ def subscribe(self, event, notif_cb, subscribe_cb, error_cb):
#Do like the current Probe
- if not block:
- raise RuntimeError("This function does not allow non-blocking mode yet")
-
- self.MockEvent= event
- self.MockCB = callback
+ self.MockEvent = event
+ self.MockCB = notif_cb
+ self.MockSubscribeCB = subscribe_cb
+ self.MockSubscriptionErrorCb = error_cb
return str(id(event))
- def unsubscribe(self, address, block=True):
+ def unsubscribe(self, address):
self.MockEventAddr = address
return None
@@ -343,29 +346,34 @@ class ProbeManagerTest(unittest.TestCase):
act2 = self.probeManager.get_registered_probes_list("act2")[0][1]
ad1 = MockAddon()
+ ad1_address = "Address1"
+ def callback(value):
+ pass
+ def error_cb():
+ pass
#ErrorCase: install, update, uninstall without currentActivity
#Action functions should do a warning if there is no activity
- self.assertRaises(RuntimeWarning, self.probeManager.install, ad1)
- self.assertRaises(RuntimeWarning, self.probeManager.update, ad1, ad1)
- self.assertRaises(RuntimeWarning, self.probeManager.uninstall, ad1)
+ self.assertRaises(RuntimeWarning, self.probeManager.install, ad1_address, ad1, callback)
+ self.assertRaises(RuntimeWarning, self.probeManager.update, ad1_address, ad1)
+ self.assertRaises(RuntimeWarning, self.probeManager.uninstall, ad1_address)
assert act1.MockAction is None, "Action should not be installed on inactive proxy"
assert act2.MockAction is None, "Action should not be installed on inactive proxy"
self.probeManager.currentActivity = "act1"
- self.probeManager.install(ad1)
+ self.probeManager.install(ad1, callback, error_cb)
assert act1.MockAction == ad1, "Action should have been installed"
assert act2.MockAction is None, "Action should not be installed on inactive proxy"
- self.probeManager.update(ad1, ad1)
+ self.probeManager.update(ad1_address, ad1)
assert act1.MockActionUpdate == ad1, "Action should have been updated"
assert act2.MockActionUpdate is None, "Should not update on inactive"
self.probeManager.currentActivity = "act2"
- self.probeManager.uninstall(ad1)
- assert act1.MockAction == ad1, "Action should still be installed"
+ self.probeManager.uninstall(ad1_address)
+ assert act1.MockActionAddress == ad1_address, "Action should still be installed"
self.probeManager.currentActivity = "act1"
- self.probeManager.uninstall(ad1)
+ self.probeManager.uninstall(ad1_address)
assert act1.MockAction is None, "Action should be uninstalled"
def test_events(self):
@@ -379,17 +387,19 @@ class ProbeManagerTest(unittest.TestCase):
ad2.i, ad2.s = (2, "test2")
cb1 = lambda *args: None
+ install_cb1 = lambda *args:None
+ error_cb1 = lambda *args:None
cb2 = lambda *args: None
#ErrorCase: unsubscribe and subscribe without current activity
#Event functions should do a warning if there is no activity
- self.assertRaises(RuntimeWarning, self.probeManager.subscribe, ad1, cb1)
+ self.assertRaises(RuntimeWarning, self.probeManager.subscribe, ad1, cb1, install_cb1, error_cb1)
self.assertRaises(RuntimeWarning, self.probeManager.unsubscribe, None)
assert act1.MockEvent is None, "No event should be on act1"
assert act2.MockEvent is None, "No event should be on act2"
self.probeManager.currentActivity = "act1"
- self.probeManager.subscribe(ad1, cb1)
+ self.probeManager.subscribe(ad1, cb1, install_cb1, error_cb1)
assert act1.MockEvent == ad1, "Event should have been installed"
assert act1.MockCB == cb1, "Callback should have been set"
assert act2.MockEvent is None, "No event should be on act2"
@@ -398,7 +408,6 @@ class ProbeManagerTest(unittest.TestCase):
assert act1.MockEventAddr == "SomeAddress", "Unsubscribe should have been called"
assert act2.MockEventAddr is None, "Unsubscribe should not have been called"
-
class ProbeProxyTest(unittest.TestCase):
def setUp(self):
dbus.SessionBus = MockSessionBus
@@ -422,46 +431,59 @@ class ProbeProxyTest(unittest.TestCase):
action.i, action.s = 5, "action"
action2 = MockAddon()
action2.i, action2.s = 10, "action2"
+ action2_address = "Addr2"
#Check if the installed action is the good one
address = "Addr1"
+
+ def action_installed_cb(value):
+ pass
+ def error_cb(value):
+ pass
+
#Set the return value of probe install
self.mockObj.MockRet["install"] = address
- self.probeProxy.install(action, block=True)
+ self.probeProxy.install(action, action_installed_cb, error_cb)
assert pickle.loads(self.mockObj.MockCall["install"]["args"][0]) == action, "1 argument, the action"
+ self.mockObj.MockCall["install"]["kwargs"]["reply_handler"](address)
#ErrorCase: Update should fail on noninstalled actions
- self.assertRaises(RuntimeWarning, self.probeProxy.update, action2, action2, block=True)
+ self.assertRaises(RuntimeWarning, self.probeProxy.update, action2_address, action2)
#Test the update
- self.probeProxy.update(action, action2, block=True)
+ self.probeProxy.update(address, action2)
args = self.mockObj.MockCall["update"]["args"]
assert args[0] == address, "arg 1 should be the action address"
assert pickle.loads(args[1]) == action2._props, "arg2 should be the new action properties"
#ErrorCase: Uninstall on not installed action (silent fail)
#Test the uninstall
- self.probeProxy.uninstall(action2, block=True)
+ self.probeProxy.uninstall(action2_address)
assert not "uninstall" in self.mockObj.MockCall, "Uninstall should not be called if action is not installed"
- self.probeProxy.uninstall(action, block=True)
+ self.probeProxy.uninstall(address)
assert self.mockObj.MockCall["uninstall"]["args"][0] == address, "1 argument, the action address"
def test_events(self):
event = MockAddon()
event.i, event.s = 5, "event"
+ event_address = 'event1'
event2 = MockAddon()
event2.i, event2.s = 10, "event2"
+ event_address2 = 'event2'
def callback(event):
global message_box
message_box = event
+ subs_cb = lambda *args : None
+ error_cb = lambda *args : None
#Check if the installed event is the good one
address = "Addr1"
#Set the return value of probe subscribe
self.mockObj.MockRet["subscribe"] = address
- self.probeProxy.subscribe(event, callback, block=True)
+ self.probeProxy.subscribe(event, callback, subs_cb, error_cb)
+ self.probeProxy._ProbeProxy__update_event(event, callback, subs_cb, event_address)
assert pickle.loads(self.mockObj.MockCall["subscribe"]["args"][0]) == event, "1 argument, the event"
#Call the callback with the event
@@ -478,11 +500,11 @@ class ProbeProxyTest(unittest.TestCase):
#ErrorCase: unsubcribe for non subscribed event
#Test the unsubscribe
- self.probeProxy.unsubscribe("otheraddress", block=True)
+ self.probeProxy.unsubscribe(event_address2)
assert not "unsubscribe" in self.mockObj.MockCall, "Unsubscribe should not be called if event is not subscribeed"
- self.probeProxy.unsubscribe(address, block=True)
- assert self.mockObj.MockCall["unsubscribe"]["args"][0] == address, "1 argument, the event address"
+ self.probeProxy.unsubscribe(event_address)
+ assert self.mockObj.MockCall["unsubscribe"]["args"][0] == event_address, "1 argument, the event address"
#ErrorCase: eventOccured triggered by uninstalled event
#Test the callback with unregistered event
diff --git a/tests/propertiestests.py b/tests/propertiestests.py
index 2494ea6..cb8e884 100644
--- a/tests/propertiestests.py
+++ b/tests/propertiestests.py
@@ -540,6 +540,62 @@ class TFilePropertyTest(unittest.TestCase):
except FileConstraintError:
pass
+class TResourcePropertyTest(unittest.TestCase):
+ def test_valid_names(self):
+ class klass1(TPropContainer):
+ res = TResourceProperty()
+
+ name1 = "file_" + unicode(uuid.uuid1()) + ".png"
+ name2 = unicode(uuid.uuid1()) + "_" + unicode(uuid.uuid1()) + ".extension"
+ name3 = "/home/user/.sugar/_random/new_image1231_" + unicode(uuid.uuid1()).upper() + ".mp3"
+ name4 = "a_" + unicode(uuid.uuid1())
+ name5 = ""
+
+ obj1 = klass1()
+
+ obj1.res = name1
+ assert obj1.res == name1, "Could not assign the valid name correctly : %s" % name1
+
+ obj1.res = name2
+ assert obj1.res == name2, "Could not assign the valid name correctly : %s" % name2
+
+ obj1.res = name3
+ assert obj1.res == name3, "Could not assign the valid name correctly : %s" % name3
+
+ obj1.res = name4
+ assert obj1.res == name4, "Could not assign the valid name correctly : %s" % name4
+
+ obj1.res = name5
+ assert obj1.res == name5, "Could not assign the valid name correctly : %s" % name5
+
+ def test_invalid_names(self):
+ class klass1(TPropContainer):
+ res = TResourceProperty()
+
+ bad_name1 = ".jpg"
+ bad_name2 = "_.jpg"
+ bad_name3 = "_" + unicode(uuid.uuid1())
+
+ obj1 = klass1()
+
+ try:
+ obj1.res = bad_name1
+ assert False, "A invalid name was accepted : %s" % bad_name1
+ except ResourceConstraintError:
+ pass
+
+ try:
+ obj1.res = bad_name2
+ assert False, "A invalid name was accepted : %s" % bad_name2
+ except ResourceConstraintError:
+ pass
+
+ try:
+ obj1.res = bad_name3
+ assert False, "A invalid name was accepted : %s" % bad_name3
+ except ResourceConstraintError:
+ pass
+
class TAddonPropertyTest(unittest.TestCase):
def test_wrong_value(self):
class klass1(TPropContainer):
diff --git a/tests/translatortests.py b/tests/translatortests.py
new file mode 100644
index 0000000..3b5ca6f
--- /dev/null
+++ b/tests/translatortests.py
@@ -0,0 +1,131 @@
+# Copyright (C) 2009, Tutorius.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import os
+import uuid
+
+from sugar.tutorius.translator import *
+from sugar.tutorius.properties import *
+from sugar.tutorius.tutorial import *
+from sugar.tutorius.vault import Vault
+from sugar.tutorius import addon
+
+##############################################################################
+## Helper classes
+class ResourceAction(TPropContainer):
+ resource = TResourceProperty()
+
+ def __init__(self):
+ TPropContainer.__init__(self)
+
+class NestedResource(TPropContainer):
+ nested = TAddonProperty()
+
+ def __init__(self):
+ TPropContainer.__init__(self)
+ self.nested = ResourceAction()
+
+class ListResources(TPropContainer):
+ nested_list = TAddonListProperty()
+
+ def __init__(self):
+ TPropContainer.__init__(self)
+ self.nested_list = [ResourceAction(), ResourceAction()]
+
+##
+##############################################################################
+
+class ResourceTranslatorTests(unittest.TestCase):
+ temp_path = "/tmp/"
+ file_name = "file.txt"
+
+ def setUp(self):
+ # Generate a tutorial ID
+ self.tutorial_id = unicode(uuid.uuid1())
+
+ # Create a dummy fsm
+ self.fsm = Tutorial("TestTutorial1")
+ # Add a few states
+ act1 = addon.create('BubbleMessage', message="Hi", position=[300, 450])
+ ev1 = addon.create('GtkWidgetEventFilter', "0.12.31.2.2", "clicked")
+ act2 = addon.create('BubbleMessage', message="Second message", position=[250, 150], tail_pos=[1,2])
+ self.fsm.add_action("INIT", act1)
+ st2 = self.fsm.add_state((act2,))
+ self.fsm.add_transition("INIT",(ev1, st2))
+
+ # Create a dummy metadata dictionnary
+ self.test_metadata_dict = {}
+ self.test_metadata_dict['name'] = 'TestTutorial1'
+ self.test_metadata_dict['guid'] = unicode(self.tutorial_id)
+ self.test_metadata_dict['version'] = '1'
+ self.test_metadata_dict['description'] = 'This is a test tutorial 1'
+ self.test_metadata_dict['rating'] = '3.5'
+ self.test_metadata_dict['category'] = 'Test'
+ self.test_metadata_dict['publish_state'] = 'false'
+ activities_dict = {}
+ activities_dict['org.laptop.tutoriusactivity'] = '1'
+ activities_dict['org.laptop,writus'] = '1'
+ self.test_metadata_dict['activities'] = activities_dict
+
+ Vault.saveTutorial(self.fsm, self.test_metadata_dict)
+
+ try:
+ os.mkdir(self.temp_path)
+ except:
+ pass
+ abs_file_path = os.path.join(self.temp_path, self.file_name)
+ new_file = file(abs_file_path, "w")
+
+ # Add the resource in the Vault
+ self.res_name = Vault.add_resource(self.tutorial_id, abs_file_path)
+
+ # Use a dummy prob manager - we shouldn't be using it
+ self.prob_man = object()
+
+ self.translator = ResourceTranslator(self.prob_man, self.tutorial_id)
+
+ def tearDown(self):
+ Vault.deleteTutorial(self.tutorial_id)
+
+ os.unlink(os.path.join(self.temp_path, self.file_name))
+
+ def test_translate(self):
+ # Create an action with a resource property
+ res_action = ResourceAction()
+ res_action.resource = self.res_name
+
+ self.translator.translate(res_action)
+
+ assert getattr(res_action, "resource").type == "file", "Resource was not converted to file"
+
+ assert res_action.resource.default == Vault.get_resource_path(self.tutorial_id, self.res_name), "Transformed resource path is not the same as the one given by the vault"
+
+ def test_recursive_translate(self):
+ nested_action = NestedResource()
+
+ self.translator.translate(nested_action)
+
+ assert getattr(getattr(nested_action, "nested"), "resource").type == "file", "Nested resource was not converted properly"
+
+ def test_list_translate(self):
+ list_action = ListResources()
+
+ self.translator.translate(list_action)
+
+ for container in list_action.nested_list:
+ assert getattr(container, "resource").type == "file", "Element of list was not converted properly"
+