• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 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 // This test is meant to verify the interaction of the most common and
9 // representative edition features. Each new edition feature must have its own
10 // unit test and we'll selectively accept new features when we believe doing so
11 // improves test coverage in a meaningful way.
12 //
13 // Note that new features that break the backward compatibility poses challenges
14 // to shared unit tests infrastructure this test uses. It may force us to split
15 // the shared tests. Keep the shared unit tests (message_unittest.inc)
16 // representative without sacrificing test coverage.
17 
18 #include <functional>
19 #include <string>
20 #include <utility>
21 
22 #include <gtest/gtest.h>
23 #include "absl/log/absl_check.h"
24 #include "absl/strings/string_view.h"
25 #include "google/protobuf/arena.h"
26 #include "google/protobuf/edition_unittest.pb.h"
27 #include "google/protobuf/explicitly_constructed.h"
28 #include "google/protobuf/generated_message_tctable_decl.h"
29 #include "google/protobuf/has_bits.h"
30 #include "google/protobuf/internal_visibility.h"
31 #include "google/protobuf/unittest_import.pb.h"
32 
33 #define MESSAGE_TEST_NAME EditionMessageTest
34 #define MESSAGE_FACTORY_TEST_NAME EditionMessageFactoryTest
35 #define UNITTEST_PACKAGE_NAME "edition_unittest"
36 #define UNITTEST ::edition_unittest
37 #define UNITTEST_IMPORT ::protobuf_unittest_import
38 
39 // Must include after the above macros.
40 // clang-format off
41 #include "google/protobuf/test_util.inc"
42 #include "google/protobuf/message_unittest.inc"
43 // clang-format on
44 
45 // Must be included last.
46 #include "google/protobuf/port_def.inc"
47 
48 namespace google {
49 namespace protobuf {
50 namespace internal {
51 namespace {
52 
53 
TEST(EditionMessageTest,AllSetMethodsOnStringField)54 TEST(EditionMessageTest, AllSetMethodsOnStringField) {
55   UNITTEST::TestAllTypes msg;
56 
57   msg.set_optional_string(absl::string_view("Abcdef"));
58   EXPECT_EQ(msg.optional_string(), "Abcdef");
59 
60   msg.set_optional_string("Asciiz");
61   EXPECT_EQ(msg.optional_string(), "Asciiz");
62 
63   std::string value = "std::string value 1";
64   msg.set_optional_string(value);
65   EXPECT_EQ(msg.optional_string(), "std::string value 1");
66 
67   value = "std::string value 2";
68   msg.set_optional_string(std::cref(value));
69   EXPECT_EQ(msg.optional_string(), "std::string value 2");
70 
71   value = "std::string value 3";
72   msg.set_optional_string(std::move(value));
73   EXPECT_EQ(msg.optional_string(), "std::string value 3");
74 }
75 
TEST(EditionMessageTest,AllAddMethodsOnRepeatedStringField)76 TEST(EditionMessageTest, AllAddMethodsOnRepeatedStringField) {
77   UNITTEST::TestAllTypes msg;
78 
79   msg.add_repeated_string(absl::string_view("Abcdef"));
80   EXPECT_EQ(msg.repeated_string(0), "Abcdef");
81   msg.clear_repeated_string();
82 
83   msg.add_repeated_string("Asciiz");
84   EXPECT_EQ(msg.repeated_string(0), "Asciiz");
85   msg.clear_repeated_string();
86 
87   std::string value = "std::string value 1";
88   msg.add_repeated_string(value);
89   EXPECT_EQ(msg.repeated_string(0), "std::string value 1");
90   msg.clear_repeated_string();
91 
92   value = "std::string value 2";
93   msg.add_repeated_string(std::cref(value));
94   EXPECT_EQ(msg.repeated_string(0), "std::string value 2");
95   msg.clear_repeated_string();
96 
97   value = "std::string value 3";
98   msg.add_repeated_string(std::move(value));
99   EXPECT_EQ(msg.repeated_string(0), "std::string value 3");
100   msg.clear_repeated_string();
101 }
102 
103 template <typename T>
GetTableIfAvailable(...)104 static const TcParseTableBase* GetTableIfAvailable(...) {
105   return nullptr;
106 }
107 
108 template <typename T>
GetTableIfAvailable(decltype(TcParser::GetTable<T> ()) )109 static const TcParseTableBase* GetTableIfAvailable(
110     decltype(TcParser::GetTable<T>())) {
111   return TcParser::GetTable<T>();
112 }
113 
TEST(EditionMessageTest,TestRegressionInlinedStringAuxIdxMismatchOnFastParser)114 TEST(EditionMessageTest,
115      TestRegressionInlinedStringAuxIdxMismatchOnFastParser) {
116   using Proto = UNITTEST::InlinedStringIdxRegressionProto;
117 
118   auto* table = GetTableIfAvailable<Proto>(nullptr);
119   // Only test when TDP is on, and we have these fields inlined.
120   if (table != nullptr &&
121       table->fast_entry(1)->target() == TcParser::FastSiS1) {
122     // optional string str1 = 1;
123     // The aux_idx points to the inlined_string_idx and not the actual aux_idx.
124     EXPECT_EQ(table->fast_entry(1)->bits.aux_idx(), 1);
125     // optional InlinedStringIdxRegressionProto sub = 2;
126     EXPECT_EQ(table->fast_entry(2)->bits.aux_idx(), 1);
127     // optional string str2 = 3;
128     // The aux_idx points to the inlined_string_idx and not the actual aux_idx.
129     EXPECT_EQ(table->fast_entry(3)->bits.aux_idx(), 2);
130     // optional string str3 = 4;
131     // The aux_idx points to the inlined_string_idx and not the actual aux_idx.
132     EXPECT_EQ(table->fast_entry(0)->bits.aux_idx(), 3);
133   }
134 
135   std::string encoded;
136   {
137     Proto proto;
138     // We use strings longer than SSO.
139     proto.set_str1(std::string(100, 'a'));
140     proto.set_str2(std::string(100, 'a'));
141     proto.set_str3(std::string(100, 'a'));
142     encoded = proto.SerializeAsString();
143   }
144   Arena arena;
145   auto* proto = Arena::Create<Proto>(&arena);
146   // We don't alter donation here, so it works even if the idx are bad.
147   ASSERT_TRUE(proto->ParseFromString(encoded));
148   // Now we alter donation bits. str2's bit (#2) will be off, but its aux_idx
149   // (#3) will point to a donated string.
150   proto = Arena::Create<Proto>(&arena);
151   // String view fields don't allow mutable accessors which obviate the needs
152   // for donation tracker. We will clean up the internal logic after migration
153   // to string view fields matures.
154   proto->set_str1("");
155   proto->set_str2("");
156   proto->set_str3("");
157   // With the bug, this breaks the cleanup list, causing UB on arena
158   // destruction.
159   ASSERT_TRUE(proto->ParseFromString(encoded));
160 }
161 
162 }  // namespace
163 }  // namespace internal
164 }  // namespace protobuf
165 }  // namespace google
166 
167 #include "google/protobuf/port_undef.inc"
168