def test_partition(self): a = MockTarget('a', [], 1) b = MockTarget('b', [a], 1) c = MockTarget('c', [b], 1) d = MockTarget('d', [c, a], 1) e = MockTarget('e', [d], 1) targets = [a, b, c, d, e] all_vts = self.cache_manager._sort_and_validate_targets(targets) [print_vt(vt) for vt in all_vts] print '' invalid_vts = filter(lambda vt: not vt.valid, all_vts) self.assertEquals(5, len(invalid_vts)) self.assertEquals(5, len(all_vts)) vts_targets = [vt.targets[0] for vt in all_vts] self.assertEquals(set(targets), set(vts_targets)) ic = InvalidationCheck(all_vts, [], 3) partitioned = ic.all_vts_partitioned [print_vt(vt) for vt in partitioned] # NOTE(ryan): several correct partitionings are possible, but in all cases 4 1-source targets will be added to the # first partition before it exceeds the limit of 3, and the final target will be in a partition by itself. self.assertEquals(2, len(partitioned)) self.assertEquals(4, len(partitioned[0].targets)) self.assertEquals(1, len(partitioned[1].targets))
def setupTargets(self): a = MockTarget('a', exclusives={'a': '1', 'b': '1'}) b = MockTarget('b', exclusives={'a': '1'}) c = MockTarget('c', exclusives={'a': '2'}) d = MockTarget('d', dependencies=[a, b]) e = MockTarget('e', dependencies=[a, c], exclusives={'c': '1'}) return a, b, c, d, e
def testSort(self): a = MockTarget('a', []) b = MockTarget('b', [a]) c = MockTarget('c', [b]) d = MockTarget('d', [c, a]) e = MockTarget('e', [d]) self.assertEquals(InternalTarget.sort_targets([a,b,c,d,e]), [e,d,c,b,a]) self.assertEquals(InternalTarget.sort_targets([b,d,a,e,c]), [e,d,c,b,a]) self.assertEquals(InternalTarget.sort_targets([e,d,c,b,a]), [e,d,c,b,a])
def test_dependents_direct(self): a = MockTarget('a') b = MockTarget('b', [a]) c = MockTarget('c', [b]) d = MockTarget('d', [c, a]) e = MockTarget('e', [d]) context = self.create_context(options={}, target_roots=[a, b, c, d, e]) dependees = context.dependents(lambda t: t in set([e, c])) self.assertEquals(set([c]), dependees.pop(d)) self.assertEquals(0, len(dependees))
def test_detect_cycle_direct(self): a = MockTarget('a') # no cycles yet InternalTarget.sort_targets([a]) a.update_dependencies([a]) try: InternalTarget.sort_targets([a]) self.fail("Expected a cycle to be detected") except InternalTarget.CycleException: # expected pass
def testDetectCycleDirect(self): a = MockTarget('a') # no cycles yet InternalTarget.sort_targets([a]) a.internal_dependencies = [a] try: InternalTarget.sort_targets([a]) self.fail("Expected a cycle to be detected") except InternalTarget.CycleException: # expected pass
def test_detect_cycle_indirect(self): c = MockTarget('c') b = MockTarget('b', [c]) a = MockTarget('a', [c, b]) # no cycles yet InternalTarget.sort_targets([a]) c.internal_dependencies = [a] try: InternalTarget.sort_targets([a]) self.fail("Expected a cycle to be detected") except InternalTarget.CycleException: # expected pass
def test_diamond_in_different_orders(self): a = MockTarget('a') b = MockTarget('b', [a]) c = MockTarget('c', [a]) d = MockTarget('d', [c, b]) def test_diamond_dag(dag): self.assertEquals(dag._roots, set([dag.lookup(d)])) self.assertEquals(dag.leaves, set([dag.lookup(a)])) self.check_dag_node(dag, d, [b, c], []) self.check_dag_node(dag, c, [a], [d]) self.check_dag_node(dag, b, [a], [d]) self.check_dag_node(dag, a, [], [b, c]) test_diamond_dag(make_dag([a, b, c, d])) test_diamond_dag(make_dag([d, c, b, a])) test_diamond_dag(make_dag([b, d, a, c]))
def test_check_exclusives(self): a = MockTarget('a', exclusives={'a': '1', 'b': '1'}) b = MockTarget('b', exclusives={'a': '1'}) c = MockTarget('c', exclusives={'a': '2'}) d = MockTarget('d', dependencies=[a, b]) e = MockTarget('e', dependencies=[a, c], exclusives={'c': '1'}) context = Context(CheckExclusivesTest.config, options={}, run_tracker=None, target_roots=[d, e]) check_exclusives_task = CheckExclusives(context, signal_error=True) try: check_exclusives_task.execute([d, e]) self.fail( "Expected a conflicting exclusives exception to be thrown.") except TaskError: pass
def testClasspathUpdates(self): # Check that exclusive groups classpaths accumulate properly. a = MockTarget('a', exclusives={'a': '1', 'b': '1'}) b = MockTarget('b', exclusives={'a': '1', 'b': '<none>'}) c = MockTarget('c', exclusives={'a': '2', 'b': '2'}) d = MockTarget('d') context = Context(CheckExclusivesTest.config, options={}, run_tracker=None, target_roots=[a, b, c, d]) context.products.require_data('exclusives_groups') check_exclusives_task = CheckExclusives(context, signal_error=True) check_exclusives_task.execute([a, b, c, d]) egroups = context.products.get_data('exclusives_groups') egroups.set_base_classpath_for_group("a=1,b=1", ["a1", "b1"]) egroups.set_base_classpath_for_group("a=1,b=<none>", ["a1"]) egroups.set_base_classpath_for_group("a=2,b=2", ["a2", "b2"]) egroups.set_base_classpath_for_group("a=<none>,b=<none>", ["none"]) egroups.update_compatible_classpaths(None, ["update_without_group"]) egroups.update_compatible_classpaths("a=<none>,b=<none>", ["update_all"]) egroups.update_compatible_classpaths("a=1,b=<none>", ["update_a1bn"]) egroups.update_compatible_classpaths("a=2,b=2", ["update_only_a2b2"]) self.assertEquals(egroups.get_classpath_for_group("a=2,b=2"), [ "a2", "b2", "update_without_group", "update_all", "update_only_a2b2" ]) self.assertEquals( egroups.get_classpath_for_group("a=1,b=1"), ["a1", "b1", "update_without_group", "update_all", "update_a1bn"]) self.assertEquals( egroups.get_classpath_for_group("a=1,b=<none>"), ["a1", "update_without_group", "update_all", "update_a1bn"]) self.assertEquals(egroups.get_classpath_for_group("a=<none>,b=<none>"), ["none", "update_without_group", "update_all"]) # make sure repeated additions of the same thing are idempotent. egroups.update_compatible_classpaths("a=1,b=1", ["a1", "b1", "xxx"]) self.assertEquals(egroups.get_classpath_for_group("a=1,b=1"), [ "a1", "b1", "update_without_group", "update_all", "update_a1bn", "xxx" ])
def test_simple_dag(self): a = MockTarget('a') b = MockTarget('b', [a]) c = MockTarget('c', [b]) d = MockTarget('d', [c, a]) e = MockTarget('e', [d]) def test_dag(dag): self.assertEquals(dag._roots, set([dag.lookup(e)])) self.assertEquals(dag.leaves, set([dag.lookup(a)])) self.check_dag_node(dag, e, [d], []) self.check_dag_node(dag, d, [a, c], [e]) self.check_dag_node(dag, c, [b], [d]) self.check_dag_node(dag, b, [a], [c]) self.check_dag_node(dag, a, [], [b, d]) test_dag(make_dag([e, d, c, b, a])) test_dag(make_dag([a, b, c, d, e])) test_dag(make_dag([a, b, e, d, c])) test_dag(make_dag([d, a, c, e, b]))
def test_classpath_compatibility(self): # test the compatibility checks for different exclusive groups. a = MockTarget('a', exclusives={'a': '1', 'b': '1'}) b = MockTarget('b', exclusives={'a': '1', 'b': '<none>'}) c = MockTarget('c', exclusives={'a': '2', 'b': '2'}) d = MockTarget('d') context = Context(CheckExclusivesTest.config, options={}, run_tracker=None, target_roots=[a, b, c, d]) context.products.require_data('exclusives_groups') check_exclusives_task = CheckExclusives(context, signal_error=True) check_exclusives_task.execute([a, b, c, d]) egroups = context.products.get_data('exclusives_groups') # Expected compatibility: # a is compatible with nothing but itself. self.assertTrue( egroups._is_compatible(egroups.target_to_key[a], egroups.target_to_key[a])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[a], egroups.target_to_key[b])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[a], egroups.target_to_key[d])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[a], egroups.target_to_key[c])) # b is compatible with itself and a. self.assertTrue( egroups._is_compatible(egroups.target_to_key[b], egroups.target_to_key[a])) self.assertTrue( egroups._is_compatible(egroups.target_to_key[b], egroups.target_to_key[b])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[b], egroups.target_to_key[c])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[b], egroups.target_to_key[d])) # c is compatible with nothing but itself self.assertTrue( egroups._is_compatible(egroups.target_to_key[c], egroups.target_to_key[c])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[c], egroups.target_to_key[a])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[c], egroups.target_to_key[b])) self.assertFalse( egroups._is_compatible(egroups.target_to_key[c], egroups.target_to_key[d])) # d is compatible with everything. self.assertTrue( egroups._is_compatible(egroups.target_to_key[d], egroups.target_to_key[a])) self.assertTrue( egroups._is_compatible(egroups.target_to_key[d], egroups.target_to_key[b])) self.assertTrue( egroups._is_compatible(egroups.target_to_key[d], egroups.target_to_key[c])) self.assertTrue( egroups._is_compatible(egroups.target_to_key[d], egroups.target_to_key[d]))
def test_binary_search_dag(self): rrr = MockTarget('rrr') rrl = MockTarget('rrl') rlr = MockTarget('rlr') rll = MockTarget('rll') lrr = MockTarget('lrr') lrl = MockTarget('lrl') llr = MockTarget('llr') lll = MockTarget('lll') rr = MockTarget('rr', [rrr, rrl]) rl = MockTarget('rl', [rlr, rll]) lr = MockTarget('lr', [lrr, lrl]) ll = MockTarget('ll', [llr, lll]) r = MockTarget('r', [rr, rl]) l = MockTarget('l', [lr, ll]) root = MockTarget('root', [r, l]) def test_dag(dag): def t(n): return dag.lookup(n) self.assertEquals(dag._roots, set([t(root)])) self.assertEquals( dag.leaves, set(map(t, [rrr, rrl, rlr, rll, lrr, lrl, llr, lll]))) self.check_dag_node(dag, root, [r, l], []) self.check_dag_node(dag, r, [rl, rr], [root]) self.check_dag_node(dag, l, [ll, lr], [root]) self.check_dag_node(dag, rr, [rrl, rrr], [r]) self.check_dag_node(dag, rl, [rll, rlr], [r]) self.check_dag_node(dag, lr, [lrl, lrr], [l]) self.check_dag_node(dag, ll, [lll, llr], [l]) self.check_dag_node(dag, rrr, [], [rr]) self.check_dag_node(dag, rrl, [], [rr]) self.check_dag_node(dag, rlr, [], [rl]) self.check_dag_node(dag, rll, [], [rl]) self.check_dag_node(dag, lrr, [], [lr]) self.check_dag_node(dag, lrl, [], [lr]) self.check_dag_node(dag, llr, [], [ll]) self.check_dag_node(dag, lll, [], [ll]) # Test in order test_dag( make_dag([ root, r, l, rr, rl, lr, ll, rrr, rrl, rlr, rll, lrr, lrl, llr, lll ])) # Test a couple of randomly chosen orders test_dag( make_dag([ lrl, r, root, rl, rrr, rll, lr, lrr, ll, lll, l, rr, rrl, rlr, llr ])) test_dag( make_dag([ ll, rrl, lrl, rl, rlr, lr, root, rrr, rll, r, llr, rr, lrr, l, lll ])) test_dag( make_dag([ rr, rlr, rl, rrr, rrl, l, root, lr, lrr, llr, r, rll, lrl, ll, lll ])) test_dag( make_dag([ l, lll, rrr, rll, ll, lrl, llr, rl, root, r, lr, rlr, rr, lrr, rrl ]))
def test_find_children_across_unused_target(self): a = MockTarget('a') b = MockTarget('b', [a]) c = MockTarget('c', [b]) d = MockTarget('d', [c, a]) e = MockTarget('e', [d])