• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.net.module.util;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertTrue;
23 
24 import androidx.test.filters.SmallTest;
25 import androidx.test.runner.AndroidJUnit4;
26 
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 
30 import java.io.ByteArrayOutputStream;
31 import java.io.PrintWriter;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.function.Consumer;
37 
38 @RunWith(AndroidJUnit4.class)
39 @SmallTest
40 public class SharedLogTest {
41     private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
42     private static final String TIMESTAMP = "HH:MM:SS";
43     private static final String TAG = "top";
44 
45     @Test
testBasicOperation()46     public void testBasicOperation() {
47         final SharedLog logTop = new SharedLog(TAG);
48         assertTrue(TAG.equals(logTop.getTag()));
49 
50         logTop.mark("first post!");
51 
52         final SharedLog logLevel2a = logTop.forSubComponent("twoA");
53         final SharedLog logLevel2b = logTop.forSubComponent("twoB");
54         logLevel2b.e("2b or not 2b");
55         logLevel2b.e("No exception", null);
56         logLevel2b.e("Wait, here's one", new Exception("Test"));
57         logLevel2a.w("second post?");
58 
59         final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
60         logTop.log("still logging");
61         logLevel2b.e(new Exception("Got another exception"));
62         logLevel3.i("3 >> 2");
63         logLevel2a.mark("ok: last post");
64         logTop.logf("finished!");
65 
66         final String[] expected = {
67             " - MARK first post!",
68             " - [twoB] ERROR 2b or not 2b",
69             " - [twoB] ERROR No exception",
70             // No stacktrace in shared log, only in logcat
71             " - [twoB] ERROR Wait, here's one: Test",
72             " - [twoA] WARN second post?",
73             " - still logging",
74             " - [twoB] ERROR java.lang.Exception: Got another exception",
75             " - [twoA.three] 3 >> 2",
76             " - [twoA] MARK ok: last post",
77             " - finished!",
78         };
79         // Verify the logs are all there and in the correct order.
80         assertDumpLogs(expected, logTop);
81 
82         // In fact, because they all share the same underlying LocalLog,
83         // every subcomponent SharedLog's dump() is identical.
84         assertDumpLogs(expected, logLevel2a);
85         assertDumpLogs(expected, logLevel2b);
86         assertDumpLogs(expected, logLevel3);
87     }
88 
assertDumpLogs(String[] expected, SharedLog log)89     private static void assertDumpLogs(String[] expected, SharedLog log) {
90         verifyLogLines(expected, dump(log));
91         verifyLogLines(reverse(expected), reverseDump(log));
92     }
93 
dump(SharedLog log)94     private static String dump(SharedLog log) {
95         return getSharedLogString(pw -> log.dump(null /* fd */, pw, null /* args */));
96     }
97 
reverseDump(SharedLog log)98     private static String reverseDump(SharedLog log) {
99         return getSharedLogString(pw -> log.reverseDump(pw));
100     }
101 
reverse(String[] ary)102     private static String[] reverse(String[] ary) {
103         final List<String> ls = new ArrayList<>(Arrays.asList(ary));
104         Collections.reverse(ls);
105         return ls.toArray(new String[ary.length]);
106     }
107 
getSharedLogString(Consumer<PrintWriter> functor)108     private static String getSharedLogString(Consumer<PrintWriter> functor) {
109         final ByteArrayOutputStream ostream = new ByteArrayOutputStream();
110         final PrintWriter pw = new PrintWriter(ostream, true);
111         functor.accept(pw);
112 
113         final String dumpOutput = ostream.toString();
114         assertNotNull(dumpOutput);
115         assertFalse("".equals(dumpOutput));
116         return dumpOutput;
117     }
118 
verifyLogLines(String[] expected, String gottenLogs)119     private static void verifyLogLines(String[] expected, String gottenLogs) {
120         final String[] lines = gottenLogs.split("\n");
121         assertEquals(expected.length, lines.length);
122 
123         for (int i = 0; i < expected.length; i++) {
124             String got = lines[i];
125             String want = expected[i];
126             assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
127             assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
128                     got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
129         }
130     }
131 }
132