1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tests.init; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assume.assumeTrue; 22 23 import com.android.server.os.TombstoneProtos.Tombstone; 24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 25 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 26 import com.android.tradefed.util.CommandResult; 27 28 import org.junit.After; 29 import org.junit.Before; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 33 import java.io.File; 34 import java.io.FileInputStream; 35 import java.io.InputStream; 36 import java.util.ArrayList; 37 38 @RunWith(DeviceJUnit4ClassRunner.class) 39 public class MteUpgradeTest extends BaseHostJUnit4Test { 40 @Before setUp()41 public void setUp() throws Exception { 42 CommandResult result = 43 getDevice().executeShellV2Command("/system/bin/mte_upgrade_test_helper --checking"); 44 assumeTrue("mte_upgrade_test_binary needs to segfault", result.getExitCode() == 139); 45 } 46 47 @After tearDown()48 public void tearDown() throws Exception { 49 // Easier here than in a finally in testCrash, and doesn't really hurt. 50 getDevice().executeShellV2Command("stop mte_upgrade_test_helper"); 51 getDevice().executeShellV2Command("stop mte_upgrade_test_helper_overridden"); 52 getDevice().setProperty("sys.mte_crash_test_uuid", ""); 53 } 54 parseTombstone(String tombstonePath)55 Tombstone parseTombstone(String tombstonePath) throws Exception { 56 File tombstoneFile = getDevice().pullFile(tombstonePath); 57 InputStream istr = new FileInputStream(tombstoneFile); 58 Tombstone tombstoneProto; 59 try { 60 tombstoneProto = Tombstone.parseFrom(istr); 61 } finally { 62 istr.close(); 63 } 64 return tombstoneProto; 65 } 66 67 @Test testCrash()68 public void testCrash() throws Exception { 69 String uuid = java.util.UUID.randomUUID().toString(); 70 getDevice().reboot(); 71 assertThat(getDevice().setProperty("sys.mte_crash_test_uuid", uuid)).isTrue(); 72 73 CommandResult result = getDevice().executeShellV2Command("start mte_upgrade_test_helper"); 74 assertThat(result.getExitCode()).isEqualTo(0); 75 java.lang.Thread.sleep(20000); 76 String[] tombstonesAfter = getDevice().getChildren("/data/tombstones"); 77 ArrayList<String> segvCodeNames = new ArrayList<String>(); 78 for (String tombstone : tombstonesAfter) { 79 if (!tombstone.endsWith(".pb")) { 80 continue; 81 } 82 String tombstoneFilename = "/data/tombstones/" + tombstone; 83 Tombstone tombstoneProto = parseTombstone(tombstoneFilename); 84 if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(uuid))) { 85 continue; 86 } 87 assertThat(tombstoneProto.getSignalInfo().getName()).isEqualTo("SIGSEGV"); 88 segvCodeNames.add(tombstoneProto.getSignalInfo().getCodeName()); 89 getDevice().deleteFile(tombstoneFilename); 90 // remove the non .pb file as well. 91 getDevice().deleteFile(tombstoneFilename.substring(0, tombstoneFilename.length() - 3)); 92 } 93 assertThat(segvCodeNames.size()).isAtLeast(3); 94 assertThat(segvCodeNames.get(0)).isEqualTo("SEGV_MTEAERR"); 95 assertThat(segvCodeNames.get(1)).isEqualTo("SEGV_MTESERR"); 96 assertThat(segvCodeNames.get(2)).isEqualTo("SEGV_MTEAERR"); 97 } 98 99 @Test testCrashOverridden()100 public void testCrashOverridden() throws Exception { 101 String uuid = java.util.UUID.randomUUID().toString(); 102 getDevice().reboot(); 103 assertThat(getDevice().setProperty("sys.mte_crash_test_uuid", uuid)).isTrue(); 104 105 CommandResult result = 106 getDevice().executeShellV2Command("start mte_upgrade_test_helper_overridden"); 107 assertThat(result.getExitCode()).isEqualTo(0); 108 java.lang.Thread.sleep(20000); 109 String[] tombstonesAfter = getDevice().getChildren("/data/tombstones"); 110 ArrayList<String> segvCodeNames = new ArrayList<String>(); 111 for (String tombstone : tombstonesAfter) { 112 if (!tombstone.endsWith(".pb")) { 113 continue; 114 } 115 String tombstoneFilename = "/data/tombstones/" + tombstone; 116 Tombstone tombstoneProto = parseTombstone(tombstoneFilename); 117 if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(uuid))) { 118 continue; 119 } 120 assertThat(tombstoneProto.getSignalInfo().getName()).isEqualTo("SIGSEGV"); 121 segvCodeNames.add(tombstoneProto.getSignalInfo().getCodeName()); 122 getDevice().deleteFile(tombstoneFilename); 123 // remove the non .pb file as well. 124 getDevice().deleteFile(tombstoneFilename.substring(0, tombstoneFilename.length() - 3)); 125 } 126 assertThat(segvCodeNames.size()).isAtLeast(3); 127 assertThat(segvCodeNames.get(0)).isEqualTo("SEGV_MTEAERR"); 128 assertThat(segvCodeNames.get(1)).isEqualTo("SEGV_MTEAERR"); 129 assertThat(segvCodeNames.get(2)).isEqualTo("SEGV_MTEAERR"); 130 } 131 132 @Test testDowngrade()133 public void testDowngrade() throws Exception { 134 CommandResult result = 135 getDevice() 136 .executeShellV2Command( 137 "MEMTAG_OPTIONS=async BIONIC_MEMTAG_UPGRADE_SECS=5" 138 + " /system/bin/mte_upgrade_test_helper --check-downgrade"); 139 assertThat(result.getExitCode()).isEqualTo(0); 140 } 141 142 @Test testAppProcess()143 public void testAppProcess() throws Exception { 144 CommandResult result = 145 getDevice() 146 .executeShellV2Command( 147 "MEMTAG_OPTIONS=async BIONIC_MEMTAG_UPGRADE_SECS=5" 148 + " /data/local/tmp/app_process64 --get-mode"); 149 assertThat(result.getExitCode()).isEqualTo(1); // ASYNC 150 } 151 } 152