diff --git a/tests/gold_tests/autest-site/ordered_set_queue.py b/tests/gold_tests/autest-site/ordered_set_queue.py new file mode 100644 index 00000000000..5001cf7ade1 --- /dev/null +++ b/tests/gold_tests/autest-site/ordered_set_queue.py @@ -0,0 +1,106 @@ +''' +Implement an OrderedSetQueue +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import collections +try: + import queue as Queue +except ImportError: + import Queue + + +# +# This is borrowed from the following (MIT licensed) recipe: +# https://code.activestate.com/recipes/576694/ +# + +class OrderedSet(collections.MutableSet): + + def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # key --> [key, prev, next] + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.map) + + def __contains__(self, key): + return key in self.map + + def add(self, key): + if key not in self.map: + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + def discard(self, key): + if key in self.map: + key, prev, next = self.map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + # We set last=False so that FIFO is the default behavior. + def pop(self, last=False): + if not self: + raise KeyError('set is empty') + key = self.end[1][0] if last else self.end[2][0] + self.discard(key) + return key + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return set(self) == set(other) + + +class OrderedSetQueue(Queue.Queue): + """ + Make use of the OrderedSet to make a FIFO Queue.Queue that only has unique + elements in it. + """ + + def _init(self, maxsize): + self.queue = OrderedSet() + + def _put(self, item): + self.queue.add(item) + + def _get(self): + return self.queue.pop() diff --git a/tests/gold_tests/autest-site/ports.py b/tests/gold_tests/autest-site/ports.py index db6a66f104b..b660e507a6e 100644 --- a/tests/gold_tests/autest-site/ports.py +++ b/tests/gold_tests/autest-site/ports.py @@ -23,10 +23,8 @@ import hosts.output as host -try: - import queue as Queue -except ImportError: - import Queue +from ordered_set_queue import OrderedSetQueue + g_ports = None # ports we can use @@ -126,7 +124,7 @@ def _setup_port_queue(amount=1000): host.WriteDebug( '_setup_port_queue', "Populating the port queue.") - g_ports = Queue.Queue() + g_ports = OrderedSetQueue() else: # The queue has already been populated. host.WriteDebug( @@ -232,7 +230,7 @@ def get_port(obj, name): "Using port from port queue: {}".format(port)) # setup clean up step to recycle the port obj.Setup.Lambda(func_cleanup=lambda: g_ports.put( - port), description="recycling port") + port), description=f"recycling port: {port}, queue size: {g_ports.qsize()}") except PortQueueSelectionError: port = _get_port_by_bind() host.WriteVerbose(