tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    42 
    42 
    43 #include <QtTest/QtTest>
    43 #include <QtTest/QtTest>
    44 
    44 
    45 #include <QtScript/qscriptengineagent.h>
    45 #include <QtScript/qscriptengineagent.h>
    46 #include <QtScript/qscriptengine.h>
    46 #include <QtScript/qscriptengine.h>
       
    47 #include <QtScript/qscriptprogram.h>
    47 #include <qscriptvalueiterator.h>
    48 #include <qscriptvalueiterator.h>
    48 
    49 
    49 //TESTED_CLASS=
    50 //TESTED_CLASS=
    50 //TESTED_FILES=
    51 //TESTED_FILES=
    51 
    52 
    82     void functionEntryAndExit_functionCallWithoutReturn();
    83     void functionEntryAndExit_functionCallWithoutReturn();
    83     void functionEntryAndExit_functionDefinition();
    84     void functionEntryAndExit_functionDefinition();
    84     void functionEntryAndExit_native();
    85     void functionEntryAndExit_native();
    85     void functionEntryAndExit_native2();
    86     void functionEntryAndExit_native2();
    86     void functionEntryAndExit_nativeThrowing();
    87     void functionEntryAndExit_nativeThrowing();
       
    88     void functionEntryAndExit_builtin_data();
    87     void functionEntryAndExit_builtin();
    89     void functionEntryAndExit_builtin();
    88     void functionEntryAndExit_objects();
    90     void functionEntryAndExit_objects();
    89     void functionEntryAndExit_slots();
    91     void functionEntryAndExit_slots();
    90     void functionEntryAndExit_property_set();
    92     void functionEntryAndExit_property_set();
    91     void functionEntryAndExit_property_get();
    93     void functionEntryAndExit_property_get();
   108     void syntaxError();
   110     void syntaxError();
   109     void extension_invoctaion();
   111     void extension_invoctaion();
   110     void extension();
   112     void extension();
   111     void isEvaluatingInExtension();
   113     void isEvaluatingInExtension();
   112     void hasUncaughtException();
   114     void hasUncaughtException();
       
   115     void evaluateProgram();
       
   116     void evaluateProgram_SyntaxError();
       
   117     void evaluateNullProgram();
       
   118     void QTBUG6108();
   113 
   119 
   114 private:
   120 private:
   115     double m_testProperty;
   121     double m_testProperty;
   116 };
   122 };
   117 
   123 
   469                                                        | ScriptEngineSpy::IgnoreScriptUnload));
   475                                                        | ScriptEngineSpy::IgnoreScriptUnload));
   470     {
   476     {
   471         spy->clear();
   477         spy->clear();
   472         eng.evaluate("eval('function foo() { print(123); }')");
   478         eng.evaluate("eval('function foo() { print(123); }')");
   473 
   479 
   474         QEXPECT_FAIL("","Eval is threaded in different way that in old backend", Abort);
   480         QEXPECT_FAIL("","QTBUG-6140 Eval is threaded in different way that in old backend", Abort);
   475         QCOMPARE(spy->count(), 3);
   481         QCOMPARE(spy->count(), 3);
   476 
   482 
   477         QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad);
   483         QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad);
   478         QVERIFY(spy->at(0).scriptId != -1);
   484         QVERIFY(spy->at(0).scriptId != -1);
   479 
   485 
   804         QVERIFY(spy->at(5).value.isError());
   810         QVERIFY(spy->at(5).value.isError());
   805     }
   811     }
   806     delete spy;
   812     delete spy;
   807 }
   813 }
   808 
   814 
       
   815 void tst_QScriptEngineAgent::functionEntryAndExit_builtin_data()
       
   816 {
       
   817   QTest::addColumn<QString>("script");
       
   818   QTest::addColumn<QString>("result");
       
   819 
       
   820   QTest::newRow("string native") << "'ciao'.toString()" << "ciao";
       
   821   QTest::newRow("string object") << "String('ciao').toString()" << "ciao";
       
   822   QTest::newRow("number native") << "(123).toString()" << "123";
       
   823   QTest::newRow("number object") << "Number(123).toString()" << "123";
       
   824   QTest::newRow("array native") << "['s','a'].toString()" << "s, a";
       
   825   QTest::newRow("array object") << "Array('s', 'a').toString()" << "s,a";
       
   826   QTest::newRow("boolean native") << "false.toString()" << "false";
       
   827   QTest::newRow("boolean object") << "Boolean(true).toString()" << "true";
       
   828   QTest::newRow("regexp native") << "/a/.toString()" << "/a/";
       
   829   QTest::newRow("regexp object") << "RegExp('a').toString()" << "/a/";
       
   830 }
       
   831 
   809 /** check behaiviour of built-in function */
   832 /** check behaiviour of built-in function */
   810 void tst_QScriptEngineAgent::functionEntryAndExit_builtin()
   833 void tst_QScriptEngineAgent::functionEntryAndExit_builtin()
   811 {
   834 {
       
   835     QFETCH(QString, script);
       
   836     QFETCH(QString, result);
   812     QScriptEngine eng;
   837     QScriptEngine eng;
   813     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng, ~(ScriptEngineSpy::IgnoreFunctionEntry
   838     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng, ~(ScriptEngineSpy::IgnoreFunctionEntry
   814                                                        | ScriptEngineSpy::IgnoreFunctionExit));
   839                                                        | ScriptEngineSpy::IgnoreFunctionExit));
   815     {
   840     {
   816         spy->clear();
   841         spy->clear();
   817         eng.evaluate("'ciao'.toString()");
   842         eng.evaluate(script);
   818 
   843 
   819         if (qt_script_isJITEnabled())
   844         if (qt_script_isJITEnabled()) {
   820             QEXPECT_FAIL("", "Some events are missing when JIT is enabled", Abort);
   845             QEXPECT_FAIL("string native", "QTBUG-6187 Some events are missing when JIT is enabled", Abort);
       
   846             QEXPECT_FAIL("number native", "QTBUG-6187 Some events are missing when JIT is enabled", Abort);
       
   847             QEXPECT_FAIL("array native", "QTBUG-6187 Some events are missing when JIT is enabled", Abort);
       
   848             QEXPECT_FAIL("boolean native", "QTBUG-6187 Some events are missing when JIT is enabled", Abort);
       
   849             QEXPECT_FAIL("regexp native", "QTBUG-6187 Some events are missing when JIT is enabled", Abort);
       
   850         }
   821         QCOMPARE(spy->count(), 4);
   851         QCOMPARE(spy->count(), 4);
   822 
   852 
   823         // evaluate() entry
   853         // evaluate() entry
   824         QCOMPARE(spy->at(0).type, ScriptEngineEvent::FunctionEntry);
   854         QCOMPARE(spy->at(0).type, ScriptEngineEvent::FunctionEntry);
   825 
   855 
   828         QCOMPARE(spy->at(1).scriptId, qint64(-1));
   858         QCOMPARE(spy->at(1).scriptId, qint64(-1));
   829 
   859 
   830         // built-in native function exit
   860         // built-in native function exit
   831         QCOMPARE(spy->at(2).type, ScriptEngineEvent::FunctionExit);
   861         QCOMPARE(spy->at(2).type, ScriptEngineEvent::FunctionExit);
   832         QCOMPARE(spy->at(2).scriptId, qint64(-1));
   862         QCOMPARE(spy->at(2).scriptId, qint64(-1));
   833         QVERIFY(spy->at(2).value.isString());
   863         QCOMPARE(spy->at(2).value.toString(), QString(result));
   834         QCOMPARE(spy->at(2).value.toString(), QString("ciao"));
       
   835 
   864 
   836         // evaluate() exit
   865         // evaluate() exit
   837         QCOMPARE(spy->at(3).type, ScriptEngineEvent::FunctionExit);
   866         QCOMPARE(spy->at(3).type, ScriptEngineEvent::FunctionExit);
   838         QCOMPARE(spy->at(3).scriptId, spy->at(0).scriptId);
   867         QCOMPARE(spy->at(3).scriptId, spy->at(0).scriptId);
   839         QVERIFY(spy->at(3).value.isString());
   868         QVERIFY(spy->at(3).value.isString());
   840         QCOMPARE(spy->at(3).value.toString(), QString("ciao"));
   869         QCOMPARE(spy->at(3).value.toString(), QString(result));
   841     }
   870     }
   842     delete spy;
   871     delete spy;
   843 }
   872 }
   844 
   873 
   845 /** check behaiviour of object creation*/
   874 /** check behaiviour of object creation*/
  1154     QScriptEngine eng;
  1183     QScriptEngine eng;
  1155     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng, ~(ScriptEngineSpy::IgnorePositionChange));
  1184     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng, ~(ScriptEngineSpy::IgnorePositionChange));
  1156     {
  1185     {
  1157         spy->clear();
  1186         spy->clear();
  1158         eng.evaluate(";");
  1187         eng.evaluate(";");
  1159         QEXPECT_FAIL("","JSC do not evaluate ';' to statemant",Continue);
  1188         QEXPECT_FAIL("","QTBUG-6142 JSC do not evaluate ';' to statemant",Continue);
  1160         QCOMPARE(spy->count(), 1);
  1189         QCOMPARE(spy->count(), 1);
  1161         if (spy->count()) {
  1190         if (spy->count()) {
  1162             QEXPECT_FAIL("","JSC do not evaluate ';' to statemant",Continue);
  1191             QEXPECT_FAIL("","QTBUG-6142 JSC do not evaluate ';' to statemant",Continue);
  1163             QCOMPARE(spy->at(0).type, ScriptEngineEvent::PositionChange);
  1192             QCOMPARE(spy->at(0).type, ScriptEngineEvent::PositionChange);
  1164             QEXPECT_FAIL("","JSC do not evaluate ';' to statemant",Continue);
  1193             QEXPECT_FAIL("","QTBUG-6142 JSC do not evaluate ';' to statemant",Continue);
  1165             QVERIFY(spy->at(0).scriptId != -1);
  1194             QVERIFY(spy->at(0).scriptId != -1);
  1166             QEXPECT_FAIL("","JSC do not evaluate ';' to statemant",Continue);
  1195             QEXPECT_FAIL("","QTBUG-6142 JSC do not evaluate ';' to statemant",Continue);
  1167             QCOMPARE(spy->at(0).lineNumber, 1);
  1196             QCOMPARE(spy->at(0).lineNumber, 1);
  1168             QEXPECT_FAIL("","JSC do not evaluate ';' to statemant",Continue);
  1197             QEXPECT_FAIL("","QTBUG-6142 JSC do not evaluate ';' to statemant",Continue);
  1169             QCOMPARE(spy->at(0).columnNumber, 1);
  1198             QCOMPARE(spy->at(0).columnNumber, 1);
  1170         }
  1199         }
  1171     }
  1200     }
  1172 
  1201 
  1173     {
  1202     {
  1545         QCOMPARE(spy->at(1).lineNumber, 1);
  1574         QCOMPARE(spy->at(1).lineNumber, 1);
  1546         QCOMPARE(spy->at(1).columnNumber, 46);
  1575         QCOMPARE(spy->at(1).columnNumber, 46);
  1547     }
  1576     }
  1548 
  1577 
  1549     {
  1578     {
  1550         QEXPECT_FAIL("","I believe the test is wrong. Expressions shouldn't call positionChange "
  1579         QEXPECT_FAIL("","QTBUG-6142 I believe the test is wrong. Expressions shouldn't call positionChange "
  1551                      "because statement '1+2' will call it at least twice, why debugger have to "
  1580                      "because statement '1+2' will call it at least twice, why debugger have to "
  1552                      "stop here so many times?", Abort);
  1581                      "stop here so many times?", Abort);
  1553         spy->clear();
  1582         spy->clear();
  1554         eng.evaluate("c = {a: 10, b: 20}");
  1583         eng.evaluate("c = {a: 10, b: 20}");
  1555         QCOMPARE(spy->count(), 2);
  1584         QCOMPARE(spy->count(), 2);
  2082 
  2111 
  2083         //create exception
  2112         //create exception
  2084 
  2113 
  2085         i = 2;
  2114         i = 2;
  2086         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ContextPush);
  2115         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ContextPush);
  2087         QEXPECT_FAIL("","The test is broken, contextPush event do not provide scriptId", Continue);
       
  2088         QVERIFY(spy->at(i).scriptId == -1);
       
  2089         i = 3;
  2116         i = 3;
  2090         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionEntry);
  2117         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionEntry);
  2091         QVERIFY(spy->at(i).scriptId == -1);
  2118         QVERIFY(spy->at(i).scriptId == -1);
  2092         i = 4;
  2119         i = 4;
  2093         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionExit);
  2120         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionExit);
  2094         QVERIFY(spy->at(i).scriptId == -1);
  2121         QVERIFY(spy->at(i).scriptId == -1);
  2095         i = 5;
  2122         i = 5;
  2096         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ContextPop);
  2123         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ContextPop);
  2097         QEXPECT_FAIL("","The test is broken, contextPop event do not provide scriptId", Continue);
       
  2098         QVERIFY(spy->at(i).scriptId == -1);
       
  2099         i = 6;
  2124         i = 6;
  2100         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ExceptionThrow);
  2125         QCOMPARE(spy->at(i).type, ScriptEngineEvent::ExceptionThrow);
  2101         QCOMPARE(spy->at(i).scriptId, spy->at(0).scriptId);
  2126         QCOMPARE(spy->at(i).scriptId, spy->at(0).scriptId);
  2102         QVERIFY(!spy->at(i).hasExceptionHandler);
  2127         QVERIFY(!spy->at(i).hasExceptionHandler);
  2103         QVERIFY(spy->at(i).value.isError());
  2128         QVERIFY(spy->at(i).value.isError());
  2104         QEXPECT_FAIL("","There are other messages in JSC",Continue);
  2129         QEXPECT_FAIL("","QTBUG-6137 There are other messages in JSC",Continue);
  2105         QCOMPARE(spy->at(i).value.toString(), QString("SyntaxError: Expected `}'"));
  2130         QCOMPARE(spy->at(i).value.toString(), QString("SyntaxError: Expected `}'"));
  2106         QCOMPARE(spy->at(i).scriptId, spy->at(0).scriptId);
  2131         QCOMPARE(spy->at(i).scriptId, spy->at(0).scriptId);
  2107         i = 7;
  2132         i = 7;
  2108         //exit script
  2133         //exit script
  2109         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionExit);
  2134         QCOMPARE(spy->at(i).type, ScriptEngineEvent::FunctionExit);
  2132         QCOMPARE(spy->at(1).type, ScriptEngineEvent::DebuggerInvocationRequest);
  2157         QCOMPARE(spy->at(1).type, ScriptEngineEvent::DebuggerInvocationRequest);
  2133         QCOMPARE(spy->at(1).scriptId, spy->at(0).scriptId);
  2158         QCOMPARE(spy->at(1).scriptId, spy->at(0).scriptId);
  2134         QCOMPARE(spy->at(1).lineNumber, lineNumber);
  2159         QCOMPARE(spy->at(1).lineNumber, lineNumber);
  2135         QCOMPARE(spy->at(1).columnNumber, 1);
  2160         QCOMPARE(spy->at(1).columnNumber, 1);
  2136 
  2161 
  2137         QEXPECT_FAIL("","In JSC Eval('debugger') returns undefined",Abort);
  2162         QEXPECT_FAIL("","QTBUG-6135 In JSC Eval('debugger') returns undefined",Abort);
  2138         QVERIFY(ret.isString());
  2163         QVERIFY(ret.isString());
  2139         QCOMPARE(ret.toString(), QString::fromLatin1("extension(DebuggerInvocationRequest)"));
  2164         QCOMPARE(ret.toString(), QString::fromLatin1("extension(DebuggerInvocationRequest)"));
  2140     }
  2165     }
  2141     delete spy;
  2166     delete spy;
  2142 }
  2167 }
  2217   scriptValue = QScriptValue(eng.globalObject().property("foo")).call();
  2242   scriptValue = QScriptValue(eng.globalObject().property("foo")).call();
  2218   QVERIFY(!eng.hasUncaughtException());
  2243   QVERIFY(!eng.hasUncaughtException());
  2219   QVERIFY2(spy->isPass(), "At least one of a functionExit event should set hasUncaughtException flag.");
  2244   QVERIFY2(spy->isPass(), "At least one of a functionExit event should set hasUncaughtException flag.");
  2220 }
  2245 }
  2221 
  2246 
       
  2247 void tst_QScriptEngineAgent::evaluateProgram()
       
  2248 {
       
  2249     QScriptEngine eng;
       
  2250     QScriptProgram program("1 + 2", "foo.js", 123);
       
  2251     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng);
       
  2252     qint64 scriptId = -1;
       
  2253     for (int x = 0; x < 10; ++x) {
       
  2254         spy->clear();
       
  2255         (void)eng.evaluate(program);
       
  2256         QCOMPARE(spy->count(), (x == 0) ? 4 : 3);
       
  2257 
       
  2258         if (x == 0) {
       
  2259             // script is only loaded on first execution
       
  2260             QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad);
       
  2261             scriptId = spy->at(0).scriptId;
       
  2262             QVERIFY(scriptId != -1);
       
  2263             QCOMPARE(spy->at(0).script, program.sourceCode());
       
  2264             QCOMPARE(spy->at(0).fileName, program.fileName());
       
  2265             QCOMPARE(spy->at(0).lineNumber, program.firstLineNumber());
       
  2266             spy->removeFirst();
       
  2267         }
       
  2268 
       
  2269         QCOMPARE(spy->at(0).type, ScriptEngineEvent::FunctionEntry); // evaluate()
       
  2270         QCOMPARE(spy->at(0).scriptId, scriptId);
       
  2271 
       
  2272         QCOMPARE(spy->at(1).type, ScriptEngineEvent::PositionChange);
       
  2273         QCOMPARE(spy->at(1).scriptId, scriptId);
       
  2274         QCOMPARE(spy->at(1).lineNumber, program.firstLineNumber());
       
  2275 
       
  2276         QCOMPARE(spy->at(2).type, ScriptEngineEvent::FunctionExit); // evaluate()
       
  2277         QCOMPARE(spy->at(2).scriptId, scriptId);
       
  2278         QVERIFY(spy->at(2).value.isNumber());
       
  2279         QCOMPARE(spy->at(2).value.toNumber(), qsreal(3));
       
  2280     }
       
  2281 }
       
  2282 
       
  2283 void tst_QScriptEngineAgent::evaluateProgram_SyntaxError()
       
  2284 {
       
  2285     QScriptEngine eng;
       
  2286     QScriptProgram program("this is not valid syntax", "foo.js", 123);
       
  2287     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng);
       
  2288     qint64 scriptId = -1;
       
  2289     for (int x = 0; x < 10; ++x) {
       
  2290         spy->clear();
       
  2291         (void)eng.evaluate(program);
       
  2292         QCOMPARE(spy->count(), (x == 0) ? 8 : 7);
       
  2293 
       
  2294         if (x == 0) {
       
  2295             // script is only loaded on first execution
       
  2296             QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad);
       
  2297             scriptId = spy->at(0).scriptId;
       
  2298             QVERIFY(scriptId != -1);
       
  2299             QCOMPARE(spy->at(0).script, program.sourceCode());
       
  2300             QCOMPARE(spy->at(0).fileName, program.fileName());
       
  2301             QCOMPARE(spy->at(0).lineNumber, program.firstLineNumber());
       
  2302             spy->removeFirst();
       
  2303         }
       
  2304 
       
  2305         QCOMPARE(spy->at(0).type, ScriptEngineEvent::FunctionEntry); // evaluate()
       
  2306         QCOMPARE(spy->at(0).scriptId, scriptId);
       
  2307 
       
  2308         QCOMPARE(spy->at(1).type, ScriptEngineEvent::ContextPush); // SyntaxError constructor
       
  2309         QCOMPARE(spy->at(2).type, ScriptEngineEvent::FunctionEntry); // SyntaxError constructor
       
  2310         QCOMPARE(spy->at(3).type, ScriptEngineEvent::FunctionExit); // SyntaxError constructor
       
  2311         QCOMPARE(spy->at(4).type, ScriptEngineEvent::ContextPop); // SyntaxError constructor
       
  2312 
       
  2313         QCOMPARE(spy->at(5).type, ScriptEngineEvent::ExceptionThrow);
       
  2314         QVERIFY(spy->at(5).value.isError());
       
  2315         QCOMPARE(spy->at(5).value.toString(), QString::fromLatin1("SyntaxError: Parse error"));
       
  2316 
       
  2317         QCOMPARE(spy->at(6).type, ScriptEngineEvent::FunctionExit); // evaluate()
       
  2318         QCOMPARE(spy->at(6).scriptId, scriptId);
       
  2319     }
       
  2320 }
       
  2321 
       
  2322 void tst_QScriptEngineAgent::evaluateNullProgram()
       
  2323 {
       
  2324     QScriptEngine eng;
       
  2325     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng);
       
  2326     (void)eng.evaluate(QScriptProgram());
       
  2327     QCOMPARE(spy->count(), 0);
       
  2328 }
       
  2329 
       
  2330 void tst_QScriptEngineAgent::QTBUG6108()
       
  2331 {
       
  2332     QScriptEngine eng;
       
  2333     ScriptEngineSpy *spy = new ScriptEngineSpy(&eng);
       
  2334     eng.evaluate("eval('a = 1')");
       
  2335     QCOMPARE(spy->count(), 5);
       
  2336 
       
  2337     QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad);
       
  2338     QVERIFY(spy->at(0).scriptId != -1);
       
  2339 
       
  2340     QCOMPARE(spy->at(1).type, ScriptEngineEvent::FunctionEntry);
       
  2341     QVERIFY(spy->at(1).scriptId != -1);
       
  2342     QCOMPARE(spy->at(1).scriptId, spy->at(0).scriptId);
       
  2343 
       
  2344     QCOMPARE(spy->at(2).type, ScriptEngineEvent::PositionChange);
       
  2345     QVERIFY(spy->at(2).scriptId != -1);
       
  2346     QCOMPARE(spy->at(2).scriptId, spy->at(0).scriptId);
       
  2347     QCOMPARE(spy->at(2).lineNumber, 1);
       
  2348 
       
  2349     QCOMPARE(spy->at(3).type, ScriptEngineEvent::FunctionExit);
       
  2350     QVERIFY(spy->at(3).scriptId != -1);
       
  2351     QCOMPARE(spy->at(3).scriptId, spy->at(0).scriptId);
       
  2352 
       
  2353     QCOMPARE(spy->at(4).type, ScriptEngineEvent::ScriptUnload);
       
  2354     QCOMPARE(spy->at(4).scriptId, spy->at(0).scriptId);
       
  2355 }
  2222 
  2356 
  2223 QTEST_MAIN(tst_QScriptEngineAgent)
  2357 QTEST_MAIN(tst_QScriptEngineAgent)
  2224 #include "tst_qscriptengineagent.moc"
  2358 #include "tst_qscriptengineagent.moc"