From b514fecbeae6a4fed9e593ea6405dbeec7fe7883 Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Tue, 17 Jan 2012 12:37:07 +0100 Subject: [PATCH] Console API: Add console.assert console.assert tests if an expression is true. If it is false, it writes a message to the console and prints the JavaScript stack trace at that point. Change-Id: I5487552cb8a947e1947914166834e0bdedba3354 Reviewed-by: Kai Koehne --- doc/src/declarative/qdeclarativedebugging.qdoc | 13 +++++ .../qml/v8/qdeclarativebuiltinfunctions.cpp | 52 +++++++++++++----- .../qml/v8/qdeclarativebuiltinfunctions_p.h | 1 + src/declarative/qml/v8/qv8engine.cpp | 1 + .../qdeclarativeconsole/data/assert.qml | 62 ++++++++++++++++++++++ .../tst_qdeclarativeconsole.cpp | 20 +++++++ 6 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeconsole/data/assert.qml diff --git a/doc/src/declarative/qdeclarativedebugging.qdoc b/doc/src/declarative/qdeclarativedebugging.qdoc index c59952d..49fe224 100644 --- a/doc/src/declarative/qdeclarativedebugging.qdoc +++ b/doc/src/declarative/qdeclarativedebugging.qdoc @@ -49,6 +49,19 @@ The output is generated using the qDebug, qWarning, qCritical methods in C++ \hint Setting the environment variable QML_CONSOLE_EXTENDED also prints the source code location of the call. +\section2 Assert + +\c console.assert tests that an expression is true. If not, it will write an optional message +to the console and print the stack trace. + +\qml +function f() { + var x = 12 + console.assert(x == 12, "This will pass"); + console.assert(x > 12, "This will fail"); +} +\endqml + \section2 Timer \c console.time and console.timeEnd log the time (in milliseconds) that was spent between diff --git a/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp b/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp index a77c8a0..5f0b3ff 100644 --- a/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp +++ b/src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp @@ -94,6 +94,22 @@ static QString extendMessage(const QString &msg) { return msg; } +static void printStack() { + //The v8 default is currently 10 stack frames. + v8::Handle stackTrace = + v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview); + int stackCount = stackTrace->GetFrameCount(); + + for (int i = 0; i < stackCount; i++) { + v8::Local frame = stackTrace->GetFrame(i); + v8::String::Utf8Value func_name(frame->GetFunctionName()); + v8::String::Utf8Value script_name(frame->GetScriptName()); + int lineNumber = frame->GetLineNumber(); + int columnNumber = frame->GetColumn(); + qDebug("%s (%s:%d:%d)\n", *func_name, *script_name, lineNumber, columnNumber); + } +} + v8::Handle console(ConsoleLogTypes logType, const v8::Arguments &args) { v8::HandleScope handleScope; @@ -252,19 +268,7 @@ v8::Handle consoleTrace(const v8::Arguments &args) if (args.Length() != 0) V8THROW_ERROR("console.trace(): Invalid arguments"); - //The v8 default is currently 10 stack frames. - v8::Handle stackTrace = - v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview); - int stackCount = stackTrace->GetFrameCount(); - - for (int i = 0; i < stackCount; i++) { - v8::Local frame = stackTrace->GetFrame(i); - v8::String::Utf8Value func_name(frame->GetFunctionName()); - v8::String::Utf8Value script_name(frame->GetScriptName()); - int lineNumber = frame->GetLineNumber(); - int columnNumber = frame->GetColumn(); - qDebug("%s (%s:%d:%d)\n", *func_name, *script_name, lineNumber, columnNumber); - } + printStack(); return v8::Undefined(); } @@ -273,6 +277,28 @@ v8::Handle consoleWarn(const v8::Arguments &args) return console(Warn, args); } +v8::Handle consoleAssert(const v8::Arguments &args) +{ + if (args.Length() == 0) + V8THROW_ERROR("console.assert(): Missing argument"); + + if (!args[0]->ToBoolean()->Value()) { + QString message; + for (int i = 1; i < args.Length(); ++i) { + if (i != 1) + message.append(QLatin1Char(' ')); + + v8::Local value = args[i]; + message.append(V8ENGINE()->toString(value->ToString())); + } + + message = extendMessage(message); + qCritical("%s", qPrintable(message)); + printStack(); + } + return v8::Undefined(); +} + v8::Handle stringArg(const v8::Arguments &args) { QString value = V8ENGINE()->toString(args.This()->ToString()); diff --git a/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h b/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h index 8761bdc..cdb31b6 100644 --- a/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h +++ b/src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h @@ -70,6 +70,7 @@ v8::Handle consoleTimeEnd(const v8::Arguments &args); v8::Handle consoleCount(const v8::Arguments &args); v8::Handle consoleTrace(const v8::Arguments &args); v8::Handle consoleWarn(const v8::Arguments &args); +v8::Handle consoleAssert(const v8::Arguments &args); v8::Handle isQtObject(const v8::Arguments &args); v8::Handle rgba(const v8::Arguments &args); v8::Handle hsla(const v8::Arguments &args); diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index aaf912a..fa35533 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -530,6 +530,7 @@ void QV8Engine::initializeGlobal(v8::Handle global) console->Set(v8::String::New("info"), consoleLogFn); console->Set(v8::String::New("warn"), V8FUNCTION(consoleWarn, this)); console->Set(v8::String::New("error"), V8FUNCTION(consoleError, this)); + console->Set(v8::String::New("assert"), V8FUNCTION(consoleAssert, this)); console->Set(v8::String::New("count"), V8FUNCTION(consoleCount, this)); console->Set(v8::String::New("profile"), V8FUNCTION(consoleProfile, this)); diff --git a/tests/auto/declarative/qdeclarativeconsole/data/assert.qml b/tests/auto/declarative/qdeclarativeconsole/data/assert.qml new file mode 100644 index 0000000..c623b1a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeconsole/data/assert.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +QtObject { + property int q:1 + function assertFail() { + console.assert(0, "This will fail too") + } + + Component.onCompleted: { + var x = 12; + console.assert(x == 12, "This will pass"); + try { + console.assert(x < 12, "This will fail"); + } catch (e) { + console.log(e); + } + console.assert("x < 12", "This will pass too") + assertFail(); + console.assert(1) + } +} diff --git a/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp b/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp index f750377..9a4a39f 100644 --- a/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp +++ b/tests/auto/declarative/qdeclarativeconsole/tst_qdeclarativeconsole.cpp @@ -54,6 +54,7 @@ private slots: void logging(); void tracing(); void profiling(); + void assert(); private: QDeclarativeEngine engine; @@ -120,6 +121,25 @@ void tst_qdeclarativeconsole::profiling() delete object; } +void tst_qdeclarativeconsole::assert() +{ + QUrl testUrl = testFileUrl("assert.qml"); + + // assert() + QTest::ignoreMessage(QtCriticalMsg, "This will fail"); + QTest::ignoreMessage(QtCriticalMsg, "This will fail too"); + QString trace1 = QString::fromLatin1("onCompleted (%1:%2:%3)\n").arg(testUrl.toString()).arg(54).arg(17); + QString trace2 = QString::fromLatin1("onCompleted (%1:%2:%3)\n").arg(testUrl.toString()).arg(59).arg(9); + QString trace3 = QString::fromLatin1("assertFail (%1:%2:%3)\n").arg(testUrl.toString()).arg(47).arg(17); + QTest::ignoreMessage(QtDebugMsg, qPrintable(trace1)); + QTest::ignoreMessage(QtDebugMsg, qPrintable(trace2)); + QTest::ignoreMessage(QtDebugMsg, qPrintable(trace3)); + + QDeclarativeComponent component(&engine, testUrl); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; +} QTEST_MAIN(tst_qdeclarativeconsole) -- 2.7.4