From 0e6a6058676275afaf1fd006c449377f9710a527 Mon Sep 17 00:00:00 2001 From: Tatiana Borisova Date: Thu, 6 Apr 2023 16:02:29 +0200 Subject: [PATCH] Add enum registration logic and enums-test in QML QtProtobufgen registers global and local enums in QML context now. Registration is in qml extension plugin part. Task-number: QTBUG-104513 Change-Id: Iecbc08d4b915113e7d5753b1f1d24d3c34088ba2 Reviewed-by: Qt CI Bot Reviewed-by: Fabian Kosmale --- .../Qt6ProtobufToolsMacros.cmake | 12 +- .../qtprotobufgen/enumdefinitionprinter.cpp | 10 +- .../qtprotobufgen/enumdefinitionprinter.h | 1 + .../messagedefinitionprinter.cpp | 8 +- .../qtprotobufgen/messagedefinitionprinter.h | 1 + .../qtprotobufgen/qprotobufgenerator.cpp | 83 ++++- src/tools/qtprotobufgen/qprotobufgenerator.h | 2 + src/tools/qtprotoccommon/commontemplates.cpp | 46 ++- src/tools/qtprotoccommon/commontemplates.h | 7 +- tests/auto/protobufqml/CMakeLists.txt | 1 + tests/auto/protobufqml/enums/CMakeLists.txt | 61 ++++ .../protobufqml/enums/qml/tst_enumtypes.qml | 320 ++++++++++++++++++ .../enums/tst_protobuf_enumtypes_qml.cpp | 13 + .../shared/data/proto/additionalenums.proto | 45 +++ 14 files changed, 594 insertions(+), 16 deletions(-) create mode 100644 tests/auto/protobufqml/enums/CMakeLists.txt create mode 100644 tests/auto/protobufqml/enums/qml/tst_enumtypes.qml create mode 100644 tests/auto/protobufqml/enums/tst_protobuf_enumtypes_qml.cpp create mode 100644 tests/auto/shared/data/proto/additionalenums.proto diff --git a/src/tools/qtprotobufgen/Qt6ProtobufToolsMacros.cmake b/src/tools/qtprotobufgen/Qt6ProtobufToolsMacros.cmake index 731e0f33..1295cb07 100644 --- a/src/tools/qtprotobufgen/Qt6ProtobufToolsMacros.cmake +++ b/src/tools/qtprotobufgen/Qt6ProtobufToolsMacros.cmake @@ -174,7 +174,7 @@ endfunction() function(_qt_internal_protobuf_preparse_proto_files out_proto_files out_proto_includes out_generated_files base_dir) - cmake_parse_arguments(arg "GENERATE_PACKAGE_SUBFOLDERS" "" "PROTO_FILES" ${ARGN}) + cmake_parse_arguments(arg "GENERATE_PACKAGE_SUBFOLDERS;QML" "" "PROTO_FILES" ${ARGN}) unset(proto_files) unset(proto_includes) @@ -208,6 +208,9 @@ function(_qt_internal_protobuf_preparse_proto_files "${folder_path}${basename}.qpb.cpp" "${folder_path}${basename}_protobuftyperegistrations.cpp" ) + if(arg_QML) + list(APPEND output_files "${folder_path}${basename}plugin.cpp") + endif() endforeach() list(REMOVE_DUPLICATES proto_files) list(REMOVE_DUPLICATES proto_includes) @@ -256,9 +259,16 @@ function(qt6_add_protobuf target) if(arg_GENERATE_PACKAGE_SUBFOLDERS) list(APPEND extra_pre_parse_options "GENERATE_PACKAGE_SUBFOLDERS") endif() + + if(arg_QML) + set(arg_QML QML) + else() + set(arg_QML "") + endif() _qt_internal_protobuf_preparse_proto_files(proto_files proto_includes generated_files "${base_dir}" ${extra_pre_parse_options} + ${arg_QML} PROTO_FILES ${arg_PROTO_FILES} ) diff --git a/src/tools/qtprotobufgen/enumdefinitionprinter.cpp b/src/tools/qtprotobufgen/enumdefinitionprinter.cpp index 8a5925a1..d433ebe8 100644 --- a/src/tools/qtprotobufgen/enumdefinitionprinter.cpp +++ b/src/tools/qtprotobufgen/enumdefinitionprinter.cpp @@ -25,11 +25,15 @@ void EnumDefinitionPrinter::printRegisterBody() m_printer->Print(m_typeMap, CommonTemplates::RegistrarEnumTemplate()); m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationGlobalEnumDefinition()); Indent(); - if (Options::instance().hasQml()) - m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterTypeEnumTemplate()); - m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationGlobalEnumTemplate()); m_printer->Print(m_typeMap, CommonTemplates::RegisterEnumSerializersTemplate()); Outdent(); m_printer->Print(CommonTemplates::SimpleBlockEnclosureTemplate()); } + +void EnumDefinitionPrinter::printQmlPluginRegisterBody() +{ + Indent(); + m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterGlobalEnumTypeTemplate()); + Outdent(); +} diff --git a/src/tools/qtprotobufgen/enumdefinitionprinter.h b/src/tools/qtprotobufgen/enumdefinitionprinter.h index 9e8a58f2..1682d7c9 100644 --- a/src/tools/qtprotobufgen/enumdefinitionprinter.h +++ b/src/tools/qtprotobufgen/enumdefinitionprinter.h @@ -19,6 +19,7 @@ public: void run() { printRegisterBody(); } void printRegisterBody(); + void printQmlPluginRegisterBody(); }; } // namespace QtProtobuf diff --git a/src/tools/qtprotobufgen/messagedefinitionprinter.cpp b/src/tools/qtprotobufgen/messagedefinitionprinter.cpp index 197a277b..ac2e5f8d 100644 --- a/src/tools/qtprotobufgen/messagedefinitionprinter.cpp +++ b/src/tools/qtprotobufgen/messagedefinitionprinter.cpp @@ -74,7 +74,6 @@ void MessageDefinitionPrinter::printRegisterBody() if (Options::instance().hasQml()) { m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationQmlListTemplate()); - m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterTypeTemplate()); } common::iterateMessageFields( @@ -536,3 +535,10 @@ void MessageDefinitionPrinter::printClassRegistration(Printer *printer) printer->Print(m_typeMap, CommonTemplates::RegistrarTemplate()); } + +void MessageDefinitionPrinter::printQmlPluginClassRegistration() +{ + Indent(); + m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterMessageTypeTemplate()); + Outdent(); +} diff --git a/src/tools/qtprotobufgen/messagedefinitionprinter.h b/src/tools/qtprotobufgen/messagedefinitionprinter.h index efbe943d..282ea4c6 100644 --- a/src/tools/qtprotobufgen/messagedefinitionprinter.h +++ b/src/tools/qtprotobufgen/messagedefinitionprinter.h @@ -19,6 +19,7 @@ public: void printClassDefinition(); void printClassRegistration(::google::protobuf::io::Printer *printer); + void printQmlPluginClassRegistration(); private: void printRegisterBody(); diff --git a/src/tools/qtprotobufgen/qprotobufgenerator.cpp b/src/tools/qtprotobufgen/qprotobufgenerator.cpp index d66b11a7..ea2271f2 100644 --- a/src/tools/qtprotobufgen/qprotobufgenerator.cpp +++ b/src/tools/qtprotobufgen/qprotobufgenerator.cpp @@ -39,7 +39,8 @@ bool QProtobufGenerator::Generate(const FileDescriptor *file, GeneratorContext *generatorContext, std::string *error) const { - assert(file != nullptr && generatorContext != nullptr); + assert(file != nullptr); + assert(generatorContext != nullptr); if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) { *error = "Invalid proto used. qtprotobufgen only supports 'proto3' syntax"; @@ -52,7 +53,8 @@ bool QProtobufGenerator::Generate(const FileDescriptor *file, void QProtobufGenerator::GenerateSources(const FileDescriptor *file, GeneratorContext *generatorContext) const { - assert(file != nullptr && generatorContext != nullptr); + assert(file != nullptr); + assert(generatorContext != nullptr); std::string filename = utils::extractFileBasename(file->name()); std::string basename = generateBaseName(file, filename); @@ -64,6 +66,10 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file, std::shared_ptr sourcePrinter(new Printer(sourceStream.get(), '$')); std::shared_ptr registrationPrinter(new Printer(registrationStream.get(), '$')); + if (Options::instance().hasQml()) { + GenerateQmlPluginSource(file, generatorContext); + } + printDisclaimer(sourcePrinter.get()); sourcePrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}}, CommonTemplates::InternalIncludeTemplate()); @@ -77,7 +83,7 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file, sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}}, CommonTemplates::ExternalIncludeTemplate()); if (Options::instance().hasQml()) { - sourcePrinter->Print({{"include", "QtQml/QQmlEngine"}}, + sourcePrinter->Print({{"include", "QtQml/qqmlengine.h"}}, CommonTemplates::ExternalIncludeTemplate()); } @@ -101,15 +107,77 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file, CloseFileNamespaces(file, sourcePrinter.get()); // Include the moc file: - sourcePrinter->Print({{"source_file", filename + CommonTemplates::ProtoFileSuffix()}}, - "#include \"moc_$source_file$.cpp\"\n"); + sourcePrinter->Print({{"source_file", + "moc_" + filename + CommonTemplates::ProtoFileSuffix() + ".cpp"}}, + CommonTemplates::MocIncludeTemplate()); } +void QProtobufGenerator::GenerateQmlPluginSource(const FileDescriptor *file, + GeneratorContext *context) const +{ + assert(file != nullptr); + assert(context != nullptr); + std::string filename = utils::extractFileBasename(file->name()); + std::string basename = generateBaseName(file, filename); + std::string pluginName = utils::capitalizeAsciiName(basename); + std::string qmlPackageUri = file->package(); + + std::unique_ptr qmlPluginStream( + context->Open(basename + "plugin.cpp")); + std::shared_ptr registrationPluginPrinter(new Printer(qmlPluginStream.get(), '$')); + + printDisclaimer(registrationPluginPrinter.get()); + + registrationPluginPrinter->Print({{"include", "QtQml/qqmlextensionplugin.h"}}, + CommonTemplates::ExternalIncludeTemplate()); + registrationPluginPrinter->Print({{"include", "QtQml/qqml.h"}}, + CommonTemplates::ExternalIncludeTemplate()); + registrationPluginPrinter->Print({{"include", "QtQml/qqmlengine.h"}}, + CommonTemplates::ExternalIncludeTemplate()); + registrationPluginPrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}}, + CommonTemplates::InternalIncludeTemplate()); + if (Options::instance().exportMacro().empty()) { + registrationPluginPrinter->Print({{"plugin_name", pluginName}}, + CommonTemplates::QmlExtensionPluginClassNoExport()); + } else { + registrationPluginPrinter->Print({{"export_macro", Options::instance().exportMacro()}, + {"plugin_name", pluginName}}, + CommonTemplates::QmlExtensionPluginClass()); + } + registrationPluginPrinter->Print({{"plugin_name", pluginName}, + {"qml_package", qmlPackageUri}}, + CommonTemplates::QmlExtensionPluginClassBody()); + + common::iterateMessages(file, [®istrationPluginPrinter](const Descriptor *message) { + if (message->enum_type_count() > 0) { + MessageDefinitionPrinter messageDefinition(message, registrationPluginPrinter); + messageDefinition.printQmlPluginClassRegistration(); + } + }); + + for (int i = 0; i < file->enum_type_count(); ++i) { + EnumDefinitionPrinter enumSourceDefinition(file->enum_type(i), + registrationPluginPrinter); + enumSourceDefinition.printQmlPluginRegisterBody(); + } + + registrationPluginPrinter->Indent(); + registrationPluginPrinter->Indent(); + registrationPluginPrinter->Print(CommonTemplates::SimpleBlockEnclosureTemplate()); + registrationPluginPrinter->Outdent(); + registrationPluginPrinter->Outdent(); + registrationPluginPrinter->Print(CommonTemplates::SemicolonBlockEnclosureTemplate()); + // Include the moc file: + registrationPluginPrinter->Print({{"source_file", filename + "plugin.moc"}}, + CommonTemplates::MocIncludeTemplate()); +} + void QProtobufGenerator::GenerateHeader(const FileDescriptor *file, GeneratorContext *generatorContext) const { - assert(file != nullptr && generatorContext != nullptr); + assert(file != nullptr); + assert(generatorContext != nullptr); std::string filename = utils::extractFileBasename(file->name()); std::string basename = generateBaseName(file, filename); @@ -234,7 +302,8 @@ void QProtobufGenerator::GenerateHeader(const FileDescriptor *file, bool QProtobufGenerator::GenerateMessages(const FileDescriptor *file, GeneratorContext *generatorContext) const { - assert(file != nullptr && generatorContext != nullptr); + assert(file != nullptr); + assert(generatorContext != nullptr); if (file->message_type_count() <= 0 && file->enum_type_count() <= 0) { return false; diff --git a/src/tools/qtprotobufgen/qprotobufgenerator.h b/src/tools/qtprotobufgen/qprotobufgenerator.h index 8aec33a6..a0761bc4 100644 --- a/src/tools/qtprotobufgen/qprotobufgenerator.h +++ b/src/tools/qtprotobufgen/qprotobufgenerator.h @@ -32,6 +32,8 @@ private: ::google::protobuf::compiler::GeneratorContext *generatorContext) const; void GenerateSources(const ::google::protobuf::FileDescriptor *file, ::google::protobuf::compiler::GeneratorContext *generatorContext) const; + void GenerateQmlPluginSource(const ::google::protobuf::FileDescriptor *file, + ::google::protobuf::compiler::GeneratorContext *context) const; }; } // namespace QtProtobuf diff --git a/src/tools/qtprotoccommon/commontemplates.cpp b/src/tools/qtprotoccommon/commontemplates.cpp index 433f783f..69fb31ea 100644 --- a/src/tools/qtprotoccommon/commontemplates.cpp +++ b/src/tools/qtprotoccommon/commontemplates.cpp @@ -854,10 +854,23 @@ const char *CommonTemplates::QmlRegisterTypeTemplate() { return "qmlRegisterType<$scope_type$>(\"$qml_package$\", 1, 0, \"$type$\");\n"; } -const char *CommonTemplates::QmlRegisterTypeEnumTemplate() + +const char *CommonTemplates::QmlRegisterGlobalEnumTypeTemplate() { - return "qmlRegisterUncreatableType<$enum_gadget$>(\"$qml_package$\", 1, 0, \"$type$\", " - "QStringLiteral(\"$full_type$ Could not be created from qml context\"));\n"; + return " qmlRegisterUncreatableMetaObject(\n" + " $scope_namespaces$::staticMetaObject,\n" + " uri, 1, 0, \"$type$\", " + "\"You can only use the nested enums of $type$, " + "but not create its instances in QML scope.\");\n"; +} + +const char *CommonTemplates::QmlRegisterMessageTypeTemplate() +{ + return " qmlRegisterUncreatableMetaObject(\n" + " $full_type$::staticMetaObject,\n" + " uri, 1, 0, \"$type$\", " + "\"You can only use the nested enums of $type$, " + "but not create its instances in QML scope.\");\n"; } const char *CommonTemplates::RepeatedSuffix() @@ -936,3 +949,30 @@ const char *CommonTemplates::ExportMacroTemplate() "#endif\n"; } +const char *CommonTemplates::QmlExtensionPluginClass() +{ + return "\nclass QPB_$export_macro$_EXPORT $plugin_name$Plugin : public QQmlExtensionPlugin\n"; +} + +const char *CommonTemplates::QmlExtensionPluginClassNoExport() +{ + return "\nclass $plugin_name$Plugin : public QQmlExtensionPlugin\n"; +} + +const char *CommonTemplates::QmlExtensionPluginClassBody() +{ + return "{\n" + " Q_OBJECT\n" + " Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)\n\n" + "public:\n" + " $plugin_name$Plugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }\n\n" + " void registerTypes(const char *uri) override\n" + " {\n" + " Q_ASSERT(uri == QLatin1String(\"$qml_package$\"));\n" + " qmlRegisterModule(uri, 1, 0);\n"; +} + +const char *CommonTemplates::MocIncludeTemplate() +{ + return "#include \"$source_file$\"\n"; +} diff --git a/src/tools/qtprotoccommon/commontemplates.h b/src/tools/qtprotoccommon/commontemplates.h index 0e2b3435..085ad9cc 100644 --- a/src/tools/qtprotoccommon/commontemplates.h +++ b/src/tools/qtprotoccommon/commontemplates.h @@ -173,7 +173,8 @@ public: static const char *RegistrarTemplate(); static const char *RegistrarEnumTemplate(); static const char *QmlRegisterTypeTemplate(); - static const char *QmlRegisterTypeEnumTemplate(); + static const char *QmlRegisterGlobalEnumTypeTemplate(); + static const char *QmlRegisterMessageTypeTemplate(); static const char *RepeatedSuffix(); static const char *ProtoFileSuffix(); @@ -190,7 +191,11 @@ public: static const char *QtProtobufFieldEnum(); static const char *ExportMacroTemplate(); + static const char *QmlExtensionPluginClass(); + static const char *QmlExtensionPluginClassNoExport(); + static const char *QmlExtensionPluginClassBody(); static const char *QObjectConstructorMessageDeclarationTemplate(); + static const char *MocIncludeTemplate(); }; } // namespace qtprotoccommon diff --git a/tests/auto/protobufqml/CMakeLists.txt b/tests/auto/protobufqml/CMakeLists.txt index 5dae7e22..d9bdadff 100644 --- a/tests/auto/protobufqml/CMakeLists.txt +++ b/tests/auto/protobufqml/CMakeLists.txt @@ -2,3 +2,4 @@ # SPDX-License-Identifier: BSD-3-Clause add_subdirectory(basic) +add_subdirectory(enums) diff --git a/tests/auto/protobufqml/enums/CMakeLists.txt b/tests/auto/protobufqml/enums/CMakeLists.txt new file mode 100644 index 00000000..dc764119 --- /dev/null +++ b/tests/auto/protobufqml/enums/CMakeLists.txt @@ -0,0 +1,61 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_test(tst_protobuf_enumtypes_qml + QMLTEST + SOURCES + tst_protobuf_enumtypes_qml.cpp + LIBRARIES + Qt6::Qml +) + +qt_add_qml_module(tst_protobuf_enumtypes_qml + URI QmlTestUri + VERSION 1.0 + QML_FILES qml/tst_enumtypes.qml +) +qt_autogen_tools_initial_setup(tst_protobuf_enumtypes_qml) + +qt_add_protobuf(tst_protobuf_enumtypes_qmlplugin + PROTO_FILES + ../../protobuf/enums/enummessages.proto + QML + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated" +) + +qt_add_qml_module(tst_protobuf_enumtypes_qmlplugin + URI qtprotobufnamespace.tests + PLUGIN_TARGET tst_protobuf_enumtypes_qmlplugin + NO_PLUGIN_OPTIONAL + NO_GENERATE_PLUGIN_SOURCE + VERSION 1.0 + OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/qtprotobufnamespace/tests +) + +qt_add_protobuf(tst_protobuf_additionalenumtypes_qmlplugin + PROTO_FILES + ../../shared/data/proto/additionalenums.proto + QML + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated_gen" +) + +qt_add_qml_module(tst_protobuf_additionalenumtypes_qmlplugin + URI qtprotobufnamespace.tests.enums + PLUGIN_TARGET tst_protobuf_additionalenumtypes_qmlplugin + NO_PLUGIN_OPTIONAL + NO_GENERATE_PLUGIN_SOURCE + VERSION 1.0 + OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/qtprotobufnamespace/tests/enums +) + +qt_autogen_tools_initial_setup(tst_protobuf_enumtypes_qmlplugin) +qt_autogen_tools_initial_setup(tst_protobuf_additionalenumtypes_qmlplugin) + +if(QT_BUILD_STANDALONE_TESTS) + qt_import_qml_plugins(tst_protobuf_enumtypes_qml) + qt_import_qml_plugins(tst_protobuf_enumtypes_qmlplugin) + qt_import_qml_plugins(tst_protobuf_additionalenumtypes_qmlplugin) +endif() + diff --git a/tests/auto/protobufqml/enums/qml/tst_enumtypes.qml b/tests/auto/protobufqml/enums/qml/tst_enumtypes.qml new file mode 100644 index 00000000..1975ce58 --- /dev/null +++ b/tests/auto/protobufqml/enums/qml/tst_enumtypes.qml @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick +import QtTest + +import qtprotobufnamespace.tests +import qtprotobufnamespace.tests.enums as EnumPack_ + +TestCase { + name: "QtProtobuf enum types test" + property simpleEnumMessage localEnumMessage + property repeatedEnumMessage localRepeatedEnumMessage + property mixedEnumUsageMessage localMixedEnumMessage + property simpleFileEnumMessage globalEnumMessage + property stepChildEnumMessage localStepChildEnumMessage + + property EnumPack_.simpleEnumMessage localEnumMessage2 + property EnumPack_.mixedEnumUsageMessage localMixedEnumMessage2 + + function test_1init() { + localEnumMessage.localEnum = SimpleEnumMessage.LOCAL_ENUM_VALUE3 + localEnumMessage2.localEnum = EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE3 + + localMixedEnumMessage.localEnum = MixedEnumUsageMessage.LOCAL_ENUM_VALUE3 + localMixedEnumMessage2.localEnum + = EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE3 + + localMixedEnumMessage.localEnumList = [ + MixedEnumUsageMessage.LOCAL_ENUM_VALUE0, + MixedEnumUsageMessage.LOCAL_ENUM_VALUE1, + ] + localRepeatedEnumMessage.localEnumList = [ + RepeatedEnumMessage.LOCAL_ENUM_VALUE0, + RepeatedEnumMessage.LOCAL_ENUM_VALUE1, + RepeatedEnumMessage.LOCAL_ENUM_VALUE3 + ] + + globalEnumMessage.globalEnum = TestEnum.TEST_ENUM_VALUE4 + globalEnumMessage.globalEnumList = [ + TestEnum.TEST_ENUM_VALUE0, + TestEnum.TEST_ENUM_VALUE1 + ] + + localStepChildEnumMessage.localStepChildList =[ + SimpleEnumMessage.LOCAL_ENUM_VALUE0, + SimpleEnumMessage.LOCAL_ENUM_VALUE1 + ] + } + + function test_enumValues_data() { + return [ + // TestEnum + { tag: "TestEnum.TEST_ENUM_VALUE0 == 0", + field: TestEnum.TEST_ENUM_VALUE0, answer: 0 }, + { tag: "TestEnum.TEST_ENUM_VALUE1 == 1", + field: TestEnum.TEST_ENUM_VALUE1, answer: 1 }, + { tag: "TestEnum.TEST_ENUM_VALUE2 == 2", + field: TestEnum.TEST_ENUM_VALUE2, answer: 2 }, + { tag: "TestEnum.TEST_ENUM_VALUE3 == 4", + field: TestEnum.TEST_ENUM_VALUE3, answer: 4 }, + { tag: "TestEnum.TEST_ENUM_VALUE4 == 3", + field: TestEnum.TEST_ENUM_VALUE4, answer: 3 }, + // EnumPack_.TestEnum + { tag: "EnumPack_.TestEnum.TEST_ENUM_VALUE0 == 0", + field: EnumPack_.TestEnum.TEST_ENUM_VALUE0, answer: 0 }, + { tag: "EnumPack_.TestEnum.TEST_ENUM_VALUE1 == 1", + field: EnumPack_.TestEnum.TEST_ENUM_VALUE1, answer: 1 }, + { tag: "EnumPack_.TestEnum.TEST_ENUM_VALUE2 == 2", + field: EnumPack_.TestEnum.TEST_ENUM_VALUE2, answer: 2 }, + { tag: "EnumPack_.TestEnum.TEST_ENUM_VALUE3 == 4", + field: EnumPack_.TestEnum.TEST_ENUM_VALUE3, answer: 4 }, + { tag: "EnumPack_.TestEnum.TEST_ENUM_VALUE4 == 3", + field: EnumPack_.TestEnum.TEST_ENUM_VALUE4, answer: 3 }, + // TestEnumSecondInFile + { tag: "TestEnumSecondInFile.TEST_ENUM_SIF_VALUE0 == 0", + field: TestEnumSecondInFile.TEST_ENUM_SIF_VALUE0, answer: 0 }, + { tag: "TestEnumSecondInFile.TEST_ENUM_SIF_VALUE1 == 1", + field: TestEnumSecondInFile.TEST_ENUM_SIF_VALUE1, answer: 1 }, + { tag: "TestEnumSecondInFile.TEST_ENUM_SIF_VALUE2 == 2", + field: TestEnumSecondInFile.TEST_ENUM_SIF_VALUE2, answer: 2 }, + // EnumPack_.TestEnumSecondInFile + { tag: "EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE0 == 0", + field: EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE0, + answer: 0 }, + { tag: "EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE1 == 1", + field: EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE1, + answer: 1 }, + { tag: "EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE2 == 2", + field: EnumPack_.TestEnumSecondInFile.TEST_ENUM_SIF_VALUE2, + answer: 2 }, + // SimpleEnumMessage + { tag: "SimpleEnumMessage.LOCAL_ENUM_VALUE0 == 0", + field: SimpleEnumMessage.LOCAL_ENUM_VALUE0, answer: 0 }, + { tag: "SimpleEnumMessage.LOCAL_ENUM_VALUE1 == 1", + field: SimpleEnumMessage.LOCAL_ENUM_VALUE1, answer: 1 }, + { tag: "SimpleEnumMessage.LOCAL_ENUM_VALUE2 == 2", + field: SimpleEnumMessage.LOCAL_ENUM_VALUE2, answer: 2 }, + { tag: "SimpleEnumMessage.LOCAL_ENUM_VALUE3 == 3", + field: SimpleEnumMessage.LOCAL_ENUM_VALUE3, answer: 3 }, + { tag: "SimpleEnumMessage.LocalEnumProtoFieldNumber == 1", + field: SimpleEnumMessage.LocalEnumProtoFieldNumber, answer: 1 }, + // EnumPack_.SimpleEnumMessage + { tag: "EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE0 == 0", + field: EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE0, + answer: 0 }, + { tag: "EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE1 == 1", + field: EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE1, + answer: 1 }, + { tag: "EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE2 == 2", + field: EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE2, + answer: 2 }, + { tag: "EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE3 == 3", + field: EnumPack_.SimpleEnumMessage.LOCAL_ENUM_VALUE3, + answer: 3 }, + { tag: "EnumPack_.SimpleEnumMessage.LocalEnumProtoFieldNumber == 1", + field: EnumPack_.SimpleEnumMessage.LocalEnumProtoFieldNumber, + answer: 1 }, + // RepeatedEnumMessage + { tag: "RepeatedEnumMessage.LOCAL_ENUM_VALUE0 == 0", + field: RepeatedEnumMessage.LOCAL_ENUM_VALUE0, answer: 0 }, + { tag: "RepeatedEnumMessage.LOCAL_ENUM_VALUE1 == 1", + field: RepeatedEnumMessage.LOCAL_ENUM_VALUE1, answer: 1 }, + { tag: "RepeatedEnumMessage.LOCAL_ENUM_VALUE2 == 2", + field: RepeatedEnumMessage.LOCAL_ENUM_VALUE2, answer: 2 }, + { tag: "RepeatedEnumMessage.LOCAL_ENUM_VALUE3 == 3", + field: RepeatedEnumMessage.LOCAL_ENUM_VALUE3, answer: 3 }, + { tag: "RepeatedEnumMessage.LocalEnumListProtoFieldNumber == 1", + field: RepeatedEnumMessage.LocalEnumListProtoFieldNumber, answer: 1 }, + // MixedEnumUsageMessage + { tag: "MixedEnumUsageMessage.LOCAL_ENUM_VALUE0 == 0", + field: MixedEnumUsageMessage.LOCAL_ENUM_VALUE0, answer: 0 }, + { tag: "MixedEnumUsageMessage.LOCAL_ENUM_VALUE1 == 1", + field: MixedEnumUsageMessage.LOCAL_ENUM_VALUE1, answer: 1 }, + { tag: "MixedEnumUsageMessage.LOCAL_ENUM_VALUE2 == 2", + field: MixedEnumUsageMessage.LOCAL_ENUM_VALUE2, answer: 2 }, + { tag: "MixedEnumUsageMessage.LOCAL_ENUM_VALUE3 == 3", + field: MixedEnumUsageMessage.LOCAL_ENUM_VALUE3, answer: 3 }, + { tag: "MixedEnumUsageMessage.LocalEnumProtoFieldNumber == 1", + field: MixedEnumUsageMessage.LocalEnumProtoFieldNumber, answer: 1 }, + { tag: "MixedEnumUsageMessage.LocalEnumListProtoFieldNumber == 2", + field: MixedEnumUsageMessage.LocalEnumListProtoFieldNumber, answer: 2 }, + { tag: "MixedEnumUsageMessage.LocalEnumMapProtoFieldNumber == 3", + field: MixedEnumUsageMessage.LocalEnumMapProtoFieldNumber, answer: 3 }, + // EnumPack_.MixedEnumUsageMessage + { tag: "EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE0 == 0", + field: EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE0, + answer: 0 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE1 == 1", + field: EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE1, + answer: 1 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE2 == 2", + field: EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE2, + answer: 2 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE3 == 3", + field: EnumPack_.MixedEnumUsageMessage.LOCAL_ENUM_VALUE3, + answer: 3 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LocalEnumProtoFieldNumber == 1", + field: EnumPack_.MixedEnumUsageMessage.LocalEnumProtoFieldNumber, + answer: 1 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LocalEnumListProtoFieldNumber == 2", + field: EnumPack_.MixedEnumUsageMessage.LocalEnumListProtoFieldNumber, + answer: 2 }, + { tag: "EnumPack_.MixedEnumUsageMessage.LocalEnumMapProtoFieldNumber == 3", + field: EnumPack_.MixedEnumUsageMessage.LocalEnumMapProtoFieldNumber, + answer: 3 }, + ] + } + + function test_enumValues(data) { + compare(data.field, data.answer) + } + + function test_checkMessagesFields_data() { + return [ + { tag: "localEnumMessage.localEnum == 3", + field: localEnumMessage.localEnum, answer: 3 }, + { tag: "EnumPack_.localEnumMessage2.localEnum == 3", + field: localEnumMessage2.localEnum, answer: 3 }, + { tag: "localMixedEnumMessage.localEnum == 3", + field: localMixedEnumMessage.localEnum, answer: 3 }, + { tag: "EnumPack_.localMixedEnumMessage2.localEnum == 3", + field: localMixedEnumMessage2.localEnum, answer: 3 }, + { tag: "globalEnumMessage.globalEnum == 3", + field: globalEnumMessage.globalEnum, answer: 3 }, + { tag: "localMixedEnumMessage.localEnumList[0] == 0", + field: localMixedEnumMessage.localEnumList[0], + answer: 0 }, + { tag: "localMixedEnumMessage.localEnumList[1] == 1", + field: localMixedEnumMessage.localEnumList[1], + answer: 1 }, + { tag: "localRepeatedEnumMessage.localEnumList[0] == 0", + field: localRepeatedEnumMessage.localEnumList[0], + answer: 0 }, + { tag: "localRepeatedEnumMessage.localEnumList[1] == 1", + field: localRepeatedEnumMessage.localEnumList[1], + answer: 1 }, + { tag: "localRepeatedEnumMessage.localEnumList[2] == 3", + field: localRepeatedEnumMessage.localEnumList[2], + answer: 3 }, + { tag: "globalEnumMessage.globalEnumList[0] == 0", + field: globalEnumMessage.globalEnumList[0], + answer: 0 }, + { tag: "globalEnumMessage.globalEnumList[1] == 1", + field: globalEnumMessage.globalEnumList[1], + answer: 1 }, + { tag: "localStepChildEnumMessage.localStepChildList[0] == 0", + field: localStepChildEnumMessage.localStepChildList[0], + answer: 0 }, + { tag: "localStepChildEnumMessage.localStepChildList[1] == 1", + field: localStepChildEnumMessage.localStepChildList[1], + answer: 1 }, + ] + } + + function test_checkMessagesFields(data) { + compare(data.field, data.answer) + } + + function test_enumListSizes_data() { + return [ + { tag: "MixedEnumUsageMessage enum list size == 2", + field: localMixedEnumMessage.localEnumList.length, answer: 2 }, + { tag: "StepChildEnumMessage enum list size == 2", + field: localStepChildEnumMessage.localStepChildList.length, answer: 2 }, + { tag: "RepeatedEnumMessage enum list size == 3", + field: localRepeatedEnumMessage.localEnumList.length, answer: 3 }, + { tag: "Global TestEnum list size == 2", + field: globalEnumMessage.globalEnumList.length, answer: 2 }, + ] + } + + function test_enumListSizes(data) { + compare(data.field, data.answer) + } + + function test_checkMessageTypes_data() { + return [ + { tag: "localEnumMessage.localEnum is number", + field: typeof(localEnumMessage.localEnum), answer: "number" }, + { tag: "localMixedEnumMessage.localEnum is number", + field: typeof(localMixedEnumMessage.localEnum), answer: "number" }, + { tag: "EnumPack_.localEnumMessage2.localEnum is number", + field: typeof(localEnumMessage2.localEnum), answer: "number" }, + { tag: "localMixedEnumMessage2.localEnum is number", + field: typeof(localMixedEnumMessage2.localEnum), answer: "number" }, + { tag: "globalEnumMessage.globalEnum is number", + field: typeof(globalEnumMessage.globalEnum), answer: "number" }, + { tag: "localMixedEnumMessage.localEnumList is object", + field: typeof(localMixedEnumMessage.localEnumList), + answer: "object" }, + { tag: "localMixedEnumMessage.localEnumList[0] is number", + field: typeof(localMixedEnumMessage.localEnumList[0]), + answer: "number" }, + { tag: "localMixedEnumMessage.localEnumList[1] is number", + field: typeof(localMixedEnumMessage.localEnumList[1]), + answer: "number" }, + { tag: "localRepeatedEnumMessage.localEnumList is object", + field: typeof(localRepeatedEnumMessage.localEnumList), + answer: "object" }, + { tag: "localRepeatedEnumMessage.localEnumList[0] is number", + field: typeof(localRepeatedEnumMessage.localEnumList[0]), + answer: "number" }, + { tag: "localRepeatedEnumMessage.localEnumList[1] is number", + field: typeof(localRepeatedEnumMessage.localEnumList[1]), + answer: "number" }, + { tag: "localRepeatedEnumMessage.localEnumList[2] is number", + field: typeof(localRepeatedEnumMessage.localEnumList[2]), + answer: "number" }, + { tag: "globalEnumMessage.globalEnumList is object", + field: typeof(globalEnumMessage.globalEnumList), + answer: "object" }, + { tag: "globalEnumMessage.globalEnumList[0] is number", + field: typeof(globalEnumMessage.globalEnumList[0]), + answer: "number" }, + { tag: "globalEnumMessage.globalEnumList[1] is number", + field: typeof(globalEnumMessage.globalEnumList[1]), + answer: "number" }, + { tag: "localStepChildEnumMessage.localStepChildList is object", + field: typeof(localStepChildEnumMessage.localStepChildList), + answer: "object" }, + { tag: "localStepChildEnumMessage.localStepChildList[0] == 0", + field: typeof(localStepChildEnumMessage.localStepChildList[0]), + answer: "number" }, + { tag: "localStepChildEnumMessage.localStepChildList[1] == 1", + field: typeof(localStepChildEnumMessage.localStepChildList[1]), + answer: "number" }, + ] + } + + function test_checkMessageTypes(data) { + compare(data.field, data.answer) + } + +} diff --git a/tests/auto/protobufqml/enums/tst_protobuf_enumtypes_qml.cpp b/tests/auto/protobufqml/enums/tst_protobuf_enumtypes_qml.cpp new file mode 100644 index 00000000..43eb8407 --- /dev/null +++ b/tests/auto/protobufqml/enums/tst_protobuf_enumtypes_qml.cpp @@ -0,0 +1,13 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include + +class TestSetup : public QObject +{ + Q_OBJECT +}; + +QUICK_TEST_MAIN_WITH_SETUP(tst_protobuf_enumtypes_qml, TestSetup) +#include "tst_protobuf_enumtypes_qml.moc" + diff --git a/tests/auto/shared/data/proto/additionalenums.proto b/tests/auto/shared/data/proto/additionalenums.proto new file mode 100644 index 00000000..4d260f42 --- /dev/null +++ b/tests/auto/shared/data/proto/additionalenums.proto @@ -0,0 +1,45 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +syntax = "proto3"; + +package qtprotobufnamespace.tests.enums; + +message SimpleEnumMessage { + enum LocalEnum { + LOCAL_ENUM_VALUE0 = 0; + LOCAL_ENUM_VALUE1 = 1; + LOCAL_ENUM_VALUE2 = 2; + LOCAL_ENUM_VALUE3 = 3; + } + + LocalEnum localEnum = 1; +} + +message MixedEnumUsageMessage +{ + enum LocalEnum { + LOCAL_ENUM_VALUE0 = 0; + LOCAL_ENUM_VALUE1 = 1; + LOCAL_ENUM_VALUE2 = 2; + LOCAL_ENUM_VALUE3 = 3; + } + + LocalEnum localEnum = 1; + repeated LocalEnum localEnumList = 2; + map localEnumMap = 3; +} + +enum TestEnum { + TEST_ENUM_VALUE0 = 0; + TEST_ENUM_VALUE1 = 1; + TEST_ENUM_VALUE2 = 2; + TEST_ENUM_VALUE3 = 4; + TEST_ENUM_VALUE4 = 3; +} + +enum TestEnumSecondInFile { + TEST_ENUM_SIF_VALUE0 = 0; + TEST_ENUM_SIF_VALUE1 = 1; + TEST_ENUM_SIF_VALUE2 = 2; +} +