#!/usr/bin/env python # # Copyright (C) 2018 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. # from vts.runners.host import asserts from vts.runners.host import base_test from vts.runners.host import const from vts.runners.host import test_runner import time class VtsKernelCheckpointTest(base_test.BaseTestClass): _CHECKPOINTTESTFILE = "/data/local/tmp/checkpointtest" _ORIGINALVALUE = "original value" _MODIFIEDVALUE = "modified value" def getFstab(self): self.dut.adb.root() for prop in ["fstab_suffix", "hardware", "hardware.platform"]: extension = self.dut.adb.shell("getprop ro.boot." + prop, no_except = True) extension = extension[const.STDOUT] if not extension: continue for filename in ["/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."]: contents = self.dut.adb.shell("cat " + filename + extension, no_except = True) if contents[const.EXIT_CODE] != 0: continue return contents[const.STDOUT] return "" def isCheckpoint(self): fstab = self.getFstab().splitlines() for line in fstab: parts = line.split() if len(parts) != 5: # fstab has five parts for each entry: # [device-name] [mount-point] [type] [mount_flags] [fsmgr_flags] continue flags = parts[4] # the fsmgr_flags field is the fifth one, thus index 4 flags = flags.split(',') if any(flag.startswith("checkpoint=") for flag in flags): return True return False def setUpClass(self): self.dut = self.android_devices[0] self.shell = self.dut.shell self.isCheckpoint_ = self.isCheckpoint() def reboot(self): self.dut.adb.reboot() try: self.dut.adb.wait_for_device(timeout=900) except self.dut.adb.AdbError as e: asserts.fail("Exception thrown waiting for device:" + e.msg()) # Should not be necessary, but without these retries, test fails # regularly on taimen with Android Q for i in range(1, 30): try: self.dut.adb.root() break except: time.sleep(1) for i in range(1, 30): try: self.dut.adb.shell("ls"); break except: time.sleep(1) def checkBooted(self): for i in range(1, 900): result = self.dut.adb.shell("getprop sys.boot_completed") try: boot_completed = int(result) asserts.assertEqual(boot_completed, 1) return except: time.sleep(1) asserts.fail("sys.boot_completed not set") def testCheckpointEnabled(self): result = self.dut.adb.shell("getprop ro.product.first_api_level") try: first_api_level = int(result) asserts.assertTrue(first_api_level < 29 or self.isCheckpoint_, "User Data Checkpoint is disabled") except: pass def testRollback(self): if not self.isCheckpoint_: return self.dut.adb.root() # Make sure that we are fully booted so we don't get entangled in # someone else's checkpoint self.checkBooted() # Create a file and initiate checkpoint self.dut.adb.shell("setprop persist.vold.dont_commit_checkpoint 1") self.dut.adb.shell("echo " + self._ORIGINALVALUE + " > " + self._CHECKPOINTTESTFILE) result = self.dut.adb.shell("vdc checkpoint startCheckpoint 1", no_except = True) asserts.assertEqual(result[const.EXIT_CODE], 0) self.reboot() # Modify the file but do not commit self.dut.adb.shell("echo " + self._MODIFIEDVALUE + " > " + self._CHECKPOINTTESTFILE) self.reboot() # Check the file is unchanged result = self.dut.adb.shell("cat " + self._CHECKPOINTTESTFILE) asserts.assertEqual(result.strip(), self._ORIGINALVALUE) # Clean up self.dut.adb.shell("setprop persist.vold.dont_commit_checkpoint 0") result = self.dut.adb.shell("vdc checkpoint commitChanges", no_except = True) asserts.assertEqual(result[const.EXIT_CODE], 0) self.reboot() self.dut.adb.shell("rm " + self._CHECKPOINTTESTFILE) def testCommit(self): if not self.isCheckpoint_: return self.dut.adb.root() # Make sure that we are fully booted so we don't get entangled in # someone else's checkpoint self.checkBooted() # Create a file and initiate checkpoint self.dut.adb.shell("setprop persist.vold.dont_commit_checkpoint 1") self.dut.adb.shell("echo " + self._ORIGINALVALUE + " > " + self._CHECKPOINTTESTFILE) result = self.dut.adb.shell("vdc checkpoint startCheckpoint 1", no_except = True) asserts.assertEqual(result[const.EXIT_CODE], 0) self.reboot() # Modify the file and commit the checkpoint self.dut.adb.shell("echo " + self._MODIFIEDVALUE + " > " + self._CHECKPOINTTESTFILE) self.dut.adb.shell("setprop persist.vold.dont_commit_checkpoint 0") result = self.dut.adb.shell("vdc checkpoint commitChanges", no_except = True) asserts.assertEqual(result[const.EXIT_CODE], 0) self.reboot() # Check file has changed result = self.dut.adb.shell("cat " + self._CHECKPOINTTESTFILE) asserts.assertEqual(result.strip(), self._MODIFIEDVALUE) # Clean up self.dut.adb.shell("rm " + self._CHECKPOINTTESTFILE) if __name__ == "__main__": test_runner.main()