| # Copyright 2024 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import enum |
| import unittest |
| |
| from crossbench.helper.state import (BaseState, StateMachine, |
| UnexpectedStateError) |
| from tests import test_helper |
| |
| |
| @enum.unique |
| class CustomState(BaseState): |
| INITIAL = enum.auto() |
| READY = enum.auto() |
| DONE = enum.auto() |
| |
| |
| class StateMachineTestCase(unittest.TestCase): |
| |
| def test_init(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| self.assertIs(state_machine.state, CustomState.INITIAL) |
| state_machine = StateMachine(CustomState.READY) |
| self.assertIs(state_machine.state, CustomState.READY) |
| |
| def test_eq(self): |
| state_machine = StateMachine(CustomState.READY) |
| state_machine_2 = StateMachine(CustomState.READY) |
| self.assertEqual(state_machine, state_machine) |
| self.assertEqual(state_machine, state_machine_2) |
| self.assertEqual(state_machine, CustomState.READY) |
| self.assertNotEqual(state_machine, None) |
| self.assertNotEqual(state_machine, CustomState.INITIAL) |
| self.assertNotEqual(state_machine, StateMachine(CustomState.INITIAL)) |
| |
| def test_transition(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| state_machine.transition(CustomState.INITIAL, to=CustomState.READY) |
| self.assertEqual(state_machine.state, CustomState.READY) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.transition(CustomState.INITIAL, to=CustomState.READY) |
| self.assertIn("INITIAL", str(cm.exception)) |
| self.assertIn("READY", str(cm.exception)) |
| |
| def test_transition_multi_current(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| state_machine.transition( |
| CustomState.INITIAL, CustomState.READY, to=CustomState.READY) |
| self.assertEqual(state_machine.state, CustomState.READY) |
| state_machine.transition( |
| CustomState.INITIAL, CustomState.READY, to=CustomState.READY) |
| self.assertEqual(state_machine.state, CustomState.READY) |
| state_machine.transition( |
| CustomState.INITIAL, CustomState.READY, to=CustomState.DONE) |
| self.assertEqual(state_machine.state, CustomState.DONE) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.transition( |
| CustomState.INITIAL, CustomState.READY, to=CustomState.DONE) |
| self.assertIn("INITIAL", str(cm.exception)) |
| self.assertIn("READY", str(cm.exception)) |
| self.assertIn("DONE", str(cm.exception)) |
| |
| def test_expect(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| state_machine.expect(CustomState.INITIAL) |
| with self.assertRaises(RuntimeError) as cm: |
| state_machine.expect(CustomState.READY) |
| self.assertIn("INITIAL", str(cm.exception)) |
| self.assertIn("READY", str(cm.exception)) |
| |
| def test_expect_before(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| state_machine.expect_before(CustomState.READY) |
| state_machine.expect_before(CustomState.DONE) |
| |
| state_machine.transition(CustomState.INITIAL, to=CustomState.READY) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.expect_before(CustomState.READY) |
| self.assertEqual(cm.exception.state, CustomState.READY) |
| self.assertEqual(cm.exception.expected, (CustomState.INITIAL,)) |
| state_machine.expect_before(CustomState.DONE) |
| |
| state_machine.transition(CustomState.READY, to=CustomState.DONE) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.expect_before(CustomState.DONE) |
| self.assertEqual(cm.exception.state, CustomState.DONE) |
| self.assertEqual(cm.exception.expected, |
| (CustomState.INITIAL, CustomState.READY)) |
| |
| def test_expect_at_least(self): |
| state_machine = StateMachine(CustomState.INITIAL) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.expect_at_least(CustomState.READY) |
| self.assertEqual(cm.exception.state, CustomState.INITIAL) |
| self.assertEqual(cm.exception.expected, |
| (CustomState.READY, CustomState.DONE)) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.expect_at_least(CustomState.DONE) |
| self.assertEqual(cm.exception.state, CustomState.INITIAL) |
| self.assertEqual(cm.exception.expected, (CustomState.DONE,)) |
| |
| state_machine.transition(CustomState.INITIAL, to=CustomState.READY) |
| state_machine.expect_at_least(CustomState.INITIAL) |
| state_machine.expect_at_least(CustomState.READY) |
| with self.assertRaises(UnexpectedStateError) as cm: |
| state_machine.expect_at_least(CustomState.DONE) |
| self.assertEqual(cm.exception.state, CustomState.READY) |
| self.assertEqual(cm.exception.expected, (CustomState.DONE,)) |
| |
| state_machine.transition(CustomState.READY, to=CustomState.DONE) |
| state_machine.expect_at_least(CustomState.INITIAL) |
| state_machine.expect_at_least(CustomState.READY) |
| state_machine.expect_at_least(CustomState.DONE) |
| |
| |
| if __name__ == "__main__": |
| test_helper.run_pytest(__file__) |