]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - qt/tests/qscriptengine/tst_qscriptengine.cpp
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / qt / tests / qscriptengine / tst_qscriptengine.cpp
index 37f3d11012d8dc9cd3c9aefdc2f0a4877db0d0cd..1ec9ad3f0c0979c6c756ff1ea183a375cb0e3f06 100644 (file)
@@ -18,6 +18,8 @@
 */
 
 #include "qscriptengine.h"
 */
 
 #include "qscriptengine.h"
+#include "qscriptprogram.h"
+#include "qscriptsyntaxcheckresult.h"
 #include "qscriptvalue.h"
 #include <QtTest/qtest.h>
 
 #include "qscriptvalue.h"
 #include <QtTest/qtest.h>
 
@@ -33,8 +35,15 @@ public slots:
     void cleanup() {}
 
 private slots:
     void cleanup() {}
 
 private slots:
+    void globalObject();
     void evaluate();
     void collectGarbage();
     void evaluate();
     void collectGarbage();
+    void reportAdditionalMemoryCost();
+    void nullValue();
+    void undefinedValue();
+    void evaluateProgram();
+    void checkSyntax_data();
+    void checkSyntax();
 };
 
 /* Evaluating a script that throw an unhandled exception should return an invalid value. */
 };
 
 /* Evaluating a script that throw an unhandled exception should return an invalid value. */
@@ -45,6 +54,17 @@ void tst_QScriptEngine::evaluate()
     QVERIFY2(engine.evaluate("ping").isValid(), "Script throwing an unhandled exception should return an exception value");
 }
 
     QVERIFY2(engine.evaluate("ping").isValid(), "Script throwing an unhandled exception should return an exception value");
 }
 
+void tst_QScriptEngine::globalObject()
+{
+    QScriptEngine engine;
+    QScriptValue global = engine.globalObject();
+    QScriptValue self = engine.evaluate("this");
+    QVERIFY(global.isObject());
+    QVERIFY(engine.globalObject().equals(engine.evaluate("this")));
+    QEXPECT_FAIL("", "strictlyEquals is broken - bug 36600 in bugs.webkit.org", Continue);
+    QVERIFY(engine.globalObject().strictlyEquals(self));
+}
+
 /* Test garbage collection, at least try to not crash. */
 void tst_QScriptEngine::collectGarbage()
 {
 /* Test garbage collection, at least try to not crash. */
 void tst_QScriptEngine::collectGarbage()
 {
@@ -54,5 +74,235 @@ void tst_QScriptEngine::collectGarbage()
     engine.collectGarbage();
     QCOMPARE(foo.call().toString(), QString::fromAscii("pong"));
 }
     engine.collectGarbage();
     QCOMPARE(foo.call().toString(), QString::fromAscii("pong"));
 }
