aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/map_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/map_test.cc')
-rw-r--r--src/google/protobuf/map_test.cc204
1 files changed, 155 insertions, 49 deletions
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 829a60ff..080b9dfc 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -37,14 +37,13 @@
#endif // _WIN32
#include <algorithm>
-#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
#include <set>
#include <sstream>
+#include <unordered_map>
#include <vector>
-#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
@@ -54,6 +53,7 @@
#include <google/protobuf/map_test_util.h>
#include <google/protobuf/map_unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/test_util2.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/tokenizer.h>
@@ -76,19 +76,23 @@
#include <gmock/gmock.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/casts.h>
-namespace google {
-using google::protobuf::unittest::ForeignMessage;
-using google::protobuf::unittest::TestAllTypes;
-using google::protobuf::unittest::TestMap;
-using google::protobuf::unittest::TestRecursiveMapMessage;
+#include <google/protobuf/port_def.inc>
+namespace google {
namespace protobuf {
+
+using unittest::ForeignMessage;
+using unittest::TestAllTypes;
+using unittest::TestMap;
+using unittest::TestRecursiveMapMessage;
+
namespace internal {
void MapTestForceDeterministic() {
- ::google::protobuf::io::CodedOutputStream::SetDefaultSerializationDeterministic();
+ io::CodedOutputStream::SetDefaultSerializationDeterministic();
}
// Map API Test =====================================================
@@ -309,8 +313,8 @@ static int64 median(Iterator i0, Iterator i1) {
}
static int64 Now() {
- return google::protobuf::util::TimeUtil::TimestampToNanoseconds(
- google::protobuf::util::TimeUtil::GetCurrentTime());
+ return util::TimeUtil::TimestampToNanoseconds(
+ util::TimeUtil::GetCurrentTime());
}
// Arbitrary odd integers for creating test data.
@@ -505,8 +509,8 @@ static void StressTestIterators(int n) {
ASSERT_EQ(n, m.size());
// Create maps of pointers and iterators.
// These should remain valid even if we modify m.
- hash_map<int, Map<int, int>::value_type*> mp(n);
- hash_map<int, Map<int, int>::iterator> mi(n);
+ std::unordered_map<int, Map<int, int>::value_type*> mp(n);
+ std::unordered_map<int, Map<int, int>::iterator> mi(n);
for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
mp[it->first] = &*it;
mi[it->first] = it;
@@ -868,7 +872,7 @@ TEST_F(MapImplTest, Assigner) {
EXPECT_TRUE(other.find(key_other) == other.end());
// Self assign
- other = other;
+ other = *&other; // Avoid -Wself-assign.
EXPECT_EQ(2, other.size());
EXPECT_EQ(value1, other.at(key1));
EXPECT_EQ(value2, other.at(key2));
@@ -895,8 +899,8 @@ TEST_F(MapImplTest, EqualRange) {
int key = 100, key_missing = 101;
map_[key] = 100;
- std::pair<google::protobuf::Map<int32, int32>::iterator,
- google::protobuf::Map<int32, int32>::iterator> range = map_.equal_range(key);
+ std::pair<Map<int32, int32>::iterator, Map<int32, int32>::iterator> range =
+ map_.equal_range(key);
EXPECT_TRUE(map_.find(key) == range.first);
EXPECT_TRUE(++map_.find(key) == range.second);
@@ -904,9 +908,9 @@ TEST_F(MapImplTest, EqualRange) {
EXPECT_TRUE(map_.end() == range.first);
EXPECT_TRUE(map_.end() == range.second);
- std::pair<google::protobuf::Map<int32, int32>::const_iterator,
- google::protobuf::Map<int32, int32>::const_iterator> const_range =
- const_map_.equal_range(key);
+ std::pair<Map<int32, int32>::const_iterator,
+ Map<int32, int32>::const_iterator>
+ const_range = const_map_.equal_range(key);
EXPECT_TRUE(const_map_.find(key) == const_range.first);
EXPECT_TRUE(++const_map_.find(key) == const_range.second);
@@ -1436,7 +1440,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
// Test iterators.
{
int index = 0;
- hash_map<int32, int32> result;
+ std::unordered_map<int32, int32> result;
for (RepeatedFieldRef<Message>::iterator it = mf_int32_int32.begin();
it != mf_int32_int32.end(); ++it) {
const Message& message = *it;
@@ -1448,7 +1452,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
++index;
}
EXPECT_EQ(10, index);
- for (hash_map<int32, int32>::const_iterator it = result.begin();
+ for (std::unordered_map<int32, int32>::const_iterator it = result.begin();
it != result.end(); ++it) {
EXPECT_EQ(message.map_int32_int32().at(it->first), it->second);
}
@@ -1456,7 +1460,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
{
int index = 0;
- hash_map<int32, double> result;
+ std::unordered_map<int32, double> result;
for (RepeatedFieldRef<Message>::iterator it = mf_int32_double.begin();
it != mf_int32_double.end(); ++it) {
const Message& message = *it;
@@ -1468,7 +1472,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
++index;
}
EXPECT_EQ(10, index);
- for (hash_map<int32, double>::const_iterator it = result.begin();
+ for (std::unordered_map<int32, double>::const_iterator it = result.begin();
it != result.end(); ++it) {
EXPECT_EQ(message.map_int32_double().at(it->first), it->second);
}
@@ -1476,7 +1480,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
{
int index = 0;
- hash_map<string, string> result;
+ std::unordered_map<string, string> result;
for (RepeatedFieldRef<Message>::iterator it = mf_string_string.begin();
it != mf_string_string.end(); ++it) {
const Message& message = *it;
@@ -1488,7 +1492,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
++index;
}
EXPECT_EQ(10, index);
- for (hash_map<string, string>::const_iterator it = result.begin();
+ for (std::unordered_map<string, string>::const_iterator it = result.begin();
it != result.end(); ++it) {
EXPECT_EQ(message.map_string_string().at(it->first), it->second);
}
@@ -1975,8 +1979,7 @@ TEST(GeneratedMapFieldTest, CopyAssignmentOperator) {
MapTestUtil::ExpectMapFieldsSet(message2);
}
-#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \
- !defined(GOOGLE_PROTOBUF_NO_RTTI)
+#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || PROTOBUF_RTTI
TEST(GeneratedMapFieldTest, UpcastCopyFrom) {
// Test the CopyFrom method that takes in the generic const Message&
// parameter.
@@ -1984,7 +1987,7 @@ TEST(GeneratedMapFieldTest, UpcastCopyFrom) {
MapTestUtil::SetMapFields(&message1);
- const Message* source = implicit_cast<const Message*>(&message1);
+ const Message* source = ::google::protobuf::implicit_cast<const Message*>(&message1);
message2.CopyFrom(*source);
MapTestUtil::ExpectMapFieldsSet(message2);
@@ -2116,7 +2119,7 @@ TEST(GeneratedMapFieldTest, SerializationToArray) {
MapTestUtil::SetMapFields(&message1);
int size = message1.ByteSize();
data.resize(size);
- uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+ uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
uint8* end = message1.SerializeWithCachedSizesToArray(start);
EXPECT_EQ(size, end - start);
EXPECT_TRUE(message2.ParseFromString(data));
@@ -2132,7 +2135,7 @@ TEST(GeneratedMapFieldTest, SerializationToStream) {
data.resize(size);
{
// Allow the output stream to buffer only one byte at a time.
- io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
io::CodedOutputStream output_stream(&array_stream);
message1.SerializeWithCachedSizes(&output_stream);
EXPECT_FALSE(output_stream.HadError());
@@ -2204,6 +2207,7 @@ TEST(GeneratedMapFieldTest, UnorderedWireFormat) {
EXPECT_TRUE(message.ParseFromString(data));
EXPECT_EQ(1, message.map_int32_int32().size());
+ ASSERT_NE(message.map_int32_int32().find(2), message.map_int32_int32().end());
EXPECT_EQ(1, message.map_int32_int32().at(2));
}
@@ -2279,10 +2283,21 @@ TEST(GeneratedMapFieldTest, KeysValuesUnknownsWireFormat) {
wire_format.push_back(c);
if (is_key) expected_key = static_cast<int>(c);
if (is_value) expected_value = static_cast<int>(c);
- ASSERT_TRUE(message.ParseFromString(wire_format));
- ASSERT_EQ(1, message.map_int32_int32().size());
- ASSERT_EQ(expected_key, message.map_int32_int32().begin()->first);
- ASSERT_EQ(expected_value, message.map_int32_int32().begin()->second);
+ bool res = message.ParseFromString(wire_format);
+ bool expect_success = true;
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+ // Unfortunately the old map parser accepts malformed input, the new
+ // parser accepts only correct input.
+ if (j != items - 1) expect_success = false;
+#endif
+ if (expect_success) {
+ ASSERT_TRUE(res);
+ ASSERT_EQ(1, message.map_int32_int32().size());
+ ASSERT_EQ(expected_key, message.map_int32_int32().begin()->first);
+ ASSERT_EQ(expected_value, message.map_int32_int32().begin()->second);
+ } else {
+ ASSERT_FALSE(res);
+ }
}
}
}
@@ -2307,6 +2322,7 @@ TEST(GeneratedMapFieldTest, MissedKeyWireFormat) {
EXPECT_TRUE(message.ParseFromString(data));
EXPECT_EQ(1, message.map_int32_int32().size());
+ ASSERT_NE(message.map_int32_int32().find(0), message.map_int32_int32().end());
EXPECT_EQ(1, message.map_int32_int32().at(0));
}
@@ -2318,6 +2334,7 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) {
EXPECT_TRUE(message.ParseFromString(data));
EXPECT_EQ(1, message.map_int32_int32().size());
+ ASSERT_NE(message.map_int32_int32().find(1), message.map_int32_int32().end());
EXPECT_EQ(0, message.map_int32_int32().at(1));
}
@@ -2330,7 +2347,7 @@ TEST(GeneratedMapFieldTest, MissedValueTextFormat) {
" key: 1234567890\n"
"}";
- EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message));
+ EXPECT_TRUE(TextFormat::ParseFromString(text, &message));
EXPECT_EQ(1, message.map_int32_foreign_message().size());
EXPECT_EQ(11, message.ByteSize());
}
@@ -3041,7 +3058,7 @@ static string DeterministicSerializationWithSerializePartialToCodedStream(
const T& t) {
const int size = t.ByteSize();
string result(size, '\0');
- io::ArrayOutputStream array_stream(string_as_array(&result), size);
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
io::CodedOutputStream output_stream(&array_stream);
output_stream.SetSerializationDeterministic(true);
t.SerializePartialToCodedStream(&output_stream);
@@ -3054,7 +3071,7 @@ template <typename T>
static string DeterministicSerializationWithSerializeToCodedStream(const T& t) {
const int size = t.ByteSize();
string result(size, '\0');
- io::ArrayOutputStream array_stream(string_as_array(&result), size);
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
io::CodedOutputStream output_stream(&array_stream);
output_stream.SetSerializationDeterministic(true);
t.SerializeToCodedStream(&output_stream);
@@ -3067,7 +3084,7 @@ template <typename T>
static string DeterministicSerialization(const T& t) {
const int size = t.ByteSize();
string result(size, '\0');
- io::ArrayOutputStream array_stream(string_as_array(&result), size);
+ io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
io::CodedOutputStream output_stream(&array_stream);
output_stream.SetSerializationDeterministic(true);
t.SerializeWithCachedSizes(&output_stream);
@@ -3084,13 +3101,13 @@ static void TestDeterministicSerialization(const protobuf_unittest::TestMaps& t,
const string& filename) {
string expected;
GOOGLE_CHECK_OK(File::GetContents(
- TestSourceDir() + "/google/protobuf/testdata/" + filename,
+ TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + filename),
&expected, true));
const string actual = DeterministicSerialization(t);
EXPECT_EQ(expected, actual);
protobuf_unittest::TestMaps u;
EXPECT_TRUE(u.ParseFromString(actual));
- EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(u, t));
+ EXPECT_TRUE(util::MessageDifferencer::Equals(u, t));
}
// Helper for MapSerializationTest. Return a 7-bit ASCII string.
@@ -3146,7 +3163,7 @@ TEST(MapSerializationTest, DeterministicSubmessage) {
const string filename = "golden_message_maps";
string golden;
GOOGLE_CHECK_OK(File::GetContents(
- TestSourceDir() + "/google/protobuf/testdata/" + filename,
+ TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + filename),
&golden, true));
t.ParseFromString(golden);
*(p.mutable_m()) = t;
@@ -3177,18 +3194,35 @@ TEST(TextFormatMapTest, SerializeAndParse) {
MapTestUtil::ExpectMapFieldsSet(dest);
}
+TEST(TextFormatMapTest, DynamicMessage) {
+ TestMap prototype;
+ DynamicMessageFactory factory;
+ std::unique_ptr<Message> message(
+ factory.GetPrototype(prototype.GetDescriptor())->New());
+ MapReflectionTester tester(message->GetDescriptor());
+ tester.SetMapFieldsViaReflection(message.get());
+
+ string expected_text;
+ GOOGLE_CHECK_OK(File::GetContents(
+ TestUtil::GetTestDataPath("net/proto2/internal/"
+ "testdata/map_test_data.txt"),
+ &expected_text, true));
+
+ EXPECT_EQ(message->DebugString(), expected_text);
+}
+
TEST(TextFormatMapTest, Sorted) {
unittest::TestMap message;
MapReflectionTester tester(message.GetDescriptor());
tester.SetMapFieldsViaReflection(&message);
string expected_text;
- GOOGLE_CHECK_OK(File::GetContents(
- TestSourceDir() +
- "/google/protobuf/"
- "testdata/map_test_data.txt",
- &expected_text, true));
+ GOOGLE_CHECK_OK(
+ File::GetContents(TestUtil::GetTestDataPath("net/proto2/internal/"
+ "testdata/map_test_data.txt"),
+ &expected_text, true));
+ CleanStringLineEndings(&expected_text, false);
EXPECT_EQ(message.DebugString(), expected_text);
// Test again on the reverse order.
@@ -3200,16 +3234,88 @@ TEST(TextFormatMapTest, Sorted) {
TEST(TextFormatMapTest, ParseCorruptedString) {
string serialized_message;
- GOOGLE_CHECK_OK(File::GetContents(
- TestSourceDir() +
- "/google/protobuf/testdata/golden_message_maps",
- &serialized_message, true));
+ GOOGLE_CHECK_OK(
+ File::GetContents(TestUtil::GetTestDataPath(
+ "net/proto2/internal/testdata/golden_message_maps"),
+ &serialized_message, true));
protobuf_unittest::TestMaps message;
GOOGLE_CHECK(message.ParseFromString(serialized_message));
TestParseCorruptedString<protobuf_unittest::TestMaps, true>(message);
TestParseCorruptedString<protobuf_unittest::TestMaps, false>(message);
}
+// Previously, serializing to text format will disable iterator from generated
+// API. Now, the iterator can be still used even after serializing to text
+// format.
+TEST(TextFormatMapTest, NoDisableIterator) {
+ unittest::TestMap source;
+ (*source.mutable_map_int32_int32())[1] = 1;
+
+ // Get iterator.
+ Map<int32, int32>::iterator iter =
+ source.mutable_map_int32_int32()->find(1);
+
+ // Serialize message to text format, which will invalidate the previous
+ // iterator previously.
+ string output;
+ TextFormat::Printer printer;
+ printer.PrintToString(source, &output);
+
+ // Modify map via the iterator (invalidated in prvious implementation.).
+ iter->second = 2;
+
+ // In previous implementation, the new change won't be reflected in text
+ // format, because the previous iterator has been invalidated.
+ output.clear();
+ printer.PrintToString(source, &output);
+ string expected =
+ "map_int32_int32 {\n"
+ " key: 1\n"
+ " value: 2\n"
+ "}\n";
+ EXPECT_EQ(output, expected);
+}
+
+// Previously, serializing to text format will disable iterator from reflection
+// API.
+TEST(TextFormatMapTest, NoDisableReflectionIterator) {
+ unittest::TestMap source;
+ (*source.mutable_map_int32_int32())[1] = 1;
+
+ // Get iterator. This will also sync internal repeated field with map inside
+ // of MapField.
+ const Reflection* reflection = source.GetReflection();
+ const FieldDescriptor* field_desc =
+ source.GetDescriptor()->FindFieldByName("map_int32_int32");
+ RepeatedPtrField<Message>* map_field =
+ reflection->MutableRepeatedPtrField<Message>(&source, field_desc);
+ RepeatedPtrField<Message>::iterator iter = map_field->begin();
+
+ // Serialize message to text format, which will invalidate the prvious
+ // iterator previously.
+ string output;
+ TextFormat::Printer printer;
+ printer.PrintToString(source, &output);
+
+ // Modify map via the iterator (invalidated in prvious implementation.).
+ const Reflection* map_entry_reflection = iter->GetReflection();
+ const FieldDescriptor* value_field_desc =
+ iter->GetDescriptor()->FindFieldByName("value");
+ map_entry_reflection->SetInt32(&(*iter), value_field_desc, 2);
+ GOOGLE_LOG(INFO) << iter->DebugString();
+
+ // In previous implementation, the new change won't be reflected in text
+ // format, because the previous iterator has been invalidated.
+ output.clear();
+ printer.PrintToString(source, &output);
+ string expected =
+ "map_int32_int32 {\n"
+ " key: 1\n"
+ " value: 2\n"
+ "}\n";
+ EXPECT_EQ(output, expected);
+}
+
// arena support =================================================
TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {