1 /* 2 * Copyright (C) 2010 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 com.android.dumprendertree2; 18 19 import android.os.Bundle; 20 import android.os.Message; 21 import android.util.Log; 22 import android.webkit.WebView; 23 24 import java.io.ByteArrayInputStream; 25 import java.io.ByteArrayOutputStream; 26 import java.io.IOException; 27 import java.io.ObjectInputStream; 28 import java.io.ObjectOutputStream; 29 import java.io.Serializable; 30 31 /** 32 * A class that represent a result of the test. It is responsible for returning the result's 33 * raw data and generating its own diff in HTML format. 34 */ 35 public abstract class AbstractResult implements Comparable<AbstractResult>, Serializable { 36 37 private static final String LOG_TAG = "AbstractResult"; 38 39 public enum TestType { 40 TEXT { 41 @Override createResult(Bundle bundle)42 public AbstractResult createResult(Bundle bundle) { 43 return new TextResult(bundle); 44 } 45 }, 46 RENDER_TREE { 47 @Override createResult(Bundle bundle)48 public AbstractResult createResult(Bundle bundle) { 49 /** TODO: RenderTree tests are not yet supported */ 50 return null; 51 } 52 }; 53 createResult(Bundle bundle)54 public abstract AbstractResult createResult(Bundle bundle); 55 } 56 57 /** 58 * A code representing the result of comparing actual and expected results. 59 */ 60 public enum ResultCode implements Serializable { 61 RESULTS_MATCH("Results match"), 62 RESULTS_DIFFER("Results differ"), 63 NO_EXPECTED_RESULT("No expected result"), 64 NO_ACTUAL_RESULT("No actual result"); 65 66 private String mTitle; 67 ResultCode(String title)68 private ResultCode(String title) { 69 mTitle = title; 70 } 71 72 @Override toString()73 public String toString() { 74 return mTitle; 75 } 76 } 77 78 String mAdditionalTextOutputString; 79 compareTo(AbstractResult another)80 public int compareTo(AbstractResult another) { 81 return getRelativePath().compareTo(another.getRelativePath()); 82 } 83 setAdditionalTextOutputString(String additionalTextOutputString)84 public void setAdditionalTextOutputString(String additionalTextOutputString) { 85 mAdditionalTextOutputString = additionalTextOutputString; 86 } 87 getAdditionalTextOutputString()88 public String getAdditionalTextOutputString() { 89 return mAdditionalTextOutputString; 90 } 91 getBytes()92 public byte[] getBytes() { 93 ByteArrayOutputStream baos = null; 94 ObjectOutputStream oos = null; 95 try { 96 try { 97 baos = new ByteArrayOutputStream(); 98 oos = new ObjectOutputStream(baos); 99 oos.writeObject(this); 100 } finally { 101 if (baos != null) { 102 baos.close(); 103 } 104 if (oos != null) { 105 oos.close(); 106 } 107 } 108 } catch (IOException e) { 109 Log.e(LOG_TAG, "Unable to serialize result: " + getRelativePath(), e); 110 } 111 112 return baos == null ? null : baos.toByteArray(); 113 } 114 create(byte[] bytes)115 public static AbstractResult create(byte[] bytes) { 116 ByteArrayInputStream bais = null; 117 ObjectInputStream ois = null; 118 AbstractResult result = null; 119 try { 120 try { 121 bais = new ByteArrayInputStream(bytes); 122 ois = new ObjectInputStream(bais); 123 result = (AbstractResult)ois.readObject(); 124 } finally { 125 if (bais != null) { 126 bais.close(); 127 } 128 if (ois != null) { 129 ois.close(); 130 } 131 } 132 } catch (IOException e) { 133 Log.e(LOG_TAG, "Unable to deserialize result!", e); 134 } catch (ClassNotFoundException e) { 135 Log.e(LOG_TAG, "Unable to deserialize result!", e); 136 } 137 return result; 138 } 139 clearResults()140 public void clearResults() { 141 mAdditionalTextOutputString = null; 142 } 143 144 /** 145 * Makes the result object obtain the results of the test from the webview 146 * and store them in the format that suits itself bests. This method is asynchronous. 147 * The message passed as a parameter is a message that should be sent to its target 148 * when the result finishes obtaining the result. 149 * 150 * @param webview 151 * @param resultObtainedMsg 152 */ obtainActualResults(WebView webview, Message resultObtainedMsg)153 public abstract void obtainActualResults(WebView webview, Message resultObtainedMsg); 154 setExpectedImageResult(byte[] expectedResult)155 public abstract void setExpectedImageResult(byte[] expectedResult); 156 setExpectedImageResultPath(String relativePath)157 public abstract void setExpectedImageResultPath(String relativePath); 158 getExpectedImageResultPath()159 public abstract String getExpectedImageResultPath(); 160 setExpectedTextResult(String expectedResult)161 public abstract void setExpectedTextResult(String expectedResult); 162 setExpectedTextResultPath(String relativePath)163 public abstract void setExpectedTextResultPath(String relativePath); 164 getExpectedTextResultPath()165 public abstract String getExpectedTextResultPath(); 166 167 /** 168 * Returns result's image data that can be written to the disk. It can be null 169 * if there is an error of some sort or for example the test times out. 170 * 171 * <p> Some tests will not provide data (like text tests) 172 * 173 * @return 174 * results image data 175 */ getActualImageResult()176 public abstract byte[] getActualImageResult(); 177 178 /** 179 * Returns result's text data. It can be null 180 * if there is an error of some sort or for example the test times out. 181 * 182 * @return 183 * results text data 184 */ getActualTextResult()185 public abstract String getActualTextResult(); 186 187 /** 188 * Returns the status code representing the result of comparing actual and expected results. 189 * 190 * @return 191 * the status code from comparing actual and expected results 192 */ getResultCode()193 public abstract ResultCode getResultCode(); 194 195 /** 196 * Returns whether this test crashed. 197 * 198 * @return 199 * whether this test crashed 200 */ didCrash()201 public abstract boolean didCrash(); 202 203 /** 204 * Returns whether this test timed out. 205 * 206 * @return 207 * whether this test timed out 208 */ didTimeOut()209 public abstract boolean didTimeOut(); 210 211 /** 212 * Sets that this test timed out. 213 */ setDidTimeOut()214 public abstract void setDidTimeOut(); 215 216 /** 217 * Returns whether the test passed. 218 * 219 * @return 220 * whether the test passed 221 */ didPass()222 public boolean didPass() { 223 // Tests that crash can't have timed out or have an actual result. 224 assert !(didCrash() && didTimeOut()); 225 assert !(didCrash() && getResultCode() != ResultCode.NO_ACTUAL_RESULT); 226 return !didCrash() && !didTimeOut() && getResultCode() == ResultCode.RESULTS_MATCH; 227 } 228 229 /** 230 * Return the type of the result data. 231 * 232 * @return 233 * the type of the result data. 234 */ getType()235 public abstract TestType getType(); 236 getRelativePath()237 public abstract String getRelativePath(); 238 239 /** 240 * Returns a piece of HTML code that presents a visual diff between a result and 241 * the expected result. 242 * 243 * @return 244 * a piece of HTML code with a visual diff between the result and the expected result 245 */ getDiffAsHtml()246 public abstract String getDiffAsHtml(); 247 getBundle()248 public abstract Bundle getBundle(); 249 } 250