1# JSAPI Test Suite
2
3The tests in this directory exercise the JSAPI.
4
5
6## Building and running the tests
7
8If you built JS, you already built the tests.
9
10The tests are built by default when you build JS. All the tests are compiled
11into a single binary named jsapi-tests. They all run in a single process.
12They must be run from the js/src directory.
13
14To run the tests:
15
16    $OBJDIR/dist/bin/jsapi-tests
17
18To run the tests in a debugger:
19
20    gdb $OBJDIR/dist/bin/jsapi-tests
21
22
23## Creating new tests
24
251.  You can either add to an existing test*.cpp file or make a new one.
26    Copy an existing test and replace the body with your test code.
27    The test harness provides `cx`, `rt`, and `global` for your use.
28
292.  If you made a new .cpp file, add it to the UNIFIED_SOURCES list
30    in moz.build.
31
32
33## Writing test code
34
35Here is a sample test:
36
37    #include "jsapi-tests/tests.h"
38
39    BEGIN_TEST(testIntString_bug515273)
40    {
41        RootedValue v(cx);
42
43        EVAL("'42';", &v);
44        JSString *str = v.toString();
45        CHECK(JS_StringHasBeenInterned(cx, str));
46        CHECK(JS_FlatStringEqualsLiteral(JS_ASSERT_STRING_IS_FLAT(str), "42"));
47        return true;
48    }
49    END_TEST(testIntString_bug515273)
50
51The BEGIN_TEST and END_TEST macros bracket each test. By convention, the test
52name is <testFilename>_<detail>. (The above test is in testIntString.cpp.)
53
54The curly braces are required. This block is the body of a C++ member function
55that returns bool. The test harness calls this member function
56automatically. If the function returns true, the test passes. False, it fails.
57
58JSAPI tests often need extra global C/C++ code: a JSClass, a getter or setter
59function, a resolve hook. Put these before the BEGIN_TEST macro.
60
61The body of the test can use these member variables and macros, defined in
62tests.h:
63
64    JSRuntime *rt;
65    JSContext *cx;
66    JSObject *global;
67
68        The test framework creates these fresh for each test. The default
69        environment has reasonable default settings, including
70        JSOPTION_VAROBJFIX, JSOPTION_JIT, a global object of a class with
71        JSCLASS_GLOBAL_FLAGS, and an error reporter that prints to stderr.
72        See also "Custom test setup" below.
73
74    EXEC(const char *code);
75
76        Execute some JS code in global scope, using JS::Evaluate. Return
77        false if that fails. (This means that if the code throws an uncaught JS
78        exception, the test fails.)
79
80    EVAL(const char *code, jsval *vp);
81
82        Same as EXEC, but store the result value in *vp.
83
84    CHECK(bool cond);
85
86        If the condition is not true, print an error message and return false,
87        failing the test.
88
89    CHECK_SAME(jsval a, jsval b);
90
91        If a and b are different values, print an error message and return
92        false, failing the test.
93
94        This is like CHECK(sameValue(a, b)) but with a more detailed error
95        message on failure. See sameValue below.
96
97    CHECK_EQUAL(const T &a, const U &b);
98
99        CHECK(a == b), but with a more detailed error message.
100
101    CHECK_NULL(const T *ptr);
102
103        CHECK(ptr == nullptr), but with a more detailed error message.
104
105        (This is here because CHECK_EQUAL(ptr, nullptr) fails to compile on GCC
106        2.5 and before.)
107
108
109    bool knownFail;
110
111        Set this to true if your test is known to fail. The test runner will
112        print a TEST-KNOWN-FAIL line rather than a TEST-UNEXPECTED-FAIL
113        line. This way you can check in a test illustrating a bug ahead of the
114        fix.
115
116        If your test actually crashes the process or triggers an assertion,
117        this of course will not help, so you should add something like
118
119            knownFail = true;  // see bug 123456
120            return false;  // the code below crashes!
121
122        as the first two lines of the test.
123
124    bool isNegativeZero(jsval v);
125    bool isNaN(jsval v);
126
127        Self-explanatory.
128
129    bool sameValue(jsval v1, jsval v2);
130
131        True if v1 and v2 are the same value according to the ES5 SameValue()
132        function, to wit:
133
134        SameValue(NaN, NaN) is true.
135        SameValue(-0, 0) is false.
136        Otherwise SameValue(a, b) iff a === b.
137
138
139## Custom test setup
140
141Before executing each test, the test framework calls the tests' init() member
142function, which populates the rt, cx, and global member variables.
143
144A test can customize the test setup process by overloading virtual member
145functions from the JSAPITest class, like this:
146
147    const JSClass globalClassWithResolve = { ... };
148
149    BEGIN_TEST(testGlobalResolveHook)
150        {
151            RootedValue v;
152            EVAL("v", v.address());
153            CHECK_SAME(v, JSVAL_VOID);
154            return true;
155        }
156
157        // Other class members can go here.
158
159        // This one overloads a base-class method.
160        virtual JSClass *getGlobalJSClass() {
161            return &globalClassWithResolve;
162        }
163    END_TEST(testGlobalResolveHook)
164
165The overloadable member functions are:
166
167    virtual bool init();
168    virtual void uninit();
169    virtual JSRuntime * createRuntime();
170    virtual JSContext * createContext();
171    virtual JSClass * getGlobalClass();
172    virtual JSObject * createGlobal();
173
174