151ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom/*
251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project
351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom *
451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * you may not use this file except in compliance with the License.
651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * You may obtain a copy of the License at
751ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom *
851ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
951ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom *
1051ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
1151ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
1251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * See the License for the specific language governing permissions and
1451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom * limitations under the License.
1551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom */
1651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
17cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrompackage dalvik.system.profiler;
18cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom
19cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.AsciiHprofWriter;
20cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.BinaryHprofReader;
21cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.BinaryHprofWriter;
22cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.HprofData.Sample;
23cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.HprofData.StackTrace;
24cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.HprofData.ThreadEvent;
25cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.HprofData;
26cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport dalvik.system.profiler.SamplingProfiler.ThreadSet;
27d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.ByteArrayInputStream;
28d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.ByteArrayOutputStream;
29d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.File;
30d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.FileOutputStream;
31d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.InputStream;
32d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.io.OutputStream;
3351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstromimport java.math.BigInteger;
3451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstromimport java.security.KeyPairGenerator;
3551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstromimport java.security.SecureRandom;
36d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.Arrays;
37d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.HashMap;
38d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.HashSet;
39d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.List;
40d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.Map;
41d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstromimport java.util.Set;
4251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstromimport javax.crypto.spec.DHParameterSpec;
4351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstromimport junit.framework.TestCase;
4451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
4551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrompublic class SamplingProfilerTest extends TestCase {
4651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
47d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    /**
48d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * Run the SamplingProfiler to gather some data on an actual
49d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * computation, then assert that it looks correct with test_HprofData.
50d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     */
51d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_SamplingProfiler() throws Exception {
5251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        ThreadSet threadSet = SamplingProfiler.newArrayThreadSet(Thread.currentThread());
5351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        SamplingProfiler profiler = new SamplingProfiler(12, threadSet);
54d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        profiler.start(100);
5551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        toBeMeasured();
5651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        profiler.stop();
5751ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        profiler.shutdown();
58d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(profiler.getHprofData(), true);
5951ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    }
6051ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
6151ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    private static final String P_STR =
62d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            "9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e3"
6351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            + "1db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b";
6451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    private static final String G_STR =
6551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            "98ab7c5c431479d8645e33aa09758e0907c78747798d0968576f9877421a9089"
6651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            + "756f7876e76590b76765645c987976d764dd4564698a87585e64554984bb4445"
6751ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            + "76e5764786f875b4456c";
6851ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
6951ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    private static final byte[] P = new BigInteger(P_STR,16).toByteArray();
7051ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    private static final byte[] G = new BigInteger(G_STR,16).toByteArray();
7151ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
7251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    private static void toBeMeasured () throws Exception {
7351ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        long start = System.currentTimeMillis();
7451ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        for (int i = 0; i < 10000; i++) {
7551ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            BigInteger p = new BigInteger(P);
7651ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            BigInteger g = new BigInteger(G);
7751ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            KeyPairGenerator gen = KeyPairGenerator.getInstance("DH");
7851ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom            gen.initialize(new DHParameterSpec(p, g), new SecureRandom());
7951ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        }
8051ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom        long end = System.currentTimeMillis();
8151ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom    }
8251ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom
83d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_null() throws Exception {
84d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        try {
85d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            new HprofData(null);
86d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            fail();
87d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        } catch (NullPointerException expected) {
88d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
89d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
90d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
91d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_empty() throws Exception {
92d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Map<StackTrace, int[]> stackTraces = new HashMap<StackTrace, int[]>();
93d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData hprofData = new HprofData(stackTraces);
94d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
95d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
96d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
97d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_timeMillis() throws Exception {
98d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Map<StackTrace, int[]> stackTraces = new HashMap<StackTrace, int[]>();
99d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData hprofData = new HprofData(stackTraces);
100d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        long now = System.currentTimeMillis();
101d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.setStartMillis(now);
102d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(now, hprofData.getStartMillis());
103d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
104d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
105d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
106d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_addThreadEvent_null() throws Exception {
107d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Map<StackTrace, int[]> stackTraces = new HashMap<StackTrace, int[]>();
108d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData hprofData = new HprofData(stackTraces);
109d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        try {
110d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            hprofData.addThreadEvent(null);
111d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            fail();
112d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        } catch (NullPointerException expected) {
113d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
114d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
115d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
116d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
117d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_addThreadEvent() throws Exception {
118d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Map<StackTrace, int[]> stackTraces = new HashMap<StackTrace, int[]>();
119d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData hprofData = new HprofData(stackTraces);
120d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
121d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // should have nothing in the thread history to start
122d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(0, hprofData.getThreadHistory().size());
123d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
124d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // add thread 1
125d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int threadId = 1;
126d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int objectId = 2;
127d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ThreadEvent start1 = ThreadEvent.start(objectId, threadId,
128d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                                               "thread-name", "thread-group", "parent-group");
129d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.addThreadEvent(start1);
130d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Arrays.asList(start1), hprofData.getThreadHistory());
131d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
132d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
133d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // remove thread 2, which should not exist (but that's okay on the RI)
134d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ThreadEvent end2 = ThreadEvent.end(threadId+1);
135d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.addThreadEvent(end2);
136d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Arrays.asList(start1, end2), hprofData.getThreadHistory());
137d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, false); // non-strict from here down because of this RI data
138d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
139d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // remove thread 1, which should exist
140d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ThreadEvent end1 = ThreadEvent.end(threadId);
141d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.addThreadEvent(end1);
142d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Arrays.asList(start1, end2, end1), hprofData.getThreadHistory());
143d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, false);
144d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
145d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // remove thread 1 again, which should not exist (its not okay to have end followed by end)
146d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        try {
147d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            hprofData.addThreadEvent(ThreadEvent.end(threadId));
148d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            fail();
149d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        } catch (IllegalArgumentException expected) {
150d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
151d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Arrays.asList(start1, end2, end1), hprofData.getThreadHistory());
152d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, false);
153d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
154d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
155d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    public void test_HprofData_addStackTrace() throws Exception {
156d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Map<StackTrace, int[]> stackTraces = new HashMap<StackTrace, int[]>();
157d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData hprofData = new HprofData(stackTraces);
158d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
159d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // should have no samples to start
160d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(0, hprofData.getSamples().size());
161d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
162d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // attempt to add a stack for a non-existent thread, should fail
163d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int stackTraceId = 1;
164d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int threadId = 2;
165d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int objectId = 3;
166d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int sampleCount = 4;
167d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        StackTraceElement[] stackFrames = new Throwable().getStackTrace();
168d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        final int[] countCell = new int[] { 4 };
169d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        StackTrace stackTrace = new StackTrace(stackTraceId, threadId, stackFrames);
170d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        try {
171d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            hprofData.addStackTrace(stackTrace, countCell);
172d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            fail();
173d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        } catch (IllegalArgumentException expected) {
174d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
175d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
176d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // add the thread and add the event
177d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ThreadEvent start = ThreadEvent.start(objectId, threadId,
178d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                                              "thread-name", "thread-group", "parent-group");
179d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.addThreadEvent(start);
180d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        hprofData.addStackTrace(stackTrace, countCell);
181d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Set<Sample> samples = hprofData.getSamples();
182d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotNull(samples);
183d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotSame(samples, hprofData.getSamples());
184d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(1, samples.size());
185d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Sample sample = samples.iterator().next();
186d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotNull(sample);
187d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(stackTrace, sample.stackTrace);
188d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(sampleCount, sample.count);
189d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
190d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
191d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // confirm we can mutate the sample count, but that its not
192d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // visible in the current sample, but it will be visible in a
193d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // new one.
194d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        countCell[0] += 42;
195d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(sampleCount, sample.count);
196d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Sample sample2 = hprofData.getSamples().iterator().next();
197d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(sampleCount + 42, sample2.count);
198d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
199d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
200d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        // try to reuse the stackTraceId, should fail
201d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        try {
202d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            hprofData.addStackTrace(stackTrace, countCell);
203d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            fail();
204d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        } catch (IllegalArgumentException expected) {
205d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
206d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(1, hprofData.getSamples().size());
207d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData(hprofData, true);
208d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
209d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
210d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
211d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    private void test_HprofData(HprofData hprofData, boolean strict) throws Exception {
212d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertHprofData(hprofData, strict);
213d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData_ascii(hprofData);
214d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        test_HprofData_binary(hprofData, strict);
215d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
216d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
217d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    /**
218d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * Assert general properities of HprofData hold true.
219d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     */
220d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    private void assertHprofData(HprofData hprofData, boolean strict) throws Exception {
221d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        List<ThreadEvent> threadHistory = hprofData.getThreadHistory();
222d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotNull(threadHistory);
223cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom        Set<Integer> threadsSeen = new HashSet<Integer>();
224cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom        Set<Integer> threadsActive = new HashSet<Integer>();
225d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        for (ThreadEvent event : threadHistory) {
226d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertNotNull(event);
227d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertNotNull(event.type);
228d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            switch (event.type) {
229d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                case START:
230d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertNotNull(event.threadName);
231d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertTrue(threadsActive.add(event.threadId));
232d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertTrue(threadsSeen.add(event.threadId));
233d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    break;
234d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                case END:
235d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertEquals(-1, event.objectId);
236d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertNull(event.threadName);
237d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertNull(event.groupName);
238d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    assertNull(event.parentGroupName);
239d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    if (strict) {
240d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                        assertTrue(threadsActive.remove(event.threadId));
241d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    }
242d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                    break;
243d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            }
244d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
245d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
246d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        Set<Sample> samples = hprofData.getSamples();
247d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotNull(samples);
248d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        for (Sample sample : samples) {
249d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertNotNull(sample);
250d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertTrue(sample.count > 0);
251d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertNotNull(sample.stackTrace);
252d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertTrue(sample.stackTrace.stackTraceId != -1);
253d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertTrue(threadsSeen.contains(sample.stackTrace.getThreadId()));
254d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            assertNotNull(sample.stackTrace.getStackFrames());
255d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
256d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
257d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
258d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    /**
259d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * Convert to HprofData to ASCII to see if it triggers any exceptions
260d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     */
261d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    private void test_HprofData_ascii(HprofData hprofData) throws Exception {
262d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ByteArrayOutputStream out = new ByteArrayOutputStream();
263e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom        AsciiHprofWriter.write(hprofData, out);
264d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertFalse(out.toByteArray().length == 0);
265d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
266d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
267d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    /**
268d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * Convert to HprofData to binary and then reparse as to
269d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     * HprofData. Make sure the accessible data is equivalent.
270d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom     */
271d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    private void test_HprofData_binary(HprofData hprofData, boolean strict) throws Exception {
272d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
273d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        ByteArrayOutputStream out = new ByteArrayOutputStream();
274e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom        BinaryHprofWriter.write(hprofData, out);
275d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        out.close();
276d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
277d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        byte[] bytes = out.toByteArray();
278d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertFalse(bytes.length == 0);
279d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        if (false) {
280d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            File file = new File("/sdcard/java.hprof");
281d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            OutputStream debug = new FileOutputStream(file);
282d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            debug.write(bytes);
283d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            debug.close();
284d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom            System.out.println("Wrote binary hprof data to " + file);
285d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        }
286d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
287d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        InputStream in = new ByteArrayInputStream(bytes);
288d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        BinaryHprofReader reader = new BinaryHprofReader(in);
289d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertTrue(reader.getStrict());
290d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        reader.read();
291d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        in.close();
292d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals("JAVA PROFILE 1.0.2", reader.getVersion());
293d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertNotNull(reader.getHprofData());
294d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
295d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        HprofData parsed = reader.getHprofData();
296d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertHprofData(hprofData, strict);
297d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom
298d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Long.toHexString(hprofData.getStartMillis()),
299d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                     Long.toHexString(parsed.getStartMillis()));
300d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Long.toHexString(hprofData.getFlags()),
301d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                     Long.toHexString(parsed.getFlags()));
302d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(Long.toHexString(hprofData.getDepth()),
303d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                     Long.toHexString(parsed.getDepth()));
304d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(hprofData.getThreadHistory(),
305d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                     parsed.getThreadHistory());
306d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom        assertEquals(hprofData.getSamples(),
307d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom                     parsed.getSamples());
308d7fd1b88b89ca762afe5609d84a8eedfb611cbe1Brian Carlstrom    }
30951ee38b9c39b0c36bce728a797b2c5e637be3d2cBrian Carlstrom}
310