1#!/usr/bin/python3 2# 3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7"""Unit tests for server/cros/dynamic_suite/host_spec.py.""" 8 9import unittest 10 11import common 12 13from autotest_lib.server.cros.dynamic_suite import host_spec 14from autotest_lib.server.cros.dynamic_suite.fakes import FakeHost 15 16 17class HostSpecTest(unittest.TestCase): 18 """Unit tests for dynamic_suite.host_spec module. 19 20 @var _BOARD: fake board to reimage 21 """ 22 23 24 _BOARD = 'board' 25 _SPECS = [host_spec.HostSpec([_BOARD]), 26 host_spec.HostSpec([_BOARD, 'pool:bvt']), 27 host_spec.HostSpec([_BOARD], ['label1'])] 28 29 30 def testOrderSpecsByComplexity(self): 31 """Should return new host spec list with simpler entries later.""" 32 reordered = host_spec.order_by_complexity(self._SPECS) 33 34 for spec in self._SPECS[1:]: 35 self.assertTrue(spec in reordered[:-1]) 36 self.assertEquals(self._SPECS[0], reordered[-1]) 37 38 39 def testSpecSubsets(self): 40 """Validate HostSpec subset checks.""" 41 self.assertTrue(self._SPECS[0].is_subset(self._SPECS[1])) 42 self.assertTrue(self._SPECS[0].is_subset(self._SPECS[2])) 43 self.assertFalse(self._SPECS[1].is_subset(self._SPECS[2])) 44 self.assertFalse(self._SPECS[2].is_subset(self._SPECS[1])) 45 self.assertFalse(self._SPECS[1].is_subset(self._SPECS[0])) 46 self.assertFalse(self._SPECS[2].is_subset(self._SPECS[0])) 47 48 49 def testTrivialSpec(self): 50 """Validate that HostSpecs are correctly marked as trivial.""" 51 self.assertTrue(self._SPECS[0].is_trivial) 52 self.assertTrue(self._SPECS[1].is_trivial) 53 self.assertFalse(self._SPECS[2].is_trivial) 54 55 56class HostGroupTest(unittest.TestCase): 57 """Unit tests for dynamic_suite.host_spec.HostGroup derived classes. 58 """ 59 60 61 def testCanConstructExplicit(self): 62 """Should be able to make an ExplicitHostGroup.""" 63 host_list = [FakeHost('h1'), FakeHost('h2'), FakeHost('h3')] 64 hosts_per_spec = {host_spec.HostSpec(['l1']): host_list[:1], 65 host_spec.HostSpec(['l2']): host_list[1:]} 66 group = host_spec.ExplicitHostGroup(hosts_per_spec) 67 for host in host_list: 68 self.assertTrue(host.hostname in group.as_args()['hosts']) 69 70 71 def testExplicitEnforcesHostUniqueness(self): 72 """Should fail to make ExplicitHostGroup with duplicate hosts.""" 73 host_list = [FakeHost('h1'), FakeHost('h2'), FakeHost('h3')] 74 hosts_per_spec = {host_spec.HostSpec(['l1']): host_list[:1], 75 host_spec.HostSpec(['l2']): host_list} 76 self.assertRaises(ValueError, 77 host_spec.ExplicitHostGroup, hosts_per_spec) 78 79 80 def testCanConstructByMetahostsWithDependencies(self): 81 """Should be able to make a HostGroup from labels.""" 82 labels = ['meta_host', 'dep1', 'dep2'] 83 num = 3 84 group = host_spec.MetaHostGroup(labels, num) 85 args = group.as_args() 86 self.assertEquals(labels[:1] * num, args['meta_hosts']) 87 self.assertEquals(labels[1:], args['dependencies']) 88 89 90 def testExplicitCanTrackSuccess(self): 91 """Track success/failure in an ExplicitHostGroup.""" 92 host_list = [FakeHost('h1'), FakeHost('h2'), FakeHost('h3')] 93 specs = [host_spec.HostSpec(['l1']), host_spec.HostSpec(['l2'])] 94 hosts_per_spec = {specs[0]: host_list[:1], specs[1]: host_list[1:]} 95 group = host_spec.ExplicitHostGroup(hosts_per_spec) 96 97 # Reimage just the one host that satisfies specs[0]. 98 group.mark_host_success(host_list[0].hostname) 99 self.assertTrue(group.enough_hosts_succeeded()) 100 self.assertTrue(specs[1] in group.doomed_specs) 101 102 # Reimage some host that satisfies specs[1]. 103 group.mark_host_success(host_list[2].hostname) 104 self.assertTrue(group.enough_hosts_succeeded()) 105 self.assertFalse(group.doomed_specs) 106 107 108 def testExplicitCanTrackSuccessWithSupersets(self): 109 """Track success/failure in an ExplicitHostGroup with supersets.""" 110 host_list = [FakeHost('h1'), FakeHost('h2'), FakeHost('h3')] 111 specs = [host_spec.HostSpec(['l1']), 112 host_spec.HostSpec(['l2']), 113 host_spec.HostSpec(['l2', 'l1'])] 114 hosts_per_spec = {specs[0]: host_list[:1], 115 specs[1]: host_list[1:2], 116 specs[2]: host_list[2:]} 117 group = host_spec.ExplicitHostGroup(hosts_per_spec) 118 119 # Reimage just the one host that satisfies specs[2]. 120 # Because satisfying specs[2] statisfies all the specs, we should have 121 # no doomed specs. 122 group.mark_host_success(host_list[2].hostname) 123 self.assertTrue(group.enough_hosts_succeeded()) 124 self.assertFalse(group.doomed_specs) 125 126 127 def testExplicitCanTrackUnsatisfiedSpecs(self): 128 """Track unsatisfiable HostSpecs in ExplicitHostGroup.""" 129 group = host_spec.ExplicitHostGroup() 130 satisfiable_spec = host_spec.HostSpec(['l2']) 131 unsatisfiable_spec = host_spec.HostSpec(['l1'], ['e1']) 132 group.add_host_for_spec(unsatisfiable_spec, None) 133 group.add_host_for_spec(satisfiable_spec, FakeHost('h1')) 134 self.assertTrue(unsatisfiable_spec in group.unsatisfied_specs) 135 self.assertTrue(satisfiable_spec not in group.unsatisfied_specs) 136 137 138 def testExplicitOneHostEnoughToSatisfySpecs(self): 139 """One host is enough to satisfy a HostSpec in ExplicitHostGroup.""" 140 satisfiable_spec = host_spec.HostSpec(['l1']) 141 group = host_spec.ExplicitHostGroup() 142 group.add_host_for_spec(satisfiable_spec, FakeHost('h1')) 143 group.add_host_for_spec(satisfiable_spec, None) 144 self.assertTrue(satisfiable_spec not in group.unsatisfied_specs) 145 146 group = host_spec.ExplicitHostGroup() 147 group.add_host_for_spec(satisfiable_spec, None) 148 group.add_host_for_spec(satisfiable_spec, FakeHost('h1')) 149 self.assertTrue(satisfiable_spec not in group.unsatisfied_specs) 150 151 152 def testExplicitSubsetSpecSatisfiedIfAnyAre(self): 153 """Ensures that any satisfied spec also satisfies a subset HostSpec.""" 154 specs = [host_spec.HostSpec(['l1'], ['l3']), 155 host_spec.HostSpec(['l1'], ['l3', 'l4']), 156 host_spec.HostSpec(['l1'], ['l5', 'l4']), 157 host_spec.HostSpec(['l1'], ['l2', 'l3', 'l4'])] 158 group = host_spec.ExplicitHostGroup() 159 group.add_host_for_spec(specs[0], None) 160 group.add_host_for_spec(specs[1], FakeHost('h1')) 161 group.add_host_for_spec(specs[2], FakeHost('h2')) 162 group.add_host_for_spec(specs[3], None) 163 164 self.assertTrue(specs[0] not in group.unsatisfied_specs) 165 self.assertTrue(specs[1] not in group.unsatisfied_specs) 166 self.assertTrue(specs[2] not in group.unsatisfied_specs) 167 self.assertTrue(specs[3] in group.unsatisfied_specs) 168 169 170 def testMetaCanTrackSuccess(self): 171 """Track success/failure in a MetaHostGroup.""" 172 labels = ['meta_host', 'dep1', 'dep2'] 173 num = 3 174 group = host_spec.MetaHostGroup(labels, num) 175 176 self.assertFalse(group.enough_hosts_succeeded()) 177 178 group.mark_host_success('h1') 179 self.assertTrue(group.enough_hosts_succeeded()) 180 181 182if __name__ == '__main__': 183 unittest.main() 184