def test_place_during_reconfigure(self):
        # Create leaf scheduler which will return RESOURCE_CONSTRAINT
        scheduler = LeafScheduler("foo", 1, False)
        scheduler._placement_hosts = MagicMock()
        scheduler._placement_hosts.return_value = []

        # Create scheduler handler
        handler = SchedulerHandler()
        handler._create_scheduler = MagicMock()
        handler._create_scheduler.return_value = scheduler

        # Configure scheduler handler with leaf scheduler
        handler.configure([
            SchedulerRole("foo",
                          "parent-id",
                          scheduler_children=[ChildInfo(id="child")])
        ])
        assert_that(handler._schedulers, has_length(1))

        concurrency = 5
        threads = []
        results = {}
        done = [False]

        # Define the thread which keeps calling place, to make sure it
        # always return RESOURCE_CONSTRAINT
        def _loop():
            while True:
                actual_response = handler.place(PlaceRequest(
                    Resource(), "foo"))
                assert_that(actual_response.result,
                            is_not(PlaceResultCode.SYSTEM_ERROR))

                if done[0]:
                    results[threading.current_thread().name] = True
                    break

        for _ in xrange(concurrency):
            thread = threading.Thread(target=_loop)
            thread.start()
            threads.append(thread)

        # Reconfigure scheduler to demote it. To test when reconfiguring,
        # there is no race when new schedulers replacing the old ones.
        handler.configure([])
        assert_that(handler._schedulers, has_length(0))
        time.sleep(0.1)
        done[0] = True

        for thread in threads:
            thread.join()

        assert_that(len(results), equal_to(concurrency))
    def test_place_during_reconfigure(self):
        # Create leaf scheduler which will return RESOURCE_CONSTRAINT
        scheduler = LeafScheduler("foo", 1, False)
        scheduler._placement_hosts = MagicMock()
        scheduler._placement_hosts.return_value = []

        # Create scheduler handler
        handler = SchedulerHandler()
        handler._create_scheduler = MagicMock()
        handler._create_scheduler.return_value = scheduler

        # Configure scheduler handler with leaf scheduler
        handler.configure(
            [SchedulerRole("foo", "parent-id",
                           scheduler_children=[ChildInfo(id="child")])])
        assert_that(handler._schedulers, has_length(1))

        concurrency = 5
        threads = []
        results = {}
        done = [False]

        # Define the thread which keeps calling place, to make sure it
        # always return RESOURCE_CONSTRAINT
        def _loop():
            while True:
                actual_response = handler.place(
                    PlaceRequest(Resource(), "foo"))
                assert_that(actual_response.result,
                            is_not(PlaceResultCode.SYSTEM_ERROR))

                if done[0]:
                    results[threading.current_thread().name] = True
                    break

        for _ in xrange(concurrency):
            thread = threading.Thread(target=_loop)
            thread.start()
            threads.append(thread)

        # Reconfigure scheduler to demote it. To test when reconfiguring,
        # there is no race when new schedulers replacing the old ones.
        handler.configure([])
        assert_that(handler._schedulers, has_length(0))
        time.sleep(0.1)
        done[0] = True

        for thread in threads:
            thread.join()

        assert_that(len(results), equal_to(concurrency))