LCOV - code coverage report
Current view: directory - js/src/jsapi-tests - testParseJSON.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 140 138 98.6 %
Date: 2012-06-02 Functions: 56 52 92.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99:
       3                 :  */
       4                 : 
       5                 : #include <limits>
       6                 : #include <math.h>
       7                 : 
       8                 : #include "tests.h"
       9                 : #include "jsstr.h"
      10                 : #include "vm/String.h"
      11                 : 
      12                 : using namespace js;
      13                 : 
      14                 : class AutoInflatedString {
      15                 :     JSContext * const cx;
      16                 :     jschar *chars_;
      17                 :     size_t length_;
      18                 : 
      19                 :   public:
      20              38 :     AutoInflatedString(JSContext *cx) : cx(cx), chars_(NULL), length_(0) { }
      21              38 :     ~AutoInflatedString() {
      22              38 :         JS_free(cx, chars_);
      23              38 :     }
      24                 : 
      25              38 :     template<size_t N> void operator=(const char (&str)[N]) {
      26              38 :         length_ = N - 1;
      27              38 :         chars_ = InflateString(cx, str, &length_);
      28              38 :         if (!chars_)
      29               0 :             abort();
      30              38 :     }
      31                 : 
      32              38 :     const jschar *chars() const { return chars_; }
      33              38 :     size_t length() const { return length_; }
      34                 : };
      35                 : 
      36                 : template<size_t N> JSFlatString *
      37               3 : NewString(JSContext *cx, const jschar (&chars)[N])
      38                 : {
      39               3 :     return js_NewStringCopyN(cx, chars, N);
      40                 : }
      41                 : 
      42               4 : BEGIN_TEST(testParseJSON_success)
      43                 : {
      44                 :     // Primitives
      45               1 :     CHECK(TryParse(cx, "true", JSVAL_TRUE));
      46               1 :     CHECK(TryParse(cx, "false", JSVAL_FALSE));
      47               1 :     CHECK(TryParse(cx, "null", JSVAL_NULL));
      48               1 :     CHECK(TryParse(cx, "0", INT_TO_JSVAL(0)));
      49               1 :     CHECK(TryParse(cx, "1", INT_TO_JSVAL(1)));
      50               1 :     CHECK(TryParse(cx, "-1", INT_TO_JSVAL(-1)));
      51               1 :     CHECK(TryParse(cx, "1", DOUBLE_TO_JSVAL(1)));
      52               1 :     CHECK(TryParse(cx, "1.75", DOUBLE_TO_JSVAL(1.75)));
      53               1 :     CHECK(TryParse(cx, "9e9", DOUBLE_TO_JSVAL(9e9)));
      54               1 :     CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity())));
      55                 : 
      56                 :     JSFlatString *str;
      57                 : 
      58               1 :     const jschar emptystr[] = { '\0' };
      59               1 :     str = js_NewStringCopyN(cx, emptystr, 0);
      60               1 :     CHECK(str);
      61               1 :     CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
      62                 : 
      63               1 :     const jschar nullstr[] = { '\0' };
      64               1 :     str = NewString(cx, nullstr);
      65               1 :     CHECK(str);
      66               1 :     CHECK(TryParse(cx, "\"\\u0000\"", STRING_TO_JSVAL(str)));
      67                 : 
      68               1 :     const jschar backstr[] = { '\b' };
      69               1 :     str = NewString(cx, backstr);
      70               1 :     CHECK(str);
      71               1 :     CHECK(TryParse(cx, "\"\\b\"", STRING_TO_JSVAL(str)));
      72               1 :     CHECK(TryParse(cx, "\"\\u0008\"", STRING_TO_JSVAL(str)));
      73                 : 
      74               1 :     const jschar newlinestr[] = { '\n', };
      75               1 :     str = NewString(cx, newlinestr);
      76               1 :     CHECK(str);
      77               1 :     CHECK(TryParse(cx, "\"\\n\"", STRING_TO_JSVAL(str)));
      78               1 :     CHECK(TryParse(cx, "\"\\u000A\"", STRING_TO_JSVAL(str)));
      79                 : 
      80                 : 
      81                 :     // Arrays
      82                 :     jsval v, v2;
      83                 :     JSObject *obj;
      84                 : 
      85               1 :     CHECK(Parse(cx, "[]", &v));
      86               1 :     CHECK(!JSVAL_IS_PRIMITIVE(v));
      87               1 :     obj = JSVAL_TO_OBJECT(v);
      88               1 :     CHECK(JS_IsArrayObject(cx, obj));
      89               1 :     CHECK(JS_GetProperty(cx, obj, "length", &v2));
      90               1 :     CHECK_SAME(v2, JSVAL_ZERO);
      91                 : 
      92               1 :     CHECK(Parse(cx, "[1]", &v));
      93               1 :     CHECK(!JSVAL_IS_PRIMITIVE(v));
      94               1 :     obj = JSVAL_TO_OBJECT(v);
      95               1 :     CHECK(JS_IsArrayObject(cx, obj));
      96               1 :     CHECK(JS_GetProperty(cx, obj, "0", &v2));
      97               1 :     CHECK_SAME(v2, JSVAL_ONE);
      98               1 :     CHECK(JS_GetProperty(cx, obj, "length", &v2));
      99               1 :     CHECK_SAME(v2, JSVAL_ONE);
     100                 : 
     101                 : 
     102                 :     // Objects
     103               1 :     CHECK(Parse(cx, "{}", &v));
     104               1 :     CHECK(!JSVAL_IS_PRIMITIVE(v));
     105               1 :     obj = JSVAL_TO_OBJECT(v);
     106               1 :     CHECK(!JS_IsArrayObject(cx, obj));
     107                 : 
     108               1 :     CHECK(Parse(cx, "{ \"f\": 17 }", &v));
     109               1 :     CHECK(!JSVAL_IS_PRIMITIVE(v));
     110               1 :     obj = JSVAL_TO_OBJECT(v);
     111               1 :     CHECK(!JS_IsArrayObject(cx, obj));
     112               1 :     CHECK(JS_GetProperty(cx, obj, "f", &v2));
     113               1 :     CHECK_SAME(v2, INT_TO_JSVAL(17));
     114                 : 
     115               1 :     return true;
     116                 : }
     117                 : 
     118                 : template<size_t N> inline bool
     119               4 : Parse(JSContext *cx, const char (&input)[N], jsval *vp)
     120                 : {
     121               8 :     AutoInflatedString str(cx);
     122               4 :     str = input;
     123               4 :     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), vp));
     124               4 :     return true;
     125                 : }
     126                 : 
     127                 : template<size_t N> inline bool
     128              16 : TryParse(JSContext *cx, const char (&input)[N], const jsval &expected)
     129                 : {
     130              32 :     AutoInflatedString str(cx);
     131                 :     jsval v;
     132              16 :     str = input;
     133              16 :     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), &v));
     134              16 :     CHECK_SAME(v, expected);
     135              16 :     return true;
     136                 : }
     137               1 : END_TEST(testParseJSON_success)
     138                 : 
     139               4 : BEGIN_TEST(testParseJSON_error)
     140                 : {
     141               1 :     CHECK(Error(cx, "["));
     142               1 :     CHECK(Error(cx, "[,]"));
     143               1 :     CHECK(Error(cx, "[1,]"));
     144               1 :     CHECK(Error(cx, "{a:2}"));
     145               1 :     CHECK(Error(cx, "{\"a\":2,}"));
     146               1 :     CHECK(Error(cx, "]"));
     147               1 :     CHECK(Error(cx, "'bad string'"));
     148               1 :     CHECK(Error(cx, "\""));
     149               1 :     CHECK(Error(cx, "{]"));
     150               1 :     CHECK(Error(cx, "[}"));
     151               1 :     return true;
     152                 : }
     153                 : 
     154                 : template<size_t N> inline bool
     155              10 : Error(JSContext *cx, const char (&input)[N])
     156                 : {
     157              20 :     AutoInflatedString str(cx);
     158                 :     jsval dummy;
     159              10 :     str = input;
     160                 : 
     161              10 :     ContextPrivate p = {0, 0};
     162              10 :     CHECK(!JS_GetContextPrivate(cx));
     163              10 :     JS_SetContextPrivate(cx, &p);
     164              10 :     JSErrorReporter old = JS_SetErrorReporter(cx, reportJSONEror);
     165              10 :     JSBool ok = JS_ParseJSON(cx, str.chars(), str.length(), &dummy);
     166              10 :     JS_SetErrorReporter(cx, old);
     167              10 :     JS_SetContextPrivate(cx, NULL);
     168                 : 
     169              10 :     CHECK(!ok);
     170              10 :     CHECK(!p.unexpectedErrorCount);
     171              10 :     CHECK(p.expectedErrorCount == 1);
     172                 : 
     173                 :     /* We do not execute JS, so there should be no exception thrown. */
     174              10 :     CHECK(!JS_IsExceptionPending(cx));
     175                 : 
     176              10 :     return true;
     177                 : }
     178                 : 
     179                 : struct ContextPrivate {
     180                 :     unsigned unexpectedErrorCount;
     181                 :     unsigned expectedErrorCount;
     182                 : };
     183                 : 
     184                 : static void
     185              10 : reportJSONEror(JSContext *cx, const char *message, JSErrorReport *report)
     186                 : {
     187              10 :     ContextPrivate *p = static_cast<ContextPrivate *>(JS_GetContextPrivate(cx));
     188              10 :     if (report->errorNumber == JSMSG_JSON_BAD_PARSE)
     189              10 :         p->expectedErrorCount++;
     190                 :     else
     191               0 :         p->unexpectedErrorCount++;
     192              10 : }
     193                 : 
     194               1 : END_TEST(testParseJSON_error)
     195                 : 
     196                 : static JSBool
     197               9 : Censor(JSContext *cx, unsigned argc, jsval *vp)
     198                 : {
     199               9 :     JS_ASSERT(argc == 2);
     200                 : #ifdef DEBUG
     201               9 :     jsval *argv = JS_ARGV(cx, vp);
     202               9 :     JS_ASSERT(JSVAL_IS_STRING(argv[0]));
     203                 : #endif
     204               9 :     JS_SET_RVAL(cx, vp, JSVAL_NULL);
     205               9 :     return true;
     206                 : }
     207                 : 
     208               4 : BEGIN_TEST(testParseJSON_reviver)
     209                 : {
     210               1 :     JSFunction *fun = JS_NewFunction(cx, Censor, 0, 0, global, "censor");
     211               1 :     CHECK(fun);
     212                 : 
     213               1 :     jsval filter = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun));
     214                 : 
     215               1 :     CHECK(TryParse(cx, "true", filter));
     216               1 :     CHECK(TryParse(cx, "false", filter));
     217               1 :     CHECK(TryParse(cx, "null", filter));
     218               1 :     CHECK(TryParse(cx, "1", filter));
     219               1 :     CHECK(TryParse(cx, "1.75", filter));
     220               1 :     CHECK(TryParse(cx, "[]", filter));
     221               1 :     CHECK(TryParse(cx, "[1]", filter));
     222               1 :     CHECK(TryParse(cx, "{}", filter));
     223               1 :     return true;
     224                 : }
     225                 : 
     226                 : template<size_t N> inline bool
     227               8 : TryParse(JSContext *cx, const char (&input)[N], jsval filter)
     228                 : {
     229              16 :     AutoInflatedString str(cx);
     230                 :     jsval v;
     231               8 :     str = input;
     232               8 :     CHECK(JS_ParseJSONWithReviver(cx, str.chars(), str.length(), filter, &v));
     233               8 :     CHECK_SAME(v, JSVAL_NULL);
     234               8 :     return true;
     235                 : }
     236               3 : END_TEST(testParseJSON_reviver)

Generated by: LCOV version 1.7