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