1 /*
2  * Copyright (C) 2017 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 android.contentcaptureservice.cts;
18 
19 import static android.contentcaptureservice.cts.Helper.MY_PACKAGE;
20 import static android.contentcaptureservice.cts.Helper.TAG;
21 
22 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
23 
24 import android.app.Activity;
25 import android.util.Log;
26 import android.view.contentcapture.ContentCaptureManager;
27 
28 import androidx.annotation.NonNull;
29 
30 import com.android.compatibility.common.util.SafeCleanerRule;
31 
32 import org.junit.AssumptionViolatedException;
33 import org.junit.rules.TestRule;
34 import org.junit.runner.Description;
35 import org.junit.runners.model.Statement;
36 
37 /**
38  * Custom JUnit4 rule that improves ContentCapture-related logging by:
39  *
40  * <ol>
41  *   <li>Setting logging level to verbose before test start.
42  *   <li>Call {@code dumpsys} in case of failure.
43  * </ol>
44  */
45 public class ContentCaptureLoggingTestRule implements TestRule, SafeCleanerRule.Dumper {
46 
47     private boolean mDumped;
48 
49     @Override
apply(Statement base, Description description)50     public Statement apply(Statement base, Description description) {
51         return new Statement() {
52 
53             @Override
54             public void evaluate() throws Throwable {
55                 final String testName = description.getDisplayName();
56                 try {
57                     base.evaluate();
58                 } catch (Throwable t) {
59                     dump(testName, t);
60                     throw t;
61                 }
62             }
63         };
64     }
65 
66     @Override
67     public void dump(@NonNull String testName, @NonNull Throwable t) {
68         if (mDumped) {
69             Log.e(TAG, "dump(" + testName + "): already dumped");
70             return;
71         }
72         if ((t instanceof AssumptionViolatedException)) {
73             // This exception is used to indicate a test should be skipped and is
74             // ignored by JUnit runners - we don't need to dump it...
75             Log.w(TAG, "ignoring exception: " + t);
76             return;
77         }
78         // TODO(b/123540602, b/120784831): should dump to a file (and integrate with tradefed)
79         // instead of outputting to log directly...
80         Log.e(TAG, "Dumping after exception on " + testName, t);
81         final String serviceDump = runShellCommand("dumpsys content_capture");
82         Log.e(TAG, "content_capture dump: \n" + serviceDump);
83         final String activityDump = runShellCommand("dumpsys activity %s %s %s",
84                 MY_PACKAGE, Activity.DUMP_ARG_DUMP_DUMPABLE, ContentCaptureManager.DUMPABLE_NAME);
85 
86         Log.e(TAG, "activity dump: \n" + activityDump);
87         mDumped = true;
88     }
89 }
90