From 95dc6d21b68c21051852f2b576b9d08854da369f Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 26 Mar 2015 12:19:21 +0100 Subject: [PATCH] testing part 1 --- mix/CMakeLists.txt | 44 +- mix/MixApplication.cpp | 71 +++- mix/MixApplication.h | 17 + mix/main.cpp | 15 +- mix/qml.qrc | 2 +- mix/qml/Application.qml | 397 ++++++++++++++++++ mix/test.qrc | 6 + mix/test/TestMain.qml | 51 +++ .../TestTransactionDebug.qml} | 0 9 files changed, 567 insertions(+), 36 deletions(-) create mode 100644 mix/qml/Application.qml create mode 100644 mix/test.qrc create mode 100644 mix/test/TestMain.qml rename mix/{qml/main.qml => test/TestTransactionDebug.qml} (100%) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index d57dafcac..4cb285b85 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -16,7 +16,7 @@ include_directories(${Boost_INCLUDE_DIRS}) include_directories(BEFORE ..) find_package (Qt5WebEngine QUIET) -qt5_add_resources(UI_RESOURCES res.qrc qml.qrc) +qt5_add_resources(UI_RESOURCES res.qrc qml.qrc test.qrc) file(GLOB HEADERS "*.h") @@ -37,32 +37,18 @@ eth_add_executable(${EXECUTABLE} UI_RESOURCES ${UI_RESOURCES} ) -target_link_libraries(${EXECUTABLE} Qt5::Core) -target_link_libraries(${EXECUTABLE} Qt5::Gui) -target_link_libraries(${EXECUTABLE} Qt5::Widgets) -target_link_libraries(${EXECUTABLE} Qt5::Network) -target_link_libraries(${EXECUTABLE} Qt5::Quick) -target_link_libraries(${EXECUTABLE} Qt5::Qml) -target_link_libraries(${EXECUTABLE} webthree) -target_link_libraries(${EXECUTABLE} ethereum) -target_link_libraries(${EXECUTABLE} evm) -target_link_libraries(${EXECUTABLE} ethcore) -target_link_libraries(${EXECUTABLE} devcrypto) -target_link_libraries(${EXECUTABLE} secp256k1) -if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) -target_link_libraries(${EXECUTABLE} serpent) -endif() -target_link_libraries(${EXECUTABLE} lll) -target_link_libraries(${EXECUTABLE} solidity) -target_link_libraries(${EXECUTABLE} evmcore) -target_link_libraries(${EXECUTABLE} devcore) -target_link_libraries(${EXECUTABLE} jsqrc) -target_link_libraries(${EXECUTABLE} web3jsonrpc) +find_package(Qt5QuickTest REQUIRED) +find_package(Qt5Test REQUIRED) +set(LIBRARIES "Qt5::Core;Qt5::Gui;Qt5::Widgets;Qt5::Network;Qt5::Quick;Qt5::Qml;webthree;ethereum;evm;ethcore;devcrypto;solidity;evmcore;devcore;jsqrc;web3jsonrpc") if (${ETH_HAVE_WEBENGINE}) add_definitions(-DETH_HAVE_WEBENGINE) - target_link_libraries(${EXECUTABLE} Qt5::WebEngine) + list(APPEND LIBRARIES "Qt5::WebEngine") endif() + list(APPEND LIBRARIES "Qt5::QuickTest") + list(APPEND LIBRARIES "Qt5::Test") + +target_link_libraries(${EXECUTABLE} ${LIBRARIES}) # eth_install_executable is defined in cmake/EthExecutableHelper.cmake eth_install_executable(${EXECUTABLE} @@ -71,5 +57,15 @@ eth_install_executable(${EXECUTABLE} #add qml asnd stdc files to project tree in Qt creator file(GLOB_RECURSE QMLFILES "qml/*.*") +file(GLOB_RECURSE TESTFILE "test/*.*") file(GLOB_RECURSE SOLFILES "stdc/*.*") -add_custom_target(mix_qml SOURCES ${QMLFILES} ${SOLFILES}) +add_custom_target(mix_qml SOURCES ${QMLFILES} ${SOLFILES} ${TESTFILES}) + + +#test target +#set(TEST_EXECUTABLE mix_test) +#qt5_add_resources(UI_RESOURCES test.qrc) +#add_executable(${TEST_EXECUTABLE} ${UI_RESOURCES} ${SRC_LIST} ${HEADERS}) + + + diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index 028f1cb0b..7eefcc38e 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -23,6 +23,10 @@ #include #include #include +#include +#include +#include +#include #ifdef ETH_HAVE_WEBENGINE #include #endif @@ -37,21 +41,73 @@ using namespace dev::mix; +ApplicationService::ApplicationService() +{ +#ifdef ETH_HAVE_WEBENGINE + QtWebEngine::initialize(); +#endif + QFont f; + m_systemPointSize = f.pointSize(); +} + + +#include + +bool ApplicationService::waitForSignal(QObject* _item, QString _signalName, int _timeout) +{ + QSignalSpy spy(_item, ("2" + _signalName.toStdString()).c_str()); + QMetaObject const* mo = _item->metaObject(); + + QStringList methods; + + for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) { + if (mo->method(i).methodType() == QMetaMethod::Signal) { + methods << QString::fromLatin1(mo->method(i).methodSignature()); + } + } + + QElapsedTimer timer; + timer.start(); + + while (!spy.size()) { + int remaining = _timeout - int(timer.elapsed()); + if (remaining <= 0) + break; + QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QTest::qSleep(10); + } + + return spy.size(); +} + MixApplication::MixApplication(int& _argc, char* _argv[]): QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()) +{ + initialize(); + //m_engine->load(QUrl("qrc:/qml/main.qml")); + m_engine->load(QUrl("qrc:/test/TestMain.qml")); + + + if (!m_engine->rootObjects().empty()) + { + QWindow *window = qobject_cast(m_engine->rootObjects().at(0)); + if (window) + window->setIcon(QIcon(":/res/mix_256x256x32.png")); + } +} + + +void MixApplication::initialize() { setOrganizationName(tr("Ethereum")); setOrganizationDomain(tr("ethereum.org")); setApplicationName(tr("Mix")); setApplicationVersion("0.1"); -#ifdef ETH_HAVE_WEBENGINE - QtWebEngine::initialize(); -#endif - QFont f; - m_engine->rootContext()->setContextProperty("systemPointSize", f.pointSize()); qmlRegisterType("org.ethereum.qml.CodeModel", 1, 0, "CodeModel"); qmlRegisterType("org.ethereum.qml.ClientModel", 1, 0, "ClientModel"); + qmlRegisterType("org.ethereum.qml.ApplicationService", 1, 0, "ApplicationService"); qmlRegisterType("org.ethereum.qml.FileIo", 1, 0, "FileIo"); qmlRegisterType("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); @@ -63,10 +119,7 @@ MixApplication::MixApplication(int& _argc, char* _argv[]): qmlRegisterType("HttpServer", 1, 0, "HttpServer"); qRegisterMetaType("CodeModel*"); qRegisterMetaType("ClientModel*"); - - m_engine->load(QUrl("qrc:/qml/main.qml")); - QWindow *window = qobject_cast(m_engine->rootObjects().at(0)); - window->setIcon(QIcon(":/res/mix_256x256x32.png")); + qRegisterMetaType("ClientModel*"); } MixApplication::~MixApplication() diff --git a/mix/MixApplication.h b/mix/MixApplication.h index 49a6e0047..ce3544392 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -33,12 +33,29 @@ namespace dev namespace mix { +class ApplicationService: public QObject +{ + Q_OBJECT + Q_PROPERTY(int systemPointSize READ systemPointSize CONSTANT) + +public: + ApplicationService(); + int systemPointSize() const { return m_systemPointSize; } +public slots: + bool waitForSignal(QObject* _item, QString _signalName, int _timeout); + +private: + int m_systemPointSize = 0; +}; + + class MixApplication: public QApplication { Q_OBJECT public: MixApplication(int& _argc, char* _argv[]); + static void initialize(); virtual ~MixApplication(); QQmlApplicationEngine* engine() { return m_engine.get(); } diff --git a/mix/main.cpp b/mix/main.cpp index 798520e39..908606bd9 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -24,6 +24,10 @@ #include #include "MixApplication.h" #include "Exceptions.h" + +#include + + using namespace dev::mix; int main(int _argc, char* _argv[]) @@ -43,8 +47,15 @@ int main(int _argc, char* _argv[]) #endif try { - MixApplication app(_argc, _argv); - return app.exec(); + + // + MixApplication::initialize(); + //MixApplication app(_argc, _argv); + return quick_test_main(_argc, _argv, "mix", "/home/arkady/src/cpp-ethereum/mix/test/TestMain.qml"); + + + //MixApplication app(_argc, _argv); + //return app.exec(); } catch (boost::exception const& _e) { diff --git a/mix/qml.qrc b/mix/qml.qrc index bed954741..fd437d881 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -1,6 +1,7 @@ qml/AlertMessageDialog.qml + qml/Application.qml qml/BasicMessage.qml qml/BigIntValue.qml qml/CallStack.qml @@ -59,7 +60,6 @@ qml/js/ProjectModel.js qml/js/QEtherHelper.js qml/js/TransactionHelper.js - qml/main.qml qml/qmldir diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml new file mode 100644 index 000000000..b112cf527 --- /dev/null +++ b/mix/qml/Application.qml @@ -0,0 +1,397 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Dialogs 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.1 +import QtQuick.PrivateWidgets 1.1 +import Qt.labs.settings 1.0 +import org.ethereum.qml.QEther 1.0 +import org.ethereum.qml.CodeModel 1.0 +import org.ethereum.qml.ClientModel 1.0 +import org.ethereum.qml.FileIo 1.0 +import org.ethereum.qml.Clipboard 1.0 +import org.ethereum.qml.ApplicationService 1.0 + +ApplicationWindow { + + id: mainApplication + signal loaded; + visible: true + width: 1200 + height: 800 + minimumWidth: 400 + minimumHeight: 300 + title: qsTr("Mix") + property alias systemPointSize: appService.systemPointSize; + property alias mainContent: mainContent; + property alias codeModel: codeModel; + property alias clientModel: clientModel; + property alias projectModel: projectModel; + property alias appService: appService; + + ApplicationService { + id: appService + } + + CodeModel { + id: codeModel + } + + ClientModel { + id: clientModel + codeModel: codeModel + } + + ProjectModel { + id: projectModel + } + + FileIo { + id: fileIo + } + + Clipboard { + id: clipboard + } + + Connections { + target: mainApplication + onClosing: + { + mainApplication.close(); + close.accepted = false; + } + } + + Component.onCompleted: { + loaded(); + } + + function close() { + projectModel.appIsClosing = true; + if (projectModel.projectPath !== "") + projectModel.closeProject(function() { Qt.quit(); }) + else + Qt.quit(); + } + + menuBar: MenuBar { + Menu { + title: qsTr("File") + MenuItem { action: createProjectAction } + MenuItem { action: openProjectAction } + MenuSeparator {} + MenuItem { action: saveAllFilesAction } + MenuItem { action: saveCurrentDocument } + MenuSeparator {} + MenuItem { action: addExistingFileAction } + MenuItem { action: addNewJsFileAction } + MenuItem { action: addNewHtmlFileAction } + MenuItem { action: addNewCssFileAction } + MenuSeparator {} + MenuItem { action: addNewContractAction } + MenuItem { action: closeProjectAction } + MenuSeparator {} + MenuItem { action: exitAppAction } + } + Menu { + title: qsTr("Deploy") + MenuItem { action: mineAction } + MenuSeparator {} + MenuItem { action: editStatesAction } + MenuSeparator {} + MenuItem { action: deployViaRpcAction } + MenuSeparator {} + MenuItem { action: toggleRunOnLoadAction } + } + Menu { + title: qsTr("Debug") + MenuItem { action: debugRunAction } + MenuSeparator {} + MenuItem { action: toggleAssemblyDebuggingAction } + } + Menu { + title: qsTr("Windows") + MenuItem { action: openNextDocumentAction } + MenuItem { action: openPrevDocumentAction } + MenuSeparator {} + MenuItem { action: toggleProjectNavigatorAction } + MenuItem { action: showHideRightPanelAction } + MenuItem { action: toggleTransactionLogAction } + MenuItem { action: toggleWebPreviewAction } + MenuItem { action: toggleWebPreviewOrientationAction } + //MenuItem { action: toggleCallsInLog } + } + } + + MainContent { + id: mainContent; + anchors.fill: parent + } + + ModalDialog { + objectName: "dialog" + id: dialog + } + + AlertMessageDialog { + objectName: "alertMessageDialog" + id: messageDialog + } + + Settings { + id: mainWindowSettings + property alias mainWidth: mainApplication.width + property alias mainHeight: mainApplication.height + property alias mainX: mainApplication.x + property alias mainY: mainApplication.y + } + + Action { + id: exitAppAction + text: qsTr("Exit") + shortcut: "Ctrl+Q" + onTriggered: + { + mainApplication.close(); + } + } + + Action { + id: mineAction + text: qsTr("New Block") + shortcut: "Ctrl+M" + onTriggered: clientModel.mine(); + enabled: codeModel.hasContract && !clientModel.running && !clientModel.mining + } + + StateList { + id: stateList + } + + Action { + id: editStatesAction + text: qsTr("Edit States") + shortcut: "Ctrl+Alt+E" + onTriggered: stateList.show(); + } + + Connections { + target: projectModel.stateListModel + + function updateRunLabel() + { + debugRunAction.text = qsTr("Deploy") + " \"" + projectModel.stateListModel.defaultStateName() + "\""; + } + + onDefaultStateChanged: updateRunLabel() + onStateListModelReady: updateRunLabel() + } + + Action { + id: debugRunAction + text: qsTr("Deploy") + shortcut: "F5" + onTriggered: mainContent.startQuickDebugging() + enabled: codeModel.hasContract && !clientModel.running + } + + Action { + id: toggleAssemblyDebuggingAction + text: qsTr("Show VM Code") + shortcut: "Ctrl+Alt+V" + onTriggered: mainContent.rightPane.assemblyMode = !mainContent.rightPane.assemblyMode; + checked: mainContent.rightPane.assemblyMode; + enabled: true + } + + Action { + id: toggleWebPreviewAction + text: qsTr("Show Web View") + shortcut: "F2" + checkable: true + checked: mainContent.webViewVisible + onTriggered: mainContent.toggleWebPreview(); + } + + Action { + id: toggleTransactionLogAction + text: qsTr("Show States and Transactions") + shortcut: "Alt+1" + checkable: true + checked: mainContent.rightPane.transactionLog.visible + onTriggered: mainContent.rightPane.transactionLog.visible = !mainContent.rightPane.transactionLog.visible + } + + Action { + id: toggleProjectNavigatorAction + text: qsTr("Show Project Navigator") + shortcut: "Alt+0" + checkable: true + checked: mainContent.projectViewVisible + onTriggered: mainContent.toggleProjectView(); + } + + Action { + id: toggleWebPreviewOrientationAction + text: qsTr("Horizontal Web View") + shortcut: "" + checkable: true + checked: mainContent.webViewHorizontal + onTriggered: mainContent.toggleWebPreviewOrientation(); + } + + Action { + id: toggleRunOnLoadAction + text: qsTr("Load State on Startup") + shortcut: "" + checkable: true + checked: mainContent.runOnProjectLoad + onTriggered: mainContent.runOnProjectLoad = !mainContent.runOnProjectLoad + } + + Action { + id: showHideRightPanelAction + text: qsTr("Show Right View") + shortcut: "F7" + checkable: true + checked: mainContent.rightViewVisible + onTriggered: mainContent.toggleRightView(); + } + + Action { + id: createProjectAction + text: qsTr("&New Project") + shortcut: "Ctrl+N" + enabled: true; + onTriggered: projectModel.createProject(); + } + + Action { + id: openProjectAction + text: qsTr("&Open Project") + shortcut: "Ctrl+O" + enabled: true; + onTriggered: openProjectFileDialog.open() + } + + FileDialog { + id: openProjectFileDialog + visible: false + title: qsTr("Open a Project") + selectFolder: true + onAccepted: { + var path = openProjectFileDialog.fileUrl.toString(); + path += "/"; + projectModel.loadProject(path); + } + } + + Action { + id: addNewJsFileAction + text: qsTr("New JavaScript File") + shortcut: "Ctrl+Alt+J" + enabled: !projectModel.isEmpty + onTriggered: projectModel.newJsFile(); + } + + Action { + id: addNewHtmlFileAction + text: qsTr("New HTML File") + shortcut: "Ctrl+Alt+H" + enabled: !projectModel.isEmpty + onTriggered: projectModel.newHtmlFile(); + } + + Action { + id: addNewCssFileAction + text: qsTr("New CSS File") + shortcut: "Ctrl+Alt+S" + enabled: !projectModel.isEmpty + onTriggered: projectModel.newCssFile(); + } + + Action { + id: addNewContractAction + text: qsTr("New Contract") + shortcut: "Ctrl+Alt+C" + enabled: !projectModel.isEmpty + onTriggered: projectModel.newContract(); + } + + Action { + id: addExistingFileAction + text: qsTr("Add Existing File") + shortcut: "Ctrl+Alt+A" + enabled: !projectModel.isEmpty + onTriggered: addExistingFileDialog.open() + } + + FileDialog { + id: addExistingFileDialog + visible: false + title: qsTr("Add a File") + selectFolder: false + onAccepted: { + var paths = addExistingFileDialog.fileUrls; + projectModel.addExistingFiles(paths); + } + } + + Action { + id: saveAllFilesAction + text: qsTr("Save All") + shortcut: "Ctrl+Shift+A" + enabled: !projectModel.isEmpty + onTriggered: projectModel.saveAll(); + } + + Action { + id: saveCurrentDocument + text: qsTr("Save Current Document") + shortcut: "Ctrl+S" + enabled: !projectModel.isEmpty + onTriggered: projectModel.saveCurrentDocument(); + } + + Action { + id: closeProjectAction + text: qsTr("Close Project") + shortcut: "Ctrl+W" + enabled: !projectModel.isEmpty + onTriggered: projectModel.closeProject(); + } + + Action { + id: openNextDocumentAction + text: qsTr("Next Document") + shortcut: "Ctrl+Tab" + enabled: !projectModel.isEmpty + onTriggered: projectModel.openNextDocument(); + } + + Action { + id: openPrevDocumentAction + text: qsTr("Previous Document") + shortcut: "Ctrl+Shift+Tab" + enabled: !projectModel.isEmpty + onTriggered: projectModel.openPrevDocument(); + } + + Action { + id: toggleBreakpointAction + text: qsTr("Toggle Breakpoint") + shortcut: "F9" + enabled: mainContent.codeEditor.editingContract(); + onTriggered: mainContent.toggleBreakpoint(); + } + + Action { + id: deployViaRpcAction + text: qsTr("Deploy to Network") + shortcut: "Ctrl+Shift+D" + enabled: !projectModel.isEmpty && codeModel.hasContract + onTriggered: projectModel.deployProject(); + } +} diff --git a/mix/test.qrc b/mix/test.qrc new file mode 100644 index 000000000..e7d2271a4 --- /dev/null +++ b/mix/test.qrc @@ -0,0 +1,6 @@ + + + test/TestMain.qml + test/TestTransactionDebug.qml + + diff --git a/mix/test/TestMain.qml b/mix/test/TestMain.qml new file mode 100644 index 000000000..737a2b2a4 --- /dev/null +++ b/mix/test/TestMain.qml @@ -0,0 +1,51 @@ +import QtQuick 2.2 +import QtTest 1.1 +//import Qt.test.qtestroot 1.0 +import "../qml" + + +TestCase +{ + +Item +{ + id: helper + function findChild(item, childId) { + if (item.children) { + var searchString = "button" + + for (var idx in item.children) { + var currentItem = item.children[idx] + + if (currentItem.id.match("^"+childId) === childId) + return currentItem; + + return findChild(currentItem, childId); + } + } + } +} + + +function test_t1() +{ + waitForRendering(mainApplication.mainContent, 10000); + mainApplication.projectModel.createProject(); + var projectDlg = helper.findChild(mainApplication, "newProjectDialog"); + + if (mainApplication.appService.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000)) + console.log("compiled"); +} + +function runTest() +{ + waitForRendering(mainApplication.mainContent, 10000); + console.log("runtest"); + mousePress(mainApplication, 10, 10); +} + +Application { + id: mainApplication +} + +} diff --git a/mix/qml/main.qml b/mix/test/TestTransactionDebug.qml similarity index 100% rename from mix/qml/main.qml rename to mix/test/TestTransactionDebug.qml