1// Copyright 2013 the V8 project authors. All rights reserved.
2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7// 1.  Redistributions of source code must retain the above copyright
8//     notice, this list of conditions and the following disclaimer.
9// 2.  Redistributions in binary form must reproduce the above copyright
10//     notice, this list of conditions and the following disclaimer in the
11//     documentation and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24description(
25"This tests if the Date setters handle invalid parameters correctly resulting in a NaN date and if a recovery from such a NaN date is only possible by using the date.setTime() and date.set[[UTC]Full]Year() functions."
26);
27
28var dateFunctionNameRoots = [
29    "Time",
30    "Milliseconds",
31    "UTCMilliseconds",
32    "Seconds",
33    "UTCSeconds",
34    "Minutes",
35    "UTCMinutes",
36    "Hours",
37    "UTCHours",
38    "Date",
39    "UTCDate",
40    "Month",
41    "UTCMonth",
42    "FullYear",
43    "UTCFullYear",
44    "Year"
45];
46
47var dateFunctionParameterNum = [
48    1,
49    1,
50    1,
51    2,
52    2,
53    3,
54    3,
55    4,
56    4,
57    1,
58    1,
59    2,
60    2,
61    3,
62    3,
63    1
64];
65
66var testValues = [
67    0,
68    Number.NaN,
69    Number.POSITIVE_INFINITY,
70    Number.NEGATIVE_INFINITY
71];
72
73function testDateFunctionWithValueNoRecoverNaN(functionNameRoot, steps)
74{
75    var date = new Date();
76    var setValue = date["get" + functionNameRoot]();
77    date.setMilliseconds(Number.NaN);
78    var params = [
79        "",
80        ", 0",
81        ", 0, 0",
82        ", 0, 0, 0"
83    ];
84    var setResult = (1 == steps) ?  date["set" + functionNameRoot](setValue)
85                  : ((2 == steps) ? date["set" + functionNameRoot](setValue, 0)
86                  : ((3 == steps) ? date["set" + functionNameRoot](setValue, 0, 0)
87                  :                  date["set" + functionNameRoot](setValue, 0, 0, 0)));
88    if (!isNaN(setResult)) {
89        testFailed("date(NaN).set" + functionNameRoot + "(" + setValue + params[steps - 1]
90                                   + ") was " + setResult + " instead of NaN");
91        return false;
92    }
93    var getResult = date["get" + functionNameRoot]();
94    if (!isNaN(getResult)) {
95        testFailed("date.get" + functionNameRoot + "() was " + getResult + " instead of NaN");
96        return false;
97    }
98    testPassed ("no recovering from NaN date using date.set" + functionNameRoot
99        + "(arg0" + params[steps - 1] + ")");
100    return true;
101}
102
103function testDateFunctionWithValueRecoverTime(functionNameRoot)
104{
105    var date = new Date();
106    var setValue = date["get" + functionNameRoot]();
107    date.setMilliseconds(Number.NaN);
108    var setResult = date["set" + functionNameRoot](setValue);
109    if (setValue != setResult) {
110        testFailed("date(NaN).set" + functionNameRoot + "(" + setValue + ") was " + setResult + " instead of " + setValue);
111        return false;
112    }
113    var getResult = date["get" + functionNameRoot]();
114    if (getResult != setValue) {
115        testFailed("date.get" + functionNameRoot + "() was " + getResult + " instead of " + setValue);
116        return false;
117    }
118    testPassed ("recover from NaN date using date.set" + functionNameRoot + "()");
119    return true;
120}
121
122function testDateFunctionWithValueRecoverFullYear(functionNameRoot)
123{
124    var result = true;
125    var date = new Date();
126    var setValue = date["get" + functionNameRoot]();
127    date.setMilliseconds(Number.NaN);
128    var setResult = date["set" + functionNameRoot](setValue);
129    var getResult = date["get" + functionNameRoot]();
130    if (getResult != setValue) {
131        testFailed("date.get" + functionNameRoot + "() was " + getResult + " instead of " + setValue);
132        result = false;
133    }
134    getResult = date.getMilliseconds();
135    if (getResult != 0) {
136        testFailed("date.getMilliseconds() was " + getResult + " instead of 0");
137        result = false;
138    }
139    getResult = date.getSeconds();
140    if (getResult != 0) {
141        testFailed("date.getSeconds() was " + getResult + " instead of 0");
142        result = false;
143    }
144    getResult = date.getMinutes();
145    if (getResult != 0) {
146        testFailed("date.getMinutes() was " + getResult + " instead of 0");
147        result = false;
148    }
149    getResult = date.getHours();
150    if (getResult != 0) {
151        testFailed("date.getHours() was " + getResult + " instead of 0");
152        result = false;
153    }
154    getResult = date.getDate();
155    if (getResult != 1) {
156        testFailed("date.getDate() was " + getResult + " instead of 1");
157        result = false;
158    }
159    getResult = date.getMonth();
160    if (getResult != 0) {
161        testFailed("date.getMonth() was " + getResult + " instead of 0");
162        result = false;
163    }
164    if (result)
165        testPassed ("recover from NaN date using date.setFullYear()");
166    else
167        testFailed ("recover from NaN date using date.setFullYear()");
168    return result;
169}
170
171function testDateFunctionWithValueRecoverUTCFullYear(functionNameRoot)
172{
173    var result = true;
174    var date = new Date();
175    var setValue = date["get" + functionNameRoot]();
176    date.setMilliseconds(Number.NaN);
177    var setResult = date["set" + functionNameRoot](setValue);
178    var getResult = date["get" + functionNameRoot]();
179    if (getResult != setValue) {
180        testFailed("date.get" + functionNameRoot + "() was " + getResult + " instead of " + setValue);
181        result = false;
182    }
183    getResult = date.getUTCMilliseconds();
184    if (getResult != 0) {
185        testFailed("date.getUTCMilliseconds() was " + getResult + " instead of 0");
186        result = false;
187    }
188    getResult = date.getUTCSeconds();
189    if (getResult != 0) {
190        testFailed("date.getUTCSeconds() was " + getResult + " instead of 0");
191        result = false;
192    }
193    getResult = date.getUTCMinutes();
194    if (getResult != 0) {
195        testFailed("date.getUTCMinutes() was " + getResult + " instead of 0");
196        result = false;
197    }
198    getResult = date.getUTCHours();
199    if (getResult != 0) {
200        testFailed("date.getUTCHours() was " + getResult + " instead of 0");
201        result = false;
202    }
203    getResult = date.getUTCDate();
204    if (getResult != 1) {
205        testFailed("date.getUTCDate() was " + getResult + " instead of 1");
206        result = false;
207    }
208    getResult = date.getUTCMonth();
209    if (getResult != 0) {
210        testFailed("date.getUTCMonth() was " + getResult + " instead of 0");
211        result = false;
212    }
213    if (result)
214        testPassed ("recover from NaN date using date.setUTCFullYear()");
215    else
216        testFailed ("recover from NaN date using date.setUTCFullYear()");
217    return result;
218}
219
220function testDateFunctionWithValueRecoverYear(functionNameRoot)
221{
222    var result = true;
223    var is13Compatible = true;
224
225    var date = new Date();
226    var setValue = date["get" + functionNameRoot]();
227    var fullYears = date.getFullYear() - 1900;
228    if (setValue != fullYears) {
229        testFailed("date.get" + functionNameRoot + "() was " + setValue + " instead of " + fullYears);
230        is13Compatible = false;
231    } else
232        testPassed("date.getYear() is compatible to JavaScript 1.3 and later");
233
234    date.setMilliseconds(Number.NaN);
235    var setResult = date["set" + functionNameRoot](setValue + 1900);
236    var getResult = date["get" + functionNameRoot]();
237    if (getResult != setValue) {
238        testFailed("date.get" + functionNameRoot + "() was " + getResult + " instead of " + setValue);
239        result = false;
240    }
241    getResult = date.getMilliseconds();
242    if (getResult != 0) {
243        testFailed("date.getMilliseconds() was " + getResult + " instead of 0");
244        result = false;
245    }
246    getResult = date.getSeconds();
247    if (getResult != 0) {
248        testFailed("date.getSeconds() was " + getResult + " instead of 0");
249        result = false;
250    }
251    getResult = date.getMinutes();
252    if (getResult != 0) {
253        testFailed("date.getMinutes() was " + getResult + " instead of 0");
254        result = false;
255    }
256    getResult = date.getHours();
257    if (getResult != 0) {
258        testFailed("date.getHours() was " + getResult + " instead of 0");
259        result = false;
260    }
261    getResult = date.getDate();
262    if (getResult != 1) {
263        testFailed("date.getDate() was " + getResult + " instead of 1");
264        result = false;
265    }
266    getResult = date.getMonth();
267    if (getResult != 0) {
268        testFailed("date.getMonth() was " + getResult + " instead of 0");
269        result = false;
270    }
271    if (result)
272        testPassed ("recover from NaN date using date.setUTCFullYear()");
273    else
274        testFailed ("recover from NaN date using date.setUTCFullYear()");
275    return result && is13Compatible;
276}
277
278function makeIEHappy(functionNameRoot, value)
279{
280    var date = new Date();
281    var setResult = date["set" + functionNameRoot](value);
282    if (!isNaN(setResult)) {
283        testFailed("date.set" + functionNameRoot
284                              + "() was "
285                              + setResult + " instead of NaN");
286         return false;
287    }
288    var getResult = date["get" + functionNameRoot]();
289    if (!isNaN(getResult)) {
290        testFailed("date.get" + functionNameRoot + "() was "
291                              + getResult + " instead of NaN");
292        return false;
293    }
294    return true
295}
296
297function testDateFunctionWithValueExpectingNaN1(functionNameRoot)
298{
299    var result = true;
300    for (var idx0 in testValues)
301        if (idx0 != 0) {
302            var date = new Date();
303            var setResult = date["set" + functionNameRoot](testValues[idx0]);
304            if (!isNaN(setResult)) {
305                testFailed("date.set" + functionNameRoot + "("
306                                      + testValues[idx0] + ") was "
307                                      + setResult + " instead of NaN");
308                result = false;
309            }
310            var getResult = date["get" + functionNameRoot]();
311            if (!isNaN(getResult)) {
312                testFailed("date.get" + functionNameRoot + "() was "
313                                      + getResult + " instead of NaN");
314                result = false;
315            }
316        } else if (!makeIEHappy(functionNameRoot))
317            result = false;
318    if (result) {
319        testPassed("date.set" + functionNameRoot + "(arg0)");
320        testPassed("date.set" + functionNameRoot + "()");
321    }
322    return result;
323}
324
325function testDateFunctionWithValueExpectingNaN2(functionNameRoot)
326{
327    var result = true;
328    for (var idx0 in testValues)
329        for (var idx1 in testValues)
330            if (idx0 != 0 || idx1 != 0) {
331                var date = new Date();
332                var setResult = date["set" + functionNameRoot](testValues[idx0],
333                                                               testValues[idx1]);
334
335                if (!isNaN(setResult)) {
336                    testFailed("date.set" + functionNameRoot + "("
337                                          + testValues[idx0] + ", "
338                                          + testValues[idx1] + ") was "
339                                          + setResult + " instead of NaN");
340                    result = false;
341                }
342                var getResult = date["get" + functionNameRoot]();
343                if (!isNaN(getResult)) {
344                    testFailed("date.get" + functionNameRoot + "() was "
345                                          + getResult + " instead of NaN");
346                    result = false;
347                }
348            }
349
350    if (result)
351        testPassed("date.set" + functionNameRoot + "(arg0, arg1)");
352    return result;
353}
354
355function testDateFunctionWithValueExpectingNaN3(functionNameRoot)
356{
357    var result = true;
358    for (var idx0 in testValues)
359        for (var idx1 in testValues)
360            for (var idx2 in testValues)
361                if (idx0 != 0 || idx1 != 0 || idx2 != 0) {
362                    var date = new Date();
363                    var setResult = date["set" + functionNameRoot](testValues[idx0],
364                                                                   testValues[idx1],
365                                                                   testValues[idx2]);
366                    if (!isNaN(setResult)) {
367                        testFailed("date.set" + functionNameRoot + "("
368                                              + testValues[idx0] + ", "
369                                              + testValues[idx1] + ", "
370                                              + testValues[idx2] + ") was "
371                                              + setResult + " instead of NaN");
372                        result = false;
373                    }
374                    var getResult = date["get" + functionNameRoot]();
375                    if (!isNaN(getResult)) {
376                        testFailed("date.get" + functionNameRoot + "() was "
377                                              + getResult + " instead of NaN");
378                        result = false;
379                    }
380                }
381
382    if (result)
383        testPassed("date.set" + functionNameRoot + "(arg0, arg1, arg2)");
384    return result;
385}
386
387function testDateFunctionWithValueExpectingNaN4(functionNameRoot)
388{
389    var result = true;
390    for (var idx0 in testValues)
391        for (var idx1 in testValues)
392            for (var idx2 in testValues)
393                for (var idx3 in testValues)
394                    if (idx0 != 0 || idx1 != 0 || idx2 != 0 || idx3 != 0) {
395                        var date = new Date();
396                        var setResult = date["set" + functionNameRoot](testValues[idx0],
397                                                                       testValues[idx1],
398                                                                       testValues[idx2],
399                                                                       testValues[idx3]);
400                        if (!isNaN(setResult)) {
401                            testFailed("date.set" + functionNameRoot + "("
402                                                  + testValues[idx0] + ", "
403                                                  + testValues[idx1] + ", "
404                                                  + testValues[idx2] + ", "
405                                                  + testValues[idx3] + ") was "
406                                                  + setResult + " instead of NaN");
407                            result = false;
408                        }
409                        var getResult = date["get" + functionNameRoot]();
410                        if (!isNaN(getResult)) {
411                            testFailed("date.get" + functionNameRoot + "() was "
412                                                  + getResult + " instead of NaN");
413                            result = false;
414                        }
415                    }
416    if (result)
417        testPassed("date.set" + functionNameRoot + "(arg0, arg1, arg2, arg3)");
418    return result;
419}
420
421
422
423function testDateFunction(functionNameRoot, functionParamNum)
424{
425    var success = true;
426
427    switch (functionParamNum) {
428    case 4:
429        success &= testDateFunctionWithValueExpectingNaN4(functionNameRoot);
430        if (functionNameRoot != "Time" &&
431            functionNameRoot != "FullYear" &&
432            functionNameRoot != "UTCFullYear" &&
433            functionNameRoot != "Year")
434            success &= testDateFunctionWithValueNoRecoverNaN(functionNameRoot, 4);
435
436    case 3:
437        success &= testDateFunctionWithValueExpectingNaN3(functionNameRoot);
438        if (functionNameRoot != "Time" &&
439            functionNameRoot != "FullYear" &&
440            functionNameRoot != "UTCFullYear" &&
441            functionNameRoot != "Year")
442            success &= testDateFunctionWithValueNoRecoverNaN(functionNameRoot, 3);
443
444    case 2:
445        success &= testDateFunctionWithValueExpectingNaN2(functionNameRoot);
446        if (functionNameRoot != "Time" &&
447            functionNameRoot != "FullYear" &&
448            functionNameRoot != "UTCFullYear" &&
449            functionNameRoot != "Year")
450            success &= testDateFunctionWithValueNoRecoverNaN(functionNameRoot, 2);
451
452    case 1:
453        success &= testDateFunctionWithValueExpectingNaN1(functionNameRoot);
454        if (functionNameRoot == "Time")
455            success &= testDateFunctionWithValueRecoverTime(functionNameRoot);
456        else if (functionNameRoot == "FullYear")
457            success &= testDateFunctionWithValueRecoverFullYear(functionNameRoot);
458        else if (functionNameRoot == "UTCFullYear")
459            success &= testDateFunctionWithValueRecoverUTCFullYear(functionNameRoot);
460        else if (functionNameRoot == "Year")
461            success &= testDateFunctionWithValueRecoverYear(functionNameRoot);
462        else
463            success &= testDateFunctionWithValueNoRecoverNaN(functionNameRoot, 1);
464    }
465
466    if (success)
467        testPassed("date.set" + functionNameRoot + " passed all tests");
468}
469
470for (var x in dateFunctionNameRoots)
471{
472    testDateFunction(dateFunctionNameRoots[x], dateFunctionParameterNum[x]);
473}
474