/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ahat;
import com.android.ahat.heapdump.AhatHeap;
import com.android.ahat.heapdump.AhatInstance;
import com.android.ahat.heapdump.AhatSnapshot;
import com.android.ahat.heapdump.Diff;
import com.android.ahat.heapdump.FieldValue;
import com.android.tools.perflib.heap.hprof.HprofClassDump;
import com.android.tools.perflib.heap.hprof.HprofConstant;
import com.android.tools.perflib.heap.hprof.HprofDumpRecord;
import com.android.tools.perflib.heap.hprof.HprofHeapDump;
import com.android.tools.perflib.heap.hprof.HprofInstanceDump;
import com.android.tools.perflib.heap.hprof.HprofInstanceField;
import com.android.tools.perflib.heap.hprof.HprofLoadClass;
import com.android.tools.perflib.heap.hprof.HprofPrimitiveArrayDump;
import com.android.tools.perflib.heap.hprof.HprofRecord;
import com.android.tools.perflib.heap.hprof.HprofRootDebugger;
import com.android.tools.perflib.heap.hprof.HprofStaticField;
import com.android.tools.perflib.heap.hprof.HprofStringBuilder;
import com.android.tools.perflib.heap.hprof.HprofType;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class DiffTest {
@Test
public void diffMatchedHeap() throws IOException {
TestDump dump = TestDump.getTestDump();
AhatHeap a = dump.getAhatSnapshot().getHeap("app");
assertNotNull(a);
AhatHeap b = dump.getBaselineAhatSnapshot().getHeap("app");
assertNotNull(b);
assertEquals(a.getBaseline(), b);
assertEquals(b.getBaseline(), a);
}
@Test
public void diffUnchanged() throws IOException {
TestDump dump = TestDump.getTestDump();
AhatInstance a = dump.getDumpedAhatInstance("unchangedObject");
assertNotNull(a);
AhatInstance b = dump.getBaselineDumpedAhatInstance("unchangedObject");
assertNotNull(b);
assertEquals(a, b.getBaseline());
assertEquals(b, a.getBaseline());
assertEquals(a.getSite(), b.getSite().getBaseline());
assertEquals(b.getSite(), a.getSite().getBaseline());
}
@Test
public void diffAdded() throws IOException {
TestDump dump = TestDump.getTestDump();
AhatInstance a = dump.getDumpedAhatInstance("addedObject");
assertNotNull(a);
assertNull(dump.getBaselineDumpedAhatInstance("addedObject"));
assertTrue(a.getBaseline().isPlaceHolder());
}
@Test
public void diffRemoved() throws IOException {
TestDump dump = TestDump.getTestDump();
assertNull(dump.getDumpedAhatInstance("removedObject"));
AhatInstance b = dump.getBaselineDumpedAhatInstance("removedObject");
assertNotNull(b);
assertTrue(b.getBaseline().isPlaceHolder());
}
@Test
public void nullClassObj() throws IOException {
// Set up a heap dump that has a null classObj.
// The heap dump is derived from the InstanceTest.asStringEmbedded test.
HprofStringBuilder strings = new HprofStringBuilder(0);
List<HprofRecord> records = new ArrayList<HprofRecord>();
List<HprofDumpRecord> dump = new ArrayList<HprofDumpRecord>();
final int stringClassObjectId = 1;
records.add(new HprofLoadClass(0, 0, stringClassObjectId, 0, strings.get("java.lang.String")));
dump.add(new HprofClassDump(stringClassObjectId, 0, 0, 0, 0, 0, 0, 0, 0,
new HprofConstant[0], new HprofStaticField[0],
new HprofInstanceField[]{
new HprofInstanceField(strings.get("count"), HprofType.TYPE_INT),
new HprofInstanceField(strings.get("hashCode"), HprofType.TYPE_INT),
new HprofInstanceField(strings.get("offset"), HprofType.TYPE_INT),
new HprofInstanceField(strings.get("value"), HprofType.TYPE_OBJECT)}));
dump.add(new HprofPrimitiveArrayDump(0x41, 0, HprofType.TYPE_CHAR,
new long[]{'n', 'o', 't', ' ', 'h', 'e', 'l', 'l', 'o', 'o', 'p'}));
ByteArrayDataOutput values = ByteStreams.newDataOutput();
values.writeInt(5); // count
values.writeInt(0); // hashCode
values.writeInt(4); // offset
values.writeInt(0x41); // value
dump.add(new HprofInstanceDump(0x42, 0, stringClassObjectId, values.toByteArray()));
dump.add(new HprofRootDebugger(stringClassObjectId));
dump.add(new HprofRootDebugger(0x42));
records.add(new HprofHeapDump(0, dump.toArray(new HprofDumpRecord[0])));
AhatSnapshot snapshot = SnapshotBuilder.makeSnapshot(strings, records);
// Diffing should not crash.
Diff.snapshots(snapshot, snapshot);
}
@Test
public void diffFields() {
List<FieldValue> a = new ArrayList<FieldValue>();
a.add(new FieldValue("n0", "t0", null));
a.add(new FieldValue("n2", "t2", null));
a.add(new FieldValue("n3", "t3", null));
a.add(new FieldValue("n4", "t4", null));
a.add(new FieldValue("n5", "t5", null));
a.add(new FieldValue("n6", "t6", null));
List<FieldValue> b = new ArrayList<FieldValue>();
b.add(new FieldValue("n0", "t0", null));
b.add(new FieldValue("n1", "t1", null));
b.add(new FieldValue("n2", "t2", null));
b.add(new FieldValue("n3", "t3", null));
b.add(new FieldValue("n5", "t5", null));
b.add(new FieldValue("n6", "t6", null));
b.add(new FieldValue("n7", "t7", null));
Diff.fields(a, b);
assertEquals(8, a.size());
assertEquals(8, b.size());
for (int i = 0; i < 8; i++) {
assertEquals(a.get(i), b.get(i).getBaseline());
assertEquals(b.get(i), a.get(i).getBaseline());
}
assertTrue(a.get(1).isPlaceHolder());
assertTrue(a.get(7).isPlaceHolder());
assertTrue(b.get(4).isPlaceHolder());
}
}