From 2c8fe66c0f7490c8aaaae27b4977b987001c6b71 Mon Sep 17 00:00:00 2001 From: mike Date: Tue, 01 Dec 2009 20:11:43 +0000 Subject: Merge branch 'master' of git://git.sugarlabs.org/tutorius/simpoirs-clone Conflicts: src/extensions/tutoriusremote.py tutorius/TProbe.py tutorius/creator.py --- (limited to 'tests') 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" + -- cgit v0.9.1