+
+void tst_QScriptEngine::reportAdditionalMemoryCost()
+{
+    // There isn't any easy way to test the responsiveness of the GC;
+    // just try to call the function a few times with various sizes.
+    QScriptEngine eng;
+    for (int i = 0; i < 100; ++i) {
+        eng.reportAdditionalMemoryCost(0);
+        eng.reportAdditionalMemoryCost(10);
+        eng.reportAdditionalMemoryCost(1000);
+        eng.reportAdditionalMemoryCost(10000);
+        eng.reportAdditionalMemoryCost(100000);
+        eng.reportAdditionalMemoryCost(1000000);
+        eng.reportAdditionalMemoryCost(10000000);
+        eng.reportAdditionalMemoryCost(-1);
+        eng.reportAdditionalMemoryCost(-1000);
+        QScriptValue obj = eng.evaluate("new Object");
+        eng.collectGarbage();
+    }
+}
+
+void tst_QScriptEngine::nullValue()
+{
+    QScriptEngine engine;
+    QScriptValue value = engine.nullValue();
+    QVERIFY(value.isValid());
+    QVERIFY(value.isNull());
+}
+
+void tst_QScriptEngine::undefinedValue()
+{
+    QScriptEngine engine;
+    QScriptValue value = engine.undefinedValue();
+    QVERIFY(value.isValid());
+    QVERIFY(value.isUndefined());
+}
+
+void tst_QScriptEngine::evaluateProgram()
+{
+    QScriptEngine eng;
+    {
+        QString code("1 + 2");
+        QString fileName("hello.js");
+        int lineNumber = 123;
+        QScriptProgram program(code, fileName, lineNumber);
+        QVERIFY(!program.isNull());
+        QCOMPARE(program.sourceCode(), code);
+        QCOMPARE(program.fileName(), fileName);
+        QCOMPARE(program.firstLineNumber(), lineNumber);
+
+        QScriptValue expected = eng.evaluate(code);
+        for (int x = 0; x < 10; ++x) {
+            QScriptValue ret = eng.evaluate(program);
+            QVERIFY(ret.equals(expected));
+        }
+
+        // operator=
+        QScriptProgram sameProgram = program;
+        QVERIFY(sameProgram == program);
+        QVERIFY(eng.evaluate(sameProgram).equals(expected));
+
+        // copy constructor
+        QScriptProgram sameProgram2(program);
+        QVERIFY(sameProgram2 == program);
+        QVERIFY(eng.evaluate(sameProgram2).equals(expected));
+
+        QScriptProgram differentProgram("2 + 3");
+        QVERIFY(differentProgram != program);
+        QVERIFY(!eng.evaluate(differentProgram).equals(expected));
+    }
+
+    // Program that accesses variable in the scope
+    {
+        QScriptProgram program("a");
+        QVERIFY(!program.isNull());
+        {
+            QScriptValue ret = eng.evaluate(program);
+            QVERIFY(ret.isError());
+            QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: a"));
+        }
+        {
+            QScriptValue ret = eng.evaluate(program);
+            QVERIFY(ret.isError());
+        }
+        eng.evaluate("a = 456");
+        {
+            QScriptValue ret = eng.evaluate(program);
+            QVERIFY(!ret.isError());
+            QCOMPARE(ret.toNumber(), 456.0);
+        }
+    }
+
+    // Program that creates closure
+    {
+        QScriptProgram program("(function() { var count = 0; return function() { return count++; }; })");
+        QVERIFY(!program.isNull());
+        QScriptValue createCounter = eng.evaluate(program);
+        QVERIFY(createCounter.isFunction());
+        QScriptValue counter = createCounter.call();
+        QVERIFY(counter.isFunction());
+        {
+            QScriptValue ret = counter.call();
+            QVERIFY(ret.isNumber());
+        }
+        QScriptValue counter2 = createCounter.call();
+        QVERIFY(counter2.isFunction());
+        QVERIFY(!counter2.equals(counter));
+        {
+            QScriptValue ret = counter2.call();
+            QVERIFY(ret.isNumber());
+        }
+    }
+
+    // Same program run in different engines
+    {
+        QString code("1 + 2");
+        QScriptProgram program(code);
+        QVERIFY(!program.isNull());
+        double expected = eng.evaluate(program).toNumber();
+        for (int x = 0; x < 2; ++x) {
+            QScriptEngine eng2;
+            for (int y = 0; y < 2; ++y) {
+                double ret = eng2.evaluate(program).toNumber();
+                QCOMPARE(ret, expected);
+            }
+        }
+    }
+
+    // No program
+    {
+        QScriptProgram program;
+        QVERIFY(program.isNull());
+        QScriptValue ret = eng.evaluate(program);
+        QVERIFY(!ret.isValid());
+    }
+}
+
+void tst_QScriptEngine::checkSyntax_data()
+{
+    QTest::addColumn<QString>("code");
+    QTest::addColumn<int>("expectedState");
+    QTest::addColumn<int>("errorLineNumber");
+    QTest::addColumn<int>("errorColumnNumber");
+    QTest::addColumn<QString>("errorMessage");
+
+    QTest::newRow("0")
+        << QString("0") << int(QScriptSyntaxCheckResult::Valid)
+        << -1 << -1 << "";
+    QTest::newRow("if (")
+        << QString("if (\n") << int(QScriptSyntaxCheckResult::Intermediate)
+        << 1 << 4 << "";
+    QTest::newRow("if else")
+        << QString("\nif else") << int(QScriptSyntaxCheckResult::Error)
+        << 2 << 4 << "SyntaxError: Parse error";
+    QTest::newRow("{if}")
+            << QString("{\n{\nif\n}\n") << int(QScriptSyntaxCheckResult::Error)
+        << 4 << 1 << "SyntaxError: Parse error";
+    QTest::newRow("foo[")
+        << QString("foo[") << int(QScriptSyntaxCheckResult::Error)
+        << 1 << 4 << "SyntaxError: Parse error";
+    QTest::newRow("foo['bar']")
+        << QString("foo['bar']") << int(QScriptSyntaxCheckResult::Valid)
+        << -1 << -1 << "";
+
+    QTest::newRow("/*")
+        << QString("/*") << int(QScriptSyntaxCheckResult::Intermediate)
+        << 1 << 1 << "Unclosed comment at end of file";
+    QTest::newRow("/*\nMy comment")
+        << QString("/*\nMy comment") << int(QScriptSyntaxCheckResult::Intermediate)
+        << 1 << 1 << "Unclosed comment at end of file";
+    QTest::newRow("/*\nMy comment */\nfoo = 10")
+        << QString("/*\nMy comment */\nfoo = 10") << int(QScriptSyntaxCheckResult::Valid)
+        << -1 << -1 << "";
+    QTest::newRow("foo = 10 /*")
+        << QString("foo = 10 /*") << int(QScriptSyntaxCheckResult::Intermediate)
+        << -1 << -1 << "";
+    QTest::newRow("foo = 10; /*")
+        << QString("foo = 10; /*") << int(QScriptSyntaxCheckResult::Intermediate)
+        << 1 << 11 << "Expected `end of file'";
+    QTest::newRow("foo = 10 /* My comment */")
+        << QString("foo = 10 /* My comment */") << int(QScriptSyntaxCheckResult::Valid)
+        << -1 << -1 << "";
+
+    QTest::newRow("/=/")
+        << QString("/=/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+    QTest::newRow("/=/g")
+        << QString("/=/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+    QTest::newRow("/a/")
+        << QString("/a/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+    QTest::newRow("/a/g")
+        << QString("/a/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+}
+
+void tst_QScriptEngine::checkSyntax()
+{
+    QFETCH(QString, code);
+    QFETCH(int, expectedState);
+    QFETCH(int, errorLineNumber);
+    QFETCH(int, errorColumnNumber);
+    QFETCH(QString, errorMessage);
+
+    QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(code);
+
+    // assignment
+    {
+        QScriptSyntaxCheckResult copy = result;
+        QCOMPARE(copy.state(), result.state());
+        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
+        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
+        QCOMPARE(copy.errorMessage(), result.errorMessage());
+    }
+    {
+        QScriptSyntaxCheckResult copy(result);
+        QCOMPARE(copy.state(), result.state());
+        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
+        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
+        QCOMPARE(copy.errorMessage(), result.errorMessage());
+    }
+
+    if (expectedState == QScriptSyntaxCheckResult::Intermediate)
+        QEXPECT_FAIL("", "QScriptSyntaxCheckResult::state() doesn't return the Intermediate state", Abort);
+    QCOMPARE(result.state(), QScriptSyntaxCheckResult::State(expectedState));
+    QCOMPARE(result.errorLineNumber(), errorLineNumber);
+    if (expectedState != QScriptSyntaxCheckResult::Valid && errorColumnNumber != 1)
+            QEXPECT_FAIL("", "QScriptSyntaxCheckResult::errorColumnNumber() doesn't return correct value", Continue);
+    QCOMPARE(result.errorColumnNumber(), errorColumnNumber);
+    QCOMPARE(result.errorMessage(), errorMessage);
+}
+
+
 QTEST_MAIN(tst_QScriptEngine)
 #include "tst_qscriptengine.moc"
 QTEST_MAIN(tst_QScriptEngine)
 #include "tst_qscriptengine.moc"