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 <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Tatiana Borisova 2023-04-06 16:02:29 +02:00
parent eb262593a5
commit 0e6a605867
14 changed files with 594 additions and 16 deletions

View File

@ -174,7 +174,7 @@ endfunction()
function(_qt_internal_protobuf_preparse_proto_files function(_qt_internal_protobuf_preparse_proto_files
out_proto_files out_proto_includes out_generated_files base_dir) 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_files)
unset(proto_includes) unset(proto_includes)
@ -208,6 +208,9 @@ function(_qt_internal_protobuf_preparse_proto_files
"${folder_path}${basename}.qpb.cpp" "${folder_path}${basename}.qpb.cpp"
"${folder_path}${basename}_protobuftyperegistrations.cpp" "${folder_path}${basename}_protobuftyperegistrations.cpp"
) )
if(arg_QML)
list(APPEND output_files "${folder_path}${basename}plugin.cpp")
endif()
endforeach() endforeach()
list(REMOVE_DUPLICATES proto_files) list(REMOVE_DUPLICATES proto_files)
list(REMOVE_DUPLICATES proto_includes) list(REMOVE_DUPLICATES proto_includes)
@ -256,9 +259,16 @@ function(qt6_add_protobuf target)
if(arg_GENERATE_PACKAGE_SUBFOLDERS) if(arg_GENERATE_PACKAGE_SUBFOLDERS)
list(APPEND extra_pre_parse_options "GENERATE_PACKAGE_SUBFOLDERS") list(APPEND extra_pre_parse_options "GENERATE_PACKAGE_SUBFOLDERS")
endif() 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 _qt_internal_protobuf_preparse_proto_files(proto_files proto_includes generated_files
"${base_dir}" "${base_dir}"
${extra_pre_parse_options} ${extra_pre_parse_options}
${arg_QML}
PROTO_FILES PROTO_FILES
${arg_PROTO_FILES} ${arg_PROTO_FILES}
) )

View File

@ -25,11 +25,15 @@ void EnumDefinitionPrinter::printRegisterBody()
m_printer->Print(m_typeMap, CommonTemplates::RegistrarEnumTemplate()); m_printer->Print(m_typeMap, CommonTemplates::RegistrarEnumTemplate());
m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationGlobalEnumDefinition()); m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationGlobalEnumDefinition());
Indent(); 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::MetaTypeRegistrationGlobalEnumTemplate());
m_printer->Print(m_typeMap, CommonTemplates::RegisterEnumSerializersTemplate()); m_printer->Print(m_typeMap, CommonTemplates::RegisterEnumSerializersTemplate());
Outdent(); Outdent();
m_printer->Print(CommonTemplates::SimpleBlockEnclosureTemplate()); m_printer->Print(CommonTemplates::SimpleBlockEnclosureTemplate());
} }
void EnumDefinitionPrinter::printQmlPluginRegisterBody()
{
Indent();
m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterGlobalEnumTypeTemplate());
Outdent();
}

View File

@ -19,6 +19,7 @@ public:
void run() { printRegisterBody(); } void run() { printRegisterBody(); }
void printRegisterBody(); void printRegisterBody();
void printQmlPluginRegisterBody();
}; };
} // namespace QtProtobuf } // namespace QtProtobuf

View File

@ -74,7 +74,6 @@ void MessageDefinitionPrinter::printRegisterBody()
if (Options::instance().hasQml()) { if (Options::instance().hasQml()) {
m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationQmlListTemplate()); m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationQmlListTemplate());
m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterTypeTemplate());
} }
common::iterateMessageFields( common::iterateMessageFields(
@ -536,3 +535,10 @@ void MessageDefinitionPrinter::printClassRegistration(Printer *printer)
printer->Print(m_typeMap, CommonTemplates::RegistrarTemplate()); printer->Print(m_typeMap, CommonTemplates::RegistrarTemplate());
} }
void MessageDefinitionPrinter::printQmlPluginClassRegistration()
{
Indent();
m_printer->Print(m_typeMap, CommonTemplates::QmlRegisterMessageTypeTemplate());
Outdent();
}

View File

@ -19,6 +19,7 @@ public:
void printClassDefinition(); void printClassDefinition();
void printClassRegistration(::google::protobuf::io::Printer *printer); void printClassRegistration(::google::protobuf::io::Printer *printer);
void printQmlPluginClassRegistration();
private: private:
void printRegisterBody(); void printRegisterBody();

View File

