Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9d8df54 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improving hierarchy dump for test failure" into sc-dev

parents ad6cdf7b 420ba54d
Loading
Loading
Loading
Loading
+41 −31
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@ package com.android.launcher3.util.rule;

import static androidx.test.InstrumentationRegistry.getInstrumentation;

import android.os.FileUtils;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import android.util.Log;

import androidx.test.uiautomator.UiDevice;
@@ -12,9 +14,12 @@ import com.android.launcher3.ui.AbstractLauncherUiTest;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FailureWatcher extends TestWatcher {
    private static final String TAG = "FailureWatcher";
@@ -26,20 +31,6 @@ public class FailureWatcher extends TestWatcher {
        mLauncher = launcher;
    }

    private static void dumpViewHierarchy(UiDevice device) {
        final ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            device.dumpWindowHierarchy(stream);
            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);
        }
    }

    @Override
    protected void succeeded(Description description) {
        super.succeeded(description);
@@ -53,22 +44,41 @@ public class FailureWatcher extends TestWatcher {

    public static void onError(UiDevice device, Description description, Throwable e) {
        if (device == null) return;
        final String pathname = getInstrumentation().getTargetContext().
                getFilesDir().getPath() + "/TestScreenshot-" + description.getMethodName()
                + ".png";
        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));
        dumpViewHierarchy(device);

        try {
            final String dumpsysResult = device.executeShellCommand(
                    "dumpsys activity service TouchInteractionService");
            Log.d(TAG, "TouchInteractionService: " + dumpsysResult);
        } catch (IOException ex) {
        final File parentFile = getInstrumentation().getTargetContext().getFilesDir();
        final File sceenshot = new File(parentFile,
                "TestScreenshot-" + description.getMethodName() + ".png");
        final File hierarchy = new File(parentFile,
                "Hierarchy-" + description.getMethodName() + ".zip");

        // Dump window hierarchy
        try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(hierarchy))) {
            out.putNextEntry(new ZipEntry("bugreport.txt"));
            dumpStringCommand("dumpsys window windows", out);
            dumpStringCommand("dumpsys package", out);
            dumpStringCommand("dumpsys activity service TouchInteractionService", out);
            out.closeEntry();

            out.putNextEntry(new ZipEntry("visible_windows.zip"));
            dumpCommand("cmd window dump-visible-window-views", out);
            out.closeEntry();
        } catch (IOException ex) { }

        Log.e(TAG, "Failed test " + description.getMethodName()
                + ",\nscreenshot will be saved to " + sceenshot
                + ",\nUI dump at: " + hierarchy
                + " (use go/web-hv to open the dump file)", e);
        device.takeScreenshot(sceenshot);
    }

        device.takeScreenshot(new File(pathname));
    private static void dumpStringCommand(String cmd, OutputStream out) throws IOException {
        out.write(("\n\n" + cmd + "\n").getBytes());
        dumpCommand(cmd, out);
    }

    private static void dumpCommand(String cmd, OutputStream out) throws IOException {
        try (AutoCloseInputStream in = new AutoCloseInputStream(getInstrumentation()
                .getUiAutomation().executeShellCommand(cmd))) {
            FileUtils.copy(in, out);
        }
    }
}