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/. */
5 package org
.mozilla
.gecko
;
7 import java
.io
.PrintWriter
;
8 import java
.io
.StringWriter
;
10 import java
.util
.LinkedList
;
12 import android
.os
.SystemClock
;
14 public class FennecMochitestAssert
implements Assert
{
15 private LinkedList
<testInfo
> mTestList
= new LinkedList
<testInfo
>();
17 // Internal state variables to make logging match up with existing mochitests
18 private int mPassed
= 0;
19 private int mFailed
= 0;
20 private int mTodo
= 0;
22 // Used to write the first line of the test file
23 private boolean mLogStarted
= false;
25 // Used to write the test-start/test-end log lines
26 private String mLogTestName
= "";
28 // Measure the time it takes to run test case
29 private long mStartTime
= 0;
32 private StructuredLogger mLogger
;
34 /** Write information to a logfile and logcat */
35 public void dumpLog(String message
) {
36 mLogger
.info(message
);
39 public void dumpLog(String message
, Throwable t
) {
40 Writer sw
= new StringWriter();
41 PrintWriter pw
= new PrintWriter(sw
);
42 t
.printStackTrace(pw
);
43 mLogger
.error(message
+ " - " + sw
.toString());
46 /** Write information to a logfile and logcat */
47 static class DumpLogCallback
implements StructuredLogger
.LoggerCallback
{
48 public void call(String output
) {
49 FennecNativeDriver
.log(FennecNativeDriver
.LogLevel
.INFO
, output
);
54 public FennecMochitestAssert() {
55 mLogger
= new StructuredLogger("robocop", new DumpLogCallback());
58 /** Set the filename used for dumpLog. */
59 public void setLogFile(String filename
) {
60 FennecNativeDriver
.setLogFile(filename
);
64 mLogger
.info("SimpleTest START");
68 if (mLogTestName
!= "") {
69 long diff
= SystemClock
.uptimeMillis() - mStartTime
;
70 mLogger
.testEnd(mLogTestName
, "OK", "finished in " + diff
+ "ms");
75 public void setTestName(String testName
) {
76 String
[] nameParts
= testName
.split("\\.");
77 mLogTestName
= nameParts
[nameParts
.length
- 1];
78 mStartTime
= SystemClock
.uptimeMillis();
80 mLogger
.testStart(mLogTestName
);
84 public boolean mResult
;
89 public testInfo(boolean r
, String n
, String d
, boolean t
, boolean i
) {
99 /** Used to log a subtest's result.
100 * test represents the subtest (an assertion).
101 * passStatus and passExpected are the actual status and the expected status if the assertion is true.
102 * failStatus and failExpected are the actual status and the expected status otherwise.
104 private void _logMochitestResult(testInfo test
, String passStatus
, String passExpected
, String failStatus
, String failExpected
) {
105 boolean isError
= true;
106 if (test
.mResult
|| test
.mTodo
) {
111 mLogger
.testStatus(mLogTestName
, test
.mName
, passStatus
, passExpected
, test
.mDiag
);
113 mLogger
.testStatus(mLogTestName
, test
.mName
, failStatus
, failExpected
, test
.mDiag
);
117 // do not count TEST-INFO messages
118 } else if (test
.mTodo
) {
120 } else if (isError
) {
126 String message
= "TEST-UNEXPECTED-" + failStatus
+ " | " + mLogTestName
+ " | "
127 + test
.mName
+ " - " + test
.mDiag
;
128 junit
.framework
.Assert
.fail(message
);
132 public void endTest() {
135 if (mLogTestName
!= "") {
136 long diff
= SystemClock
.uptimeMillis() - mStartTime
;
137 mLogger
.testEnd(mLogTestName
, "OK", "finished in " + diff
+ "ms");
141 mLogger
.info("TEST-START | Shutdown");
142 mLogger
.info("Passed: " + Integer
.toString(mPassed
));
143 mLogger
.info("Failed: " + Integer
.toString(mFailed
));
144 mLogger
.info("Todo: " + Integer
.toString(mTodo
));
145 mLogger
.info("SimpleTest FINISHED");
148 public void ok(boolean condition
, String name
, String diag
) {
149 testInfo test
= new testInfo(condition
, name
, diag
, false, false);
150 _logMochitestResult(test
, "PASS", "PASS", "FAIL", "PASS");
154 public void is(Object actual
, Object expected
, String name
) {
155 boolean pass
= checkObjectsEqual(actual
, expected
);
156 ok(pass
, name
, getEqualString(actual
, expected
, pass
));
159 public void isnot(Object actual
, Object notExpected
, String name
) {
160 boolean pass
= checkObjectsNotEqual(actual
, notExpected
);
161 ok(pass
, name
, getNotEqualString(actual
, notExpected
, pass
));
164 public void ispixel(int actual
, int r
, int g
, int b
, String name
) {
165 int aAlpha
= ((actual
>> 24) & 0xFF);
166 int aR
= ((actual
>> 16) & 0xFF);
167 int aG
= ((actual
>> 8) & 0xFF);
168 int aB
= (actual
& 0xFF);
169 boolean pass
= checkPixel(actual
, r
, g
, b
);
170 ok(pass
, name
, "Color rgba(" + aR
+ "," + aG
+ "," + aB
+ "," + aAlpha
+ ")" + (pass ?
" " : " not") + " close enough to expected rgb(" + r
+ "," + g
+ "," + b
+ ")");
173 public void isnotpixel(int actual
, int r
, int g
, int b
, String name
) {
174 int aAlpha
= ((actual
>> 24) & 0xFF);
175 int aR
= ((actual
>> 16) & 0xFF);
176 int aG
= ((actual
>> 8) & 0xFF);
177 int aB
= (actual
& 0xFF);
178 boolean pass
= checkPixel(actual
, r
, g
, b
);
179 ok(!pass
, name
, "Color rgba(" + aR
+ "," + aG
+ "," + aB
+ "," + aAlpha
+ ")" + (!pass ?
" is" : " is not") + " different enough from rgb(" + r
+ "," + g
+ "," + b
+ ")");
182 private boolean checkPixel(int actual
, int r
, int g
, int b
) {
183 // When we read GL pixels the GPU has already processed them and they
184 // are usually off by a little bit. For example a CSS-color pixel of color #64FFF5
185 // was turned into #63FFF7 when it came out of glReadPixels. So in order to compare
186 // against the expected value, we use a little fuzz factor. For the alpha we just
187 // make sure it is always 0xFF. There is also bug 691354 which crops up every so
188 // often just to make our lives difficult. However the individual color components
189 // should never be off by more than 8.
190 int aAlpha
= ((actual
>> 24) & 0xFF);
191 int aR
= ((actual
>> 16) & 0xFF);
192 int aG
= ((actual
>> 8) & 0xFF);
193 int aB
= (actual
& 0xFF);
194 boolean pass
= (aAlpha
== 0xFF) /* alpha */
195 && (Math
.abs(aR
- r
) <= 8) /* red */
196 && (Math
.abs(aG
- g
) <= 8) /* green */
197 && (Math
.abs(aB
- b
) <= 8); /* blue */
205 public void todo(boolean condition
, String name
, String diag
) {
206 testInfo test
= new testInfo(condition
, name
, diag
, true, false);
207 _logMochitestResult(test
, "PASS", "FAIL", "FAIL", "FAIL");
211 public void todo_is(Object actual
, Object expected
, String name
) {
212 boolean pass
= checkObjectsEqual(actual
, expected
);
213 todo(pass
, name
, getEqualString(actual
, expected
, pass
));
216 public void todo_isnot(Object actual
, Object notExpected
, String name
) {
217 boolean pass
= checkObjectsNotEqual(actual
, notExpected
);
218 todo(pass
, name
, getNotEqualString(actual
, notExpected
, pass
));
221 private boolean checkObjectsEqual(Object a
, Object b
) {
222 if (a
== null || b
== null) {
223 if (a
== null && b
== null) {
232 private String
getEqualString(Object a
, Object b
, boolean pass
) {
234 return a
+ " should equal " + b
;
236 return "got " + a
+ ", expected " + b
;
239 private boolean checkObjectsNotEqual(Object a
, Object b
) {
240 if (a
== null || b
== null) {
241 if ((a
== null && b
!= null) || (a
!= null && b
== null)) {
251 private String
getNotEqualString(Object a
, Object b
, boolean pass
) {
253 return a
+ " should not equal " + b
;
255 return "didn't expect " + a
+ ", but got it";
258 public void info(String name
, String message
) {
259 mLogger
.info(name
+ " | " + message
);