|
15 | 15 | #include "gtest/gtest.h"
|
16 | 16 |
|
17 | 17 | #include "./allocator_testing_utils.h"
|
| 18 | +#include "./time_bomb_allocator_testing_utils.h" |
18 | 19 | #include "rcutils/error_handling.h"
|
19 | 20 | #include "rcutils/types/string_array.h"
|
20 | 21 |
|
@@ -153,3 +154,105 @@ TEST(test_string_array, string_array_cmp) {
|
153 | 154 | ret = rcutils_string_array_fini(&incomplete_string_array);
|
154 | 155 | ASSERT_EQ(RCUTILS_RET_OK, ret);
|
155 | 156 | }
|
| 157 | + |
| 158 | +TEST(test_string_array, string_array_resize) { |
| 159 | + auto allocator = rcutils_get_default_allocator(); |
| 160 | + auto failing_allocator = get_failing_allocator(); |
| 161 | + auto invalid_allocator = rcutils_get_zero_initialized_allocator(); |
| 162 | + auto time_bomb_allocator = get_time_bomb_allocator(); |
| 163 | + rcutils_ret_t ret; |
| 164 | + |
| 165 | + ret = rcutils_string_array_resize(nullptr, 8); |
| 166 | + ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret); |
| 167 | + rcutils_reset_error(); |
| 168 | + |
| 169 | + // Start with 8 elements |
| 170 | + rcutils_string_array_t sa0; |
| 171 | + ret = rcutils_string_array_init(&sa0, 8, &allocator); |
| 172 | + ASSERT_EQ(RCUTILS_RET_OK, ret); |
| 173 | + |
| 174 | + for (size_t i = 0; i < sa0.size; i++) { |
| 175 | + const char val[] = {static_cast<char>('a' + i), '\0'}; |
| 176 | + sa0.data[i] = strdup(val); |
| 177 | + } |
| 178 | + |
| 179 | + // Resize to same size (hot path) |
| 180 | + ret = rcutils_string_array_resize(&sa0, sa0.size); |
| 181 | + ASSERT_EQ(RCUTILS_RET_OK, ret); |
| 182 | + |
| 183 | + // Grow to 16 (with allocation failure) |
| 184 | + sa0.allocator = failing_allocator; |
| 185 | + ret = rcutils_string_array_resize(&sa0, 16); |
| 186 | + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); |
| 187 | + EXPECT_EQ(8u, sa0.size); |
| 188 | + rcutils_reset_error(); |
| 189 | + |
| 190 | + // Grow to 16 (with invalid allocator) |
| 191 | + sa0.allocator = invalid_allocator; |
| 192 | + ret = rcutils_string_array_resize(&sa0, 16); |
| 193 | + EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret); |
| 194 | + EXPECT_EQ(8u, sa0.size); |
| 195 | + rcutils_reset_error(); |
| 196 | + |
| 197 | + // Grow to 16 |
| 198 | + sa0.allocator = allocator; |
| 199 | + ret = rcutils_string_array_resize(&sa0, 16); |
| 200 | + ASSERT_EQ(RCUTILS_RET_OK, ret); |
| 201 | + ASSERT_EQ(16u, sa0.size); |
| 202 | + |
| 203 | + // Check that existing data is intact |
| 204 | + for (size_t i = 0; i < 8; i++) { |
| 205 | + const char val[] = {static_cast<char>('a' + i), '\0'}; |
| 206 | + EXPECT_STREQ(val, sa0.data[i]); |
| 207 | + } |
| 208 | + |
| 209 | + // Check that new elements are empty |
| 210 | + for (size_t i = 8; i < sa0.size; i++) { |
| 211 | + const char val[] = {static_cast<char>('a' + i), '\0'}; |
| 212 | + EXPECT_STREQ(nullptr, sa0.data[i]); |
| 213 | + sa0.data[i] = strdup(val); |
| 214 | + } |
| 215 | + |
| 216 | + // Shrink to 4 (with allocation failure) |
| 217 | + sa0.allocator = failing_allocator; |
| 218 | + ret = rcutils_string_array_resize(&sa0, 4); |
| 219 | + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); |
| 220 | + EXPECT_EQ(16u, sa0.size); |
| 221 | + rcutils_reset_error(); |
| 222 | + |
| 223 | + // Shrink to 4 (with delayed allocation failure) |
| 224 | + set_time_bomb_allocator_realloc_count(time_bomb_allocator, 0); |
| 225 | + sa0.allocator = time_bomb_allocator; |
| 226 | + ret = rcutils_string_array_resize(&sa0, 4); |
| 227 | + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); |
| 228 | + EXPECT_EQ(16u, sa0.size); |
| 229 | + rcutils_reset_error(); |
| 230 | + |
| 231 | + // Shrink to 4 (with invalid allocator) |
| 232 | + sa0.allocator = invalid_allocator; |
| 233 | + ret = rcutils_string_array_resize(&sa0, 4); |
| 234 | + EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret); |
| 235 | + EXPECT_EQ(16u, sa0.size); |
| 236 | + rcutils_reset_error(); |
| 237 | + |
| 238 | + // Shrink to 4 |
| 239 | + sa0.allocator = allocator; |
| 240 | + ret = rcutils_string_array_resize(&sa0, 4); |
| 241 | + ASSERT_EQ(RCUTILS_RET_OK, ret); |
| 242 | + ASSERT_EQ(4u, sa0.size); |
| 243 | + |
| 244 | + // Check that existing data is intact |
| 245 | + for (size_t i = 0; i < sa0.size; i++) { |
| 246 | + const char val[] = {static_cast<char>('a' + i), '\0'}; |
| 247 | + EXPECT_STREQ(val, sa0.data[i]); |
| 248 | + } |
| 249 | + |
| 250 | + // Shrink to 0 |
| 251 | + ret = rcutils_string_array_resize(&sa0, 0); |
| 252 | + EXPECT_EQ(RCUTILS_RET_OK, ret); |
| 253 | + EXPECT_EQ(0u, sa0.size); |
| 254 | + |
| 255 | + sa0.allocator = allocator; |
| 256 | + ret = rcutils_string_array_fini(&sa0); |
| 257 | + ASSERT_EQ(RCUTILS_RET_OK, ret); |
| 258 | +} |
0 commit comments