diff options
author | The Qt Project <gerrit-noreply@qt-project.org> | 2020-07-01 16:21:30 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2020-07-01 16:21:30 +0000 |
commit | fa81549844b8f5f87cdbe9b5d9755d10cea6229f (patch) | |
tree | 9a952c3c9cc1d73a8e304c6727e70be7288ced63 /tests | |
parent | d0e767543e91660b8c0c7337d4987d099a18774c (diff) | |
parent | 0c6231d7ecc55ae988ab6a1b23fe1925027af113 (diff) |
Merge "Merge remote-tracking branch 'origin/qds-1.59' into 4.13" into 4.13
Diffstat (limited to 'tests')
28 files changed, 2127 insertions, 11 deletions
diff --git a/tests/unit/mockup/coreplugin/helpitem.h b/tests/unit/mockup/coreplugin/helpitem.h new file mode 100644 index 0000000000..7942036c74 --- /dev/null +++ b/tests/unit/mockup/coreplugin/helpitem.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "core_global.h" + +#include <QString> + +namespace Core { + +class HelpItem +{ +public: + HelpItem() {} + HelpItem(const QString &) {} +}; + +} // namespace Core diff --git a/tests/unit/mockup/coreplugin/icontext.h b/tests/unit/mockup/coreplugin/icontext.h new file mode 100644 index 0000000000..95b55302fb --- /dev/null +++ b/tests/unit/mockup/coreplugin/icontext.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QString> + +#include <functional> + +namespace Core { + +class IContext +{ +public: + using HelpCallback = std::function<void(const QString &)>; +}; + +} // namespace Core diff --git a/tests/unit/mockup/qmldesigner/designercore/include/documentmessage.h b/tests/unit/mockup/qmldesigner/designercore/include/documentmessage.h new file mode 100644 index 0000000000..c4edc8e07d --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/documentmessage.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "exception.h" + +#include <qmldesignercorelib_global.h> + +#include <QCoreApplication> +#include <QUrl> + +namespace QmlJS { +class DiagnosticMessage; +} + +namespace QmlDesigner { + +class DocumentMessage +{ +public: + enum Type { NoError = 0, InternalError = 1, ParseError = 2 }; + +public: + DocumentMessage() {} + DocumentMessage(const QString &) {} + + Type type() const { return m_type; } + + int line() const { return m_line; } + + int column() const { return m_column; } + + QString description() const { return m_description; } + + QUrl url() const { return m_url; } + + QString toString() const { return {}; } + +private: + Type m_type; + int m_line; + int m_column; + QString m_description; + QUrl m_url; +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryinfo.h b/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryinfo.h new file mode 100644 index 0000000000..ad854699b4 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryinfo.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmldesignercorelib_global.h" + +#include <QIcon> + +namespace QmlDesigner { + +class ItemLibraryEntry +{ +public: + QString name() const { return {}; } + TypeName typeName() const { return {}; } + QIcon typeIcon() const { return {}; } + QString libraryEntryIconPath() const { return {}; } +}; + +class ItemLibraryInfo +{ +public: + QList<ItemLibraryEntry> entries() const { return {}; } + QList<ItemLibraryEntry> entriesForType(const QByteArray &typeName, + int majorVersion, + int minorVersion) const + { + return {}; + } + ItemLibraryEntry entry(const QString &name) const { return {}; } +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryitem.h b/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryitem.h new file mode 100644 index 0000000000..ccc06640eb --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/itemlibraryitem.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QObject> +#include <QSize> +#include <QString> +#include <QVariant> + +#include "itemlibraryinfo.h" + +namespace QmlDesigner { + +class ItemLibraryItem : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QVariant itemLibraryEntry READ itemLibraryEntry FINAL) + Q_PROPERTY(QString itemName READ itemName FINAL) + Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL) + Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL) + +public: + ItemLibraryItem(QObject *) {} + ~ItemLibraryItem() override {} + + QString itemName() const { return {}; } + QString typeName() const { return {}; } + QString itemLibraryIconPath() const { return {}; } + + bool setVisible(bool) { return {}; } + bool isVisible() const { return {}; } + + void setItemLibraryEntry(const ItemLibraryEntry &) {} + QVariant itemLibraryEntry() const { return {}; } + +signals: + void visibilityChanged(); +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/metainfo.h b/tests/unit/mockup/qmldesigner/designercore/include/metainfo.h new file mode 100644 index 0000000000..22e7c5762d --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/metainfo.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmldesignercorelib_global.h" + +#include <QSharedPointer> +#include <QStringList> + +#include "itemlibraryinfo.h" +#include <nodemetainfo.h> + +namespace QmlDesigner { + +class ModelNode; +class AbstractProperty; +class ItemLibraryInfo; + +inline bool operator==(const MetaInfo &first, const MetaInfo &second) +{ + return {}; +} +inline bool operator!=(const MetaInfo &first, const MetaInfo &second) +{ + return {}; +} + +class QMLDESIGNERCORE_EXPORT MetaInfo +{ +public: + ItemLibraryInfo *itemLibraryInfo() const { return {}; } + +public: + static MetaInfo global() { return {}; } + static void clearGlobal() {} + + static void setPluginPaths(const QStringList &paths) {} +}; + +} //namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h new file mode 100644 index 0000000000..246d1ede40 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmldesignercorelib_global.h" +#include "abstractview.h" + +namespace QmlDesigner { + +class NodeInstanceView : public AbstractView +{ + Q_OBJECT + +public: + NodeInstanceView(QObject *parent) {} + ~NodeInstanceView() override {} + + void modelAttached(Model *model) override {} + void modelAboutToBeDetached(Model *model) override {} + void nodeCreated(const ModelNode &createdNode) override {} + void nodeRemoved(const ModelNode &removedNode, + const NodeAbstractProperty &parentProperty, + PropertyChangeFlags propertyChange) override + {} + void propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList) override {} + void propertiesRemoved(const QList<AbstractProperty> &propertyList) override {} + void variantPropertiesChanged(const QList<VariantProperty> &propertyList, + PropertyChangeFlags propertyChange) override + {} + void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, + PropertyChangeFlags propertyChange) override + {} + void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &propertyList, + PropertyChangeFlags propertyChange) override + {} + void nodeReparented(const ModelNode &node, + const NodeAbstractProperty &newPropertyParent, + const NodeAbstractProperty &oldPropertyParent, + AbstractView::PropertyChangeFlags propertyChange) override + {} + void nodeIdChanged(const ModelNode &node, const QString &newId, const QString &oldId) override + {} + void nodeOrderChanged(const NodeListProperty &listProperty, + const ModelNode &movedNode, + int oldIndex) override + {} + void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override {} + void nodeTypeChanged(const ModelNode &node, + const TypeName &type, + int majorVersion, + int minorVersion) override + {} + void customNotification(const AbstractView *view, + const QString &identifier, + const QList<ModelNode> &nodeList, + const QList<QVariant> &data) override + {} + + void rewriterBeginTransaction() override {} + void rewriterEndTransaction() override {} + + void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override + {} + + void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector) {} +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h new file mode 100644 index 0000000000..ed00f71d98 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QIcon> +#include <QList> +#include <QString> +#include <QVariant> + +#include "qmldesignercorelib_global.h" + +QT_BEGIN_NAMESPACE +class QDeclarativeContext; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class MetaInfo; +class Model; +class AbstractProperty; + +class NodeMetaInfo +{ +public: + NodeMetaInfo() {} + NodeMetaInfo(Model *, const TypeName &, int, int) {} + + bool isValid() const { return {}; } + bool isFileComponent() const { return {}; } + bool hasProperty(const PropertyName &) const { return {}; } + PropertyNameList propertyNames() const { return {}; } + PropertyNameList signalNames() const { return {}; } + PropertyNameList directPropertyNames() const { return {}; } + PropertyName defaultPropertyName() const { return "data"; } + bool hasDefaultProperty() const { return {}; } + TypeName propertyTypeName(const PropertyName &) const { return {}; } + bool propertyIsWritable(const PropertyName &) const { return {}; } + bool propertyIsListProperty(const PropertyName &) const { return {}; } + bool propertyIsEnumType(const PropertyName &) const { return {}; } + bool propertyIsPrivate(const PropertyName &) const { return {}; } + QString propertyEnumScope(const PropertyName &) const { return {}; } + QStringList propertyKeysForEnum(const PropertyName &) const { return {}; } + QVariant propertyCastedValue(const PropertyName &, const QVariant &) const { return {}; } + + QList<NodeMetaInfo> classHierarchy() const { return {}; } + QList<NodeMetaInfo> superClasses() const { return {}; } + NodeMetaInfo directSuperClass() const { return {}; } + + bool defaultPropertyIsComponent() const { return {}; } + + TypeName typeName() const { return {}; } + TypeName simplifiedTypeName() const { return {}; } + int majorVersion() const { return {}; } + int minorVersion() const { return {}; } + + QString componentSource() const { return {}; } + QString componentFileName() const { return {}; } + + bool hasCustomParser() const { return {}; } + + bool availableInVersion(int, int) const { return {}; } + bool isSubclassOf(const TypeName &, int = -1, int = -1) const { return {}; } + + bool isGraphicalItem() const { return {}; } + bool isLayoutable() const { return {}; } + bool isView() const { return {}; } + bool isTabView() const { return {}; } + + QString importDirectoryPath() const { return {}; } + + static void clearCache() {} +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/qmlmodelnodefacade.h b/tests/unit/mockup/qmldesigner/designercore/include/qmlmodelnodefacade.h new file mode 100644 index 0000000000..3821943d8f --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/qmlmodelnodefacade.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <modelnode.h> +#include <qmldesignercorelib_global.h> + +namespace QmlDesigner { + +class AbstractView; +class NodeInstanceView; + +class QmlModelNodeFacade +{ +public: + operator ModelNode() const { return {}; } + ModelNode modelNode() { return {}; } + const ModelNode modelNode() const { return {}; } + bool hasModelNode() const { return {}; } + static bool isValidQmlModelNodeFacade(const ModelNode &modelNode) { return {}; } + virtual bool isValid() const { return {}; } + + AbstractView *view() const { return {}; } + static NodeInstanceView *nodeInstanceView(const ModelNode &modelNode) { return {}; } + NodeInstanceView *nodeInstanceView() const { return {}; } + bool isRootNode() const { return {}; } + + QmlModelNodeFacade(const ModelNode &) {} + QmlModelNodeFacade() {} + ~QmlModelNodeFacade(){}; +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/qmlobjectnode.h b/tests/unit/mockup/qmldesigner/designercore/include/qmlobjectnode.h new file mode 100644 index 0000000000..7e2c118589 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/qmlobjectnode.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmlmodelnodefacade.h" +#include <qmldesignercorelib_global.h> + +#include <nodeinstance.h> + +namespace QmlDesigner { + +class QMLDESIGNERCORE_EXPORT QmlObjectNode : public QmlModelNodeFacade +{ +public: + QmlObjectNode() {} + QmlObjectNode(const ModelNode &modelNode){}; +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/qmlstate.h b/tests/unit/mockup/qmldesigner/designercore/include/qmlstate.h new file mode 100644 index 0000000000..50e82596b5 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/qmlstate.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmlmodelnodefacade.h" + +namespace QmlDesigner { + +class QmlModelState : public QmlModelNodeFacade +{ +public: + QmlModelState(); + QmlModelState(const ModelNode &) {} +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/qmltimeline.h b/tests/unit/mockup/qmldesigner/designercore/include/qmltimeline.h new file mode 100644 index 0000000000..0d2c05b1b5 --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/qmltimeline.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmlmodelnodefacade.h" +#include <qmldesignercorelib_global.h> + +namespace QmlDesigner { + +class QmlTimeline : public QmlModelNodeFacade +{ +public: + QmlTimeline() {} + QmlTimeline(const ModelNode &) {} + + bool isValid() const override { return {}; } + + void toogleRecording(bool b) const {} + + void resetGroupRecording() const {} +}; + +} // namespace QmlDesigner diff --git a/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h b/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h new file mode 100644 index 0000000000..39c19e4e2d --- /dev/null +++ b/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmldesignercorelib_global.h" +#include "abstractview.h" + +namespace QmlJS { +class Document; +class ScopeChain; +} + +namespace QmlDesigner { + +class TextModifier; + +namespace Internal { + +class TextToModelMerger; +class ModelToTextMerger; +class ModelNodePositionStorage; + +} //Internal + +struct CppTypeData +{ + QString superClassName; + QString importUrl; + QString versionString; + QString cppClassName; + QString typeName; + bool isSingleton = false; +}; + +class RewriterView : public AbstractView +{ + Q_OBJECT + +public: + enum DifferenceHandling { + Validate, + Amend + }; + +public: + RewriterView(DifferenceHandling, QObject *) {} + ~RewriterView() override {} + + void modelAttached(Model *) override {} + void modelAboutToBeDetached(Model *) override {} + void nodeCreated(const ModelNode &) override {} + void nodeRemoved(const ModelNode &, const NodeAbstractProperty &, PropertyChangeFlags) override + {} + void propertiesAboutToBeRemoved(const QList<AbstractProperty> &) override {} + void propertiesRemoved(const QList<AbstractProperty> &) override {} + void variantPropertiesChanged(const QList<VariantProperty> &, PropertyChangeFlags) override {} + void bindingPropertiesChanged(const QList<BindingProperty> &, PropertyChangeFlags) override {} + void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &, + PropertyChangeFlags) override + {} + void nodeReparented(const ModelNode &, + const NodeAbstractProperty &, + const NodeAbstractProperty &, + AbstractView::PropertyChangeFlags) override + {} + void nodeIdChanged(const ModelNode &, const QString &, const QString &) override {} + void nodeOrderChanged(const NodeListProperty &, const ModelNode &, int) override {} + void rootNodeTypeChanged(const QString &, int, int) override {} + void nodeTypeChanged(const ModelNode &, const TypeName &, int, int) override {} + void customNotification(const AbstractView *, + const QString &, + const QList<ModelNode> &, + const QList<QVariant> &) override + {} + + void rewriterBeginTransaction() override {} + void rewriterEndTransaction() override {} + + void importsChanged(const QList<Import> &, const QList<Import> &) override {} + + TextModifier *textModifier() const { return {}; } + void setTextModifier(TextModifier *) {} + QString textModifierContent() const { return {}; } + + void reactivateTextMofifierChangeSignals() {} + void deactivateTextMofifierChangeSignals() {} + + void auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data) override + {} + + Internal::ModelNodePositionStorage *positionStorage() const {} + + QList<DocumentMessage> warnings() const { return {}; } + QList<DocumentMessage> errors() const { return {}; } + void clearErrorAndWarnings() {} + void setErrors(const QList<DocumentMessage> &) {} + void setWarnings(const QList<DocumentMessage> &) {} + void setIncompleteTypeInformation(bool) {} + bool hasIncompleteTypeInformation() const { return false; } + void addError(const DocumentMessage &) {} + + void enterErrorState(const QString &) {} + bool inErrorState() const { return false; } + void leaveErrorState() {} + void resetToLastCorrectQml() {} + + QMap<ModelNode, QString> extractText(const QList<ModelNode> &) const; + int nodeOffset(const ModelNode &) const; + int nodeLength(const ModelNode &) const; + int firstDefinitionInsideOffset(const ModelNode &) const { return {}; } + int firstDefinitionInsideLength(const ModelNode &) const { return {}; } + bool modificationGroupActive() { return {}; } + ModelNode nodeAtTextCursorPosition(int) const { return {}; } + + bool renameId(const QString &, const QString &) { return {}; } + + const QmlJS::Document *document() const { return {}; } + const QmlJS::ScopeChain *scopeChain() const { return {}; } + + QString convertTypeToImportAlias(const QString &) const { return {}; } + + bool checkSemanticErrors() const { return {}; } + + void setCheckSemanticErrors(bool) {} + + QString pathForImport(const Import &) { return {}; } + + QStringList importDirectories() const { return {}; } + + QSet<QPair<QString, QString>> qrcMapping() const { return {}; } + + void moveToComponent(const ModelNode &) {} + + QStringList autoComplete(const QString &, int, bool = true) { return {}; } + + QList<CppTypeData> getCppTypes() { return {}; } + + void setWidgetStatusCallback(std::function<void(bool)> setWidgetStatusCallback); + + void qmlTextChanged() {} + void delayedSetup() {} + + void writeAuxiliaryData() {} + void restoreAuxiliaryData() {} + + QString getRawAuxiliaryData() const { return {}; } + QString auxiliaryDataAsQML() const { return {}; } + + ModelNode getNodeForCanonicalIndex(int) { return {}; } +}; + +} //QmlDesigner diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index 4aaac22a1b..ef00624b95 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -16,6 +16,7 @@ include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri) include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) include($$PWD/../../../src/plugins/debugger/debuggerunittestfiles.pri) include($$PWD/../../../src/plugins/compilationdatabaseprojectmanager/compilationdatabaseunittestfiles.pri) +include($$PWD/../../../src/plugins/qmldesigner/qmldesignerunittestfiles.pri) !isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):include(cplusplus.pri) !isEmpty(LLVM_VERSION) { include($$PWD/../../../src/plugins/clangtools/clangtoolsunittestfiles.pri) diff --git a/tests/unit/unittest/google-using-declarations.h b/tests/unit/unittest/google-using-declarations.h index 1a92ff3388..de52483403 100644 --- a/tests/unit/unittest/google-using-declarations.h +++ b/tests/unit/unittest/google-using-declarations.h @@ -65,6 +65,8 @@ using testing::Property; using testing::Return; using testing::ReturnRef; using testing::SafeMatcherCast; +using testing::SaveArg; +using testing::SaveArgPointee; using testing::Sequence; using testing::SizeIs; using testing::StrEq; diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 704c9c6b90..13fbe94130 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -47,6 +47,7 @@ #include <filepathview.h> #include <filestatus.h> #include <includesearchpath.h> +#include <modelnode.h> #include <nativefilepath.h> #include <pchpaths.h> #include <pchtask.h> @@ -68,6 +69,7 @@ #include <tooltipinfo.h> #include <usedmacro.h> #include <utils/link.h> +#include <variantproperty.h> #include <sqlite3ext.h> @@ -1450,6 +1452,25 @@ std::ostream &operator<<(std::ostream &out, const Diagnostic &diag) { } // namespace Internal } // namespace ClangTools +namespace QmlDesigner { + +std::ostream &operator<<(std::ostream &out, const ModelNode &node) +{ + if (!node.isValid()) + return out << "(invalid)"; + + return out << "(" << node.id() << ")"; +} +std::ostream &operator<<(std::ostream &out, const VariantProperty &property) +{ + if (!property.isValid()) + return out << "(invalid)"; + + return out << "(" << property.parentModelNode() << ", " << property.name() << ", " + << property.value() << ")"; +} +} // namespace QmlDesigner + void setFilePathCache(ClangBackEnd::FilePathCaching *cache) { filePathCache = cache; diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index e0cb55315f..565479be03 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -350,4 +350,12 @@ std::ostream &operator<<(std::ostream &out, const Diagnostic &diag); } // namespace Internal } // namespace CppTools +namespace QmlDesigner { +class ModelNode; +class VariantProperty; + +std::ostream &operator<<(std::ostream &out, const ModelNode &node); +std::ostream &operator<<(std::ostream &out, const VariantProperty &property); +} // namespace QmlDesigner + void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache); diff --git a/tests/unit/unittest/gtest-qt-printing.cpp b/tests/unit/unittest/gtest-qt-printing.cpp index cd97883b16..c097fd0b4c 100644 --- a/tests/unit/unittest/gtest-qt-printing.cpp +++ b/tests/unit/unittest/gtest-qt-printing.cpp @@ -59,9 +59,11 @@ std::ostream &operator<<(std::ostream &out, const QVariant &variant) QString output; QDebug debug(&output); - debug << variant; + debug.noquote().nospace() << variant; - return out << output; + QByteArray utf8Text = output.toUtf8(); + + return out.write(utf8Text.data(), utf8Text.size()); } std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format) @@ -88,4 +90,14 @@ void PrintTo(const QString &text, std::ostream *os) *os << text; } +void PrintTo(const QVariant &variant, std::ostream *os) +{ + *os << variant; +} + +void PrintTo(const QByteArray &text, std::ostream *os) +{ + *os << text; +} + QT_END_NAMESPACE diff --git a/tests/unit/unittest/gtest-qt-printing.h b/tests/unit/unittest/gtest-qt-printing.h index 424762273b..ebaeb2c785 100644 --- a/tests/unit/unittest/gtest-qt-printing.h +++ b/tests/unit/unittest/gtest-qt-printing.h @@ -35,10 +35,12 @@ class QVariant; class QString; class QTextCharFormat; -std::ostream &operator<<(std::ostream &out, const QVariant &variant); +std::ostream &operator<<(std::ostream &out, const QVariant &QVariant); std::ostream &operator<<(std::ostream &out, const QString &text); std::ostream &operator<<(std::ostream &out, const QByteArray &byteArray); std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format); void PrintTo(const QString &text, std::ostream *os); +void PrintTo(const QVariant &variant, std::ostream *os); +void PrintTo(const QByteArray &text, std::ostream *os); QT_END_NAMESPACE diff --git a/tests/unit/unittest/listmodeleditor-test.cpp b/tests/unit/unittest/listmodeleditor-test.cpp new file mode 100644 index 0000000000..ca0913f865 --- /dev/null +++ b/tests/unit/unittest/listmodeleditor-test.cpp @@ -0,0 +1,952 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include "mocklistmodeleditorview.h" + +#include <qmldesigner/components/listmodeleditor/listmodeleditormodel.h> +#include <qmldesigner/designercore/include/abstractview.h> +#include <qmldesigner/designercore/include/model.h> +#include <qmldesigner/designercore/include/nodelistproperty.h> +#include <qmldesigner/designercore/include/variantproperty.h> + +namespace { + +using QmlDesigner::AbstractProperty; +using QmlDesigner::AbstractView; +using QmlDesigner::ModelNode; + +MATCHER_P2(HasItem, + name, + value, + std::string(negation ? "hasn't " : "has ") + "(" + name + ", " + value + ")") +{ + QStandardItem *item = arg; + + return item->data(Qt::UserRole).toString() == name && item->data(Qt::UserRole).toDouble() == value; +} + +MATCHER(IsInvalid, std::string(negation ? "isn't null" : "is null")) +{ + return !arg.isValid(); +} + +MATCHER_P3(IsVariantProperty, + node, + name, + value, + std::string(negation ? "isn't " : "is ") + "(" + name + ", " + PrintToString(value) + ")") +{ + const QmlDesigner::VariantProperty &property = arg; + + return property.parentModelNode() == node && property.name() == name && property.value() == value; +} + +MATCHER_P2(IsVariantProperty, + name, + value, + std::string(negation ? "isn't " : "is ") + "(" + name + ", " + PrintToString(value) + ")") +{ + const QmlDesigner::VariantProperty &property = arg; + + return property.name() == name && property.value() == value; +} + +MATCHER_P2(IsAbstractProperty, node, name, std::string(negation ? "isn't " : "is ") + "(" + name + ")") +{ + const QmlDesigner::AbstractProperty &property = arg; + + return property.parentModelNode() == node && property.name() == name; +} + +class ListModelEditor : public testing::Test +{ +public: + ListModelEditor() + { + designerModel->attachView(&mockView); + + emptyListModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15); + + listModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15); + mockView.rootModelNode().defaultNodeListProperty().reparentHere(listModelNode); + element1 = createElement({{"name", "foo"}, {"value", 1}, {"value2", 42}}); + element2 = createElement({{"value", 4}, {"name", "bar"}, {"image", "pic.png"}}); + element3 = createElement({{"image", "pic.png"}, {"name", "poo"}, {"value", 111}}); + } + + using Entry = std::pair<QmlDesigner::PropertyName, QVariant>; + + ModelNode createElement(std::initializer_list<Entry> entries) + { + auto element = mockView.createModelNode("QtQml.Models/ListElement", 2, 15); + listModelNode.defaultNodeListProperty().reparentHere(element); + + for (const auto &entry : entries) { + element.variantProperty(entry.first).setValue(entry.second); + } + + return element; + } + + QList<QString> headerLabels(const QmlDesigner::ListModelEditorModel &model) const + { + QList<QString> labels; + labels.reserve(model.columnCount()); + + for (int i = 0; i < model.columnCount(); ++i) + labels.push_back(model.headerData(i, Qt::Horizontal).toString()); + + return labels; + } + + QList<QList<QVariant>> displayValues() const + { + QList<QList<QVariant>> rows; + + for (int rowIndex = 0; rowIndex < model.rowCount(); ++rowIndex) { + QList<QVariant> row; + + for (int columnIndex = 0; columnIndex < model.columnCount(); ++columnIndex) + row.push_back(model.data(model.index(rowIndex, columnIndex), Qt::DisplayRole)); + + rows.push_back(row); + } + + return rows; + } + + QList<QList<QColor>> backgroundColors() const + { + QList<QList<QColor>> rows; + + for (int rowIndex = 0; rowIndex < model.rowCount(); ++rowIndex) { + QList<QColor> row; + + for (int columnIndex = 0; columnIndex < model.columnCount(); ++columnIndex) + row.push_back( + model.data(model.index(rowIndex, columnIndex), Qt::BackgroundColorRole) + .value<QColor>()); + + rows.push_back(row); + } + + return rows; + } + + QList<QList<QmlDesigner::VariantProperty>> properties() const + { + QList<QList<QmlDesigner::VariantProperty>> properties; + properties.reserve(10); + + auto nodes = listModelNode.defaultNodeListProperty().toModelNodeList(); + + for (const ModelNode &node : nodes) + properties.push_back(node.variantProperties()); + + return properties; + } + +protected: + std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; + NiceMock<MockListModelEditorView> mockView; + QmlDesigner::ListModelEditorModel model; + ModelNode listModelNode; + ModelNode emptyListModelNode; + ModelNode element1; + ModelNode element2; + ModelNode element3; +}; + +TEST_F(ListModelEditor, CreatePropertyNameSet) +{ + model.setListModel(listModelNode); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value", "value2")); +} + +TEST_F(ListModelEditor, CreatePropertyNameSetForEmptyList) +{ + model.setListModel(emptyListModelNode); + + ASSERT_THAT(model.propertyNames(), IsEmpty()); +} + +TEST_F(ListModelEditor, HorizontalLabels) +{ + model.setListModel(listModelNode); + + ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value", "value2")); +} + +TEST_F(ListModelEditor, HorizontalLabelsForEmptyList) +{ + model.setListModel(emptyListModelNode); + + ASSERT_THAT(headerLabels(model), IsEmpty()); +} + +TEST_F(ListModelEditor, DisplayValues) +{ + model.setListModel(listModelNode); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, ChangeValueChangesDisplayValues) +{ + model.setListModel(listModelNode); + + model.setValue(0, 1, "hello"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "hello", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, EditValueCallVariantPropertiesChanged) +{ + model.setListModel(listModelNode); + + EXPECT_CALL(mockView, + variantPropertiesChanged(ElementsAre(IsVariantProperty(element1, "name", "hello")), + Eq(AbstractView::NoAdditionalChanges))); + + model.setValue(0, 1, "hello"); +} + +TEST_F(ListModelEditor, ChangeDisplayValueCallsVariantPropertiesChanged) +{ + model.setListModel(listModelNode); + + EXPECT_CALL(mockView, + variantPropertiesChanged(ElementsAre(IsVariantProperty(element1, "name", "hello")), + Eq(AbstractView::NoAdditionalChanges))) + .Times(0); + + model.setValue(0, 1, "hello", Qt::DisplayRole); +} + +TEST_F(ListModelEditor, AddRowAddedInvalidRow) +{ + model.setListModel(listModelNode); + + model.addRow(); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()), + ElementsAre(IsInvalid(), IsInvalid(), IsInvalid(), IsInvalid()))); +} + +TEST_F(ListModelEditor, AddRowCreatesNewModelNodeAndReparents) +{ + model.setListModel(listModelNode); + + EXPECT_CALL(mockView, nodeCreated(Property(&ModelNode::type, Eq("QtQml.Models.ListElement")))); + EXPECT_CALL(mockView, + nodeReparented(Property(&ModelNode::type, Eq("QtQml.Models.ListElement")), + Property(&AbstractProperty::parentModelNode, Eq(listModelNode)), + _, + _)); + + model.addRow(); +} + +TEST_F(ListModelEditor, ChangeAddedRowPropery) +{ + model.setListModel(listModelNode); + model.addRow(); + + model.setValue(3, 2, 22); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()), + ElementsAre(IsInvalid(), IsInvalid(), 22, IsInvalid()))); +} + +TEST_F(ListModelEditor, ChangeAddedRowProperyCallsVariantPropertiesChanged) +{ + model.setListModel(listModelNode); + ModelNode element4; + ON_CALL(mockView, nodeReparented(_, _, _, _)).WillByDefault(SaveArg<0>(&element4)); + model.addRow(); + + EXPECT_CALL(mockView, + variantPropertiesChanged(ElementsAre(IsVariantProperty(element4, "value", 22)), + Eq(AbstractView::PropertiesAdded))); + + model.setValue(3, 2, 22); +} + +TEST_F(ListModelEditor, AddColumnInsertsPropertyName) +{ + model.setListModel(listModelNode); + + model.addColumn("other"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "other", "value", "value2")); +} + +TEST_F(ListModelEditor, AddColumnInsertsPropertyNameToEmptyModel) +{ + model.setListModel(emptyListModelNode); + + model.addColumn("foo"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("foo")); +} + +TEST_F(ListModelEditor, AddTwiceColumnInsertsPropertyNameToEmptyModel) +{ + model.setListModel(emptyListModelNode); + model.addColumn("foo"); + + model.addColumn("foo2"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("foo", "foo2")); +} + +TEST_F(ListModelEditor, AddSameColumnInsertsPropertyName) +{ + model.setListModel(emptyListModelNode); + model.addColumn("foo"); + + model.addColumn("foo"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("foo")); +} + +TEST_F(ListModelEditor, AddColumnInsertsHeaderLabel) +{ + model.setListModel(listModelNode); + + model.addColumn("other"); + + ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "other", "value", "value2")); +} + +TEST_F(ListModelEditor, AddColumnInsertsHeaderLabelToEmptyModel) +{ + model.setListModel(emptyListModelNode); + + model.addColumn("foo"); + + ASSERT_THAT(headerLabels(model), ElementsAre("foo")); +} + +TEST_F(ListModelEditor, AddTwiceColumnInsertsHeaderLabelToEmptyModel) +{ + model.setListModel(emptyListModelNode); + model.addColumn("foo"); + + model.addColumn("foo2"); + + ASSERT_THAT(headerLabels(model), ElementsAre("foo", "foo2")); +} + +TEST_F(ListModelEditor, AddSameColumnInsertsHeaderLabel) +{ + model.setListModel(emptyListModelNode); + model.addColumn("foo"); + + model.addColumn("foo"); + + ASSERT_THAT(headerLabels(model), ElementsAre("foo")); +} + +TEST_F(ListModelEditor, AddColumnInsertsDisplayValues) +{ + model.setListModel(listModelNode); + + model.addColumn("other"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", IsInvalid(), 1, 42), + ElementsAre("pic.png", "bar", IsInvalid(), 4, IsInvalid()), + ElementsAre("pic.png", "poo", IsInvalid(), 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, ChangeAddColumnPropertyDisplayValue) +{ + model.setListModel(listModelNode); + model.addColumn("other"); + + model.setValue(1, 2, 22); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", IsInvalid(), 1, 42), + ElementsAre("pic.png", "bar", 22, 4, IsInvalid()), + ElementsAre("pic.png", "poo", IsInvalid(), 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, ChangeAddColumnPropertyCallsVariantPropertiesChanged) +{ + model.setListModel(listModelNode); + model.addColumn("other"); + + EXPECT_CALL(mockView, + variantPropertiesChanged(ElementsAre(IsVariantProperty(element2, "other", 434)), _)); + + model.setValue(1, 2, 434); +} + +TEST_F(ListModelEditor, RemoveColumnRemovesDisplayValues) +{ + model.setListModel(listModelNode); + + model.removeColumn(2); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 42), + ElementsAre("pic.png", "bar", IsInvalid()), + ElementsAre("pic.png", "poo", IsInvalid()))); +} + +TEST_F(ListModelEditor, RemoveColumnRemovesProperties) +{ + model.setListModel(listModelNode); + + EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element2, "image")))); + EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element3, "image")))); + + model.removeColumn(0); +} + +TEST_F(ListModelEditor, RemoveColumnRemovesPropertyName) +{ + model.setListModel(listModelNode); + + model.removeColumn(1); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "value", "value2")); +} + +TEST_F(ListModelEditor, RemoveRowRemovesDisplayValues) +{ + model.setListModel(listModelNode); + + model.removeRow(1); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, RemoveRowRemovesElementInListModel) +{ + model.setListModel(listModelNode); + + EXPECT_CALL(mockView, nodeRemoved(Eq(element2), _, _)); + + model.removeRow(1); +} + +TEST_F(ListModelEditor, ConvertStringFloatToFloat) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, "25.5"); + + ASSERT_THAT(element2.variantProperty("name").value().value<double>(), 25.5); + ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::Double); +} + +TEST_F(ListModelEditor, ConvertStringIntegerToDouble) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, "25"); + + ASSERT_THAT(element2.variantProperty("name").value().value<double>(), 25); + ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::Double); +} + +TEST_F(ListModelEditor, DontConvertStringToNumber) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, "hello"); + + ASSERT_THAT(element2.variantProperty("name").value().value<QString>(), "hello"); + ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::String); +} + +TEST_F(ListModelEditor, EmptyStringsRemovesProperty) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, ""); + + ASSERT_THAT(element2.variantProperty("name").value().value<QString>(), Eq("")); +} + +TEST_F(ListModelEditor, InvalidVariantRemovesProperty) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, QVariant()); + + ASSERT_FALSE(element2.hasProperty("name")); +} + +TEST_F(ListModelEditor, DispayValueIsChangedToDouble) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, "25.5"); + + ASSERT_THAT(displayValues()[1][1].type(), QVariant::Double); +} + +TEST_F(ListModelEditor, StringDispayValueIsNotChanged) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, "25.5a"); + + ASSERT_THAT(displayValues()[1][1].type(), QVariant::String); +} + +TEST_F(ListModelEditor, SetInvalidToDarkYellowBackgroundColor) +{ + model.setListModel(listModelNode); + + ASSERT_THAT( + backgroundColors(), + ElementsAre( + ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow))); +} + +TEST_F(ListModelEditor, SettingValueChangesBackgroundColor) +{ + model.setListModel(listModelNode); + + model.setValue(0, 0, "foo"); + + ASSERT_THAT( + backgroundColors(), + ElementsAre( + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow))); +} + +TEST_F(ListModelEditor, SettingValueChangesByDisplayRoleBackgroundColor) +{ + model.setListModel(listModelNode); + + model.setValue(0, 0, "foo", Qt::DisplayRole); + + ASSERT_THAT( + backgroundColors(), + ElementsAre( + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow))); +} + +TEST_F(ListModelEditor, ResettingValueChangesBackgroundColor) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, QVariant{}); + + ASSERT_THAT( + backgroundColors(), + ElementsAre( + ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)), + ElementsAre(Not(Qt::darkYellow), Qt::darkYellow, Not(Qt::darkYellow), Qt::darkYellow), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow))); +} + +TEST_F(ListModelEditor, ResettingValueChangesByDisplayRoleBackgroundColor) +{ + model.setListModel(listModelNode); + + model.setValue(1, 1, QVariant{}, Qt::DisplayRole); + + ASSERT_THAT( + backgroundColors(), + ElementsAre( + ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)), + ElementsAre(Not(Qt::darkYellow), Qt::darkYellow, Not(Qt::darkYellow), Qt::darkYellow), + ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow))); +} + +TEST_F(ListModelEditor, SettingNullValueChangesBackgroundColor) +{ + model.setListModel(listModelNode); + + model.setValue(0, 0, 0); + + ASSERT_THAT(backgroundColors(), + ElementsAre(ElementsAre(_, _, _, _), + ElementsAre(_, _, _, Qt::darkYellow), + ElementsAre(_, _, _, Qt::darkYellow))); +} + +TEST_F(ListModelEditor, DontRenamePropertyIfColumnNameExists) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "value2"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value", "value2")); +} + +TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExists) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "value2"); + + ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value", "value2")); +} + +TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExistsDoesNotChangeDisplayValues) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "value2"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExistsDoesNotChangeProperties) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "value2"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("name", "bar"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("name", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RenamePropertyButDontChangeOrder) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "mood"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "mood", "value", "value2")); +} + +TEST_F(ListModelEditor, RenameColumnButDontChangeOrder) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "mood"); + + ASSERT_THAT(headerLabels(model), ElementsAre("image", "mood", "value", "value2")); +} + +TEST_F(ListModelEditor, RenameColumnButDontChangeOrderDisplayValues) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "mood"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42), + ElementsAre("pic.png", "bar", 4, IsInvalid()), + ElementsAre("pic.png", "poo", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, RenameColumnButDontChangeOrderProperies) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "mood"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("mood", "bar"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("mood", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RemoveColumnAfterRenameColumn) +{ + model.setListModel(listModelNode); + model.renameColumn(1, "mood"); + + model.removeColumn(1); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, ChangeValueAfterRenameColumn) +{ + model.setListModel(listModelNode); + model.renameColumn(1, "mood"); + + model.setValue(1, 1, "taaa"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("mood", "taaa"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("mood", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RemovePropertyAfterRenameColumn) +{ + model.setListModel(listModelNode); + model.renameColumn(1, "mood"); + + model.setValue(1, 1, {}); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("mood", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RenameToPrecedingProperty) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "alpha"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("alpha", "image", "value", "value2")); +} + +TEST_F(ListModelEditor, RenameToPrecedingColumn) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "alpha"); + + ASSERT_THAT(headerLabels(model), ElementsAre("alpha", "image", "value", "value2")); +} + +TEST_F(ListModelEditor, RenameToPrecedingColumnDisplayValues) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "alpha"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre("foo", IsInvalid(), 1, 42), + ElementsAre("bar", "pic.png", 4, IsInvalid()), + ElementsAre("poo", "pic.png", 111, IsInvalid()))); +} + +TEST_F(ListModelEditor, RenameToPrecedingColumnProperties) +{ + model.setListModel(listModelNode); + + model.renameColumn(1, "alpha"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("alpha", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("alpha", "bar"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("alpha", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RenameToFollowingProperty) +{ + model.setListModel(listModelNode); + + model.renameColumn(2, "zoo"); + + ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value2", "zoo")); +} + +TEST_F(ListModelEditor, RenameToFollowingColumn) +{ + model.setListModel(listModelNode); + + model.renameColumn(2, "zoo"); + + ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value2", "zoo")); +} + +TEST_F(ListModelEditor, RenameToFollowingColumnDisplayValues) +{ + model.setListModel(listModelNode); + + model.renameColumn(2, "zoo"); + + ASSERT_THAT(displayValues(), + ElementsAre(ElementsAre(IsInvalid(), "foo", 42, 1), + ElementsAre("pic.png", "bar", IsInvalid(), 4), + ElementsAre("pic.png", "poo", IsInvalid(), 111))); +} + +TEST_F(ListModelEditor, RenameToFollowingColumnProperties) +{ + model.setListModel(listModelNode); + + model.renameColumn(2, "zoo"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"), + IsVariantProperty("zoo", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("name", "bar"), + IsVariantProperty("zoo", 4)), + UnorderedElementsAre(IsVariantProperty("image", "pic.png"), + IsVariantProperty("name", "poo"), + IsVariantProperty("zoo", 111)))); +} + +TEST_F(ListModelEditor, RenamePropertiesWithInvalidValue) +{ + model.setListModel(listModelNode); + + model.renameColumn(0, "mood"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("mood", "pic.png"), + IsVariantProperty("name", "bar"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("mood", "pic.png"), + IsVariantProperty("name", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, ChangeValueAfterRenamePropertiesWithInvalidValue) +{ + model.setListModel(listModelNode); + model.renameColumn(0, "mood"); + + model.setValue(0, 0, "haaa"); + + ASSERT_THAT(properties(), + ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "haaa"), + IsVariantProperty("name", "foo"), + IsVariantProperty("value", 1), + IsVariantProperty("value2", 42)), + UnorderedElementsAre(IsVariantProperty("mood", "pic.png"), + IsVariantProperty("name", "bar"), + IsVariantProperty("value", 4)), + UnorderedElementsAre(IsVariantProperty("mood", "pic.png"), + IsVariantProperty("name", "poo"), + IsVariantProperty("value", 111)))); +} + +TEST_F(ListModelEditor, RemoveLastRow) +{ + model.setListModel(emptyListModelNode); + model.addColumn("mood"); + model.addRow(); + + model.removeRow(0); + + ASSERT_THAT(displayValues(), IsEmpty()); +} + +TEST_F(ListModelEditor, RemoveLastColumn) +{ + model.setListModel(emptyListModelNode); + model.addColumn("mood"); + model.addRow(); + + model.removeColumn(0); + + ASSERT_THAT(displayValues(), ElementsAre(IsEmpty())); +} + +TEST_F(ListModelEditor, RemoveLastEmptyColumn) +{ + model.setListModel(emptyListModelNode); + model.addColumn("mood"); + model.addRow(); + model.removeRow(0); + + model.removeColumn(0); + + ASSERT_THAT(displayValues(), IsEmpty()); +} + +TEST_F(ListModelEditor, RemoveLastEmptyRow) +{ + model.setListModel(emptyListModelNode); + model.addColumn("mood"); + model.addRow(); + model.removeColumn(0); + + model.removeRow(0); + + ASSERT_THAT(displayValues(), IsEmpty()); +} + +} // namespace diff --git a/tests/unit/unittest/mockfilesystem.h b/tests/unit/unittest/mockfilesystem.h index 688edbcae5..fff5758cc6 100644 --- a/tests/unit/unittest/mockfilesystem.h +++ b/tests/unit/unittest/mockfilesystem.h @@ -34,4 +34,5 @@ class MockFileSystem : public ClangBackEnd::FileSystemInterface public: MOCK_CONST_METHOD1(directoryEntries, ClangBackEnd::FilePathIds(const QString &directoryPath)); MOCK_CONST_METHOD1(lastModified, long long(ClangBackEnd::FilePathId filePathId)); + MOCK_METHOD1(remove, void(const ClangBackEnd::FilePathIds &filePathIds)); }; diff --git a/tests/unit/unittest/mocklistmodeleditorview.h b/tests/unit/unittest/mocklistmodeleditorview.h new file mode 100644 index 0000000000..6bec164f33 --- /dev/null +++ b/tests/unit/unittest/mocklistmodeleditorview.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <googletest.h> + +#include <qmldesigner/designercore/include/abstractview.h> + +class MockListModelEditorView : public QmlDesigner::AbstractView +{ +public: + MOCK_METHOD(void, + variantPropertiesChanged, + (const QList<QmlDesigner::VariantProperty> &propertyList, + PropertyChangeFlags propertyChange), + (override)); + MOCK_METHOD(void, nodeCreated, (const QmlDesigner::ModelNode &createdNode), (override)); + MOCK_METHOD(void, + nodeReparented, + (const QmlDesigner::ModelNode &node, + const QmlDesigner::NodeAbstractProperty &newPropertyParent, + const QmlDesigner::NodeAbstractProperty &oldPropertyParent, + AbstractView::PropertyChangeFlags propertyChange), + (override)); + MOCK_METHOD(void, + propertiesRemoved, + (const QList<QmlDesigner::AbstractProperty> &propertyList), + (override)); + + MOCK_METHOD(void, + nodeRemoved, + (const QmlDesigner::ModelNode &removedNode, + const QmlDesigner::NodeAbstractProperty &parentProperty, + AbstractView::PropertyChangeFlags propertyChange), + (override)); +}; diff --git a/tests/unit/unittest/mockprecompiledheaderstorage.h b/tests/unit/unittest/mockprecompiledheaderstorage.h index de755e07eb..5dddf97fce 100644 --- a/tests/unit/unittest/mockprecompiledheaderstorage.h +++ b/tests/unit/unittest/mockprecompiledheaderstorage.h @@ -57,4 +57,5 @@ public: MOCK_CONST_METHOD1( fetchTimeStamps, ClangBackEnd::PrecompiledHeaderTimeStamps(ClangBackEnd::ProjectPartId projectPartId)); + MOCK_CONST_METHOD0(fetchAllPchPaths, ClangBackEnd::FilePaths()); }; diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 1a27eea50f..1f5bc53759 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -107,6 +107,12 @@ FilePathIds MockSqliteReadStatement::values<ClangBackEnd::FilePathId>(std::size_ return valuesReturnFilePathIds(reserveSize, projectPartId); } +template<> +ClangBackEnd::FilePaths MockSqliteReadStatement::values<ClangBackEnd::FilePath>(std::size_t reserveSize) +{ + return valuesReturnFilePaths(reserveSize); +} + template <> std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize) { diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 04e1f8effc..11a7b126e5 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -113,6 +113,8 @@ public: MOCK_METHOD1(valueReturnFilePath, Utils::optional<ClangBackEnd::FilePath>(int)); + MOCK_METHOD1(valuesReturnFilePaths, ClangBackEnd::FilePaths(std::size_t)); + MOCK_METHOD1(valueReturnSmallString, Utils::optional<Utils::SmallString>(int)); @@ -233,6 +235,9 @@ template<> FilePathIds MockSqliteReadStatement::values<ClangBackEnd::FilePathId>(std::size_t reserveSize, const int &projectPartId); +template<> +ClangBackEnd::FilePaths MockSqliteReadStatement::values<ClangBackEnd::FilePath>(std::size_t reserveSize); + template <> std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize); diff --git a/tests/unit/unittest/pchtaskqueue-test.cpp b/tests/unit/unittest/pchtaskqueue-test.cpp index 598a2a5132..6a4a2211d8 100644 --- a/tests/unit/unittest/pchtaskqueue-test.cpp +++ b/tests/unit/unittest/pchtaskqueue-test.cpp @@ -25,14 +25,18 @@ #include "googletest.h" +#include "mockfilesystem.h" #include "mockpchcreator.h" #include "mockprecompiledheaderstorage.h" #include "mocksqlitetransactionbackend.h" #include "mocktaskscheduler.h" #include "testenvironment.h" +#include <filepathcaching.h> #include <pchtaskqueue.h> #include <progresscounter.h> +#include <refactoringdatabaseinitializer.h> +#include <sqlitedatabase.h> namespace { @@ -45,9 +49,26 @@ using ClangBackEnd::SlotUsage; class PchTaskQueue : public testing::Test { protected: + ClangBackEnd::FilePathId filePathId(Utils::SmallStringView path) + { + return filePathCache.filePathId(ClangBackEnd::FilePathView{path}); + } + + ClangBackEnd::FilePathIds filePathIds(const Utils::PathStringVector &paths) + { + return filePathCache.filePathIds(Utils::transform(paths, [](const Utils::PathString &path) { + return ClangBackEnd::FilePathView(path); + })); + } + +protected: + Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; + ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockSytemPchTaskScheduler; NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockProjectPchTaskScheduler; NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage; + NiceMock<MockFileSystem> mockFileSystem; MockSqliteTransactionBackend mockSqliteTransactionBackend; NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback; ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()}; @@ -57,7 +78,9 @@ protected: progressCounter, mockPrecompiledHeaderStorage, mockSqliteTransactionBackend, - testEnvironment}; + testEnvironment, + mockFileSystem, + filePathCache}; IncludeSearchPaths systemIncludeSearchPaths{ {"/includes", 1, IncludeSearchPathType::BuiltIn}, {"/other/includes", 2, IncludeSearchPathType::System}}; @@ -390,4 +413,91 @@ TEST_F(PchTaskQueue, DeleteSystemPchEntryInDatabaseIfNoPchIsGenerated) tasks.front()(mockPchCreator); } +TEST_F(PchTaskQueue, DontDeleteUnusedPchsIfSystemTaskAreProcessed) +{ + QString pchsDirectory{testEnvironment.pchBuildDirectory()}; + ON_CALL(mockSytemPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 1})); + ON_CALL(mockProjectPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockFileSystem, directoryEntries(Eq(pchsDirectory))) + .WillByDefault(Return(filePathIds({"/tmp/foo", "/tmp/bar"}))); + ON_CALL(mockPrecompiledHeaderStorage, fetchAllPchPaths()) + .WillByDefault(Return(ClangBackEnd::FilePaths{"/tmp/foo", "/tmp/poo"})); + + EXPECT_CALL(mockFileSystem, remove(_)).Times(0); + + queue.processEntries(); +} + +TEST_F(PchTaskQueue, DontDeleteUnusedPchsIfProjectTaskAreProcessed) +{ + QString pchsDirectory{testEnvironment.pchBuildDirectory()}; + ON_CALL(mockSytemPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockProjectPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 1})); + ON_CALL(mockFileSystem, directoryEntries(Eq(pchsDirectory))) + .WillByDefault(Return(filePathIds({"/tmp/foo", "/tmp/bar"}))); + ON_CALL(mockPrecompiledHeaderStorage, fetchAllPchPaths()) + .WillByDefault(Return(ClangBackEnd::FilePaths{"/tmp/foo", "/tmp/poo"})); + + EXPECT_CALL(mockFileSystem, remove(_)).Times(0); + + queue.processEntries(); +} + +TEST_F(PchTaskQueue, DontDeleteUnusedPchsIfSystemTaskIsAdded) +{ + QString pchsDirectory{testEnvironment.pchBuildDirectory()}; + ON_CALL(mockSytemPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockProjectPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockFileSystem, directoryEntries(Eq(pchsDirectory))) + .WillByDefault(Return(filePathIds({"/tmp/foo", "/tmp/bar"}))); + ON_CALL(mockPrecompiledHeaderStorage, fetchAllPchPaths()) + .WillByDefault(Return(ClangBackEnd::FilePaths{"/tmp/foo", "/tmp/poo"})); + queue.addSystemPchTasks({systemTask1}); + + EXPECT_CALL(mockFileSystem, remove(_)).Times(0); + + queue.processEntries(); +} + +TEST_F(PchTaskQueue, DontDeleteUnusedPchsIfProjectTaskIsAdded) +{ + QString pchsDirectory{testEnvironment.pchBuildDirectory()}; + ON_CALL(mockSytemPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockProjectPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockFileSystem, directoryEntries(Eq(pchsDirectory))) + .WillByDefault(Return(filePathIds({"/tmp/foo", "/tmp/bar"}))); + ON_CALL(mockPrecompiledHeaderStorage, fetchAllPchPaths()) + .WillByDefault(Return(ClangBackEnd::FilePaths{"/tmp/foo", "/tmp/poo"})); + queue.addProjectPchTasks({projectTask1}); + + EXPECT_CALL(mockFileSystem, remove(_)).Times(0); + + queue.processEntries(); +} + +TEST_F(PchTaskQueue, DeleteUnusedPchs) +{ + QString pchsDirectory{testEnvironment.pchBuildDirectory()}; + ON_CALL(mockSytemPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockProjectPchTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0})); + ON_CALL(mockFileSystem, directoryEntries(Eq(pchsDirectory))) + .WillByDefault(Return(filePathIds({ + "/tmp/foo", + "/tmp/bar", + "/tmp/hoo", + "/tmp/too", + }))); + ON_CALL(mockPrecompiledHeaderStorage, fetchAllPchPaths()) + .WillByDefault(Return(ClangBackEnd::FilePaths{ + "/tmp/foo", + "/tmp/poo", + "/tmp/too", + })); + + EXPECT_CALL(mockFileSystem, + remove(UnorderedElementsAre(filePathId("/tmp/bar"), filePathId("/tmp/hoo")))); + + queue.processEntries(); +} + } // namespace diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp index 8b3727decd..77574a28b9 100644 --- a/tests/unit/unittest/precompiledheaderstorage-test.cpp +++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp @@ -53,6 +53,7 @@ protected: MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement; MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement; MockSqliteReadStatement &fetchTimeStampsStatement = storage.fetchTimeStampsStatement; + MockSqliteReadStatement &fetchAllPchPathsStatement = storage.fetchAllPchPathsStatement; }; TEST_F(PrecompiledHeaderStorage, UseTransaction) @@ -458,6 +459,32 @@ TEST_F(PrecompiledHeaderStorage, FetchTimeStampsBusy) storage.fetchTimeStamps(23); } +TEST_F(PrecompiledHeaderStorage, FetchAllPchPaths) +{ + InSequence s; + + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchAllPchPathsStatement, valuesReturnFilePaths(_)); + EXPECT_CALL(database, commit()); + + storage.fetchAllPchPaths(); +} + +TEST_F(PrecompiledHeaderStorage, FetchAllPchPathsIsBusy) +{ + InSequence s; + + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchAllPchPathsStatement, valuesReturnFilePaths(_)) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(database, rollback()); + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchAllPchPathsStatement, valuesReturnFilePaths(_)); + EXPECT_CALL(database, commit()); + + storage.fetchAllPchPaths(); +} + class PrecompiledHeaderStorageSlowTest : public testing::Test { protected: @@ -478,4 +505,18 @@ TEST_F(PrecompiledHeaderStorageSlowTest, NoFetchTimeStamps) Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::system, Eq(33)))); } +TEST_F(PrecompiledHeaderStorageSlowTest, FetchAllPchPaths) +{ + storage.insertProjectPrecompiledHeader(11, "/tmp/yi", 22); + storage.insertProjectPrecompiledHeader(12, "/tmp/er", 22); + storage.insertSystemPrecompiledHeaders({11, 12}, "/tmp/se", 33); + storage.insertSystemPrecompiledHeaders({13}, "/tmp/wu", 33); + storage.insertProjectPrecompiledHeader(13, "/tmp/san", 22); + + auto filePathIds = storage.fetchAllPchPaths(); + + ASSERT_THAT(filePathIds, + UnorderedElementsAre("/tmp/er", "/tmp/san", "/tmp/se", "/tmp/wu", "/tmp/yi")); +} + } // namespace diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index e9a96ace5f..3917237d0b 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -1,4 +1,5 @@ INCLUDEPATH += ../mockup +INCLUDEPATH += ../mockup/qmldesigner/designercore/include QT += core network testlib widgets CONFIG += console c++14 testcase @@ -38,8 +39,11 @@ CONFIG(release, debug|release):QMAKE_LFLAGS += -Wl,--strip-debug } gcc:!clang: QMAKE_CXXFLAGS += -Wno-noexcept-type -msvc: QMAKE_CXXFLAGS += /bigobj /wd4267 /wd4141 /wd4146 +msvc{ +QMAKE_CXXFLAGS += /bigobj /wd4267 /wd4141 /wd4146 /wd4624 +QMAKE_LFLAGS += /INCREMENTAL +} # create fake CppTools.json for the mime type definitions dependencyList = "\"Dependencies\" : []" cpptoolsjson.input = $$PWD/../../../src/plugins/cpptools/CppTools.json.in @@ -65,6 +69,7 @@ SOURCES += \ gtest-qt-printing.cpp \ lastchangedrowid-test.cpp \ lineprefixer-test.cpp \ + listmodeleditor-test.cpp \ locatorfilter-test.cpp \ mimedatabase-utilities.cpp \ pchmanagerclientserverinprocess-test.cpp \ @@ -132,18 +137,15 @@ SOURCES += \ sqlstatementbuilder-test.cpp \ createtablesqlstatementbuilder-test.cpp -!isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):matchingtext-test.cpp +!isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):SOURCES += matchingtext-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ - activationsequencecontextprocessor-test.cpp \ - activationsequenceprocessor-test.cpp \ chunksreportedmonitor.cpp \ clangasyncjob-base.cpp \ clangcodecompleteresults-test.cpp \ clangcodemodelserver-test.cpp \ clangcompletecodejob-test.cpp \ - clangcompletioncontextanalyzer-test.cpp \ clangdiagnosticfilter-test.cpp \ clangdocumentprocessors-test.cpp \ clangdocumentprocessor-test.cpp \ @@ -183,6 +185,12 @@ SOURCES += \ unsavedfile-test.cpp \ utf8positionfromlinecolumn-test.cpp \ readexporteddiagnostics-test.cpp + +!isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):SOURCE += \ + clangcompletioncontextanalyzer-test.cpp \ + activationsequencecontextprocessor-test.cpp \ + activationsequenceprocessor-test.cpp + } !isEmpty(LIBTOOLING_LIBS) { @@ -198,7 +206,6 @@ SOURCES += \ refactoringclientserverinprocess-test.cpp \ refactoringclient-test.cpp \ refactoringcompilationdatabase-test.cpp \ - refactoringengine-test.cpp \ refactoringserver-test.cpp \ sourcerangeextractor-test.cpp \ symbolindexing-test.cpp \ @@ -207,6 +214,9 @@ SOURCES += \ usedmacrocollector-test.cpp \ builddependencycollector-test.cpp \ tokenprocessor-test.cpp + +!isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):SOURCES += refactoringengine-test.cpp + } !isEmpty(CLANGFORMAT_LIBS) { @@ -237,6 +247,7 @@ HEADERS += \ mockclangpathwatcher.h \ mockclangpathwatchernotifier.h \ mockfilesystem.h \ + mocklistmodeleditorview.h \ mockpchcreator.h \ mockpchmanagerclient.h \ mockpchmanagernotifier.h \ @@ -288,7 +299,11 @@ HEADERS += \ mockbuilddependencygenerator.h \ mockpchtasksmerger.h \ mockpchtaskqueue.h \ - mockpchtaskgenerator.h + mockpchtaskgenerator.h \ + ../mockup/qmldesigner/designercore/include/nodeinstanceview.h \ + ../mockup/qmldesigner/designercore/include/rewriterview.h \ + ../mockup/qmldesigner/designercore/include/itemlibraryitem.h + !isEmpty(LIBCLANG_LIBS) { HEADERS += \ |