resize_uninitialized_test.cc (4653B)
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; 28 size_t size() const { return 0; } 29 size_t capacity() const { return 0; } 30 char& operator[](size_t) { 31 static char c = '\0'; 32 return c; 33 } 34 void resize(size_t) { resize_call_count += 1; } 35 void append(size_t, value_type) { append_call_count += 1; } 36 void reserve(size_t) {} 37 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 { 47 size_t size() const { return 0; } 48 size_t capacity() const { return 0; } 49 char& operator[](size_t) { 50 static char c = '\0'; 51 return c; 52 } 53 void resize(size_t) { resize_call_count += 1; } 54 void __resize_default_init(size_t) { resize_default_init_call_count += 1; } 55 void __append_default_init(size_t) { append_default_init_call_count += 1; } 56 void reserve(size_t) {} 57 default_init_string& erase(size_t = 0, size_t = 0) { return *this; } 58 }; 59 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 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