def test_equality(self): res1 = PoolResource( Resource(uri='linux.precise.ros.segbot.roberto', rapp='rocon_apps/teleop')) self.assertEqual( res1, PoolResource( Resource(uri='linux.precise.ros.segbot.roberto', rapp='rocon_apps/teleop'))) # different uri self.assertNotEqual(res1, PoolResource(TEST_ANOTHER)) # different rapp name self.assertNotEqual( res1, PoolResource( Resource(uri='linux.precise.ros.segbot.roberto', rapp='other_package/teleop'))) # different owner res2 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp='rocon_apps/teleop')) res2.allocate(copy.deepcopy(ROBERTO_REQUEST)) self.assertNotEqual(res1, res2) # different status res3 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp='rocon_apps/teleop')) res3.status = CurrentStatus.MISSING self.assertEqual(res1.owner, res3.owner) self.assertNotEqual(res1.status, res3.status) self.assertNotEqual(res1, res3)
def test_allocate_four_resources_success(self): """ Similar to test_allocate_four_resources_failure(), but the order of the request is different, so the allocator succeeds. """ pool = ResourcePool( KnownResources(resources=[ CurrentStatus(uri=DUDE1_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE2_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE3_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE4_NAME, rapps={TELEOP_RAPP, EXAMPLE_RAPP}) ])) rq = ActiveRequest( Request(id=unique_id.toMsg(RQ_UUID), resources=[ Resource(rapp=EXAMPLE_RAPP, uri=DUDE4_NAME), Resource(rapp=TELEOP_RAPP, uri=DUDE2_NAME), Resource(rapp=TELEOP_RAPP, uri=DUDE3_NAME), Resource(rapp=TELEOP_RAPP, uri=ANY_NAME) ])) alloc = pool.allocate(rq) self.assertTrue(alloc) bot_names = [DUDE4_NAME, DUDE2_NAME, DUDE3_NAME, DUDE1_NAME] for name, i in zip(bot_names, range(4)): self.assertEqual(pool[name].status, CurrentStatus.ALLOCATED) self.assertEqual(alloc[i].uri, name)
def test_allocate_permutation_two_resources(self): """ Request a regexp allocation followed by an exact allocation. Initially the exact resource gets assigned to the regexp, so the second part of the request fails. The allocator must try the other permutation for it to succeed. """ pool = ResourcePool( KnownResources(resources=[ CurrentStatus(uri=MARVIN_NAME, rapps={TELEOP_RAPP, EXAMPLE_RAPP}), CurrentStatus(uri=ROBERTO_NAME, rapps={TELEOP_RAPP}) ])) rq = ActiveRequest( Request(id=unique_id.toMsg(RQ_UUID), resources=[ Resource(rapp=TELEOP_RAPP, uri=ANY_NAME), Resource(rapp=EXAMPLE_RAPP, uri=MARVIN_NAME) ])) alloc = pool.allocate(rq) self.assertTrue(alloc) self.assertEqual(len(alloc), 2) self.assertEqual(pool[MARVIN_NAME].status, CurrentStatus.ALLOCATED) self.assertEqual(pool[MARVIN_NAME].owner, RQ_UUID) self.assertEqual(pool[ROBERTO_NAME].status, CurrentStatus.ALLOCATED) self.assertEqual(pool[ROBERTO_NAME].owner, RQ_UUID) self.assertEqual(alloc[0], Resource(rapp=TELEOP_RAPP, uri=ROBERTO_NAME)) self.assertEqual(alloc[1], Resource(rapp=EXAMPLE_RAPP, uri=MARVIN_NAME))
def test_allocate_four_resources_failure(self): """ Similar to test_allocate_permutation_two_resources(), but here there are more permutations, so the allocator gives up after the initial failure. """ pool = ResourcePool( KnownResources(resources=[ CurrentStatus(uri=DUDE1_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE2_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE3_NAME, rapps={TELEOP_RAPP}), CurrentStatus(uri=DUDE4_NAME, rapps={TELEOP_RAPP, EXAMPLE_RAPP}) ])) rq = ActiveRequest( Request(id=unique_id.toMsg(RQ_UUID), resources=[ Resource(rapp=TELEOP_RAPP, uri=ANY_NAME), Resource(rapp=EXAMPLE_RAPP, uri=DUDE4_NAME), Resource(rapp=TELEOP_RAPP, uri=DUDE2_NAME), Resource(rapp=TELEOP_RAPP, uri=DUDE3_NAME) ])) self.assertRaises(InvalidRequestError, pool.allocate, rq) for name in [DUDE1_NAME, DUDE2_NAME, DUDE3_NAME, DUDE4_NAME]: self.assertEqual(pool[name].status, CurrentStatus.AVAILABLE) self.assertIsNone(pool[name].owner)
def test_release(self): res1 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp=EXAMPLE_RAPP)) self.assertEqual(res1.status, CurrentStatus.AVAILABLE) self.assertEqual(res1.owner, None) res1.allocate(copy.deepcopy(ROBERTO_REQUEST)) self.assertEqual(res1.status, CurrentStatus.ALLOCATED) self.assertEqual(res1.owner, RQ_UUID) self.assertRaises(ResourceNotOwnedError, res1.release, DIFF_UUID) self.assertEqual(res1.status, CurrentStatus.ALLOCATED) res1.release(RQ_UUID) self.assertEqual(res1.status, CurrentStatus.AVAILABLE) res2 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp=EXAMPLE_RAPP)) res2.allocate(copy.deepcopy(ROBERTO_REQUEST)) self.assertEqual(res2.status, CurrentStatus.ALLOCATED) res2.status = CurrentStatus.MISSING # resource now missing res2.release(RQ_UUID) self.assertEqual(res2.status, CurrentStatus.MISSING) res3 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp=EXAMPLE_RAPP)) res3.allocate(copy.deepcopy(ROBERTO_REQUEST)) res3.release() self.assertEqual(res3.status, CurrentStatus.AVAILABLE) res4 = PoolResource( Resource(uri='rocon:/segbot/roberto', rapp=EXAMPLE_RAPP)) res4.allocate(copy.deepcopy(ROBERTO_REQUEST)) res4.status = CurrentStatus.MISSING # resource now missing res4.release() self.assertEqual(res4.status, CurrentStatus.MISSING)
def __init__(self): rospy.init_node("example_scheduler") # simplifying assumptions: all requests want a single robot, # and any of these will do: self.avail = deque([ # FIFO queue of available robots Resource(rapp='example_rapp', uri='rocon:/turtlebot/roberto'), Resource(rapp='example_rapp', uri='rocon:/turtlebot/marvin') ]) self.ready_queue = deque() # FIFO queue of waiting requests self.sch = Scheduler(self.callback) rospy.spin()
def test_timeout_scheduler(self): """ Initialize ROCON scheduler node for timeout test. """ rospy.init_node("timeout_scheduler") # simplifying assumptions: all requests want a single robot, # and any of these will do: self.avail = deque( # FIFO queue of available robots [ Resource(rapp='example_rapp', uri='rocon:/turtlebot/roberto'), Resource(rapp='example_rapp', uri='rocon:/turtlebot/marvin') ]) self.ready_queue = deque() # FIFO queue of waiting requests self.seen_requester = False self.timer = rospy.Timer(rospy.Duration(2.0), self.check_finished) self.sch = Scheduler(self.callback, frequency=1.0) rospy.spin()
def test_matching_allocation_one_resource(self): pool = ResourcePool(SINGLETON_POOL) self.assertEqual(len(pool), 1) self.assertEqual(pool.known_resources(), SINGLETON_POOL) self.assertFalse(pool.changed) res = Resource(rapp=TELEOP_RAPP, uri=ANY_NAME) subset = pool._match_subset(res, {CurrentStatus.AVAILABLE}) self.assertNotIn(MARVIN_NAME, subset) self.assertIn(ROBERTO_NAME, subset) self.assertEqual(subset, set([ROBERTO_NAME])) self.assertEqual( pool.match_list([ROBERTO_RESOURCE], {CurrentStatus.AVAILABLE}), [set([ROBERTO_NAME])]) rq = copy.deepcopy(ANY_REQUEST) alloc = pool.allocate(rq) self.assertTrue(alloc) self.assertTrue(pool.changed) self.assertEqual(alloc[0], ROBERTO_RESOURCE) self.assertEqual(pool[ROBERTO_NAME].status, CurrentStatus.ALLOCATED) self.assertEqual(pool[ROBERTO_NAME].owner, RQ_UUID) self.assertTrue(pool.changed) self.assertEqual( pool.known_resources(), KnownResources(resources=[ CurrentStatus(uri=ROBERTO_NAME, rapps=TEST_RAPPS, status=CurrentStatus.ALLOCATED, owner=unique_id.toMsg(RQ_UUID)) ])) self.assertFalse(pool.changed)
def request_turtlebot(self): """ Request any tutlebot able to run *example_rapp*. :returns: UUID of new request sent. """ bot = Resource(rapp='example_rapp', uri='rocon:/turtlebot') request_id = self.rqr.new_request([bot]) self.rqr.send_requests() return request_id
def request_turtlebot(self): """ Request any tutlebot able to run *example_rapp*. :returns: UUID of new request sent. """ bot = Resource(rapp='example_rapp', uri='rocon:/turtlebot') rq_id = self.rqr.new_request([bot]) rospy.loginfo(' new request: ' + str(rq_id)) return rq_id
def test_match_failures(self): pool = ResourcePool(SINGLETON_POOL) res = Resource(rapp=TELEOP_RAPP, uri=NOT_TURTLEBOT_NAME) subset = pool._match_subset(res, {CurrentStatus.AVAILABLE}) self.assertEqual(len(subset), 0) self.assertNotIn(MARVIN_NAME, subset) self.assertNotIn(ROBERTO_NAME, subset) self.assertEqual(subset, set()) # test null resources list: match_null = pool.match_list([], {CurrentStatus.AVAILABLE}) self.assertEqual(match_null, []) self.assertFalse(match_null) # test not matching resource: matches = pool.match_list([NOT_TURTLEBOT_RESOURCE], {CurrentStatus.AVAILABLE}) self.assertEqual(matches, []) self.assertFalse(matches) rq = copy.deepcopy(NOT_TURTLEBOT_REQUEST) alloc = pool.allocate(rq) self.assertFalse(alloc)
def test_matching_allocation_two_resources(self): pool = ResourcePool(DOUBLETON_POOL) self.assertEqual(len(pool), 2) res = Resource(rapp=TELEOP_RAPP, uri=ANY_NAME) subset = pool._match_subset(res, {CurrentStatus.AVAILABLE}) self.assertIn(MARVIN_NAME, subset) self.assertIn(ROBERTO_NAME, subset) self.assertEqual(subset, set([MARVIN_NAME, ROBERTO_NAME])) self.assertEqual( pool.match_list([ROBERTO_RESOURCE], {CurrentStatus.AVAILABLE}), [set([ROBERTO_NAME])]) rq = copy.deepcopy(ANY_REQUEST) alloc = pool.allocate(rq) self.assertTrue(alloc) if alloc[0] == MARVIN_RESOURCE: self.assertEqual(pool[MARVIN_NAME].status, CurrentStatus.ALLOCATED) self.assertEqual(pool[MARVIN_NAME].owner, RQ_UUID) elif alloc[0] == ROBERTO_RESOURCE: self.assertEqual(pool[ROBERTO_NAME].status, CurrentStatus.ALLOCATED) self.assertEqual(pool[ROBERTO_NAME].owner, RQ_UUID) else: self.fail('allocation failed to yield any expected result')
def test_match(self): res1 = PoolResource(TEST_STATUS) self.assertTrue( res1.match(Resource(rapp=EXAMPLE_RAPP, uri=r'rocon:/segbot'))) #self.assertTrue(res1.match(Resource(rapp=EXAMPLE_RAPP, uri=''))) self.assertTrue(res1.match(Resource(rapp=EXAMPLE_RAPP, uri='rocon:'))) self.assertTrue( res1.match(Resource(rapp=EXAMPLE_RAPP, uri='rocon:/segbot/roberto'))) self.assertFalse( res1.match(Resource(rapp=EXAMPLE_RAPP, uri='rocon:segbot/marvin'))) self.assertTrue( res1.match( Resource(rapp=EXAMPLE_RAPP, uri=r'rocon:/segbot|turtlebot/'))) # different rapps: diff_rapp = Resource(rapp='different/rapp', uri=r'rocon:/segbot') self.assertFalse(res1.match(diff_rapp)) res1.rapps.add('different/rapp') self.assertTrue(res1.match(diff_rapp)) res1.rapps.remove('different/rapp') self.assertFalse(res1.match(diff_rapp))
# ROS dependencies import unique_id from scheduler_msgs.msg import Request, Resource from concert_scheduler_requests.transitions import ActiveRequest # module being tested: from concert_scheduler_requests.priority_queue import * # some resources for testing RQR_ID = uuid.uuid4() RQ1_UUID = uuid.uuid4() RQ2_UUID = uuid.uuid4() EXAMPLE_RAPP = 'tests/example_rapp' MARVIN_NAME = 'rocon:/turtlebot/marvin' MARVIN = Resource(uri=MARVIN_NAME, rapp=EXAMPLE_RAPP) ROBERTO_NAME = 'rocon:/turtlebot/roberto' ROBERTO = Resource(uri=ROBERTO_NAME, rapp=EXAMPLE_RAPP) # some useful Resource and Request messages MARVIN_RESOURCE = Resource(rapp=EXAMPLE_RAPP, uri=MARVIN_NAME) MARVIN_REQUEST = ActiveRequest(Request( id=unique_id.toMsg(RQ1_UUID), resources=[MARVIN_RESOURCE])) ROBERTO_RESOURCE = Resource(rapp=EXAMPLE_RAPP, uri=ROBERTO_NAME) ROBERTO_REQUEST = ActiveRequest(Request( id=unique_id.toMsg(RQ2_UUID), resources=[ROBERTO_RESOURCE])) ###############################
#!/usr/bin/env python # dummy scheduler node for requester testing # enable some python3 compatibility options: from __future__ import absolute_import, print_function, unicode_literals import rospy from scheduler_msgs.msg import Request from scheduler_msgs.msg import Resource import rocon_scheduler_requests.scheduler as scheduler # Constants TEST_RESOURCE = Resource(name='test_rapp', platform_info='linux.precise.ros.segbot.roberto') # Global variables queued_request = None # pending request queued_requester = None # corresponding requester ID sch = None # scheduler object timer = None # timer request object def allocate(event): """ Timer handler: simulated resource availability event. """ global queued_request global queued_requester global sch if queued_request: queued_request.grant([TEST_RESOURCE]) print('Request granted: ' + str(queued_request.get_uuid()))
#!/usr/bin/env python """ Scheduler for testing example_requester. """ # enable some python3 compatibility options: from __future__ import absolute_import, print_function, unicode_literals import unittest import rospy from scheduler_msgs.msg import Request, Resource from rocon_scheduler_requests import Scheduler # Resource to grant TEST_RESOURCE = Resource(rapp='test_rapp', uri='rocon:/turtlebot/roberto') # Global variables # :todo: make these class variables queued_request = None # pending request queued_requester = None # corresponding requester ID class TestExampleRequester(unittest.TestCase): def test_example_requester_(self): """ Initialize ROCON scheduler node for example requester. """ self.number_of_requests = 3 # number of requests desired self.queued_request = None rospy.init_node("test_example_requester") self.sch = Scheduler(self.callback) rospy.spin() # spin in the main thread def allocate(self, event): """ Timer handler: simulated resource availability event.
import copy import uuid import unittest # ROS dependencies import unique_id from scheduler_msgs.msg import Request, Resource # module being tested: from concert_scheduler_requests.transitions import * RQR_UUID = uuid.UUID('01234567-89ab-cdef-0123-456789abcdef') TEST_UUID = uuid.UUID('01234567-89ab-cdef-fedc-ba9876543210') DIFF_UUID = uuid.UUID('01234567-cdef-fedc-89ab-ba9876543210') TEST_RAPP = 'test_rapp' TEST_RESOURCE = Resource(rapp=TEST_RAPP, uri='rocon:/segbot/roberto') TEST_WILDCARD = Resource(rapp=TEST_RAPP, uri='rocon:/segbot') class TestTransitions(unittest.TestCase): """Unit tests for scheduler request state transitions. These tests do not require a running ROS core. """ #################### # utility methods #################### def assert_invalid(self, request_type, old_status, operation, exception, *args): """
# module being tested: from concert_resource_pool.resource_pool import * # some definitions for testing RQ_UUID = uuid.UUID('01234567-89ab-cdef-0123-456789abcdef') TEST_UUID = unique_id.fromURL('package://concert_simple_scheduler/test_uuid') DIFF_UUID = unique_id.fromURL('package://concert_simple_scheduler/diff_uuid') EXAMPLE_RAPP = 'tests/example_rapp' TELEOP_RAPP = 'rocon_apps/teleop' TEST_RAPPS = [TELEOP_RAPP, EXAMPLE_RAPP] TEST_STATUS = CurrentStatus(uri='rocon:/segbot/roberto', rapps=[EXAMPLE_RAPP]) TEST_RESOURCE_NAME = 'rocon:/segbot/roberto' TEST_RESOURCE = Resource(uri=TEST_RESOURCE_NAME, id=unique_id.toMsg(TEST_UUID), rapp=EXAMPLE_RAPP) TEST_RESOURCE_STRING = ("""rocon:/segbot/roberto, status: 0 owner: None priority: 0 rapps: """ + EXAMPLE_RAPP) TEST_ANOTHER = Resource(uri='rocon:/segbot/marvin', rapp=EXAMPLE_RAPP) TEST_ANOTHER_NAME = 'rocon:/segbot/marvin' TEST_ANOTHER_STRING = ("""rocon:/segbot/marvin, status: 0 owner: None priority: 0 rapps: """ + EXAMPLE_RAPP)
import uuid import unittest # ROS dependencies import unique_id from scheduler_msgs.msg import Request from scheduler_msgs.msg import Resource # module being tested: from rocon_scheduler_requests.transitions import * RQR_UUID = uuid.UUID('01234567-89ab-cdef-0123-456789abcdef') TEST_UUID = uuid.UUID('01234567-89ab-cdef-fedc-ba9876543210') DIFF_UUID = uuid.UUID('01234567-cdef-fedc-89ab-ba9876543210') TEST_RAPP = 'test_rapp' TEST_RESOURCE = Resource(name=TEST_RAPP, platform_info='linux.precise.ros.segbot.roberto') TEST_WILDCARD = Resource(name=TEST_RAPP, platform_info='linux.precise.ros.segbot.*') class TestTransitions(unittest.TestCase): """Unit tests for scheduler request state transitions. These tests do not require a running ROS core. """ def test_abort(self): rq1 = ResourceReply(Request(id=unique_id.toMsg(TEST_UUID), resources=[TEST_RESOURCE], status=Request.NEW)) rq1.abort()