• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/descriptor_visitor.h"
9 
10 #include <string>
11 #include <vector>
12 
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
15 #include "absl/strings/string_view.h"
16 #include "google/protobuf/unittest.pb.h"
17 
18 namespace google {
19 namespace protobuf {
20 namespace {
21 
22 using ::testing::Contains;
23 using ::testing::IsSupersetOf;
24 using ::testing::Not;
25 
26 constexpr absl::string_view kUnittestProtoFile =
27     "google/protobuf/unittest.proto";
28 
TEST(VisitDescriptorsTest,SingleTypeNoProto)29 TEST(VisitDescriptorsTest, SingleTypeNoProto) {
30   const FileDescriptor& file =
31       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
32   std::vector<absl::string_view> descriptors;
33   VisitDescriptors(file, [&](const Descriptor& descriptor) {
34     descriptors.push_back(descriptor.full_name());
35   });
36   EXPECT_THAT(descriptors,
37               IsSupersetOf({"protobuf_unittest.TestAllTypes",
38                             "protobuf_unittest.TestAllTypes.NestedMessage"}));
39 }
40 
TEST(VisitDescriptorsTest,SingleTypeWithProto)41 TEST(VisitDescriptorsTest, SingleTypeWithProto) {
42   const FileDescriptor& file =
43       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
44   FileDescriptorProto proto;
45   file.CopyTo(&proto);
46   std::vector<absl::string_view> descriptors;
47   VisitDescriptors(
48       file, proto,
49       [&](const Descriptor& descriptor, const DescriptorProto& proto) {
50         descriptors.push_back(descriptor.full_name());
51         EXPECT_EQ(descriptor.name(), proto.name());
52       });
53   EXPECT_THAT(descriptors,
54               IsSupersetOf({"protobuf_unittest.TestAllTypes",
55                             "protobuf_unittest.TestAllTypes.NestedMessage"}));
56 }
57 
TEST(VisitDescriptorsTest,SingleTypeMutableProto)58 TEST(VisitDescriptorsTest, SingleTypeMutableProto) {
59   const FileDescriptor& file =
60       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
61   FileDescriptorProto proto;
62   file.CopyTo(&proto);
63   std::vector<absl::string_view> descriptors;
64   VisitDescriptors(file, proto,
65                    [&](const Descriptor& descriptor, DescriptorProto& proto) {
66                      descriptors.push_back(descriptor.full_name());
67                      EXPECT_EQ(descriptor.name(), proto.name());
68                      proto.set_name("<redacted>");
69                    });
70   EXPECT_THAT(descriptors,
71               IsSupersetOf({"protobuf_unittest.TestAllTypes",
72                             "protobuf_unittest.TestAllTypes.NestedMessage"}));
73   EXPECT_EQ(proto.message_type(0).name(), "<redacted>");
74 }
75 
TEST(VisitDescriptorsTest,AllTypesDeduce)76 TEST(VisitDescriptorsTest, AllTypesDeduce) {
77   const FileDescriptor& file =
78       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
79   std::vector<absl::string_view> descriptors;
80   VisitDescriptors(file, [&](const auto& descriptor) {
81     descriptors.push_back(descriptor.name());
82   });
83   EXPECT_THAT(descriptors, Contains(kUnittestProtoFile));
84   EXPECT_THAT(descriptors, IsSupersetOf({"TestAllTypes", "TestSparseEnum",
85                                          "SPARSE_C", "optional_int32",
86                                          "oneof_nested_message", "oneof_field",
87                                          "optional_nested_message_extension"}));
88 }
89 
TEST(VisitDescriptorsTest,AllTypesDeduceSelective)90 TEST(VisitDescriptorsTest, AllTypesDeduceSelective) {
91   const FileDescriptor& file =
92       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
93   std::vector<absl::string_view> descriptors;
94   VisitDescriptors(
95       file,
96       // Only select on descriptors with a full_name method.
97       [&](const auto& descriptor)
98           -> std::enable_if_t<
99               !std::is_void<decltype(descriptor.full_name())>::value> {
100         descriptors.push_back(descriptor.full_name());
101       });
102   // FileDescriptor doesn't have a full_name method.
103   EXPECT_THAT(descriptors, Not(Contains(kUnittestProtoFile)));
104   EXPECT_THAT(descriptors,
105               IsSupersetOf(
106                   {"protobuf_unittest.TestAllTypes",
107                    "protobuf_unittest.TestSparseEnum", "protobuf_unittest.SPARSE_C",
108                    "protobuf_unittest.TestAllTypes.optional_int32",
109                    "protobuf_unittest.TestAllTypes.oneof_nested_message",
110                    "protobuf_unittest.TestAllTypes.oneof_field",
111                    "protobuf_unittest.optional_nested_message_extension"}));
112 }
113 
TestHandle(const Descriptor & message,const DescriptorProto & proto,std::vector<absl::string_view> * result)114 void TestHandle(const Descriptor& message, const DescriptorProto& proto,
115                 std::vector<absl::string_view>* result) {
116   if (result != nullptr) result->push_back(message.full_name());
117   EXPECT_EQ(message.name(), proto.name());
118 }
TestHandle(const EnumDescriptor & enm,const EnumDescriptorProto & proto,std::vector<absl::string_view> * result)119 void TestHandle(const EnumDescriptor& enm, const EnumDescriptorProto& proto,
120                 std::vector<absl::string_view>* result) {
121   if (result != nullptr) result->push_back(enm.full_name());
122   EXPECT_EQ(enm.name(), proto.name());
123 }
TEST(VisitDescriptorsTest,AllTypesDeduceDelegate)124 TEST(VisitDescriptorsTest, AllTypesDeduceDelegate) {
125   const FileDescriptor& file =
126       *protobuf_unittest::TestAllTypes::GetDescriptor()->file();
127   FileDescriptorProto proto;
128   file.CopyTo(&proto);
129   std::vector<absl::string_view> descriptors;
130 
131   VisitDescriptors(file, proto,
132                    [&](const auto& descriptor, const auto& proto)
133                        -> decltype(TestHandle(descriptor, proto, nullptr)) {
134                      TestHandle(descriptor, proto, &descriptors);
135                    });
136 
137   EXPECT_THAT(descriptors, IsSupersetOf({"protobuf_unittest.TestAllTypes",
138                                          "protobuf_unittest.TestSparseEnum"}));
139 }
140 
141 }  // namespace
142 }  // namespace protobuf
143 }  // namespace google
144