1# Copyright (C) 2016 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import adb 16import os 17import unittest 18import fastboot 19import subprocess 20 21class ShellTest(unittest.TestCase): 22 def __init__(self, *args, **kwargs): 23 super(ShellTest, self).__init__(*args, **kwargs) 24 self.fastboot = fastboot.FastbootDevice() 25 26 def exists_validvals(self, varname, varlist, validlist): 27 self.assertIn(varname, varlist) 28 self.assertIn(varlist[varname], validlist) 29 return varlist[varname] 30 31 def exists_yes_no(self, varname, varlist): 32 return self.exists_validvals(varname, varlist, ["yes", "no"]) 33 34 def exists_nonempty(self, varname, varlist): 35 self.assertIn(varname, varlist) 36 self.assertGreater(len(varlist[varname]), 0) 37 return varlist[varname] 38 39 def exists_integer(self, varname, varlist, base=10): 40 val = 0 41 self.assertIn(varname, varlist) 42 try: 43 val = int(varlist[varname], base) 44 except ValueError: 45 self.fail("%s (%s) is not an integer" % (varname, varlist[varname])) 46 return val 47 48 def get_exists(self, varname): 49 val = self.fastboot.getvar(varname) 50 self.assertIsNotNone(val) 51 return val 52 53 def get_exists_validvals(self, varname, validlist): 54 val = self.get_exists(varname) 55 self.assertIn(val, validlist) 56 return val 57 58 def get_exists_yes_no(self, varname): 59 return self.get_exists_validvals(varname, ["yes", "no"]) 60 61 def get_exists_nonempty(self, varname): 62 val = self.get_exists(varname) 63 self.assertGreater(len(val), 0) 64 return val 65 66 def get_exists_integer(self, varname, base=10): 67 val = self.get_exists(varname) 68 try: 69 num = int(val, base) 70 except ValueError: 71 self.fail("%s (%s) is not an integer" % (varname, val)) 72 return num 73 74 def test_getvarall(self): 75 """Tests that required variables are reported by getvar all""" 76 77 var_all = self.fastboot.getvar_all() 78 self.exists_nonempty("version-baseband", var_all) 79 self.exists_nonempty("version-bootloader", var_all) 80 self.exists_nonempty("product", var_all) 81 self.exists_yes_no("secure", var_all) 82 self.exists_yes_no("unlocked", var_all) 83 self.exists_validvals("off-mode-charge", var_all, ["0", "1"]) 84 self.assertIn("variant", var_all) 85 voltage = self.exists_nonempty("battery-voltage", var_all) 86 if voltage[-2:].lower() == "mv": 87 voltage = voltage[:-2] 88 try: 89 voltnum = float(voltage) 90 except ValueError: 91 self.fail("battery-voltage (%s) is not a number" % (varname, voltage)) 92 self.exists_yes_no("battery-soc-ok", var_all) 93 maxdl = self.exists_integer("max-download-size", var_all, 16) 94 self.assertGreater(maxdl, 0) 95 96 if "slot-count" in var_all: 97 try: 98 slotcount = int(var_all["slot-count"]) 99 except ValueError: 100 self.fail("slot-count (%s) is not an integer" % var_all["slot-count"]) 101 if slotcount > 1: 102 # test for A/B variables 103 slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)] 104 self.exists_validvals("current-slot", var_all, slots) 105 106 # test for slot metadata 107 for slot in slots: 108 self.exists_yes_no("slot-unbootable:"+slot, var_all) 109 self.exists_yes_no("slot-unbootable:"+slot, var_all) 110 self.exists_integer("slot-retry-count:"+slot, var_all) 111 else: 112 print "This does not appear to be an A/B device." 113 114 def test_getvar_nonexistent(self): 115 """Tests behaviour of nonexistent variables.""" 116 117 self.assertIsNone(self.fastboot.getvar("fhqwhgads")) 118 119 def test_getvar(self): 120 """Tests all variables separately""" 121 122 self.get_exists_nonempty("version-baseband") 123 self.get_exists_nonempty("version-bootloader") 124 self.get_exists_nonempty("product") 125 self.get_exists_yes_no("secure") 126 self.get_exists_yes_no("unlocked") 127 self.get_exists_validvals("off-mode-charge", ["0", "1"]) 128 self.get_exists("variant") 129 voltage = self.get_exists_nonempty("battery-voltage") 130 if voltage[-2:].lower() == "mv": 131 voltage = voltage[:-2] 132 try: 133 voltnum = float(voltage) 134 except ValueError: 135 self.fail("battery-voltage (%s) is not a number" % voltage) 136 self.get_exists_yes_no("battery-soc-ok") 137 maxdl = self.get_exists_integer("max-download-size", 16) 138 self.assertGreater(maxdl, 0) 139 140 slotcount = 0 141 try: 142 slotcountString = self.fastboot.getvar("slot-count") 143 if slotcountString != None: 144 slotcount = int(slotcountString) 145 except ValueError: 146 self.fail("slot-count (%s) is not an integer" % slotcountString) 147 if slotcount > 1: 148 # test for A/B variables 149 slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)] 150 self.get_exists_validvals("current-slot", slots) 151 152 # test for slot metadata 153 for slot in slots: 154 self.get_exists_yes_no("slot-unbootable:"+slot) 155 self.get_exists_yes_no("slot-successful:"+slot) 156 self.get_exists_integer("slot-retry-count:"+slot) 157 else: 158 print "This does not appear to be an A/B device." 159 160 def test_setactive(self): 161 """Tests that A/B devices can switch to each slot, and the change persists over a reboot.""" 162 163 slotcount = 0 164 try: 165 val = self.fastboot.getvar("slot-count") 166 if val != None: 167 slotcount = int(val) 168 except ValueError: 169 self.fail("slot-count (%s) is not an integer" % val) 170 except subprocess.CalledProcessError: 171 print "Does not appear to be an A/B device." 172 maxtries = 0 173 if slotcount > 1: 174 slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)] 175 for slot in slots: 176 self.fastboot.set_active(slot) 177 self.assertEqual(slot, self.fastboot.getvar("current-slot")) 178 self.assertEqual("no", self.fastboot.getvar("slot-unbootable:"+slot)) 179 self.assertEqual("no", self.fastboot.getvar("slot-successful:"+slot)) 180 retry = self.get_exists_integer("slot-retry-count:"+slot) 181 if maxtries == 0: 182 maxtries = retry 183 else: 184 self.assertEqual(maxtries, retry) 185 self.fastboot.reboot(True) 186 self.assertEqual(slot, self.fastboot.getvar("current-slot")) 187 self.assertEqual("no", self.fastboot.getvar("slot-unbootable:"+slot)) 188 self.assertEqual("no", self.fastboot.getvar("slot-successful:"+slot)) 189 retry = self.get_exists_integer("slot-retry-count:"+slot) 190 if maxtries == 0: 191 maxtries = retry 192 else: 193 self.assertEqual(maxtries, retry) 194 else: 195 print "Does not appear to be an A/B device." 196 197if __name__ == '__main__': 198 unittest.main(verbosity=3) 199