1 /* 2 * Copyright (C) 2006 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 android.test; 18 19 import android.content.ContentValues; 20 import android.database.sqlite.SQLiteDatabase; 21 import android.os.Environment; 22 import android.os.FileUtils; 23 import android.test.TestRunner.IntermediateTime; 24 import android.util.Log; 25 import junit.framework.Test; 26 import junit.framework.TestListener; 27 28 import java.io.File; 29 import java.io.PrintWriter; 30 import java.io.StringWriter; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.Set; 34 35 /** 36 * {@hide} Not needed for 1.0 SDK. 37 */ 38 public class TestRecorder implements TestRunner.Listener, TestListener { 39 private static final int DATABASE_VERSION = 1; 40 private static SQLiteDatabase sDb; 41 private Set<String> mFailedTests = new HashSet<String>(); 42 43 private static SQLiteDatabase getDatabase() { 44 if (sDb == null) { 45 File dir = new File(Environment.getDataDirectory(), "test_results"); 46 47 /* TODO: add a DB version number and bootstrap/upgrade methods 48 * if the format of the table changes. 49 */ 50 String dbName = "TestHarness.db"; 51 File file = new File(dir, dbName); 52 sDb = SQLiteDatabase.openOrCreateDatabase(file.getPath(), null); 53 54 if (sDb.getVersion() == 0) { 55 int code = FileUtils.setPermissions(file.getPath(), 56 FileUtils.S_IRUSR | FileUtils.S_IWUSR | 57 FileUtils.S_IRGRP | FileUtils.S_IWGRP | 58 FileUtils.S_IROTH | FileUtils.S_IWOTH, -1, -1); 59 60 if (code != 0) { 61 Log.w("TestRecorder", 62 "Set permissions for " + file.getPath() + " returned = " + code); 63 } 64 65 try { 66 sDb.execSQL("CREATE TABLE IF NOT EXISTS tests (_id INT PRIMARY KEY," + 67 "name TEXT," + 68 "result TEXT," + 69 "exception TEXT," + 70 "started INTEGER," + 71 "finished INTEGER," + 72 "time INTEGER," + 73 "iterations INTEGER," + 74 "allocations INTEGER," + 75 "parent INTEGER);"); 76 sDb.setVersion(DATABASE_VERSION); 77 } catch (Exception e) { 78 Log.e("TestRecorder", "failed to create table 'tests'", e); 79 sDb = null; 80 } 81 } 82 } 83 84 return sDb; 85 } 86 87 public TestRecorder() { 88 } 89 90 public void started(String className) { 91 ContentValues map = new ContentValues(2); 92 map.put("name", className); 93 map.put("started", System.currentTimeMillis()); 94 95 // try to update the row first in case we've ran this test before. 96 int rowsAffected = getDatabase().update("tests", map, "name = '" + className + "'", null); 97 98 if (rowsAffected == 0) { 99 getDatabase().insert("tests", null, map); 100 } 101 } 102 103 public void finished(String className) { 104 ContentValues map = new ContentValues(1); 105 map.put("finished", System.currentTimeMillis()); 106 107 getDatabase().update("tests", map, "name = '" + className + "'", null); 108 } 109 110 public void performance(String className, long itemTimeNS, int iterations, List<IntermediateTime> intermediates) { 111 ContentValues map = new ContentValues(); 112 map.put("time", itemTimeNS); 113 map.put("iterations", iterations); 114 115 getDatabase().update("tests", map, "name = '" + className + "'", null); 116 117 if (intermediates != null && intermediates.size() > 0) { 118 int n = intermediates.size(); 119 for (int i = 0; i < n; i++) { 120 TestRunner.IntermediateTime time = intermediates.get(i); 121 122 getDatabase().execSQL("INSERT INTO tests (name, time, parent) VALUES ('" + 123 time.name + "', " + time.timeInNS + ", " + 124 "(SELECT _id FROM tests WHERE name = '" + className + "'));"); 125 } 126 } 127 } 128 129 public void passed(String className) { 130 ContentValues map = new ContentValues(); 131 map.put("result", "passed"); 132 133 getDatabase().update("tests", map, "name = '" + className + "'", null); 134 } 135 136 public void failed(String className, Throwable exception) { 137 StringWriter stringWriter = new StringWriter(); 138 PrintWriter printWriter = new PrintWriter(stringWriter); 139 try { 140 exception.printStackTrace(printWriter); 141 } finally { 142 printWriter.close(); 143 } 144 ContentValues map = new ContentValues(); 145 map.put("result", "failed"); 146 map.put("exception", stringWriter.toString()); 147 148 getDatabase().update("tests", map, "name = '" + className + "'", null); 149 } 150 151 /** 152 * Reports a test case failure. 153 * 154 * @param className Name of the class/test. 155 * @param reason Reason for failure. 156 */ 157 public void failed(String className, String reason) { 158 ContentValues map = new ContentValues(); 159 map.put("result", "failed"); 160 // The reason is put as the exception. 161 map.put("exception", reason); 162 getDatabase().update("tests", map, "name = '" + className + "'", null); 163 } 164 165 public void addError(Test test, Throwable t) { 166 mFailedTests.add(test.toString()); 167 failed(test.toString(), t); 168 } 169 170 public void addFailure(Test test, junit.framework.AssertionFailedError t) { 171 mFailedTests.add(test.toString()); 172 failed(test.toString(), t.getMessage()); 173 } 174 175 public void endTest(Test test) { 176 finished(test.toString()); 177 if (!mFailedTests.contains(test.toString())) { 178 passed(test.toString()); 179 } 180 mFailedTests.remove(test.toString()); 181 } 182 183 public void startTest(Test test) { 184 started(test.toString()); 185 } 186 } 187