LCOV - app.info - js/src/jsapi-tests/testParseJSON.cpp

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-04-07 | 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