|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 package org.mozilla.gecko; |
|
6 |
|
7 import java.util.LinkedList; |
|
8 |
|
9 import android.os.SystemClock; |
|
10 |
|
11 public class FennecMochitestAssert implements Assert { |
|
12 private LinkedList<testInfo> mTestList = new LinkedList<testInfo>(); |
|
13 |
|
14 // Internal state variables to make logging match up with existing mochitests |
|
15 private int mLineNumber = 0; |
|
16 private int mPassed = 0; |
|
17 private int mFailed = 0; |
|
18 private int mTodo = 0; |
|
19 |
|
20 // Used to write the first line of the test file |
|
21 private boolean mLogStarted = false; |
|
22 |
|
23 // Used to write the test-start/test-end log lines |
|
24 private String mLogTestName = ""; |
|
25 |
|
26 // Measure the time it takes to run test case |
|
27 private long mStartTime = 0; |
|
28 |
|
29 public FennecMochitestAssert() { |
|
30 } |
|
31 |
|
32 /** Write information to a logfile and logcat */ |
|
33 public void dumpLog(String message) { |
|
34 FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message); |
|
35 } |
|
36 |
|
37 /** Write information to a logfile and logcat */ |
|
38 public void dumpLog(String message, Throwable t) { |
|
39 FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message, t); |
|
40 } |
|
41 |
|
42 /** Set the filename used for dumpLog. */ |
|
43 public void setLogFile(String filename) { |
|
44 FennecNativeDriver.setLogFile(filename); |
|
45 |
|
46 String message; |
|
47 if (!mLogStarted) { |
|
48 dumpLog(Integer.toString(mLineNumber++) + " INFO SimpleTest START"); |
|
49 mLogStarted = true; |
|
50 } |
|
51 |
|
52 if (mLogTestName != "") { |
|
53 long diff = SystemClock.uptimeMillis() - mStartTime; |
|
54 message = Integer.toString(mLineNumber++) + " INFO TEST-END | " + mLogTestName; |
|
55 message += " | finished in " + diff + "ms"; |
|
56 dumpLog(message); |
|
57 mLogTestName = ""; |
|
58 } |
|
59 } |
|
60 |
|
61 public void setTestName(String testName) { |
|
62 String[] nameParts = testName.split("\\."); |
|
63 mLogTestName = nameParts[nameParts.length - 1]; |
|
64 mStartTime = SystemClock.uptimeMillis(); |
|
65 |
|
66 dumpLog(Integer.toString(mLineNumber++) + " INFO TEST-START | " + mLogTestName); |
|
67 } |
|
68 |
|
69 class testInfo { |
|
70 public boolean mResult; |
|
71 public String mName; |
|
72 public String mDiag; |
|
73 public boolean mTodo; |
|
74 public boolean mInfo; |
|
75 public testInfo(boolean r, String n, String d, boolean t, boolean i) { |
|
76 mResult = r; |
|
77 mName = n; |
|
78 mDiag = d; |
|
79 mTodo = t; |
|
80 mInfo = i; |
|
81 } |
|
82 |
|
83 } |
|
84 |
|
85 private void _logMochitestResult(testInfo test, String passString, String failString) { |
|
86 boolean isError = true; |
|
87 String resultString = failString; |
|
88 if (test.mResult || test.mTodo) { |
|
89 isError = false; |
|
90 } |
|
91 if (test.mResult) |
|
92 { |
|
93 resultString = passString; |
|
94 } |
|
95 String diag = test.mName; |
|
96 if (test.mDiag != null) diag += " - " + test.mDiag; |
|
97 |
|
98 String message = Integer.toString(mLineNumber++) + " INFO " + resultString + " | " + mLogTestName + " | " + diag; |
|
99 dumpLog(message); |
|
100 |
|
101 if (test.mInfo) { |
|
102 // do not count TEST-INFO messages |
|
103 } else if (test.mTodo) { |
|
104 mTodo++; |
|
105 } else if (isError) { |
|
106 mFailed++; |
|
107 } else { |
|
108 mPassed++; |
|
109 } |
|
110 if (isError) { |
|
111 junit.framework.Assert.fail(message); |
|
112 } |
|
113 } |
|
114 |
|
115 public void endTest() { |
|
116 String message; |
|
117 |
|
118 if (mLogTestName != "") { |
|
119 long diff = SystemClock.uptimeMillis() - mStartTime; |
|
120 message = Integer.toString(mLineNumber++) + " INFO TEST-END | " + mLogTestName; |
|
121 message += " | finished in " + diff + "ms"; |
|
122 dumpLog(message); |
|
123 mLogTestName = ""; |
|
124 } |
|
125 |
|
126 message = Integer.toString(mLineNumber++) + " INFO TEST-START | Shutdown"; |
|
127 dumpLog(message); |
|
128 message = Integer.toString(mLineNumber++) + " INFO Passed: " + Integer.toString(mPassed); |
|
129 dumpLog(message); |
|
130 message = Integer.toString(mLineNumber++) + " INFO Failed: " + Integer.toString(mFailed); |
|
131 dumpLog(message); |
|
132 message = Integer.toString(mLineNumber++) + " INFO Todo: " + Integer.toString(mTodo); |
|
133 dumpLog(message); |
|
134 message = Integer.toString(mLineNumber++) + " INFO SimpleTest FINISHED"; |
|
135 dumpLog(message); |
|
136 } |
|
137 |
|
138 public void ok(boolean condition, String name, String diag) { |
|
139 testInfo test = new testInfo(condition, name, diag, false, false); |
|
140 _logMochitestResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL"); |
|
141 mTestList.add(test); |
|
142 } |
|
143 |
|
144 public void is(Object actual, Object expected, String name) { |
|
145 boolean pass = checkObjectsEqual(actual, expected); |
|
146 ok(pass, name, getEqualString(actual, expected, pass)); |
|
147 } |
|
148 |
|
149 public void isnot(Object actual, Object notExpected, String name) { |
|
150 boolean pass = checkObjectsNotEqual(actual, notExpected); |
|
151 ok(pass, name, getNotEqualString(actual, notExpected, pass)); |
|
152 } |
|
153 |
|
154 public void ispixel(int actual, int r, int g, int b, String name) { |
|
155 int aAlpha = ((actual >> 24) & 0xFF); |
|
156 int aR = ((actual >> 16) & 0xFF); |
|
157 int aG = ((actual >> 8) & 0xFF); |
|
158 int aB = (actual & 0xFF); |
|
159 boolean pass = checkPixel(actual, r, g, b); |
|
160 ok(pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (pass ? " " : " not") + " close enough to expected rgb(" + r + "," + g + "," + b + ")"); |
|
161 } |
|
162 |
|
163 public void isnotpixel(int actual, int r, int g, int b, String name) { |
|
164 int aAlpha = ((actual >> 24) & 0xFF); |
|
165 int aR = ((actual >> 16) & 0xFF); |
|
166 int aG = ((actual >> 8) & 0xFF); |
|
167 int aB = (actual & 0xFF); |
|
168 boolean pass = checkPixel(actual, r, g, b); |
|
169 ok(!pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (!pass ? " is" : " is not") + " different enough from rgb(" + r + "," + g + "," + b + ")"); |
|
170 } |
|
171 |
|
172 private boolean checkPixel(int actual, int r, int g, int b) { |
|
173 // When we read GL pixels the GPU has already processed them and they |
|
174 // are usually off by a little bit. For example a CSS-color pixel of color #64FFF5 |
|
175 // was turned into #63FFF7 when it came out of glReadPixels. So in order to compare |
|
176 // against the expected value, we use a little fuzz factor. For the alpha we just |
|
177 // make sure it is always 0xFF. There is also bug 691354 which crops up every so |
|
178 // often just to make our lives difficult. However the individual color components |
|
179 // should never be off by more than 8. |
|
180 int aAlpha = ((actual >> 24) & 0xFF); |
|
181 int aR = ((actual >> 16) & 0xFF); |
|
182 int aG = ((actual >> 8) & 0xFF); |
|
183 int aB = (actual & 0xFF); |
|
184 boolean pass = (aAlpha == 0xFF) /* alpha */ |
|
185 && (Math.abs(aR - r) <= 8) /* red */ |
|
186 && (Math.abs(aG - g) <= 8) /* green */ |
|
187 && (Math.abs(aB - b) <= 8); /* blue */ |
|
188 if (pass) { |
|
189 return true; |
|
190 } else { |
|
191 return false; |
|
192 } |
|
193 } |
|
194 |
|
195 public void todo(boolean condition, String name, String diag) { |
|
196 testInfo test = new testInfo(condition, name, diag, true, false); |
|
197 _logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL"); |
|
198 mTestList.add(test); |
|
199 } |
|
200 |
|
201 public void todo_is(Object actual, Object expected, String name) { |
|
202 boolean pass = checkObjectsEqual(actual, expected); |
|
203 todo(pass, name, getEqualString(actual, expected, pass)); |
|
204 } |
|
205 |
|
206 public void todo_isnot(Object actual, Object notExpected, String name) { |
|
207 boolean pass = checkObjectsNotEqual(actual, notExpected); |
|
208 todo(pass, name, getNotEqualString(actual, notExpected, pass)); |
|
209 } |
|
210 |
|
211 private boolean checkObjectsEqual(Object a, Object b) { |
|
212 if (a == null || b == null) { |
|
213 if (a == null && b == null) { |
|
214 return true; |
|
215 } |
|
216 return false; |
|
217 } else { |
|
218 return a.equals(b); |
|
219 } |
|
220 } |
|
221 |
|
222 private String getEqualString(Object a, Object b, boolean pass) { |
|
223 if (pass) { |
|
224 return a + " should equal " + b; |
|
225 } |
|
226 return "got " + a + ", expected " + b; |
|
227 } |
|
228 |
|
229 private boolean checkObjectsNotEqual(Object a, Object b) { |
|
230 if (a == null || b == null) { |
|
231 if ((a == null && b != null) || (a != null && b == null)) { |
|
232 return true; |
|
233 } else { |
|
234 return false; |
|
235 } |
|
236 } else { |
|
237 return !a.equals(b); |
|
238 } |
|
239 } |
|
240 |
|
241 private String getNotEqualString(Object a, Object b, boolean pass) { |
|
242 if(pass) { |
|
243 return a + " should not equal " + b; |
|
244 } |
|
245 return "didn't expect " + a + ", but got it"; |
|
246 } |
|
247 |
|
248 public void info(String name, String message) { |
|
249 testInfo test = new testInfo(true, name, message, false, true); |
|
250 _logMochitestResult(test, "TEST-INFO", "INFO FAILED?"); |
|
251 } |
|
252 } |