KJS-API
kjsapitest.cpp
Go to the documentation of this file.
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2008 Harri Porten (porten@kde.org) 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 * 00020 */ 00021 00022 #include "kjsobject.h" 00023 #include "kjsprototype.h" 00024 #include "kjsarguments.h" 00025 #include "kjsinterpreter.h" 00026 00027 #include "qtest_kde.h" 00028 00029 class KJSApiTest : public QObject 00030 { 00031 Q_OBJECT 00032 00033 private Q_SLOTS: 00034 void objectConstruction(); 00035 void interpreterEvaluate(); 00036 void interpreterNormalizeCode(); 00037 void objectProperties(); 00038 void prototypeConstants(); 00039 void prototypeProperties(); 00040 void prototypeFunctions(); 00041 void globalObject(); 00042 }; 00043 00044 void KJSApiTest::objectConstruction() 00045 { 00046 KJSInterpreter ip; 00047 KJSContext* ctx = ip.globalContext(); 00048 00049 // Object 00050 QVERIFY2(KJSObject().isObject(), "Broken default object"); 00051 00052 // undefined 00053 QVERIFY2(KJSUndefined().isUndefined(), 00054 "Undefined object is not undefined"); 00055 // null 00056 QVERIFY2(KJSNull().isNull(), 00057 "Null object is not null"); 00058 00059 // Boolean 00060 KJSBoolean boolObject(true); 00061 QVERIFY2(boolObject.isBoolean(), "Boolean object is not of boolean type"); 00062 QVERIFY2(boolObject.toBoolean(ctx), "Boolean object has wrong value"); 00063 QVERIFY2(!ctx->hasException(), "Boolean conversion threw exception"); 00064 00065 // Number 00066 KJSNumber numObject(42.0); 00067 QVERIFY2(numObject.isNumber(), "Number object is not of number type"); 00068 QCOMPARE(numObject.toNumber(ctx), 42.0); 00069 QCOMPARE(numObject.toInt32(ctx), 42); 00070 QVERIFY2(!ctx->hasException(), "Number conversion threw exception"); 00071 00072 // String 00073 KJSString stringObject("Trunk"); 00074 QVERIFY2(stringObject.isString(), "String object is not of string type"); 00075 QCOMPARE(stringObject.toString(ctx), QLatin1String("Trunk")); 00076 QVERIFY2(!ctx->hasException(), "String conversion threw exception"); 00077 00078 // Array 00079 KJSArray arrayObject(ctx, 3); 00080 QVERIFY2(arrayObject.isObject(), "Array object is not of object type"); 00081 QCOMPARE(arrayObject.property(ctx, "length").toNumber(ctx), 3.0); 00082 QCOMPARE(arrayObject.toString(ctx), QLatin1String(",,")); 00083 QVERIFY2(!ctx->hasException(), "Array conversion threw exception"); 00084 00085 // copying 00086 KJSObject copy(stringObject); 00087 QCOMPARE(copy.toString(ctx), QLatin1String("Trunk")); 00088 copy = numObject; 00089 QCOMPARE(copy.toNumber(ctx), 42.0); 00090 } 00091 00092 void KJSApiTest::interpreterEvaluate() 00093 { 00094 KJSInterpreter ip; 00095 KJSContext* ctx = ip.globalContext(); 00096 KJSResult res; 00097 00098 // syntax error 00099 res = ip.evaluate(")("); 00100 QVERIFY2(res.isException(), "Syntax error not caught"); 00101 00102 res = ip.evaluate("11+22"); 00103 QVERIFY2(!res.isException(), "Evaluation returned non-number object"); 00104 QCOMPARE(res.value().toNumber(ctx), 33.0); 00105 } 00106 00107 void KJSApiTest::interpreterNormalizeCode() 00108 { 00109 int errLine = -1; 00110 QString errMsg; 00111 QString norm; 00112 bool ok; 00113 00114 // syntax error case 00115 ok = KJSInterpreter::normalizeCode(")(", &norm, &errLine, &errMsg); 00116 QVERIFY(!ok); 00117 QVERIFY(!errMsg.isEmpty()); 00118 QVERIFY(errLine >= 0 && errLine <= 2); // ### imprecise 00119 00120 // success case 00121 ok = KJSInterpreter::normalizeCode("foo(); bar();", &norm); 00122 QVERIFY(ok); 00123 QVERIFY(!norm.isEmpty()); 00124 QStringList lines = norm.split('\n'); 00125 QVERIFY(lines.size() >= 2); // ### imprecise 00126 int fooLine = lines.indexOf(QRegExp(" *foo\\(\\);")); 00127 int barLine = lines.indexOf(QRegExp(" *bar\\(\\);")); 00128 QVERIFY(fooLine >= 0); 00129 QVERIFY(barLine > fooLine); 00130 } 00131 00132 void KJSApiTest::objectProperties() 00133 { 00134 KJSInterpreter ip; 00135 KJSContext* ctx = ip.globalContext(); 00136 00137 KJSObject global = ip.globalObject(); 00138 KJSObject v; 00139 00140 // bool 00141 global.setProperty(ctx, "myprop", true); 00142 v = global.property(ctx, "myprop"); 00143 QVERIFY(v.isBoolean()); 00144 QCOMPARE(v.toBoolean(ctx), true); 00145 00146 // double 00147 global.setProperty(ctx, "myprop", 21.0); 00148 v = global.property(ctx, "myprop"); 00149 QVERIFY(v.isNumber()); 00150 QCOMPARE(v.toNumber(ctx), 21.0); 00151 00152 // int 00153 global.setProperty(ctx, "myprop", 22); 00154 v = global.property(ctx, "myprop"); 00155 QVERIFY(v.isNumber()); 00156 QCOMPARE(v.toNumber(ctx), 22.0); 00157 00158 // string (8-bit) 00159 global.setProperty(ctx, "myprop", "myvalue8"); 00160 v = global.property(ctx, "myprop"); 00161 QVERIFY(v.isString()); 00162 QCOMPARE(v.toString(ctx), QLatin1String("myvalue8")); 00163 00164 // string (Unicode) 00165 global.setProperty(ctx, "myprop", QLatin1String("myvalue16")); 00166 v = global.property(ctx, "myprop"); 00167 QVERIFY(v.isString()); 00168 QCOMPARE(v.toString(ctx), QLatin1String("myvalue16")); 00169 } 00170 00171 void KJSApiTest::prototypeConstants() 00172 { 00173 KJSInterpreter ip; 00174 KJSContext* ctx = ip.globalContext(); 00175 00176 KJSPrototype proto; 00177 00178 proto.defineConstant("d0", 44.4); 00179 proto.defineConstant("s0", QLatin1String("XYZ")); 00180 00181 KJSObject obj = proto.constructObject(ctx, 0); 00182 00183 QCOMPARE(obj.property(ctx, "d0").toNumber(ctx), 44.4); 00184 QCOMPARE(obj.property(ctx, "s0").toString(ctx), QLatin1String("XYZ")); 00185 } 00186 00187 static struct O { int x; } o0 = { 42 }; 00188 00189 static KJSObject getX(KJSContext* /*context*/, void* object) 00190 { 00191 O* o = reinterpret_cast<O*>(object); 00192 int x = o->x; 00193 return KJSNumber(x); 00194 } 00195 00196 static void setX(KJSContext* context, void* object, KJSObject value) 00197 { 00198 O* o = reinterpret_cast<O*>(object); 00199 double n = value.toNumber(context); 00200 o->x = n; 00201 } 00202 00203 void KJSApiTest::prototypeProperties() 00204 { 00205 KJSInterpreter ip; 00206 KJSContext* ctx = ip.globalContext(); 00207 00208 KJSPrototype proto; 00209 00210 proto.defineProperty(ctx, "x", getX, setX); 00211 proto.defineProperty(ctx, "readOnlyX", getX); 00212 00213 KJSObject obj = proto.constructObject(ctx, &o0); 00214 00215 // read/write property 00216 QCOMPARE(obj.property(ctx, "x").toNumber(ctx), 42.0); 00217 obj.setProperty(ctx, "x", KJSNumber(43)); 00218 QCOMPARE(obj.property(ctx, "x").toNumber(ctx), 43.0); 00219 00220 QCOMPARE(obj.property(ctx, "readOnlyX").toNumber(ctx), 43.0); 00221 obj.setProperty(ctx, "readOnlyX", KJSNumber(44)); 00222 QVERIFY2(ctx->hasException(), "Write access caused no exception"); 00223 QCOMPARE(obj.property(ctx, "readOnlyX").toNumber(ctx), 43.0); 00224 } 00225 00226 static KJSObject multiply(KJSContext* context, void* object, 00227 const KJSArguments& arguments) 00228 { 00229 double factor = *reinterpret_cast<double*>(object); 00230 00231 // test number of arguments 00232 if (arguments.count() != 1) 00233 return context->throwException("Missing argument"); 00234 00235 KJSObject a0 = arguments.at(0); 00236 if (!a0.isNumber()) 00237 return KJSNumber(-2); 00238 00239 double v0 = a0.toNumber(context); 00240 00241 return KJSNumber(factor * v0); 00242 } 00243 00244 void KJSApiTest::prototypeFunctions() 00245 { 00246 KJSInterpreter ip; 00247 KJSContext* ctx = ip.globalContext(); 00248 00249 KJSPrototype proto; 00250 00251 proto.defineFunction(ctx, "multiply", multiply); 00252 00253 double factor = 3.0; 00254 KJSObject obj = proto.constructObject(ctx, &factor); 00255 ip.globalObject().setProperty(ctx, "obj", obj); 00256 00257 KJSResult res = ip.evaluate("obj.multiply(4)"); 00258 QCOMPARE(res.value().toNumber(ctx), 12.0); 00259 00260 // expect exception 00261 res = ip.evaluate("obj.multiply()"); 00262 QVERIFY2(res.isException(), "Exception did not work"); 00263 } 00264 00265 void KJSApiTest::globalObject() 00266 { 00267 KJSPrototype proto; 00268 proto.defineConstant("g0", 55.5); 00269 00270 KJSGlobalObject glob = proto.constructGlobalObject(0); 00271 00272 KJSInterpreter ip(glob); 00273 KJSResult res = ip.evaluate("2 * g0"); 00274 QCOMPARE(res.value().toNumber(ip.globalContext()), 111.0); 00275 } 00276 00277 QTEST_KDEMAIN_CORE(KJSApiTest) 00278 00279 #include "kjsapitest.moc"
KDE 4.6 API Reference