2019-06-05 15:44:17 -07:00
|
|
|
package com.android.launcher3.util.rule;
|
|
|
|
|
|
|
|
|
|
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
|
|
|
|
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
2019-06-25 16:13:42 -07:00
|
|
|
import androidx.test.uiautomator.UiDevice;
|
2019-06-05 15:44:17 -07:00
|
|
|
|
|
|
|
|
import org.junit.rules.TestWatcher;
|
|
|
|
|
import org.junit.runner.Description;
|
2020-01-17 12:20:20 -08:00
|
|
|
import org.junit.runners.model.Statement;
|
2019-06-05 15:44:17 -07:00
|
|
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
2020-01-17 12:20:20 -08:00
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.Date;
|
2019-06-05 15:44:17 -07:00
|
|
|
|
|
|
|
|
public class FailureWatcher extends TestWatcher {
|
|
|
|
|
private static final String TAG = "FailureWatcher";
|
2019-06-25 16:13:42 -07:00
|
|
|
final private UiDevice mDevice;
|
2019-06-05 15:44:17 -07:00
|
|
|
|
2019-06-25 16:13:42 -07:00
|
|
|
public FailureWatcher(UiDevice device) {
|
|
|
|
|
mDevice = device;
|
2019-06-05 15:44:17 -07:00
|
|
|
}
|
|
|
|
|
|
2019-08-23 12:11:00 -07:00
|
|
|
private static void dumpViewHierarchy(UiDevice device) {
|
2019-06-05 15:44:17 -07:00
|
|
|
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
|
|
|
try {
|
2019-08-23 12:11:00 -07:00
|
|
|
device.dumpWindowHierarchy(stream);
|
2019-06-05 15:44:17 -07:00
|
|
|
stream.flush();
|
|
|
|
|
stream.close();
|
|
|
|
|
for (String line : stream.toString().split("\\r?\\n")) {
|
|
|
|
|
Log.e(TAG, line.trim());
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
Log.e(TAG, "error dumping XML to logcat", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-17 12:20:20 -08:00
|
|
|
private static final String testsStartTime =
|
|
|
|
|
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Statement apply(Statement base, Description description) {
|
|
|
|
|
return new Statement() {
|
|
|
|
|
@Override
|
|
|
|
|
public void evaluate() throws Throwable {
|
|
|
|
|
try {
|
|
|
|
|
base.evaluate();
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
final int bug =
|
|
|
|
|
FailureInvestigator.getBugForFailure(e.toString(), testsStartTime);
|
|
|
|
|
if (bug == 0) throw e;
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "Known bug found for the original failure "
|
|
|
|
|
+ android.util.Log.getStackTraceString(e));
|
|
|
|
|
throw new AssertionError(
|
|
|
|
|
"Detected a failure that matches a known bug b/" + bug);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-05 15:44:17 -07:00
|
|
|
@Override
|
|
|
|
|
protected void failed(Throwable e, Description description) {
|
2019-08-23 12:11:00 -07:00
|
|
|
onError(mDevice, description, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void onError(UiDevice device, Description description, Throwable e) {
|
|
|
|
|
if (device == null) return;
|
2019-06-05 15:44:17 -07:00
|
|
|
final String pathname = getInstrumentation().getTargetContext().
|
2019-08-12 14:46:48 -07:00
|
|
|
getFilesDir().getPath() + "/TestScreenshot-" + description.getMethodName()
|
|
|
|
|
+ ".png";
|
2019-06-05 15:44:17 -07:00
|
|
|
Log.e(TAG, "Failed test " + description.getMethodName() +
|
|
|
|
|
", screenshot will be saved to " + pathname +
|
|
|
|
|
", track trace is below, UI object dump is further below:\n" +
|
|
|
|
|
Log.getStackTraceString(e));
|
2019-08-23 12:11:00 -07:00
|
|
|
dumpViewHierarchy(device);
|
2019-06-05 15:44:17 -07:00
|
|
|
|
|
|
|
|
try {
|
2019-08-23 12:11:00 -07:00
|
|
|
final String dumpsysResult = device.executeShellCommand(
|
2019-06-05 15:44:17 -07:00
|
|
|
"dumpsys activity service TouchInteractionService");
|
|
|
|
|
Log.d(TAG, "TouchInteractionService: " + dumpsysResult);
|
|
|
|
|
} catch (IOException ex) {
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-23 12:11:00 -07:00
|
|
|
device.takeScreenshot(new File(pathname));
|
2019-06-05 15:44:17 -07:00
|
|
|
}
|
|
|
|
|
}
|