1if (window.layoutTestController)
2    layoutTestController.dumpAsText();
3
4function description(msg)
5{
6    // For MSIE 6 compatibility
7    var span = document.createElement("span");
8    span.innerHTML = '<p>' + msg + '</p><p>On success, you will see a series of "<span class="pass">PASS</span>" messages, followed by "<span class="pass">TEST COMPLETE</span>".</p>';
9    var description = document.getElementById("description");
10    if (description.firstChild)
11        description.replaceChild(span, description.firstChild);
12    else
13        description.appendChild(span);
14}
15
16function debug(msg)
17{
18    var span = document.createElement("span");
19    document.getElementById("console").appendChild(span); // insert it first so XHTML knows the namespace
20    span.innerHTML = msg + '<br />';
21}
22
23function escapeHTML(text)
24{
25    return text.replace(/&/g, "&amp;").replace(/</g, "&lt;");
26}
27
28function testPassed(msg)
29{
30    debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
31}
32
33function testFailed(msg)
34{
35    debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
36}
37
38function areArraysEqual(_a, _b)
39{
40    if (_a.length !== _b.length)
41        return false;
42    for (var i = 0; i < _a.length; i++)
43        if (_a[i] !== _b[i])
44            return false;
45    return true;
46}
47
48function isMinusZero(n)
49{
50    // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
51    // -Infinity instead of Infinity
52    return n === 0 && 1/n < 0;
53}
54
55function isResultCorrect(_actual, _expected)
56{
57    if (_expected === 0)
58        return _actual === _expected && (1/_actual) === (1/_expected);
59    if (_actual === _expected)
60        return true;
61    if (typeof(_expected) == "number" && isNaN(_expected))
62        return typeof(_actual) == "number" && isNaN(_actual);
63    if (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([]))
64        return areArraysEqual(_actual, _expected);
65    return false;
66}
67
68function stringify(v)
69{
70    if (v === 0 && 1/v < 0)
71        return "-0";
72    else return "" + v;
73}
74
75function shouldBe(_a, _b)
76{
77    if (typeof _a != "string" || typeof _b != "string")
78        debug("WARN: shouldBe() expects string arguments");
79    var exception;
80    var _av;
81    try {
82        _av = eval(_a);
83    } catch (e) {
84        exception = e;
85    }
86    var _bv = eval(_b);
87
88    if (exception)
89        testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
90    else if (isResultCorrect(_av, _bv))
91        testPassed(_a + " is " + _b);
92    else if (typeof(_av) == typeof(_bv))
93        testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
94    else
95        testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
96}
97
98function shouldBeTrue(_a) { shouldBe(_a, "true"); }
99function shouldBeFalse(_a) { shouldBe(_a, "false"); }
100function shouldBeNaN(_a) { shouldBe(_a, "NaN"); }
101function shouldBeNull(_a) { shouldBe(_a, "null"); }
102
103function shouldBeEqualToString(a, b)
104{
105    var unevaledString = '"' + b.replace(/"/g, "\"") + '"';
106    shouldBe(a, unevaledString);
107}
108
109function shouldBeUndefined(_a)
110{
111    var exception;
112    var _av;
113    try {
114        _av = eval(_a);
115    } catch (e) {
116        exception = e;
117    }
118
119    if (exception)
120        testFailed(_a + " should be undefined. Threw exception " + exception);
121    else if (typeof _av == "undefined")
122        testPassed(_a + " is undefined.");
123    else
124        testFailed(_a + " should be undefined. Was " + _av);
125}
126
127function shouldThrow(_a, _e)
128{
129    var exception;
130    var _av;
131    try {
132        _av = eval(_a);
133    } catch (e) {
134        exception = e;
135    }
136
137    var _ev;
138    if (_e)
139        _ev =  eval(_e);
140
141    if (exception) {
142        if (typeof _e == "undefined" || exception == _ev)
143            testPassed(_a + " threw exception " + exception + ".");
144        else
145            testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + exception + ".");
146    } else if (typeof _av == "undefined")
147        testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
148    else
149        testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
150}
151
152var cookies = new Array();
153
154// This method sets the cookies using XMLHttpRequest.
155// We do not set the cookie right away as it is forbidden by the XHR spec.
156// FIXME: Add the possibility to set multiple cookies in a row.
157function setCookies(cookie)
158{
159    try {
160        var xhr = new XMLHttpRequest();
161        xhr.open("GET", "resources/setCookies.cgi", false);
162        xhr.setRequestHeader("SET_COOKIE", cookie);
163        xhr.send(null);
164        if (xhr.status == 200) {
165            // This is to clear them later.
166            cookies.push(cookie);
167            return true;
168        } else
169            return false;
170    } catch (e) {
171        return false;
172    }
173}
174
175// Normalize a cookie string
176function normalizeCookie(cookie)
177{
178    // Split the cookie string, sort it and then put it back together.
179    return cookie.split('; ').sort().join('; ');
180}
181
182// We get the cookies throught an XMLHttpRequest.
183function testCookies(result)
184{
185    var xhr = new XMLHttpRequest();
186    xhr.open("GET", "resources/getCookies.cgi", false);
187    xhr.send(null);
188    var cookie = xhr.getResponseHeader("HTTP_COOKIE") == null ? '"null"' : xhr.getResponseHeader("HTTP_COOKIE");
189
190    // Normalize the cookie strings.
191    result = normalizeCookie(result);
192    cookie = normalizeCookie(cookie);
193
194    if (cookie === result)
195        testPassed("cookie is '" + cookie + "'.");
196    else
197        testFailed("cookie was '" + cookie + "'. Expected '" + result + "'.");
198}
199
200function clearAllCookies()
201{
202    var cookieString;
203    while (cookieString = document.cookie) {
204        var cookieName = cookieString.substr(0, cookieString.indexOf("=") || cookieString.length());
205        cookies.push(cookieName);
206        clearCookies();
207    }
208}
209
210function clearCookies()
211{
212    if (!cookies.length)
213        return;
214
215    try {
216        var xhr = new XMLHttpRequest();
217        var cookie;
218        // We need to clean one cookie at a time because to be cleared the
219        // cookie must be exactly the same except for the "Max-Age"
220        // and "Expires" fields.
221        while (cookie = cookies.pop()) {
222            xhr.open("GET", "resources/clearCookies.cgi", false);
223            xhr.setRequestHeader("CLEAR_COOKIE", cookie);
224            xhr.send(null);
225        }
226    } catch (e) {
227        debug("Could not clear the cookies expect the following results to fail");
228    }
229}
230
231// This method check one cookie at a time.
232function cookiesShouldBe(cookiesToSet, result)
233{
234    if (!setCookies(cookiesToSet)) {
235        testFailed("could not set cookie(s) " + cookiesToSet);
236        return;
237    }
238    testCookies(result);
239}
240