def test_stop(self): Control.stop(1) # Validate... a, b, path = Control.get_last_set_data() self.assertFalse(a) self.assertFalse(b) self.assertEqual(1, path)
def test_reset(self): Control.reset() # Validate... a, b, path = Control.get_last_set_data() self.assertFalse(a) self.assertFalse(b) self.assertEqual(Control.num_paths(), path)
def test_red_amber(self): Control.red_amber(1) # Validate... a, b, path = Control.get_last_set_data() self.assertFalse(a) self.assertTrue(b) self.assertEqual(1, path)
def test_go(self): Control.go(1) # Validate... a, b, path = Control.get_last_set_data() self.assertTrue(a) self.assertTrue(b) self.assertEqual(1, path)
def __init__(self, path): """Initialise the class instance. This remembers the path identiy and sets up the object's 'action' queue.""" # Always initialise the parent class instance... super().__init__() assert 0 < path <= Control.num_paths(), \ "Invalid strobe ID (%s)" % path self.path = path # Create our 'action' queue. # STOP, START and QUIT commands are supplied to us through this queue. # The queue is a small, limited size. When full the queue will block. self.action_queue = queue.LifoQueue(_QUEUE_SIZE) # We operate a counter (pending count) that is incremented when # actions are placed in the queue and decremented after they have # been taken out and processed. This allows the 'wait()' method # to operate correctly - i.e. wait until a) the action queue # is empty and the event has also been processed. The value is # incremented for each put and decremented at the end of the run() # code. self.pending_count = 0 self.pending_count_lock = threading.Lock() # Timestamp of last 'demand' input self.last_demand_time = None # Flag, cleared to exit the thread run() loop self.running = True
def run(self): """The thread `run()` method. We simply sit on the back-end of the queue and process actions as they arrive. The `terminate` action causes the `run()` method to exit. As actions are processed the number of pending (put but unprocessed) actions is decremented.""" while self.running: # Get from the queue, blocking until something is retrieved. item = self.action_queue.get() assert isinstance(item, PathAction),\ "Invalid object on action_queue (%s)" % item # Process the action... if item == PathAction.go: # Traffic to be set to 'go' on this path Control.go(self.path) elif item == PathAction.stop: # Traffic to be set to 'stop' on this path Control.stop(self.path) elif item == PathAction.terminate: # The 'kill' event - # stop processing and exit the run-loop self.running = False # The action has been processed, # safely decrement the number of pending actions. self._dec_pending()
def test_stop(self): controller_one = PathController.PathController(2) controller_one.start() # Trigger the change... controller_one.stop() # Wait... controller_one.wait(10) # Validate... a, b, path = Control.get_last_set_data() self.assertFalse(a) self.assertFalse(b) self.assertEqual(2, path) # Terminate... controller_one.terminate() controller_one.join()
July 2015 """ # Import traffic-control stuff... import tcontrol.Control as Control import tcontrol.OscillatingCrossroads as OscillatingCrossroads import tcontrol.PathController as PathController # Demo objects... pri = PathController.PathController(1) sec = PathController.PathController(2) demoOc = OscillatingCrossroads.OscillatingCrossroads(pri, sec) # Uncomment to enable underlying FSM debug... #demoOc.debug() Control.init() # ----------------------------------------------------------------------------- def start(): """Starts (runs) the demo.""" demoOc.start() # ----------------------------------------------------------------------------- def stop(): """Stops the demo."""
def setUpClass(cls): """One-time initialisation.""" Control.init()
def test_invalid_path_controller(self): with self.assertRaises(AssertionError): PathController.PathController(Control.num_paths() + 1)