mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 02:42:48 +00:00
279 lines
7.9 KiB
C++
279 lines
7.9 KiB
C++
/*
|
|
* This file is part of the KDE libraries
|
|
* Copyright (C) 2008 Harri Porten (porten@kde.org)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "kjsobject.h"
|
|
#include "kjsprototype.h"
|
|
#include "kjsarguments.h"
|
|
#include "kjsinterpreter.h"
|
|
|
|
#include "qtest_kde.h"
|
|
|
|
class KJSApiTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void objectConstruction();
|
|
void interpreterEvaluate();
|
|
void interpreterNormalizeCode();
|
|
void objectProperties();
|
|
void prototypeConstants();
|
|
void prototypeProperties();
|
|
void prototypeFunctions();
|
|
void globalObject();
|
|
};
|
|
|
|
void KJSApiTest::objectConstruction()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
|
|
// Object
|
|
QVERIFY2(KJSObject().isObject(), "Broken default object");
|
|
|
|
// undefined
|
|
QVERIFY2(KJSUndefined().isUndefined(),
|
|
"Undefined object is not undefined");
|
|
// null
|
|
QVERIFY2(KJSNull().isNull(),
|
|
"Null object is not null");
|
|
|
|
// Boolean
|
|
KJSBoolean boolObject(true);
|
|
QVERIFY2(boolObject.isBoolean(), "Boolean object is not of boolean type");
|
|
QVERIFY2(boolObject.toBoolean(ctx), "Boolean object has wrong value");
|
|
QVERIFY2(!ctx->hasException(), "Boolean conversion threw exception");
|
|
|
|
// Number
|
|
KJSNumber numObject(42.0);
|
|
QVERIFY2(numObject.isNumber(), "Number object is not of number type");
|
|
QCOMPARE(numObject.toNumber(ctx), 42.0);
|
|
QCOMPARE(numObject.toInt32(ctx), 42);
|
|
QVERIFY2(!ctx->hasException(), "Number conversion threw exception");
|
|
|
|
// String
|
|
KJSString stringObject("Trunk");
|
|
QVERIFY2(stringObject.isString(), "String object is not of string type");
|
|
QCOMPARE(stringObject.toString(ctx), QLatin1String("Trunk"));
|
|
QVERIFY2(!ctx->hasException(), "String conversion threw exception");
|
|
|
|
// Array
|
|
KJSArray arrayObject(ctx, 3);
|
|
QVERIFY2(arrayObject.isObject(), "Array object is not of object type");
|
|
QCOMPARE(arrayObject.property(ctx, "length").toNumber(ctx), 3.0);
|
|
QCOMPARE(arrayObject.toString(ctx), QLatin1String(",,"));
|
|
QVERIFY2(!ctx->hasException(), "Array conversion threw exception");
|
|
|
|
// copying
|
|
KJSObject copy(stringObject);
|
|
QCOMPARE(copy.toString(ctx), QLatin1String("Trunk"));
|
|
copy = numObject;
|
|
QCOMPARE(copy.toNumber(ctx), 42.0);
|
|
}
|
|
|
|
void KJSApiTest::interpreterEvaluate()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
KJSResult res;
|
|
|
|
// syntax error
|
|
res = ip.evaluate(")(");
|
|
QVERIFY2(res.isException(), "Syntax error not caught");
|
|
|
|
res = ip.evaluate("11+22");
|
|
QVERIFY2(!res.isException(), "Evaluation returned non-number object");
|
|
QCOMPARE(res.value().toNumber(ctx), 33.0);
|
|
}
|
|
|
|
void KJSApiTest::interpreterNormalizeCode()
|
|
{
|
|
int errLine = -1;
|
|
QString errMsg;
|
|
QString norm;
|
|
bool ok;
|
|
|
|
// syntax error case
|
|
ok = KJSInterpreter::normalizeCode(")(", &norm, &errLine, &errMsg);
|
|
QVERIFY(!ok);
|
|
QVERIFY(!errMsg.isEmpty());
|
|
QVERIFY(errLine >= 0 && errLine <= 2); // ### imprecise
|
|
|
|
// success case
|
|
ok = KJSInterpreter::normalizeCode("foo(); bar();", &norm);
|
|
QVERIFY(ok);
|
|
QVERIFY(!norm.isEmpty());
|
|
QStringList lines = norm.split('\n');
|
|
QVERIFY(lines.size() >= 2); // ### imprecise
|
|
int fooLine = lines.indexOf(QRegExp(" *foo\\(\\);"));
|
|
int barLine = lines.indexOf(QRegExp(" *bar\\(\\);"));
|
|
QVERIFY(fooLine >= 0);
|
|
QVERIFY(barLine > fooLine);
|
|
}
|
|
|
|
void KJSApiTest::objectProperties()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
|
|
KJSObject global = ip.globalObject();
|
|
KJSObject v;
|
|
|
|
// bool
|
|
global.setProperty(ctx, "myprop", true);
|
|
v = global.property(ctx, "myprop");
|
|
QVERIFY(v.isBoolean());
|
|
QCOMPARE(v.toBoolean(ctx), true);
|
|
|
|
// double
|
|
global.setProperty(ctx, "myprop", 21.0);
|
|
v = global.property(ctx, "myprop");
|
|
QVERIFY(v.isNumber());
|
|
QCOMPARE(v.toNumber(ctx), 21.0);
|
|
|
|
// int
|
|
global.setProperty(ctx, "myprop", 22);
|
|
v = global.property(ctx, "myprop");
|
|
QVERIFY(v.isNumber());
|
|
QCOMPARE(v.toNumber(ctx), 22.0);
|
|
|
|
// string (8-bit)
|
|
global.setProperty(ctx, "myprop", "myvalue8");
|
|
v = global.property(ctx, "myprop");
|
|
QVERIFY(v.isString());
|
|
QCOMPARE(v.toString(ctx), QLatin1String("myvalue8"));
|
|
|
|
// string (Unicode)
|
|
global.setProperty(ctx, "myprop", QLatin1String("myvalue16"));
|
|
v = global.property(ctx, "myprop");
|
|
QVERIFY(v.isString());
|
|
QCOMPARE(v.toString(ctx), QLatin1String("myvalue16"));
|
|
}
|
|
|
|
void KJSApiTest::prototypeConstants()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
|
|
KJSPrototype proto;
|
|
|
|
proto.defineConstant("d0", 44.4);
|
|
proto.defineConstant("s0", QLatin1String("XYZ"));
|
|
|
|
KJSObject obj = proto.constructObject(ctx, 0);
|
|
|
|
QCOMPARE(obj.property(ctx, "d0").toNumber(ctx), 44.4);
|
|
QCOMPARE(obj.property(ctx, "s0").toString(ctx), QLatin1String("XYZ"));
|
|
}
|
|
|
|
static struct O { int x; } o0 = { 42 };
|
|
|
|
static KJSObject getX(KJSContext* /*context*/, void* object)
|
|
{
|
|
O* o = reinterpret_cast<O*>(object);
|
|
int x = o->x;
|
|
return KJSNumber(x);
|
|
}
|
|
|
|
static void setX(KJSContext* context, void* object, KJSObject value)
|
|
{
|
|
O* o = reinterpret_cast<O*>(object);
|
|
double n = value.toNumber(context);
|
|
o->x = n;
|
|
}
|
|
|
|
void KJSApiTest::prototypeProperties()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
|
|
KJSPrototype proto;
|
|
|
|
proto.defineProperty(ctx, "x", getX, setX);
|
|
proto.defineProperty(ctx, "readOnlyX", getX);
|
|
|
|
KJSObject obj = proto.constructObject(ctx, &o0);
|
|
|
|
// read/write property
|
|
QCOMPARE(obj.property(ctx, "x").toNumber(ctx), 42.0);
|
|
obj.setProperty(ctx, "x", KJSNumber(43));
|
|
QCOMPARE(obj.property(ctx, "x").toNumber(ctx), 43.0);
|
|
|
|
QCOMPARE(obj.property(ctx, "readOnlyX").toNumber(ctx), 43.0);
|
|
obj.setProperty(ctx, "readOnlyX", KJSNumber(44));
|
|
QVERIFY2(ctx->hasException(), "Write access caused no exception");
|
|
QCOMPARE(obj.property(ctx, "readOnlyX").toNumber(ctx), 43.0);
|
|
}
|
|
|
|
static KJSObject multiply(KJSContext* context, void* object,
|
|
const KJSArguments& arguments)
|
|
{
|
|
double factor = *reinterpret_cast<double*>(object);
|
|
|
|
// test number of arguments
|
|
if (arguments.count() != 1)
|
|
return context->throwException("Missing argument");
|
|
|
|
KJSObject a0 = arguments.at(0);
|
|
if (!a0.isNumber())
|
|
return KJSNumber(-2);
|
|
|
|
double v0 = a0.toNumber(context);
|
|
|
|
return KJSNumber(factor * v0);
|
|
}
|
|
|
|
void KJSApiTest::prototypeFunctions()
|
|
{
|
|
KJSInterpreter ip;
|
|
KJSContext* ctx = ip.globalContext();
|
|
|
|
KJSPrototype proto;
|
|
|
|
proto.defineFunction(ctx, "multiply", multiply);
|
|
|
|
double factor = 3.0;
|
|
KJSObject obj = proto.constructObject(ctx, &factor);
|
|
ip.globalObject().setProperty(ctx, "obj", obj);
|
|
|
|
KJSResult res = ip.evaluate("obj.multiply(4)");
|
|
QCOMPARE(res.value().toNumber(ctx), 12.0);
|
|
|
|
// expect exception
|
|
res = ip.evaluate("obj.multiply()");
|
|
QVERIFY2(res.isException(), "Exception did not work");
|
|
}
|
|
|
|
void KJSApiTest::globalObject()
|
|
{
|
|
KJSPrototype proto;
|
|
proto.defineConstant("g0", 55.5);
|
|
|
|
KJSGlobalObject glob = proto.constructGlobalObject(0);
|
|
|
|
KJSInterpreter ip(glob);
|
|
KJSResult res = ip.evaluate("2 * g0");
|
|
QCOMPARE(res.value().toNumber(ip.globalContext()), 111.0);
|
|
}
|
|
|
|
QTEST_KDEMAIN_CORE(KJSApiTest)
|
|
|
|
#include "kjsapitest.moc"
|