/* * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include extern "C" { #include } static constexpr size_t DEFAULT_SIZE = 10; static constexpr size_t N_ELEMENTS = 5; class VectorTest : public ::testing::Test { protected: VectorTest () { vector_init (vector, DEFAULT_SIZE, 0); } virtual ~VectorTest () { vector_free (vector); } int *vector = NULL; }; TEST_F (VectorTest, VectorAllocateAndResize) { // Allocated size should be the next power of two EXPECT_EQ (vector_get_alloc_size (vector), 16UL); // Setting elements within the allocated size should not trigger a resize vector_ensure_pos (vector, 15); EXPECT_EQ (vector_get_alloc_size (vector), 16UL); // Setting elements after should through vector_ensure_pos (vector, 16); EXPECT_EQ (vector_get_alloc_size (vector), 32UL); } TEST_F (VectorTest, VectorSize) { EXPECT_EQ (vector_len (vector), size_t (0)); // Check size after pushing one element vector_push (vector, 1); EXPECT_EQ (vector_len (vector), size_t (1)); // Check size after pushing additional elements vector_push (vector, 2); vector_push (vector, 3); EXPECT_EQ (vector_len (vector), size_t (3)); // Try adding multiple elements const int n_elements_to_add = 5; size_t expected_new_len = vector_len (vector) + n_elements_to_add; for (int i = 0; i < n_elements_to_add; i++) vector_push (vector, i); EXPECT_EQ (vector_len (vector), expected_new_len); } TEST_F (VectorTest, VectorCheckValue) { // Add elements vector_push (vector, 109); vector_push (vector, 200); EXPECT_EQ (vector_at (vector, 0), 109); EXPECT_EQ (vector_at (vector, 1), 200); // Update element vector_set (vector, 1, 400); EXPECT_EQ (vector_at (vector, 1), 400); // Add at last available position size_t prev_size = vector_len (vector); vector_set (vector, vector_len (vector) - 1, 123); EXPECT_EQ (vector_at (vector, vector_len (vector) - 1), 123); EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed"; } TEST_F (VectorTest, RemoveElement) { // Populate vector for (size_t i = 0; i < N_ELEMENTS; i++) vector_push (vector, i); EXPECT_EQ (vector_len (vector), N_ELEMENTS); for (size_t i = 0; i < vector_len (vector); i++) EXPECT_EQ (vector_at (vector, i), (int) i); // Remove element int value_to_remove = 3; int num_removed = vector_remove_unordered (vector, value_to_remove); EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1); EXPECT_EQ (num_removed, 1); for (size_t i = 0; i < vector_len (vector); i++) EXPECT_NE (vector_at (vector, i), value_to_remove); } TEST_F (VectorTest, RemoveNonExistingElement) { // Push some initial values vector_push (vector, 1); vector_push (vector, 2); vector_push (vector, 3); EXPECT_EQ (vector_len (vector), size_t (3)); // Remove non-existing element int num_removed = vector_remove_unordered (vector, 5); EXPECT_EQ (num_removed, 0); size_t prev_size = vector_len (vector); EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed"; } TEST_F (VectorTest, RemoveDuplicatedElement) { // Populate vector for (size_t i = 0; i < N_ELEMENTS; i++) vector_push (vector, i); EXPECT_EQ (vector_len (vector), N_ELEMENTS); for (size_t i = 0; i < vector_len (vector); i++) EXPECT_EQ (vector_at (vector, i), (int) i); vector_set (vector, 0, 3); // Duplicate element // Remove (duplicated) elements int value_to_remove = 3; int num_removed = vector_remove_unordered (vector, value_to_remove); EXPECT_EQ (vector_len (vector), N_ELEMENTS - 2); EXPECT_EQ (num_removed, 2); for (size_t i = 0; i < vector_len (vector); i++) EXPECT_NE (vector_at (vector, i), value_to_remove); } TEST_F (VectorTest, Iterate) { for (size_t i = 0; i < N_ELEMENTS; i++) vector_push (vector, i); int count = 0; int *elem; vector_foreach (vector, elem, { EXPECT_EQ (*elem, count++); }); } TEST_F (VectorTest, MultipleResize) { // Use small vector (size=1) to force multiple realloc operations int *small_vector; vector_init (small_vector, 1, 0); for (size_t i = 0; i < N_ELEMENTS; i++) vector_push (small_vector, i); for (size_t i = 0; i < N_ELEMENTS; i++) EXPECT_EQ (vector_at (small_vector, i), (int) i); EXPECT_EQ (vector_len (small_vector), 5UL); EXPECT_EQ (vector_get_alloc_size (small_vector), 8UL); vector_free (small_vector); } TEST_F (VectorTest, MaxSize) { const int max_size = 4; // Fill the vector until max size is reached int *small_vector; vector_init (small_vector, 2, max_size); for (int i = 0; i < max_size; i++) vector_push (small_vector, i); // Try expanding or appending elements should fail int rc = vector_ensure_pos (small_vector, max_size); EXPECT_EQ (rc, -1); rc = vector_push (small_vector, 123); EXPECT_EQ (rc, -1); vector_free (small_vector); } TEST_F (VectorTest, Contains) { // No elements EXPECT_EQ (vector_contains (vector, 1), false); // Push one element vector_push (vector, 1); EXPECT_EQ (vector_contains (vector, 1), true); // Update element vector_set (vector, 0, 2); EXPECT_EQ (vector_contains (vector, 1), false); EXPECT_EQ (vector_contains (vector, 2), true); } TEST_F (VectorTest, Remove) { // Remove element at invalid position int rc = vector_remove_at (vector, 2); EXPECT_EQ (rc, -1); // Failure // Push two elements and remove the second one vector_push (vector, 1); vector_push (vector, 2); rc = vector_remove_at (vector, 1); EXPECT_EQ (rc, 0); // Success EXPECT_EQ (vector_len (vector), size_t (1)); // Push another element: it should replace the previous one vector_push (vector, 3); EXPECT_EQ (vector_len (vector), size_t (2)); EXPECT_EQ (vector_at (vector, 1), 3); } TEST_F (VectorTest, RemoveInTheMiddle) { for (size_t i = 0; i < N_ELEMENTS; i++) vector_push (vector, i); // Remove element in central position int rc = vector_remove_at (vector, 2); EXPECT_EQ (rc, 0); // Success EXPECT_EQ (vector_contains (vector, 2), false); EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1); // Check if elements have been shifted (preserving the order) int expected[] = { 0, 1, 3, 4 }; for (size_t i = 0; i < vector_len (vector); i++) EXPECT_EQ (vector_at (vector, i), expected[i]); } TEST_F (VectorTest, Reset) { vector_push (vector, 1); vector_push (vector, 2); EXPECT_EQ (vector_len (vector), size_t (2)); vector_reset (vector); EXPECT_EQ (vector_len (vector), size_t (0)); vector_push (vector, 5); EXPECT_EQ (vector_len (vector), size_t (1)); EXPECT_EQ (vector_contains (vector, 5), true); EXPECT_EQ (vector_at (vector, 0), 5); }