1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/strings/internal/resize_uninitialized.h"
16
17 #include "gtest/gtest.h"
18
19 namespace {
20
21 int resize_call_count = 0;
22 int append_call_count = 0;
23
24 // A mock string class whose only purpose is to track how many times its
25 // resize()/append() methods have been called.
26 struct resizable_string {
27 using value_type = char;
size__anona3dbe62e0111::resizable_string28 size_t size() const { return 0; }
capacity__anona3dbe62e0111::resizable_string29 size_t capacity() const { return 0; }
operator []__anona3dbe62e0111::resizable_string30 char& operator[](size_t) {
31 static char c = '\0';
32 return c;
33 }
resize__anona3dbe62e0111::resizable_string34 void resize(size_t) { resize_call_count += 1; }
append__anona3dbe62e0111::resizable_string35 void append(size_t, value_type) { append_call_count += 1; }
reserve__anona3dbe62e0111::resizable_string36 void reserve(size_t) {}
erase__anona3dbe62e0111::resizable_string37 resizable_string& erase(size_t = 0, size_t = 0) { return *this; }
38 };
39
40 int resize_default_init_call_count = 0;
41 int append_default_init_call_count = 0;
42
43 // A mock string class whose only purpose is to track how many times its
44 // resize()/__resize_default_init()/append()/__append_default_init() methods
45 // have been called.
46 struct default_init_string {
size__anona3dbe62e0111::default_init_string47 size_t size() const { return 0; }
capacity__anona3dbe62e0111::default_init_string48 size_t capacity() const { return 0; }
operator []__anona3dbe62e0111::default_init_string49 char& operator[](size_t) {
50 static char c = '\0';
51 return c;
52 }
resize__anona3dbe62e0111::default_init_string53 void resize(size_t) { resize_call_count += 1; }
__resize_default_init__anona3dbe62e0111::default_init_string54 void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
__append_default_init__anona3dbe62e0111::default_init_string55 void __append_default_init(size_t) { append_default_init_call_count += 1; }
reserve__anona3dbe62e0111::default_init_string56 void reserve(size_t) {}
erase__anona3dbe62e0111::default_init_string57 default_init_string& erase(size_t = 0, size_t = 0) { return *this; }
58 };
59
TEST(ResizeUninit,WithAndWithout)60 TEST(ResizeUninit, WithAndWithout) {
61 resize_call_count = 0;
62 append_call_count = 0;
63 resize_default_init_call_count = 0;
64 append_default_init_call_count = 0;
65 {
66 resizable_string rs;
67
68 EXPECT_EQ(resize_call_count, 0);
69 EXPECT_EQ(append_call_count, 0);
70 EXPECT_EQ(resize_default_init_call_count, 0);
71 EXPECT_EQ(append_default_init_call_count, 0);
72 EXPECT_FALSE(
73 absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
74 EXPECT_EQ(resize_call_count, 0);
75 EXPECT_EQ(append_call_count, 0);
76 EXPECT_EQ(resize_default_init_call_count, 0);
77 EXPECT_EQ(append_default_init_call_count, 0);
78 absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
79 EXPECT_EQ(resize_call_count, 1);
80 EXPECT_EQ(append_call_count, 0);
81 EXPECT_EQ(resize_default_init_call_count, 0);
82 EXPECT_EQ(append_default_init_call_count, 0);
83 absl::strings_internal::STLStringResizeUninitializedAmortized(&rs, 1000);
84 EXPECT_EQ(resize_call_count, 1);
85 EXPECT_EQ(append_call_count, 1);
86 EXPECT_EQ(resize_default_init_call_count, 0);
87 EXPECT_EQ(append_default_init_call_count, 0);
88 }
89
90 resize_call_count = 0;
91 append_call_count = 0;
92 resize_default_init_call_count = 0;
93 append_default_init_call_count = 0;
94 {
95 default_init_string rus;
96
97 EXPECT_EQ(resize_call_count, 0);
98 EXPECT_EQ(append_call_count, 0);
99 EXPECT_EQ(resize_default_init_call_count, 0);
100 EXPECT_EQ(append_default_init_call_count, 0);
101 EXPECT_TRUE(
102 absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
103 EXPECT_EQ(resize_call_count, 0);
104 EXPECT_EQ(append_call_count, 0);
105 EXPECT_EQ(resize_default_init_call_count, 0);
106 EXPECT_EQ(append_default_init_call_count, 0);
107 absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
108 EXPECT_EQ(resize_call_count, 0);
109 EXPECT_EQ(append_call_count, 0);
110 EXPECT_EQ(resize_default_init_call_count, 1);
111 EXPECT_EQ(append_default_init_call_count, 0);
112 absl::strings_internal::STLStringResizeUninitializedAmortized(&rus, 1000);
113 EXPECT_EQ(resize_call_count, 0);
114 EXPECT_EQ(append_call_count, 0);
115 EXPECT_EQ(resize_default_init_call_count, 1);
116 EXPECT_EQ(append_default_init_call_count, 1);
117 }
118 }
119
TEST(ResizeUninit,Amortized)120 TEST(ResizeUninit, Amortized) {
121 std::string str;
122 size_t prev_cap = str.capacity();
123 int cap_increase_count = 0;
124 for (int i = 0; i < 1000; ++i) {
125 absl::strings_internal::STLStringResizeUninitializedAmortized(&str, i);
126 size_t new_cap = str.capacity();
127 if (new_cap > prev_cap) ++cap_increase_count;
128 prev_cap = new_cap;
129 }
130 EXPECT_LT(cap_increase_count, 50);
131 }
132
133 } // namespace
134