diff options
Diffstat (limited to 'src/sugar/tutorius/tests/coretests.py')
-rw-r--r-- | src/sugar/tutorius/tests/coretests.py | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/src/sugar/tutorius/tests/coretests.py b/src/sugar/tutorius/tests/coretests.py deleted file mode 100644 index eadea01..0000000 --- a/src/sugar/tutorius/tests/coretests.py +++ /dev/null @@ -1,597 +0,0 @@ -# Copyright (C) 2009, Tutorius.org -# Copyright (C) 2009, Michael Janelle-Montcalm <michael.jmontcalm@gmail.com> -# -# 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 -""" -Core Tests - -This module contains all the tests that pertain to the usage of the Tutorius -Core. This means that the Event Filters, the Finite State Machine and all the -related elements and interfaces are tested here. - -Usage of actions and event filters is tested, but not the concrete actions -and event filters. Those are in their separate test module - -""" - -import unittest - -import logging -from sugar.tutorius.actions import Action, OnceWrapper, ClickAction, TypeTextAction -from sugar.tutorius.core import * -from sugar.tutorius.filters import * - - -from actiontests import CountAction - -# Helper classes to help testing -class SimpleTutorial(Tutorial): - """ - Fake tutorial - """ - def __init__(self, start_name="INIT"): - #Tutorial.__init__(self, "Simple Tutorial", None) - self.current_state_name = start_name - self.activity = "TODO : This should be an activity" - - def set_state(self, name): - self.current_state_name = name - -class TutorialWithFSM(Tutorial): - """ - Fake tutorial, but associated with a FSM. - """ - def __init__(self, start_name="INIT", fsm=None): - Tutorial.__init__(self, start_name, fsm) - self.activity = activity.Activity() - -class TrueWhileActiveAction(Action): - """ - This action's active member is set to True after a do and to False after - an undo. - - Used to verify that a State correctly triggers the do and undo actions. - """ - def __init__(self): - Action.__init__(self) - self.active = False - - def do(self): - self.active = True - - def undo(self): - self.active = False - -class ClickableWidget(): - """ - This class fakes a widget with a clicked() method - """ - def __init__(self): - self.click_count = 0 - - def clicked(self): - self.click_count += 1 - -class FakeTextEntry(): - """ - This class fakes a widget with an insert_text() method - """ - def __init__(self): - self.text_lines = [] - self.last_entered_line = "" - self.displayed_text = "" - - def insert_text(self, text, index): - self.last_entered_line = text - self.text_lines.append(text) - self.displayed_text = self.displayed_text[0:index] + text + self.displayed_text[index+1:] - -class FakeParentWidget(): - """ - This class fakes a widet container, it implements the get_children() method - """ - def __init__(self): - self._children = [] - - def add_child(self, child): - self._children.append(child) - - def get_children(self): - return self._children - - - - -class TriggerEventFilter(EventFilter): - """ - This event filter can be triggered by simply calling its do_callback function. - - Used to fake events and see the effect on the FSM. - """ - def __init__(self, next_state): - EventFilter.__init__(self, next_state) - self.toggle_on_callback = False - - def install_handlers(self, callback, **kwargs): - """ - Forsakes the incoming callback function and just set the inner one. - """ - self._callback = self._inner_cb - - def _inner_cb(self, event_filter): - self.toggle_on_callback = not self.toggle_on_callback - -class FakeEventFilter(TriggerEventFilter): - """ - This is a fake event that is connected to the tutorial. - - The difference between this one and the TriggerEventFilter is that the - tutorial's set_state will be called on the callback. - - Do not forget to add the do_callback() after creating the object. - """ - def set_tutorial(self, tutorial): - self.tutorial = tutorial - - def _inner_cb(self, event_filter): - self.toggle_on_callback = not self.toggle_on_callback - self.tutorial.set_state(event_filter.get_next_state()) - - -class ClickActionTests(unittest.TestCase): - """ - Test class for click action - """ - def test_do_action(self): - activity = FakeParentWidget() - widget = ClickableWidget() - activity.add_child(widget) - ObjectStore().activity = activity - - action = ClickAction("0.0") - - assert widget == ObjectStore().activity.get_children()[0],\ - "The clickable widget isn't reachable from the object store \ - the test cannot pass" - - action.do() - - assert widget.click_count == 1, "clicked() should have been called by do()" - - action.do() - - assert widget.click_count == 2, "clicked() should have been called by do()" - - def test_undo(self): - activity = FakeParentWidget() - widget = ClickableWidget() - activity.add_child(widget) - ObjectStore().activity = activity - - action = ClickAction("0.0") - - assert widget == ObjectStore().activity.get_children()[0],\ - "The clickable widget isn't reachable from the object store \ - the test cannot pass" - - action.undo() - - #There is no undo for this action so the test should not fail - assert True - - - -class TypeTextActionTests(unittest.TestCase): - """ - Test class for type text action - """ - def test_do_action(self): - activity = FakeParentWidget() - widget = FakeTextEntry() - activity.add_child(widget) - ObjectStore().activity = activity - - test_text = "This is text" - - - action = TypeTextAction("0.0", test_text) - - assert widget == ObjectStore().activity.get_children()[0],\ - "The clickable widget isn't reachable from the object store \ - the test cannot pass" - - action.do() - - assert widget.last_entered_line == test_text, "insert_text() should have been called by do()" - - action.do() - - assert widget.last_entered_line == test_text, "insert_text() should have been called by do()" - assert len(widget.text_lines) == 2, "insert_text() should have been called twice" - - def test_undo(self): - activity = FakeParentWidget() - widget = FakeTextEntry() - activity.add_child(widget) - ObjectStore().activity = activity - - test_text = "This is text" - - - action = TypeTextAction("0.0", test_text) - - assert widget == ObjectStore().activity.get_children()[0],\ - "The clickable widget isn't reachable from the object store \ - the test cannot pass" - - action.undo() - - #There is no undo for this action so the test should not fail - assert True - -# State testing class -class StateTest(unittest.TestCase): - """ - This class has to test the State interface as well as the expected - functionality. - """ - - def test_action_toggle(self): - """ - Validate that the actions are properly done on setup and undone on - teardown. - - Pretty awesome. - """ - act = TrueWhileActiveAction() - - state = State("action_test", action_list=[act]) - - assert act.active == False, "Action is not initialized properly" - - state.setup() - - assert act.active == True, "Action was not triggered properly" - - state.teardown() - - assert act.active == False, "Action was not undone properly" - - def test_event_filter(self): - """ - Tests the fact that the event filters are correctly installed on setup - and uninstalled on teardown. - """ - event_filter = TriggerEventFilter("second_state") - - state = State("event_test", event_filter_list=[event_filter]) - state.set_tutorial(SimpleTutorial()) - - assert event_filter.toggle_on_callback == False, "Wrong init of event_filter" - assert event_filter._callback == None, "Event filter has a registered callback before installing handlers" - - state.setup() - - assert event_filter._callback != None, "Event filter did not register callback!" - - # 'Trigger' the event - This is more like a EventFilter test. - event_filter.do_callback() - - assert event_filter.toggle_on_callback == True, "Event filter did not execute callback" - - state.teardown() - - assert event_filter._callback == None, "Event filter did not remove callback properly" - - def test_warning_set_tutorial_twice(self): - """ - Calls set_tutorial twice and expects a warning on the second. - """ - state = State("start_state") - tut = SimpleTutorial("First") - tut2 = SimpleTutorial("Second") - - state.set_tutorial(tut) - - try: - state.set_tutorial(tut2) - assert False, "No RuntimeWarning was raised on second set_tutorial" - except : - pass - - def test_add_action(self): - """ - Tests on manipulating the actions inside a state. - """ - state = State("INIT") - - act1 = CountAction() - act2 = CountAction() - act3 = CountAction() - - # Try to add the actions - assert state.add_action(act1), "Could not add the first action" - assert state.add_action(act2), "Could not add the second action" - assert state.add_action(act3), "Could not add the third action" - - # Try to add a second time an action that was already inserted - assert state.add_action(act1) == False, "Not supposed to insert an action twice" - - # Fetch the associated actions - actions = state.get_action_list() - - # Make sure all the actions are present in the state - assert act1 in actions and act2 in actions and act3 in actions,\ - "The actions were not properly inserted in the state" - - # Clear the list - state.clear_actions() - - # Make sure the list of actions is empty now - assert len(state.get_action_list()) == 0, "Clearing of actions failed" - - def test_add_event_filter(self): - state = State("INIT") - - event1 = TriggerEventFilter("s") - event2 = TriggerEventFilter("t") - event3 = TriggerEventFilter("r") - - # Insert the event filters - assert state.add_event_filter(event1), "Could not add event filter 1" - assert state.add_event_filter(event2), "Could not add event filter 2" - assert state.add_event_filter(event3), "Could not add event filter 3" - - # Make sure we cannot insert an event twice - assert state.add_event_filter(event1) == False, "Could add twice the event filter" - - # Get the list of event filters - event_filters = state.get_event_filter_list() - - assert event1 in event_filters and event2 in event_filters and event3 in event_filters, \ - "The event filters were not all added inside the state" - - # Clear the list - state.clear_event_filters() - - assert len(state.get_event_filter_list()) == 0, \ - "Could not clear the event filter list properly" - -class FSMTest(unittest.TestCase): - """ - This class needs to text the interface and functionality of the Finite - State Machine. - """ - - def test_sample_usage(self): - act_init = TrueWhileActiveAction() - act_second = TrueWhileActiveAction() - - event_init = FakeEventFilter("SECOND") - - content = { - "INIT": State("INIT", action_list=[act_init],event_filter_list=[event_init]), - "SECOND": State("SECOND", action_list=[act_second]) - } - - fsm = FiniteStateMachine("SampleUsage", state_dict=content) - - assert fsm is not None, "Unable to create FSM" - - tut = Tutorial("SampleUsageTutorial", fsm) - - tut.attach(None) - event_init.set_tutorial(tut) - - assert fsm.current_state.name == "INIT", "Unable to set state to initial state" - - assert act_init.active, "FSM did not call the state's action DO properly" - - # Trigger the event of the INIT state - event_init.do_callback() - - assert act_init.active == False, "FSM did not teardown INIT properly" - - assert fsm.current_state.name == "SECOND", "FSM did not switch to SECOND state" - - assert act_second.active == True, "FSM did not setup SECOND properly" - - tut.detach() - - assert act_second.active == False, "FSM did not teardown SECOND properly" - - - def test_state_insert(self): - """ - This is a simple test to insert, then find a state. - """ - st1 = State("FakeState") - - fsm = FiniteStateMachine("StateInsertTest") - - fsm.add_state(st1) - - inserted_state = fsm.get_state_by_name(st1.name) - - assert inserted_state is st1, "Inserting, then fetching a state did not work" - - # Make sure we cannot insert it twice - try : - fsm.add_state(st1) - assert False, "No error raised on addition of an already present state" - except KeyError: - pass - - def test_state_find_by_name(self): - """ - Tests the interface for fetching a state by name. - - Basic functionnality - - Non-existent state - """ - - st1 = State("INIT") - - st2 = State("second") - - fsm = FiniteStateMachine("StateFindTest") - - fsm.add_state(st1) - fsm.add_state(st2) - - # Test the fetch by name - fetched_st1 = fsm.get_state_by_name(st1.name) - - assert fetched_st1 is st1, "Fetched state is not the same as the inserted one" - - fetched_st2 = fsm.get_state_by_name(st2.name) - - assert fetched_st2 is st2, "Fetched state is not the same as the inserted one" - - try: - fsm.get_state_by_name("no such state") - assert False, "Did not get a KeyError on non-existing key search" - except KeyError: - pass - except Exception: - assert False, "Did not get the right error on non-existing key search" - - def test_state_removal(self): - """ - This test removes a state from the FSM. It also verifies that the links - from other states going into the removed state are gone. - """ - st1 = State("INIT", event_filter_list=[TriggerEventFilter("second")]) - st2 = State("second", event_filter_list=[TriggerEventFilter("third")]) - st3 = State("third", event_filter_list=[TriggerEventFilter("second")]) - - fsm = FiniteStateMachine("StateRemovalTest") - - fsm.add_state(st1) - fsm.add_state(st2) - fsm.add_state(st3) - - # First tests - Removing a non-existing state and make sure we get a - # KeyError - try: - fsm.remove_state("Non-existing") - assert False, "Removing a non-existing state did not throw a KeyError" - except KeyError: - pass - except Exception: - assert False, "Removing a non-existing state dit not throw the right kind of exception" - - # Now try removing the second state - fsm.remove_state("second") - - # Make sure it cannot be fetched - try : - fetched_state = fsm.get_state_by_name("second") - assert False, "The supposedly removed state is still present in the FSM" - except KeyError: - pass - - # Make sure that there is no link to the removed state in the rest - # of the FSM - assert "second" not in fsm.get_following_states("INIT"),\ - "The link to second from INIT still exists after removal" - - assert "second" not in fsm.get_following_states("third"),\ - "The link to second from third still exists after removal" - - def test_set_same_state(self): - fsm = FiniteStateMachine("Set same state") - - st1 = State("INIT") - st1.add_action(CountAction()) - - fsm.add_state(st1) - - tut = SimpleTutorial() - - fsm.set_tutorial(tut) - - fsm.set_state("INIT") - - assert fsm.get_state_by_name("INIT").get_action_list()[0].do_count == 1, \ - "The action was not triggered on 'INIT'" - - fsm.set_state("INIT") - - do_count = fsm.get_state_by_name("INIT").get_action_list()[0].do_count - assert fsm.get_state_by_name("INIT").get_action_list()[0].do_count == 1, \ - "The action was triggered a second time, do_count = %d"%do_count - - undo_count = fsm.get_state_by_name("INIT").get_action_list()[0].undo_count - assert fsm.get_state_by_name("INIT").get_action_list()[0].undo_count == 0,\ - "The action has been undone unappropriately, undo_count = %d"%undo_count - -class FSMExplorationTests(unittest.TestCase): - def setUp(self): - self.buildFSM() - - def buildFSM(self): - """ - Create a sample FSM to play with in the rest of the tests. - """ - st1 = State("INIT") - st1.add_action(CountAction()) - st1.add_event_filter(TriggerEventFilter("Second")) - st1.add_event_filter(TriggerEventFilter("Third")) - - st2 = State("Second") - st2.add_action(TrueWhileActiveAction()) - st2.add_event_filter(TriggerEventFilter("Third")) - st2.add_event_filter(TriggerEventFilter("Fourth")) - - st3 = State("Third") - st3.add_action(CountAction()) - st3.add_action(TrueWhileActiveAction()) - - self.fsm = FiniteStateMachine("ExplorationTestingMachine") - self.fsm.add_state(st1) - self.fsm.add_state(st2) - self.fsm.add_state(st3) - - def validate_following_states(self, in_name, out_name_list): - nextStates = self.fsm.get_following_states(in_name) - assert list(nextStates).sort() == list(out_name_list).sort(), \ - "The following states for %s are wrong : got %s"%\ - (in_name, str(nextStates)) - - def validate_previous_states(self, in_name, out_name_list): - prevStates = self.fsm.get_previous_states(in_name) - assert list(prevStates).sort() == list(out_name_list).sort(), \ - "The following states for %s are wrong : got %s"%\ - (in_name, str(prevStates)) - - def test_get_following_states(self): - self.validate_following_states("INIT", ('Second', 'Third')) - - self.validate_following_states("Second", ("Third", "Fourth")) - - self.validate_following_states("Third", ()) - - def test_get_previous_states(self): - self.validate_previous_states("INIT", ()) - - self.validate_previous_states("Second", ("INIT")) - - self.validate_previous_states("Third", ("INIT", "Second")) - - self.validate_previous_states("Fourth", ("Second")) - - -if __name__ == "__main__": - unittest.main() |