You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
8.4 KiB
226 lines
8.4 KiB
# Copyright (C) 2016 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import adb
|
|
import argparse
|
|
import os
|
|
import unittest
|
|
import fastboot
|
|
import subprocess
|
|
import sys
|
|
|
|
# Default values for arguments
|
|
device_type = "phone"
|
|
|
|
class ShellTest(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.fastboot = fastboot.FastbootDevice()
|
|
|
|
def exists_validvals(self, varname, varlist, validlist):
|
|
self.assertIn(varname, varlist)
|
|
self.assertIn(varlist[varname], validlist)
|
|
return varlist[varname]
|
|
|
|
def exists_yes_no(self, varname, varlist):
|
|
return self.exists_validvals(varname, varlist, ["yes", "no"])
|
|
|
|
def exists_nonempty(self, varname, varlist):
|
|
self.assertIn(varname, varlist)
|
|
self.assertGreater(len(varlist[varname]), 0)
|
|
return varlist[varname]
|
|
|
|
def exists_integer(self, varname, varlist, base=10):
|
|
val = 0
|
|
self.assertIn(varname, varlist)
|
|
try:
|
|
val = int(varlist[varname], base)
|
|
except ValueError:
|
|
self.fail("%s (%s) is not an integer" % (varname, varlist[varname]))
|
|
return val
|
|
|
|
def get_exists(self, varname):
|
|
val = self.fastboot.getvar(varname)
|
|
self.assertIsNotNone(val)
|
|
return val
|
|
|
|
def get_exists_validvals(self, varname, validlist):
|
|
val = self.get_exists(varname)
|
|
self.assertIn(val, validlist)
|
|
return val
|
|
|
|
def get_exists_yes_no(self, varname):
|
|
return self.get_exists_validvals(varname, ["yes", "no"])
|
|
|
|
def get_exists_nonempty(self, varname):
|
|
val = self.get_exists(varname)
|
|
self.assertGreater(len(val), 0)
|
|
return val
|
|
|
|
def get_exists_integer(self, varname, base=10):
|
|
val = self.get_exists(varname)
|
|
try:
|
|
num = int(val, base)
|
|
except ValueError:
|
|
self.fail("%s (%s) is not an integer" % (varname, val))
|
|
return num
|
|
|
|
def get_slotcount(self):
|
|
slotcount = 0
|
|
try:
|
|
val = self.fastboot.getvar("slot-count")
|
|
if val != None:
|
|
slotcount = int(val)
|
|
except ValueError:
|
|
self.fail("slot-count (%s) is not an integer" % val)
|
|
except subprocess.CalledProcessError:
|
|
print "Does not appear to be an A/B device."
|
|
if not slotcount:
|
|
print "Does not appear to be an A/B device."
|
|
return slotcount
|
|
|
|
def test_getvarall(self):
|
|
"""Tests that required variables are reported by getvar all"""
|
|
|
|
var_all = self.fastboot.getvar_all()
|
|
self.exists_nonempty("version-baseband", var_all)
|
|
self.exists_nonempty("version-bootloader", var_all)
|
|
self.exists_nonempty("product", var_all)
|
|
self.exists_yes_no("secure", var_all)
|
|
self.exists_yes_no("unlocked", var_all)
|
|
self.exists_validvals("off-mode-charge", var_all, ["0", "1"])
|
|
self.assertIn("variant", var_all)
|
|
voltage = self.exists_nonempty("battery-voltage", var_all)
|
|
if voltage[-2:].lower() == "mv":
|
|
voltage = voltage[:-2]
|
|
try:
|
|
voltnum = float(voltage)
|
|
except ValueError:
|
|
self.fail("battery-voltage (%s) is not a number" % (varname, voltage))
|
|
self.exists_yes_no("battery-soc-ok", var_all)
|
|
maxdl = self.exists_integer("max-download-size", var_all, 16)
|
|
self.assertGreater(maxdl, 0)
|
|
|
|
if "slot-count" in var_all:
|
|
try:
|
|
slotcount = int(var_all["slot-count"])
|
|
except ValueError:
|
|
self.fail("slot-count (%s) is not an integer" % var_all["slot-count"])
|
|
if slotcount > 1:
|
|
# test for A/B variables
|
|
slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)]
|
|
self.exists_validvals("current-slot", var_all, slots)
|
|
|
|
# test for slot metadata
|
|
for slot in slots:
|
|
self.exists_yes_no("slot-unbootable:"+slot, var_all)
|
|
self.exists_yes_no("slot-unbootable:"+slot, var_all)
|
|
self.exists_integer("slot-retry-count:"+slot, var_all)
|
|
else:
|
|
print "This does not appear to be an A/B device."
|
|
|
|
def test_getvar_nonexistent(self):
|
|
"""Tests behaviour of nonexistent variables."""
|
|
|
|
self.assertIsNone(self.fastboot.getvar("fhqwhgads"))
|
|
|
|
def test_getvar(self):
|
|
"""Tests all variables separately"""
|
|
|
|
self.get_exists_nonempty("version-baseband")
|
|
self.get_exists_nonempty("version-bootloader")
|
|
self.get_exists_nonempty("product")
|
|
self.get_exists_yes_no("secure")
|
|
self.get_exists_yes_no("unlocked")
|
|
self.get_exists_validvals("off-mode-charge", ["0", "1"])
|
|
self.get_exists("variant")
|
|
voltage = self.get_exists_nonempty("battery-voltage")
|
|
if voltage[-2:].lower() == "mv":
|
|
voltage = voltage[:-2]
|
|
try:
|
|
voltnum = float(voltage)
|
|
except ValueError:
|
|
self.fail("battery-voltage (%s) is not a number" % voltage)
|
|
self.get_exists_yes_no("battery-soc-ok")
|
|
maxdl = self.get_exists_integer("max-download-size", 16)
|
|
self.assertGreater(maxdl, 0)
|
|
|
|
slotcount = self.get_slotcount()
|
|
if slotcount > 1:
|
|
# test for A/B variables
|
|
slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)]
|
|
self.get_exists_validvals("current-slot", slots)
|
|
|
|
# test for slot metadata
|
|
for slot in slots:
|
|
self.get_exists_yes_no("slot-unbootable:"+slot)
|
|
self.get_exists_yes_no("slot-successful:"+slot)
|
|
self.get_exists_integer("slot-retry-count:"+slot)
|
|
|
|
def test_setactive(self):
|
|
"""Tests that A/B devices can switch to each slot, and the change persists over a reboot."""
|
|
# Test invalid if not an A/B device
|
|
slotcount = self.get_slotcount()
|
|
if not slotcount:
|
|
return
|
|
|
|
maxtries = 0
|
|
slots = [chr(slotnum+ord('a')) for slotnum in range(slotcount)]
|
|
for slot in slots:
|
|
self.fastboot.set_active(slot)
|
|
self.assertEqual(slot, self.fastboot.getvar("current-slot"))
|
|
self.assertEqual("no", self.fastboot.getvar("slot-unbootable:"+slot))
|
|
self.assertEqual("no", self.fastboot.getvar("slot-successful:"+slot))
|
|
retry = self.get_exists_integer("slot-retry-count:"+slot)
|
|
if maxtries == 0:
|
|
maxtries = retry
|
|
else:
|
|
self.assertEqual(maxtries, retry)
|
|
self.fastboot.reboot(True)
|
|
self.assertEqual(slot, self.fastboot.getvar("current-slot"))
|
|
self.assertEqual("no", self.fastboot.getvar("slot-unbootable:"+slot))
|
|
self.assertEqual("no", self.fastboot.getvar("slot-successful:"+slot))
|
|
retry = self.get_exists_integer("slot-retry-count:"+slot)
|
|
if maxtries == 0:
|
|
maxtries = retry
|
|
else:
|
|
self.assertEqual(maxtries, retry)
|
|
|
|
def test_hasslot(self):
|
|
"""Tests that A/B devices report partitions that have slots."""
|
|
# Test invalid if not an A/B device
|
|
if not self.get_slotcount():
|
|
return
|
|
|
|
self.assertEqual("yes", self.fastboot.getvar("has-slot:system"))
|
|
self.assertEqual("yes", self.fastboot.getvar("has-slot:boot"))
|
|
|
|
# Additional partition on AndroidThings (IoT) devices
|
|
if device_type == "iot":
|
|
self.assertEqual("yes", self.fastboot.getvar("has-slot:oem"))
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--device-type", default="phone",
|
|
help="Type of device ('phone' or 'iot').")
|
|
parser.add_argument("extra_args", nargs="*")
|
|
args = parser.parse_args()
|
|
|
|
if args.device_type.lower() not in ("phone", "iot"):
|
|
raise ValueError("Unsupported device type '%s'." % args.device_type)
|
|
device_type = args.device_type.lower()
|
|
|
|
sys.argv[1:] = args.extra_args
|
|
unittest.main(verbosity=3)
|