1d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski/*
2d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
3d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski *
4d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * use this file except in compliance with the License. You may obtain a copy of
6d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * the License at
7d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski *
8d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0
9d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski *
10d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * License for the specific language governing permissions and limitations under
14d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski * the License.
15d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski */
16d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinskipackage com.android.internal.os;
17d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
18d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinskiimport android.support.test.filters.SmallTest;
19d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
20d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinskiimport junit.framework.TestCase;
21d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
22d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinskiimport java.nio.charset.Charset;
23d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
24d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinskipublic class KernelWakelockReaderTest extends TestCase {
25d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    /**
26d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski     * Helper class that builds the mock Kernel module file /d/wakeup_sources.
27d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski     */
28d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    private static class ProcFileBuilder {
29d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        private final static String sHeader = "name\t\tactive_count\tevent_count\twakeup_count\t" +
30d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                "expire_count\tactive_since\ttotal_time\tmax_time\tlast_change\t" +
31d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                "prevent_suspend_time\n";
32d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
33d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        private StringBuilder mStringBuilder;
34d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
35d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        private void ensureHeader() {
36d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            if (mStringBuilder == null) {
37d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                mStringBuilder = new StringBuilder();
38d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                mStringBuilder.append(sHeader);
39d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            }
40d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        }
41d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
42d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        public ProcFileBuilder addLine(String name, int count, long timeMillis) {
43d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            ensureHeader();
44d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            mStringBuilder.append(name).append("\t").append(count).append("\t0\t0\t0\t0\t")
45d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                    .append(timeMillis).append("\t0\t0\t0\n");
46d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            return this;
47d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        }
48d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
49d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        public byte[] getBytes() throws Exception {
50d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            ensureHeader();
51d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            byte[] data = mStringBuilder.toString().getBytes(Charset.forName("UTF-8"));
52d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
53d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            // The Kernel puts a \0 at the end of the data. Since each of our lines ends with \n,
54d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            // we override the last \n with a \0.
55d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            data[data.length - 1] = 0;
56d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski            return data;
57d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        }
58d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
59d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
60d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    private KernelWakelockReader mReader;
61d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
62d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @Override
63d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void setUp() throws Exception {
64d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        super.setUp();
65d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        mReader = new KernelWakelockReader();
66d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
67d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
68d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
69d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testParseEmptyFile() throws Exception {
70d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = mReader.parseProcWakelocks(new byte[0], 0, true,
71d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                new KernelWakelockStats());
72d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.isEmpty());
73d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
74d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
75d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
76d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testOnlyHeader() throws Exception {
77d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        byte[] buffer = new ProcFileBuilder().getBytes();
78d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true,
79d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                new KernelWakelockStats());
80d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.isEmpty());
81d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
82d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
83d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
84d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testOneWakelock() throws Exception {
85d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        byte[] buffer = new ProcFileBuilder()
86d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Wakelock", 34, 123) // Milliseconds
87d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .getBytes();
88d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true,
89d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                new KernelWakelockStats());
90d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(1, staleStats.size());
91d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Wakelock"));
92d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
93d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
94d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(34, entry.mCount);
95d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(123 * 1000, entry.mTotalTime); // Microseconds
96d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
97d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
98d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
99d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testTwoWakelocks() throws Exception {
100d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        byte[] buffer = new ProcFileBuilder()
101d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Wakelock", 1, 10)
102d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Fakelock", 2, 20)
103d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .getBytes();
104d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true,
105d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                new KernelWakelockStats());
106d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(2, staleStats.size());
107d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Wakelock"));
108d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Fakelock"));
109d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
110d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
111d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
112d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testDuplicateWakelocksAccumulate() throws Exception {
113d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        byte[] buffer = new ProcFileBuilder()
114d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Wakelock", 1, 10) // Milliseconds
115d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Wakelock", 1, 10) // Milliseconds
116d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .getBytes();
117d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true,
118d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                new KernelWakelockStats());
119d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(1, staleStats.size());
120d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Wakelock"));
121d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
122d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats.Entry entry = staleStats.get("Wakelock");
123d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(2, entry.mCount);
124d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(20 * 1000, entry.mTotalTime); // Microseconds
125d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
126d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
127d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    @SmallTest
128d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    public void testWakelocksBecomeStale() throws Exception {
129d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        byte[] buffer = new ProcFileBuilder()
130d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Fakelock", 3, 30)
131d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .getBytes();
132d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        KernelWakelockStats staleStats = new KernelWakelockStats();
133d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
134d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true, staleStats);
135d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(1, staleStats.size());
136d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Fakelock"));
137d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
138d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        buffer = new ProcFileBuilder()
139d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .addLine("Wakelock", 1, 10)
140d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski                .getBytes();
141d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski
142d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        staleStats = mReader.parseProcWakelocks(buffer, buffer.length, true, staleStats);
143d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertEquals(1, staleStats.size());
144d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertTrue(staleStats.containsKey("Wakelock"));
145d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski        assertFalse(staleStats.containsKey("Fakelock"));
146d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski    }
147d84ad30ee62ee9610ed4a59a8ce4dcbb8eddf7d8Adam Lesinski}
148