def testBasicSortTests(self): # Test every permutation of inputs, with legacy tests. # Cannot use equal costs because of the use of # a 2*optimal heuristic for sorting: with equal # costs the wrong sort order is < twice the optimal # weight, and thus can be selected. resource_one = testresources.TestResource() resource_two = testresources.TestResource() resource_two.setUpCost = 5 resource_two.tearDownCost = 5 resource_three = testresources.TestResource() self.case1.resources = [("_one", resource_one), ("_two", resource_two)] self.case2.resources = [("_two", resource_two), ("_three", resource_three)] self.case3.resources = [("_three", resource_three)] # acceptable sorted orders are: # 1, 2, 3, 4 # 3, 2, 1, 4 for permutation in self._permute_four(self.cases): self.assertIn(self.sortTests(permutation), [[self.case1, self.case2, self.case3, self.case4], [self.case3, self.case2, self.case1, self.case4]], "failed with permutation %s" % (permutation, ))
def testneededResourcesClosure(self): # Calling neededResources on a TestResource with dependencies includes # the needed resources of the needed resources. resource = testresources.TestResource() dep1 = testresources.TestResource() dep2 = testresources.TestResource() resource.resources.append(("dep1", dep1)) dep1.resources.append(("dep2", dep2)) self.assertEqual([dep2, dep1, resource], resource.neededResources())
def testneededResourcesDependenciesFirst(self): # Calling neededResources on a TestResource with dependencies puts the # dependencies first. resource = testresources.TestResource() dep1 = testresources.TestResource() dep2 = testresources.TestResource() resource.resources.append(("dep1", dep1)) resource.resources.append(("dep2", dep2)) self.assertEqual([dep1, dep2, resource], resource.neededResources())
def testDependentResources(self): resource1 = testresources.TestResource() resource2 = testresources.TestResource() resource1.resources = [('foo', resource2)] resourced_case = self.makeResourcedTestCase(has_resource=False) resourced_case.resources = [('resource1', resource1)] resource_set_tests = split_by_resources([resourced_case]) self.assertEqual( { frozenset(): [], frozenset([resource1, resource2]): [resourced_case] }, resource_set_tests)
def testGlobalMinimum(self): # When a local minimum leads to a global non-minum, the global # non-minimum is still reached. We construct this by having a resource # that appears very cheap (it has a low setup cost) but is very # expensive to tear down. Then we have it be used twice: the global # minimum depends on only tearing it down once. To prevent it # accidentally being chosen twice, we make one use of it be # on its own, and another with a resource to boost its cost, # finally we put a resource which is more expensive to setup # than the expensive teardown is to teardown, but less expensive # than it + the small booster to setup. # valid results are - the expensive setup, then both expensive # teardowns, and the legacy fourth, or # both expensive teardowns and then the expensive setup (and the legacy # fourth) # case1 has expensive setup (one) # case2 has expensive teardown (two) # case3 has expensive teardown + boost (three) resource_one = testresources.TestResource() resource_one.setUpCost = 20 resource_two = testresources.TestResource() resource_two.tearDownCost = 50 resource_three = testresources.TestResource() resource_three.setUpCost = 72 # node costs: # ->1 = r1.up = 20 # ->2 = r2.up = 1 # ->3 = r2.up + r3.up = 122 # 1->2 = r1.down + r2.up = 2 # 1->3 = r1.down + r2.up + r3.up = 93 # 2->1 = r2.down + r1.up = 70 # 2->3 = r3.up = 72 # 3->1 = r1.up + r2.down + r3.down= 71 # 3->2 = r3.down = 1 # 1-> = r1.down = 1 # 2-> = r2.down = 50 # 3-> = r3.down + r3.down = 51 # naive path = 2, 1, 3 = 1 + 70 + 93 + 51 = 215 # better = 2, 3, 1 = 1 + 72 + 71 + 1 = 145 acceptable_orders = [ [self.case1, self.case2, self.case3, self.case4], [self.case1, self.case3, self.case2, self.case4], [self.case2, self.case3, self.case1, self.case4], [self.case3, self.case2, self.case1, self.case4], ] self.case1.resources = [("_one", resource_one)] self.case2.resources = [("_two", resource_two)] self.case3.resources = [("_two", resource_two), ("_three", resource_three)] for permutation in self._permute_four(self.cases): self.assertIn(self.sortTests(permutation), acceptable_orders)
def testSortConsidersDependencies(self): """Tests with different dependencies are sorted together.""" # We test this by having two resources (one and two) that share a very # expensive dependency (dep). So one and two have to sort together. By # using a cheap resource directly from several tests we can force the # optimise to choose between keeping the cheap resource together or # keeping the expensive dependency together. # Test1, res_one, res_common_one # Test2, res_two, res_common_two # Test3, res_common_one, res_common_two # In a dependency naive sort, we will have test3 between test1 and # test2 always. In a dependency aware sort, test1 and two will # always group. resource_one = testresources.TestResource() resource_two = testresources.TestResource() resource_one_common = testresources.TestResource() # make it cheaper to keep a _common resource than to switch both # resources (when dependencies are ignored) resource_one_common.setUpCost = 2 resource_one_common.tearDownCost = 2 resource_two_common = testresources.TestResource() resource_two_common.setUpCost = 2 resource_two_common.tearDownCost = 2 dep = testresources.TestResource() dep.setUpCost = 20 dep.tearDownCost = 20 resource_one.resources.append(("dep1", dep)) resource_two.resources.append(("dep2", dep)) self.case1.resources = [("withdep", resource_one), ("common", resource_one_common)] self.case2.resources = [("withdep", resource_two), ("common", resource_two_common)] self.case3.resources = [("_one", resource_one_common), ("_two", resource_two_common)] self.case4.resources = [] acceptable_orders = [ [self.case1, self.case2, self.case3, self.case4], [self.case2, self.case1, self.case3, self.case4], [self.case3, self.case1, self.case2, self.case4], [self.case3, self.case2, self.case1, self.case4], ] for permutation in self._permute_four(self.cases): self.assertIn(self.sortTests(permutation), acceptable_orders)
def testSortIsStableWithinGroups(self): """Tests with the same resources maintain their relative order.""" resource_one = testresources.TestResource() resource_two = testresources.TestResource() self.case1.resources = [("_one", resource_one)] self.case2.resources = [("_one", resource_one)] self.case3.resources = [("_one", resource_one), ("_two", resource_two)] self.case4.resources = [("_one", resource_one), ("_two", resource_two)] for permutation in self._permute_four(self.cases): sorted = self.sortTests(permutation) self.assertEqual( permutation.index(self.case1) < permutation.index(self.case2), sorted.index(self.case1) < sorted.index(self.case2)) self.assertEqual( permutation.index(self.case3) < permutation.index(self.case4), sorted.index(self.case3) < sorted.index(self.case4))
class TestSplitByResources(testtools.TestCase): """Tests for split_by_resources.""" def makeTestCase(self): return unittest.TestCase('run') def makeResourcedTestCase(self, has_resource=True): case = testresources.ResourcedTestCase('run') if has_resource: case.resources = [('resource', testresources.TestResource())]
def makeResource(self, setUpCost=1, tearDownCost=1): resource = testresources.TestResource() resource.setUpCost = setUpCost resource.tearDownCost = tearDownCost return resource
def testneededResourcesDefault(self): # Calling neededResources on a default TestResource returns the # resource. resource = testresources.TestResource() self.assertEqual([resource], resource.neededResources())
def testInitiallyNoCurrentResource(self): resource_manager = testresources.TestResource() self.assertEqual(None, resource_manager._currentResource)
def testInitiallyUnused(self): resource_manager = testresources.TestResource() self.assertEqual(0, resource_manager._uses)
def testInitiallyNotDirty(self): resource_manager = testresources.TestResource() self.assertEqual(False, resource_manager._dirty)
def testUnimplementedGetResource(self): # By default, TestResource raises NotImplementedError on getResource # because make is not defined initially. resource_manager = testresources.TestResource() self.assertRaises(NotImplementedError, resource_manager.getResource)
def testDefaultCosts(self): # The base TestResource costs 1 to set up and to tear down. resource_manager = testresources.TestResource() self.assertEqual(resource_manager.setUpCost, 1) self.assertEqual(resource_manager.tearDownCost, 1)