DCCL v5
Loading...
Searching...
No Matches
dynamic_protobuf.cpp
1// Copyright 2019-2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Dynamic Compact Control Language Library
9// ("DCCL").
10//
11// DCCL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// DCCL is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
23#include "../../dynamic_protobuf_manager.h"
24#include <cassert>
25#include <dlfcn.h>
26#include <google/protobuf/descriptor.pb.h>
27#include <google/protobuf/text_format.h>
28#include <iostream>
29#include "dccl/logger.h"
30
31#include "test_a.pb.h"
32
33int main(int argc, char* argv[])
34{
35 bool verbose = false;
36 const char* lib_path = nullptr;
37 for (int i = 1; i < argc; ++i)
38 {
39 if (argv[i] && argv[i][0] == '-' && argv[i][1] == 'v' && argv[i][2] == '\0')
40 {
41 verbose = true;
42 }
43 else if (!lib_path)
44 {
45 lib_path = argv[i];
46 }
47 }
48
49 if (!lib_path)
50 {
51 std::cerr << "Usage: " << argv[0] << " [-v] /path/to/libtest_dyn_protobuf" << std::endl;
52 exit(1);
53 }
54
55 dccl::dlog.connect(verbose ? dccl::logger::ALL : dccl::logger::WARN_PLUS, &std::cerr);
56
57 void* dl_handle = dlopen(lib_path, RTLD_LAZY);
58
59 if (!dl_handle)
60 {
61 std::cerr << "Failed to open libtest_dyn_protobuf" SHARED_LIBRARY_SUFFIX
62 << ", error: " << dlerror() << std::endl;
63 exit(1);
64 }
65
66 std::shared_ptr<google::protobuf::SimpleDescriptorDatabase> simple_database(
67 new google::protobuf::SimpleDescriptorDatabase);
69
70 {
71 // testing compiled in
72 std::shared_ptr<google::protobuf::Message> adyn_msg =
74
75 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << adyn_msg->GetDescriptor()->DebugString() << std::endl;
76
77 // testing dlopen'd
78 std::shared_ptr<google::protobuf::Message> bdyn_msg =
80
81 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << bdyn_msg->GetDescriptor()->DebugString() << std::endl;
82
83 // test non-existent
84 try
85 {
86 std::shared_ptr<google::protobuf::Message> cdyn_msg =
88 // should throw / avoid static analyzer error here
89 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << cdyn_msg->GetDescriptor()->DebugString() << std::endl;
90 assert(false);
91 }
92 catch (std::exception& e)
93 {
94 // expected
95 }
96
97 // test dynamically loaded
98 google::protobuf::FileDescriptorProto d_proto;
99 std::string d_proto_str = "name: \"goby/test/util/dynamic_protobuf/test_d.proto\" "
100 "message_type { name: \"D\" field { name: \"d1\" "
101 "number: 1 label: LABEL_REQUIRED type: TYPE_DOUBLE } } ";
102
103 google::protobuf::TextFormat::ParseFromString(d_proto_str, &d_proto);
105
106 std::shared_ptr<google::protobuf::Message> ddyn_msg =
108
109 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << ddyn_msg->GetDescriptor()->DebugString() << std::endl;
110
111 // test dynamically via separate database
112 google::protobuf::FileDescriptorProto e_proto;
113 std::string e_proto_str = "name: \"goby/test/util/dynamic_protobuf/test_e.proto\" "
114 "message_type { name: \"E\" field { name: \"e1\" "
115 "number: 1 label: LABEL_REQUIRED type: TYPE_DOUBLE } } ";
116
117 google::protobuf::TextFormat::ParseFromString(e_proto_str, &e_proto);
118
119 simple_database->Add(e_proto);
120
121 std::shared_ptr<google::protobuf::Message> edyn_msg =
123 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << edyn_msg->GetDescriptor()->DebugString() << std::endl;
124
125 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << "all tests passed" << std::endl;
126 }
127
128 dccl::DynamicProtobufManager::protobuf_shutdown();
129
130 dlclose(dl_handle);
131 return 0;
132}
static GoogleProtobufMessagePointer new_protobuf_message(const std::string &protobuf_type_name, bool user_pool_first=false)
Create a new (empty) Google Protobuf message of a given type by name.
static const google::protobuf::FileDescriptor * add_protobuf_file(const google::protobuf::FileDescriptorProto &proto)
Add a protobuf file defined in a google::protobuf::FileDescriptorProto.
static void add_database(std::shared_ptr< google::protobuf::DescriptorDatabase > database)
Add a Google Protobuf DescriptorDatabase to the set of databases searched for Message Descriptors.
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Definition logger.h:191
void connect(int verbosity_mask, Slot slot)
Connect the output of one or more given verbosities to a slot (function pointer or similar)
Definition logger.h:213
Dynamic Compact Control Language namespace.
Definition any.h:28