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