1/* 2 * Copyright (C) 2012 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 17package com.android.gallery3d.util; 18 19import com.android.gallery3d.util.Profile; 20 21import android.os.Environment; 22import android.test.suitebuilder.annotation.SmallTest; 23import android.util.Log; 24 25import java.io.DataInputStream; 26import java.io.File; 27import java.io.FileInputStream; 28import java.io.IOException; 29import java.util.ArrayList; 30import java.util.HashMap; 31import junit.framework.Assert; 32import junit.framework.TestCase; 33 34@SmallTest 35public class ProfileTest extends TestCase { 36 private static final String TAG = "ProfileTest"; 37 private static final String TEST_FILE = 38 Environment.getExternalStorageDirectory().getPath() + "/test.dat"; 39 40 41 public void testProfile() throws IOException { 42 ProfileData p = new ProfileData(); 43 ParsedProfile q; 44 String[] A = {"A"}; 45 String[] B = {"B"}; 46 String[] AC = {"A", "C"}; 47 String[] AD = {"A", "D"}; 48 49 // Empty profile 50 p.dumpToFile(TEST_FILE); 51 q = new ParsedProfile(TEST_FILE); 52 assertTrue(q.mEntries.isEmpty()); 53 assertTrue(q.mSymbols.isEmpty()); 54 55 // Only one sample 56 p.addSample(A); 57 p.dumpToFile(TEST_FILE); 58 q = new ParsedProfile(TEST_FILE); 59 assertEquals(1, q.mEntries.size()); 60 assertEquals(1, q.mSymbols.size()); 61 assertEquals(1, q.mEntries.get(0).sampleCount); 62 63 // Two samples at the same place 64 p.addSample(A); 65 p.dumpToFile(TEST_FILE); 66 q = new ParsedProfile(TEST_FILE); 67 assertEquals(1, q.mEntries.size()); 68 assertEquals(1, q.mSymbols.size()); 69 assertEquals(2, q.mEntries.get(0).sampleCount); 70 71 // Two samples at the different places 72 p.reset(); 73 p.addSample(A); 74 p.addSample(B); 75 p.dumpToFile(TEST_FILE); 76 q = new ParsedProfile(TEST_FILE); 77 assertEquals(2, q.mEntries.size()); 78 assertEquals(2, q.mSymbols.size()); 79 assertEquals(1, q.mEntries.get(0).sampleCount); 80 assertEquals(1, q.mEntries.get(1).sampleCount); 81 82 // depth > 1 83 p.reset(); 84 p.addSample(AC); 85 p.dumpToFile(TEST_FILE); 86 q = new ParsedProfile(TEST_FILE); 87 assertEquals(1, q.mEntries.size()); 88 assertEquals(2, q.mSymbols.size()); 89 assertEquals(1, q.mEntries.get(0).sampleCount); 90 91 // two samples (AC and AD) 92 p.addSample(AD); 93 p.dumpToFile(TEST_FILE); 94 q = new ParsedProfile(TEST_FILE); 95 assertEquals(2, q.mEntries.size()); 96 assertEquals(3, q.mSymbols.size()); // three symbols: A, C, D 97 assertEquals(1, q.mEntries.get(0).sampleCount); 98 assertEquals(1, q.mEntries.get(0).sampleCount); 99 100 // Remove the test file 101 new File(TEST_FILE).delete(); 102 } 103} 104 105class ParsedProfile { 106 public class Entry { 107 int sampleCount; 108 int stackId[]; 109 } 110 111 ArrayList<Entry> mEntries = new ArrayList<Entry>(); 112 HashMap<Integer, String> mSymbols = new HashMap<Integer, String>(); 113 private DataInputStream mIn; 114 private byte[] mScratch = new byte[4]; // scratch buffer for readInt 115 116 public ParsedProfile(String filename) throws IOException { 117 mIn = new DataInputStream(new FileInputStream(filename)); 118 119 Entry entry = parseOneEntry(); 120 checkIsFirstEntry(entry); 121 122 while (true) { 123 entry = parseOneEntry(); 124 if (entry.sampleCount == 0) { 125 checkIsLastEntry(entry); 126 break; 127 } 128 mEntries.add(entry); 129 } 130 131 // Read symbol table 132 while (true) { 133 String line = mIn.readLine(); 134 if (line == null) break; 135 String[] fields = line.split(" +"); 136 checkIsValidSymbolLine(fields); 137 mSymbols.put(Integer.decode(fields[0]), fields[1]); 138 } 139 } 140 141 private void checkIsFirstEntry(Entry entry) { 142 Assert.assertEquals(0, entry.sampleCount); 143 Assert.assertEquals(3, entry.stackId.length); 144 Assert.assertEquals(1, entry.stackId[0]); 145 Assert.assertTrue(entry.stackId[1] > 0); // sampling period 146 Assert.assertEquals(0, entry.stackId[2]); // padding 147 } 148 149 private void checkIsLastEntry(Entry entry) { 150 Assert.assertEquals(0, entry.sampleCount); 151 Assert.assertEquals(1, entry.stackId.length); 152 Assert.assertEquals(0, entry.stackId[0]); 153 } 154 155 private void checkIsValidSymbolLine(String[] fields) { 156 Assert.assertEquals(2, fields.length); 157 Assert.assertTrue(fields[0].startsWith("0x")); 158 } 159 160 private Entry parseOneEntry() throws IOException { 161 int sampleCount = readInt(); 162 int depth = readInt(); 163 Entry e = new Entry(); 164 e.sampleCount = sampleCount; 165 e.stackId = new int[depth]; 166 for (int i = 0; i < depth; i++) { 167 e.stackId[i] = readInt(); 168 } 169 return e; 170 } 171 172 private int readInt() throws IOException { 173 mIn.read(mScratch, 0, 4); 174 return (mScratch[0] & 0xff) | 175 ((mScratch[1] & 0xff) << 8) | 176 ((mScratch[2] & 0xff) << 16) | 177 ((mScratch[3] & 0xff) << 24); 178 } 179} 180