1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sync/syncable/proto_value_ptr.h"
7 #include "testing/gtest/include/gtest/gtest.h"
14 // TestValue class is used as a template argument with ProtoValuePtr<T>
17 TestValue() : value_(0), is_initialized_(false), is_default_(false) {}
18 explicit TestValue(int value
)
19 : value_(value
), is_initialized_(true), is_default_(false) {}
21 ~TestValue() { g_delete_count
++; }
23 static void ResetCounters() {
29 static int copy_count() { return g_copy_count
; }
30 static int parse_count() { return g_parse_count
; }
31 static int delete_count() { return g_delete_count
; }
33 int value() const { return value_
; }
34 bool is_initialized() const { return is_initialized_
; }
35 bool is_default() const { return is_default_
; }
37 // TestValue uses the default traits struct with ProtoValuePtr<TestValue>.
38 // The following 4 functions are expected by the traits struct to exist
40 void CopyFrom(const TestValue
& from
) {
41 // Expected to always copy from an initialized instance
42 // to an uninitialized one.
43 // Not expected either value to be default.
44 ASSERT_FALSE(is_initialized());
45 ASSERT_FALSE(is_default());
46 ASSERT_TRUE(from
.is_initialized());
47 ASSERT_FALSE(from
.is_default());
48 value_
= from
.value();
49 is_initialized_
= true;
53 void ParseFromArray(const void* blob
, int length
) {
54 // Similarly to CopyFrom this is expected to be called on
55 // an uninitialized instance.
56 ASSERT_FALSE(is_initialized());
57 ASSERT_FALSE(is_default());
58 // The blob is an address of an integer
59 ASSERT_EQ(static_cast<int>(sizeof(int)), length
);
60 value_
= *static_cast<const int*>(blob
);
61 is_initialized_
= true;
65 int ByteSize() const { return is_initialized() ? sizeof(int) : 0; }
67 static const TestValue
& default_instance() {
68 static TestValue default_instance
;
69 default_instance
.is_default_
= true;
70 return default_instance
;
74 static int g_copy_count
;
75 static int g_parse_count
;
76 static int g_delete_count
;
82 DISALLOW_COPY_AND_ASSIGN(TestValue
);
85 // Static initializers.
86 int TestValue::g_copy_count
= 0;
87 int TestValue::g_parse_count
= 0;
88 int TestValue::g_delete_count
= 0;
92 typedef ProtoValuePtr
<TestValue
> TestPtr
;
94 class ProtoValuePtrTest
: public testing::Test
{
96 void SetUp() override
{ TestValue::ResetCounters(); }
98 static bool WrappedValuesAreShared(const TestPtr
& ptr1
, const TestPtr
& ptr2
) {
99 const TestValue
& wrapped_value_1
= ptr1
.value();
100 const TestValue
& wrapped_value_2
= ptr2
.value();
101 // Compare addresses.
102 return &wrapped_value_1
== &wrapped_value_2
;
106 TEST_F(ProtoValuePtrTest
, BasicTest
) {
107 // Basic assignment and default value.
111 EXPECT_TRUE(ptr1
->is_default());
114 EXPECT_FALSE(ptr1
->is_default());
115 EXPECT_EQ(1, ptr1
->value());
118 EXPECT_EQ(1, TestValue::copy_count());
119 EXPECT_EQ(1, TestValue::delete_count());
122 TEST_F(ProtoValuePtrTest
, SharingTest
) {
123 // Sharing between two pointers.
131 EXPECT_TRUE(ptr2
->is_default());
132 EXPECT_TRUE(ptr3
->is_default());
133 EXPECT_EQ(0, TestValue::copy_count());
134 EXPECT_EQ(0, TestValue::delete_count());
137 EXPECT_EQ(1, TestValue::copy_count());
138 EXPECT_EQ(0, TestValue::delete_count());
141 // Both |ptr2| and |ptr3| now share the same value "2".
142 // No additional copies expected.
143 EXPECT_EQ(1, TestValue::copy_count());
144 EXPECT_EQ(0, TestValue::delete_count());
145 EXPECT_FALSE(ptr3
->is_default());
146 EXPECT_EQ(2, ptr3
->value());
147 EXPECT_TRUE(WrappedValuesAreShared(ptr2
, ptr3
));
149 // Stop sharing - |ptr2| is "3" and |ptr3| is still "2".
151 EXPECT_FALSE(WrappedValuesAreShared(ptr2
, ptr3
));
152 EXPECT_EQ(3, ptr2
->value());
153 EXPECT_EQ(2, ptr3
->value());
154 // No extra copies or deletions expected.
155 EXPECT_EQ(2, TestValue::copy_count());
156 EXPECT_EQ(0, TestValue::delete_count());
158 // |ptr3| still has the old value.
159 EXPECT_EQ(2, ptr3
->value());
161 // Share again. Both values are "3".
163 EXPECT_EQ(3, ptr3
->value());
164 // This should have resulted in deleting the wrapper for the value "2".
165 EXPECT_EQ(1, TestValue::delete_count());
166 // No extra copies expected.
167 EXPECT_EQ(2, TestValue::copy_count());
169 // Set default value to one of the pointers.
170 ptr2
.set_value(empty
);
171 EXPECT_TRUE(ptr2
->is_default());
172 // The other one is still intact.
173 EXPECT_FALSE(ptr3
->is_default());
174 EXPECT_EQ(3, ptr3
->value());
175 // No extra copies or deletions expected.
176 EXPECT_EQ(1, TestValue::delete_count());
177 EXPECT_EQ(2, TestValue::copy_count());
179 // Copy the default value between the pointers.
181 EXPECT_TRUE(ptr3
->is_default());
182 // The wrapper for "3" is now deleted.
183 EXPECT_EQ(2, TestValue::delete_count());
186 // No extra deletions expected upon leaving the scope.
187 EXPECT_EQ(2, TestValue::delete_count());
190 TEST_F(ProtoValuePtrTest
, ParsingTest
) {
196 ptr1
.load(&v1
, sizeof(int));
198 EXPECT_EQ(1, TestValue::parse_count());
199 EXPECT_EQ(0, TestValue::copy_count());
201 EXPECT_EQ(v1
, ptr1
->value());
204 EXPECT_EQ(1, TestValue::delete_count());
207 } // namespace syncable
208 } // namespace syncer