diff options
Diffstat (limited to 'autotests/kconfig_compiler')
9 files changed, 305 insertions, 12 deletions
diff --git a/autotests/kconfig_compiler/CMakeLists.txt b/autotests/kconfig_compiler/CMakeLists.txt index a2ebb945..289e9583 100644 --- a/autotests/kconfig_compiler/CMakeLists.txt +++ b/autotests/kconfig_compiler/CMakeLists.txt @@ -3,14 +3,19 @@ # ../kconfig_compiler_kf5 $(srcdir)/test5.kcfg $(srcdir)/test5.kcfgc macro(GEN_KCFG_TEST_SOURCE _testName _srcs) + cmake_parse_arguments(ARG "" "KCFG" "" ${ARGN} ) + set(_kcfgFile ${ARG_KCFG}) + if (NOT _kcfgFile) + set(_kcfgFile "${_testName}.kcfg") + endif() add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h - COMMAND ${KConfig_KCFGC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc kconfig_compiler_kf5) + COMMAND ${KConfig_KCFGC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${_kcfgFile} ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_kcfgFile} ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc kconfig_compiler_kf5) -# set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h PROPERTIES GENERATED TRUE) + # set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h PROPERTIES GENERATED TRUE) qt5_generate_moc(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.moc ) -# do not run automoc on the generated file + # do not run automoc on the generated file set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp PROPERTIES SKIP_AUTOMOC TRUE) set( ${_srcs} ${${_srcs}} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h ) @@ -197,6 +202,18 @@ target_link_libraries(test_signal KF5::ConfigGui) ########### next target ############### +set(kconfigcompiler_test_signals_SRCS kconfigcompiler_test_signals.cpp) +gen_kcfg_test_source(signals_test_singleton kconfigcompiler_test_signals_SRCS KCFG signals_test.kcfg) +gen_kcfg_test_source(signals_test_no_singleton kconfigcompiler_test_signals_SRCS KCFG signals_test.kcfg) +gen_kcfg_test_source(signals_test_singleton_dpointer kconfigcompiler_test_signals_SRCS KCFG signals_test.kcfg) +gen_kcfg_test_source(signals_test_no_singleton_dpointer kconfigcompiler_test_signals_SRCS KCFG signals_test.kcfg) +add_executable(kconfigcompiler_test_signals ${kconfigcompiler_test_signals_SRCS}) +ecm_mark_as_test(kconfigcompiler_test_signals) +target_link_libraries(kconfigcompiler_test_signals Qt5::Test KF5::ConfigGui) +add_test(kconfig-kconfigcompiler-signals kconfigcompiler_test_signals) + +########### next target ############### + set(kconfigcompiler_test_SRCS kconfigcompiler_test.cpp ) add_executable(kconfigcompiler_test ${kconfigcompiler_test_SRCS}) ecm_mark_as_test(kconfigcompiler_test) diff --git a/autotests/kconfig_compiler/kconfigcompiler_test_signals.cpp b/autotests/kconfig_compiler/kconfigcompiler_test_signals.cpp new file mode 100644 index 00000000..3017fe2f --- /dev/null +++ b/autotests/kconfig_compiler/kconfigcompiler_test_signals.cpp @@ -0,0 +1,214 @@ +/* +Copyright (c) 2014 Alexander Richardson <alex.richardson@gmx.de> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "signals_test_singleton.h" +#include "signals_test_no_singleton.h" +#include "signals_test_singleton_dpointer.h" +#include "signals_test_no_singleton_dpointer.h" +#include <QtTest/QtTestGui> +#include <QtTest/QSignalSpy> +#include <QtCore/QSharedPointer> +#include <QtCore/QtGlobal> +#include <QtCore/QDebug> +#include <QTemporaryFile> +#include <QFileInfo> +#include <functional> + +class KConfigCompiler_Test_Signals : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testSetters(); + void testSetters_data(); + void testSetProperty(); + void testSetProperty_data(); + void initTestCase(); + void cleanupTestCase(); +}; + +static SignalsTestNoSingleton* noSingleton; +static SignalsTestNoSingletonDpointer* noSingletonDpointer; + +void KConfigCompiler_Test_Signals::initTestCase() +{ + // These tests do a lot quite a few I/O operations, speed that up by using a QTemporaryFile. + // At least on Linux this is often a tmpfs which means only RAM operations + QTemporaryFile* tempFile1 = new QTemporaryFile(this); + QTemporaryFile* tempFile2 = new QTemporaryFile(this); + QTemporaryFile* tempFile3 = new QTemporaryFile(this); + QTemporaryFile* tempFile4 = new QTemporaryFile(this); + QVERIFY(tempFile1->open()); + QVERIFY(tempFile2->open()); + QVERIFY(tempFile3->open()); + QVERIFY(tempFile4->open()); + + SignalsTestSingleton::instance(QFileInfo(*tempFile1).absoluteFilePath()); + SignalsTestSingletonDpointer::instance(QFileInfo(*tempFile2).absoluteFilePath()); + noSingleton = new SignalsTestNoSingleton( + KSharedConfig::openConfig(QFileInfo(*tempFile3).absoluteFilePath(), KConfig::SimpleConfig)); + noSingletonDpointer = new SignalsTestNoSingletonDpointer( + KSharedConfig::openConfig(QFileInfo(*tempFile4).absoluteFilePath(), KConfig::SimpleConfig)); +} + +void KConfigCompiler_Test_Signals::cleanupTestCase() +{ + //ensure these instances are deleted before the temporary files are closed + delete noSingleton; + delete noSingletonDpointer; + delete SignalsTestSingleton::self(); + delete SignalsTestSingletonDpointer::self(); +} + +struct TestSettersArg { + // default constructor required for Q_DECLARE_METATYPE + TestSettersArg() : obj(nullptr) {} + template<typename T> + TestSettersArg(T* object) : obj(object) { + // we can also call static methods using object->foo() so this works for all four cases + getter = [object]() { return object->foo(); }; + defaultGetter = [object]() { return object->defaultFooValue(); }; + setter = [object](const QString& s) { object->setFoo(s); }; + } + KCoreConfigSkeleton* obj; + std::function<QString()> getter; + std::function<QString()> defaultGetter; + std::function<void(const QString&)> setter; +}; + +Q_DECLARE_METATYPE(TestSettersArg); // so that QFETCH works + +void KConfigCompiler_Test_Signals::testSetters_data() +{ + QTest::addColumn<TestSettersArg>("params"); + QTest::newRow("singleton") << TestSettersArg(SignalsTestSingleton::self()); + QTest::newRow("singleton dpointer") << TestSettersArg(SignalsTestSingletonDpointer::self()); + QTest::newRow("non-singleton") << TestSettersArg(noSingleton); + QTest::newRow("non-singleton dpointer") << TestSettersArg(noSingleton); +} + +/** Ensure that a signal is emitted whenever the data is changed by using the generated setters */ +void KConfigCompiler_Test_Signals::testSetters() +{ + QFETCH(TestSettersArg, params); + const char* signal = SIGNAL(fooChanged(QString)); + const QString defaultValue = QStringLiteral("default"); + const QString changedValue = QStringLiteral("changed"); + + // make sure we are in the default state + params.obj->setDefaults(); + params.obj->writeConfig(); + + QList<QVariant> args; + QSignalSpy spy(params.obj, signal); + QVERIFY2(spy.isValid(), signal); + + //change value via setter, should get signal + QCOMPARE(params.getter(), defaultValue); + QCOMPARE(defaultValue, params.defaultGetter()); + QCOMPARE(params.getter(), params.defaultGetter()); + QVERIFY(changedValue != params.getter()); + params.setter(changedValue); + QCOMPARE(params.getter(), changedValue); + QCOMPARE(spy.count(), 0); //should have no change yet, only after writeConfig() + params.obj->writeConfig(); + QCOMPARE(spy.count(), 1); + args = spy.takeFirst(); + QCOMPARE(args.size(), 1); + QCOMPARE(args[0].value<QString>(), changedValue); + + //reset to default values via setDefaults() + QVERIFY(params.getter() != params.defaultGetter()); + QVERIFY(params.getter() != defaultValue); + QCOMPARE(params.getter(), changedValue); + params.obj->setDefaults(); + QCOMPARE(params.getter(), params.defaultGetter()); + QCOMPARE(params.getter(), defaultValue); + + QCOMPARE(spy.count(), 0); //should have no change yet, only after writeConfig() + params.obj->writeConfig(); + //TODO: This currently fails since setDefaults() does not yet cause emitting a signal + QCOMPARE(spy.count(), 1); + args = spy.takeFirst(); + QCOMPARE(args.size(), 1); + QCOMPARE(args[0].value<QString>(), defaultValue); +} + +Q_DECLARE_METATYPE(KCoreConfigSkeleton*); + +void KConfigCompiler_Test_Signals::testSetProperty_data() +{ + QTest::addColumn<KCoreConfigSkeleton*>("obj"); + QTest::newRow("singleton") << static_cast<KCoreConfigSkeleton*>(SignalsTestSingleton::self()); + QTest::newRow("singleton dpointer") << static_cast<KCoreConfigSkeleton*>(SignalsTestSingletonDpointer::self()); + QTest::newRow("non-singleton") << static_cast<KCoreConfigSkeleton*>(noSingleton); + QTest::newRow("non-singleton dpointer") << static_cast<KCoreConfigSkeleton*>(noSingletonDpointer); +} + +/** Test that the signal is emitted when modifying the values using the underlying KConfigSkeletonItem (bypassing the setters) */ +void KConfigCompiler_Test_Signals::testSetProperty() +{ + QFETCH(KCoreConfigSkeleton*, obj); + const char* signal = SIGNAL(fooChanged(QString)); + const QString propertyName = QStringLiteral("foo"); + const QString defaultValue = QStringLiteral("default"); + const QString newValue = QStringLiteral("changed"); + obj->setDefaults(); + obj->writeConfig(); + + KConfigSkeletonItem* item = obj->findItem(propertyName); + QVERIFY2(item, "Item must exist"); + QVERIFY2(!item->isImmutable(), "Item must not be immutable"); + QVERIFY2(!obj->isImmutable(propertyName), "Item must not be immutable"); + + //listen for all expected signals + QSignalSpy spy(obj, signal); + QVERIFY2(spy.isValid(), signal); + + QVERIFY(item->isEqual(defaultValue)); + QVERIFY(!item->isEqual(newValue)); + + item->setProperty(newValue); //change value now + //should have no change yet, only after writeConfig() + QCOMPARE(spy.count(), 0); + obj->writeConfig(); + //now check for the signal emissions + QCOMPARE(spy.count(), 1); + QList<QVariant> args = spy.takeFirst(); + QCOMPARE(args.size(), 1); + QVERIFY(item->isEqual(args[0])); + + //now reset to default + QVERIFY(!item->isEqual(defaultValue)); + item->setDefault(); + QVERIFY(item->isEqual(defaultValue)); + //should have no change yet, only after writeConfig() + QCOMPARE(spy.count(), 0); + obj->writeConfig(); + //now check for the signal emissions + QCOMPARE(spy.count(), 1); + args = spy.takeFirst(); + QCOMPARE(args.size(), 1); + QVERIFY(item->isEqual(args[0])); +} + +QTEST_MAIN(KConfigCompiler_Test_Signals) + +#include "kconfigcompiler_test_signals.moc" diff --git a/autotests/kconfig_compiler/signals_test.kcfg b/autotests/kconfig_compiler/signals_test.kcfg new file mode 100644 index 00000000..766c56eb --- /dev/null +++ b/autotests/kconfig_compiler/signals_test.kcfg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Alex Richardson --> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile arg="true"/> + <signal name="fooChanged"> + <argument type="String">foo</argument> + </signal> + <group name="Something"> + <entry key="foo" type="String"> + <default>default</default> + <emit signal="fooChanged" /> + </entry> + </group> +</kcfg> diff --git a/autotests/kconfig_compiler/signals_test_no_singleton.kcfgc b/autotests/kconfig_compiler/signals_test_no_singleton.kcfgc new file mode 100644 index 00000000..4d096e08 --- /dev/null +++ b/autotests/kconfig_compiler/signals_test_no_singleton.kcfgc @@ -0,0 +1,9 @@ +File=signals_test.kcfg +ClassName=SignalsTestNoSingleton +Singleton=false +Mutators=true +MemberVariables=private +GlobalEnums=false +UseEnumTypes=false +ItemAccessors=false +DefaultValueGetters=true diff --git a/autotests/kconfig_compiler/signals_test_no_singleton_dpointer.kcfgc b/autotests/kconfig_compiler/signals_test_no_singleton_dpointer.kcfgc new file mode 100644 index 00000000..11b7c435 --- /dev/null +++ b/autotests/kconfig_compiler/signals_test_no_singleton_dpointer.kcfgc @@ -0,0 +1,9 @@ +File=signals_test.kcfg +ClassName=SignalsTestNoSingletonDpointer +Singleton=false +Mutators=true +MemberVariables=dpointer +GlobalEnums=false +UseEnumTypes=false +ItemAccessors=false +DefaultValueGetters=true diff --git a/autotests/kconfig_compiler/signals_test_singleton.kcfgc b/autotests/kconfig_compiler/signals_test_singleton.kcfgc new file mode 100644 index 00000000..59e04452 --- /dev/null +++ b/autotests/kconfig_compiler/signals_test_singleton.kcfgc @@ -0,0 +1,9 @@ +File=signals_test.kcfg +ClassName=SignalsTestSingleton +Singleton=true +Mutators=true +MemberVariables=private +GlobalEnums=false +UseEnumTypes=false +ItemAccessors=false +DefaultValueGetters=true diff --git a/autotests/kconfig_compiler/signals_test_singleton_dpointer.kcfgc b/autotests/kconfig_compiler/signals_test_singleton_dpointer.kcfgc new file mode 100644 index 00000000..1f13493a --- /dev/null +++ b/autotests/kconfig_compiler/signals_test_singleton_dpointer.kcfgc @@ -0,0 +1,9 @@ +File=signals_test.kcfg +ClassName=SignalsTestSingletonDpointer +Singleton=true +Mutators=true +MemberVariables=dpointer +GlobalEnums=false +UseEnumTypes=false +ItemAccessors=false +DefaultValueGetters=true diff --git a/autotests/kconfig_compiler/test_signal.cpp.ref b/autotests/kconfig_compiler/test_signal.cpp.ref index fd2d4bc9..35b5cba2 100644 --- a/autotests/kconfig_compiler/test_signal.cpp.ref +++ b/autotests/kconfig_compiler/test_signal.cpp.ref @@ -30,19 +30,21 @@ TestSignal::TestSignal( ) { Q_ASSERT(!s_globalTestSignal()->q); s_globalTestSignal()->q = this; + KConfigCompilerSignallingItem::NotifyFunction notifyFunction = static_cast<KConfigCompilerSignallingItem::NotifyFunction>(&TestSignal::itemChanged); + setCurrentGroup( QLatin1String( "Appearance" ) ); - KConfigSkeleton::ItemString *itemEmoticonTheme; - itemEmoticonTheme = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "emoticonTheme" ), mEmoticonTheme, QLatin1String( "Default" ) ); + KConfigCompilerSignallingItem *itemEmoticonTheme; + itemEmoticonTheme = new KConfigCompilerSignallingItem(new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "emoticonTheme" ), mEmoticonTheme, QLatin1String( "Default" ) ), this, notifyFunction, signalEmoticonSettingsChanged); addItem( itemEmoticonTheme, QLatin1String( "emoticonTheme" ) ); - KConfigSkeleton::ItemBool *itemUseEmoticon; - itemUseEmoticon = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "useEmoticon" ), mUseEmoticon, true ); + KConfigCompilerSignallingItem *itemUseEmoticon; + itemUseEmoticon = new KConfigCompilerSignallingItem(new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "useEmoticon" ), mUseEmoticon, true ), this, notifyFunction, signalEmoticonSettingsChanged); addItem( itemUseEmoticon, QLatin1String( "useEmoticon" ) ); - KConfigSkeleton::ItemBool *itemEmoticonRequireSpace; - itemEmoticonRequireSpace = new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "emoticonRequireSpace" ), mEmoticonRequireSpace, true ); + KConfigCompilerSignallingItem *itemEmoticonRequireSpace; + itemEmoticonRequireSpace = new KConfigCompilerSignallingItem(new KConfigSkeleton::ItemBool( currentGroup(), QLatin1String( "emoticonRequireSpace" ), mEmoticonRequireSpace, true ), this, notifyFunction, signalEmoticonSettingsChanged); addItem( itemEmoticonRequireSpace, QLatin1String( "emoticonRequireSpace" ) ); - KConfigSkeleton::ItemString *itemStylePath; - itemStylePath = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "stylePath" ), mStylePath ); + KConfigCompilerSignallingItem *itemStylePath; + itemStylePath = new KConfigCompilerSignallingItem(new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "stylePath" ), mStylePath ), this, notifyFunction, signalStyleChanged); addItem( itemStylePath, QLatin1String( "stylePath" ) ); KConfigSkeleton::ItemString *itemStyleCSSVariant; itemStyleCSSVariant = new KConfigSkeleton::ItemString( currentGroup(), QLatin1String( "styleVariant" ), mStyleCSSVariant ); @@ -69,5 +71,9 @@ bool TestSignal::usrWriteConfig() return true; } +void TestSignal::itemChanged(quint64 flags) { + mSettingsChanged |= flags; +} + #include "test_signal.moc" diff --git a/autotests/kconfig_compiler/test_signal.h.ref b/autotests/kconfig_compiler/test_signal.h.ref index 737718d0..19b8b400 100644 --- a/autotests/kconfig_compiler/test_signal.h.ref +++ b/autotests/kconfig_compiler/test_signal.h.ref @@ -132,6 +132,9 @@ class TestSignal : public KConfigSkeleton */ void styleChanged(const QString & stylePath, const QString & StyleCSSVariant); + private: + void itemChanged(quint64 flags); + protected: TestSignal(); friend class TestSignalHelper; |