@ -39,7 +39,8 @@ bool QProtobufGenerator::Generate(const FileDescriptor *file,
GeneratorContext *generatorContext, GeneratorContext *generatorContext,
std::string *error) const std::string *error) const
{ {
assert(file != nullptr && generatorContext != nullptr); assert(file != nullptr);
assert(generatorContext != nullptr);
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) { if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
*error = "Invalid proto used. qtprotobufgen only supports 'proto3' syntax"; *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, void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
GeneratorContext *generatorContext) const GeneratorContext *generatorContext) const
{ {
assert(file != nullptr && generatorContext != nullptr); assert(file != nullptr);
assert(generatorContext != nullptr);
std::string filename = utils::extractFileBasename(file->name()); std::string filename = utils::extractFileBasename(file->name());
std::string basename = generateBaseName(file, filename); std::string basename = generateBaseName(file, filename);
@ -64,6 +66,10 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
std::shared_ptr<Printer> sourcePrinter(new Printer(sourceStream.get(), '$')); std::shared_ptr<Printer> sourcePrinter(new Printer(sourceStream.get(), '$'));
std::shared_ptr<Printer> registrationPrinter(new Printer(registrationStream.get(), '$')); std::shared_ptr<Printer> registrationPrinter(new Printer(registrationStream.get(), '$'));
if (Options::instance().hasQml()) {
GenerateQmlPluginSource(file, generatorContext);
}
printDisclaimer(sourcePrinter.get()); printDisclaimer(sourcePrinter.get());
sourcePrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}}, sourcePrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}},
CommonTemplates::InternalIncludeTemplate()); CommonTemplates::InternalIncludeTemplate());
@ -77,7 +83,7 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}}, sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}},
CommonTemplates::ExternalIncludeTemplate()); CommonTemplates::ExternalIncludeTemplate());
if (Options::instance().hasQml()) { if (Options::instance().hasQml()) {
sourcePrinter->Print({{"include", "QtQml/QQmlEngine"}}, sourcePrinter->Print({{"include", "QtQml/qqmlengine.h"}},
CommonTemplates::ExternalIncludeTemplate()); CommonTemplates::ExternalIncludeTemplate());
} }
@ -101,15 +107,77 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
CloseFileNamespaces(file, sourcePrinter.get()); CloseFileNamespaces(file, sourcePrinter.get());
// Include the moc file: // Include the moc file:
sourcePrinter->Print({{"source_file", filename + CommonTemplates::ProtoFileSuffix()}}, sourcePrinter->Print({{"source_file",
"#include \"moc_$source_file$.cpp\"\n"); "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<io::ZeroCopyOutputStream> qmlPluginStream(
context->Open(basename + "plugin.cpp"));
std::shared_ptr<Printer> 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, [&registrationPluginPrinter](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, void QProtobufGenerator::GenerateHeader(const FileDescriptor *file,
GeneratorContext *generatorContext) const GeneratorContext *generatorContext) const
{ {
assert(file != nullptr && generatorContext != nullptr); assert(file != nullptr);
assert(generatorContext != nullptr);
std::string filename = utils::extractFileBasename(file->name()); std::string filename = utils::extractFileBasename(file->name());
std::string basename = generateBaseName(file, filename); std::string basename = generateBaseName(file, filename);
@ -234,7 +302,8 @@ void QProtobufGenerator::GenerateHeader(const FileDescriptor *file,
bool QProtobufGenerator::GenerateMessages(const FileDescriptor *file, bool QProtobufGenerator::GenerateMessages(const FileDescriptor *file,
GeneratorContext *generatorContext) const 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) { if (file->message_type_count() <= 0 && file->enum_type_count() <= 0) {
return false; return false;

View File

@ -32,6 +32,8 @@ private:
::google::protobuf::compiler::GeneratorContext *generatorContext) const; ::google::protobuf::compiler::GeneratorContext *generatorContext) const;
void GenerateSources(const ::google::protobuf::FileDescriptor *file, void GenerateSources(const ::google::protobuf::FileDescriptor *file,
::google::protobuf::compiler::GeneratorContext *generatorContext) const; ::google::protobuf::compiler::GeneratorContext *generatorContext) const;
void GenerateQmlPluginSource(const ::google::protobuf::FileDescriptor *file,
::google::protobuf::compiler::GeneratorContext *context) const;
}; };
} // namespace QtProtobuf } // namespace QtProtobuf

View File

@ -854,10 +854,23 @@ const char *CommonTemplates::QmlRegisterTypeTemplate()
{ {
return "qmlRegisterType<$scope_type$>(\"$qml_package$\", 1, 0, \"$type$\");\n"; 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$\", " return " qmlRegisterUncreatableMetaObject(\n"
"QStringLiteral(\"$full_type$ Could not be created from qml context\"));\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() const char *CommonTemplates::RepeatedSuffix()
@ -936,3 +949,30 @@ const char *CommonTemplates::ExportMacroTemplate()
"#endif\n"; "#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";
}

View File

@ -173,7 +173,8 @@ public:
static const char *RegistrarTemplate(); static const char *RegistrarTemplate();
static const char *RegistrarEnumTemplate(); static const char *RegistrarEnumTemplate();
static const char *QmlRegisterTypeTemplate(); static const char *QmlRegisterTypeTemplate();
static const char *QmlRegisterTypeEnumTemplate(); static const char *QmlRegisterGlobalEnumTypeTemplate();
static const char *QmlRegisterMessageTypeTemplate();
static const char *RepeatedSuffix(); static const char *RepeatedSuffix();
static const char *ProtoFileSuffix(); static const char *ProtoFileSuffix();
@ -190,7 +191,11 @@ public:
static const char *QtProtobufFieldEnum(); static const char *QtProtobufFieldEnum();
static const char *ExportMacroTemplate(); static const char *ExportMacroTemplate();
static const char *QmlExtensionPluginClass();
static const char *QmlExtensionPluginClassNoExport();
static const char *QmlExtensionPluginClassBody();
static const char *QObjectConstructorMessageDeclarationTemplate(); static const char *QObjectConstructorMessageDeclarationTemplate();
static const char *MocIncludeTemplate();
}; };
} // namespace qtprotoccommon } // namespace qtprotoccommon

View File

@ -2,3 +2,4 @@
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(basic) add_subdirectory(basic)
add_subdirectory(enums)

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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 <QtQuickTest>
class TestSetup : public QObject
{
Q_OBJECT
};
QUICK_TEST_MAIN_WITH_SETUP(tst_protobuf_enumtypes_qml, TestSetup)
#include "tst_protobuf_enumtypes_qml.moc"

View File

@ -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<string, LocalEnum> 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;
}