diff options
Diffstat (limited to 'lib/src/test')
-rw-r--r-- | lib/src/test/CMakeLists.txt | 55 | ||||
-rw-r--r-- | lib/src/test/main.cc | 23 | ||||
-rw-r--r-- | lib/src/test/test_bitmap.cc | 261 | ||||
-rw-r--r-- | lib/src/test/test_interest_manifest.cc | 224 | ||||
-rw-r--r-- | lib/src/test/test_ip_address.cc | 73 | ||||
-rw-r--r-- | lib/src/test/test_khash.cc | 179 | ||||
-rw-r--r-- | lib/src/test/test_name.cc | 401 | ||||
-rw-r--r-- | lib/src/test/test_new_header.cc | 346 | ||||
-rw-r--r-- | lib/src/test/test_pool.cc | 209 | ||||
-rw-r--r-- | lib/src/test/test_ring.cc | 104 | ||||
-rw-r--r-- | lib/src/test/test_slab.cc | 148 | ||||
-rw-r--r-- | lib/src/test/test_udp_header.cc | 360 | ||||
-rw-r--r-- | lib/src/test/test_validation.cc | 55 | ||||
-rw-r--r-- | lib/src/test/test_vector.cc | 254 |
14 files changed, 2692 insertions, 0 deletions
diff --git a/lib/src/test/CMakeLists.txt b/lib/src/test/CMakeLists.txt new file mode 100644 index 000000000..8cf4359d2 --- /dev/null +++ b/lib/src/test/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (c) 2021-2022 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. + +find_package(Threads REQUIRED) + +############################################################## +# Test sources +############################################################## +list(APPEND TESTS_SRC + main.cc + test_name.cc + test_new_header.cc + test_udp_header.cc + test_validation.cc + test_bitmap.cc + test_interest_manifest.cc + test_ip_address.cc + test_khash.cc + test_pool.cc + test_ring.cc + test_slab.cc + test_vector.cc +) + +############################################################## +# Build single unit test executable and add it to test list +############################################################## +build_executable(lib_tests + NO_INSTALL + SOURCES ${TESTS_SRC} + LINK_LIBRARIES + PRIVATE ${LIBHICN_STATIC} + PRIVATE ${GTEST_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + INCLUDE_DIRS + PRIVATE ${Libhicn_INCLUDE_DIRS} + PRIVATE ${GTEST_INCLUDE_DIRS} + DEPENDS gtest ${LIBHICN_SHARED} + COMPONENT ${LIBHICN_COMPONENT} + DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${DEFAULT_COMPILER_OPTIONS} + LINK_FLAGS ${LINK_FLAGS} +) + +add_test_internal(lib_tests) diff --git a/lib/src/test/main.cc b/lib/src/test/main.cc new file mode 100644 index 000000000..042fcd6c0 --- /dev/null +++ b/lib/src/test/main.cc @@ -0,0 +1,23 @@ +/* + * 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 <gtest/gtest.h> + +int +main (int argc, char **argv) +{ + ::testing::InitGoogleTest (&argc, argv); + return RUN_ALL_TESTS (); +} diff --git a/lib/src/test/test_bitmap.cc b/lib/src/test/test_bitmap.cc new file mode 100644 index 000000000..7fc8eef71 --- /dev/null +++ b/lib/src/test/test_bitmap.cc @@ -0,0 +1,261 @@ +/* + * 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 <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/bitmap.h> +} + +#define DEFAULT_SIZE 10 + +class BitmapTest : public ::testing::Test +{ +protected: + BitmapTest () {} + + virtual ~BitmapTest () {} + + bitmap_t *bitmap; +}; + +/* + * TEST: bitmap allocation + */ +TEST_F (BitmapTest, BitmapAllocation) +{ + int rc; + + /* + * We take a value < 32 on purpose to avoid confusion on the choice of a 32 + * or 64 bit integer for storage + */ + size_t size_not_pow2 = DEFAULT_SIZE; + bitmap_init (bitmap, size_not_pow2, 0); + + /* + * Bitmap should have been allocated with a size rounded to the next power + * of 2 + */ + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* By default, no element should be set */ + EXPECT_FALSE (bitmap_is_set (bitmap, 0)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 0)); + + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + EXPECT_FALSE (bitmap_is_set (bitmap, size_not_pow2 - 1)); + EXPECT_TRUE (bitmap_is_unset (bitmap, size_not_pow2 - 1)); + + /* Bitmap should not have been reallocated */ + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* After setting a bit after the end, bitmap should have been reallocated */ + bitmap_set (bitmap, sizeof (bitmap[0]) * 8 - 1); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* After setting a bit after the end, bitmap should have been reallocated */ + rc = bitmap_set (bitmap, sizeof (bitmap[0]) * 8); + EXPECT_GE (rc, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 2UL); + + rc = bitmap_set (bitmap, sizeof (bitmap[0]) * 8 + 1); + EXPECT_GE (rc, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 2UL); + + bitmap_free (bitmap); + + size_t size_pow2 = 16; + + /* Limiting test for allocation size */ + bitmap_init (bitmap, size_pow2, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set (bitmap, 20); + EXPECT_TRUE (bitmap_is_set (bitmap, 20)); + EXPECT_FALSE (bitmap_is_unset (bitmap, 20)); + EXPECT_FALSE (bitmap_is_set (bitmap, 19)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 19)); + + // Test edge cases (i.e. start and end of block) + off_t start_position = 0; + bitmap_set (bitmap, start_position); + EXPECT_TRUE (bitmap_is_set (bitmap, start_position)); + EXPECT_FALSE (bitmap_is_unset (bitmap, start_position)); + + off_t end_position = BITMAP_WIDTH (bitmap) - 1; + bitmap_set (bitmap, end_position); + EXPECT_TRUE (bitmap_is_set (bitmap, end_position)); + EXPECT_FALSE (bitmap_is_unset (bitmap, end_position)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set (bitmap, 20); + bitmap_set (bitmap, 19); + bitmap_unset (bitmap, 20); + EXPECT_FALSE (bitmap_is_set (bitmap, 20)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 20)); + EXPECT_TRUE (bitmap_is_set (bitmap, 19)); + EXPECT_FALSE (bitmap_is_unset (bitmap, 19)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapSetTo) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set_to (bitmap, 40); + EXPECT_TRUE (bitmap_is_set (bitmap, 20)); + EXPECT_TRUE (bitmap_is_set (bitmap, 21)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 41)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 42)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapFirstSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get first set bit. It should be INVALID_INDEX + EXPECT_EQ (bitmap_first_set (bitmap), BITMAP_INVALID_INDEX); + + // set bit 40 + bitmap_set (bitmap, 40); + EXPECT_TRUE (bitmap_is_set (bitmap, 40)); + + // Get first set bit. It should be bit 40 (surprise):) + EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (40)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // The first set bit now should be bit #3 + EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (3)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapFirstUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get first unset bit. It should be 0 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (0)); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get first unset bit. It should be bit 1 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // The first set bit now should be still 1 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapNextSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get next unset bit >= 0. It should be INVALID + EXPECT_EQ (bitmap_next_set (bitmap, 0), BITMAP_INVALID_INDEX); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get next set bit >= 0. It should be bit 0 + EXPECT_EQ (bitmap_next_set (bitmap, 0), hicn_uword (0)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // Get next set bit >= 1. It should be 3 + EXPECT_EQ (bitmap_next_set (bitmap, 1), hicn_uword (3)); + + // set (N-2)th bit + bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2); + EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2)); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 3), + DEFAULT_SIZE * WORD_WIDTH - 2); + + // set (N-1)th bit + bitmap_unset (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2); + bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1); + EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1)); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2), + DEFAULT_SIZE * WORD_WIDTH - 1); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1), + DEFAULT_SIZE * WORD_WIDTH - 1); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapNextUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get next unset bit >= 0. It should be 0 + EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (0)); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get next set bit >= 0. It should be bit 1 + EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (1)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // Get next unset bit after 3. It should be 4 + EXPECT_EQ (bitmap_next_unset (bitmap, 3), hicn_uword (4)); + + bitmap_free (bitmap); +} diff --git a/lib/src/test/test_interest_manifest.cc b/lib/src/test/test_interest_manifest.cc new file mode 100644 index 000000000..25ac83728 --- /dev/null +++ b/lib/src/test/test_interest_manifest.cc @@ -0,0 +1,224 @@ +/* + * 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 <gtest/gtest.h> +#include <gmock/gmock.h> + +extern "C" +{ +#include <hicn/interest_manifest.h> +} + +static constexpr hicn_uword WORD_SIZE = WORD_WIDTH; + +class InterestManifestTest : public ::testing::Test +{ +protected: + static constexpr u32 n_suffixes = 0x00000014 + 1; + static constexpr u32 padding = 0x21232425; + static constexpr hicn_uword bitmap_word = ~0ULL; + static inline std::vector<uint32_t> values = { 10, 22, 23, 43, 54, 65, 66, + 4, 33, 2, 44, 99, 87, 67, + 78, 98, 76, 1, 7, 123 }; + InterestManifestTest () {} + virtual ~InterestManifestTest () {} + + uint8_t buffer[512]; + hicn_uword bitmap_saved[BITMAP_SIZE]; +}; + +TEST_F (InterestManifestTest, OneWordBitmapUpdate) +{ + hicn_uword initial_bitmap[1]; + hicn_uword curr_bitmap[1] = { 0 }; + initial_bitmap[0] = + 0x0000000000000b07; // ...000000000000000000000101100000111 + + // Consume first 4 'one' bits (i.e. suffixes), reaching position 9 + size_t pos = 0, max_suffixes = 4; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, std::size_t (9)); + EXPECT_EQ (curr_bitmap[0], hicn_uword (0x0000000000000107)); + + // Consume the remaining 2 'one' bits, reaching end of bitmap + hicn_uword curr_bitmap2[1] = { 0 }; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap2, pos, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, WORD_SIZE); + EXPECT_EQ (curr_bitmap2[0], hicn_uword (0x00000a00)); + + // Consume all suffixes at once + hicn_uword curr_bitmap3[1] = { 0 }; + max_suffixes = 16; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap3, 0, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, WORD_SIZE); + EXPECT_EQ (curr_bitmap3[0], initial_bitmap[0]); +} + +TEST_F (InterestManifestTest, TwoWordBitmapUpdate) +{ + hicn_uword initial_bitmap[2]; + initial_bitmap[0] = 0x0000000000000b07; + initial_bitmap[1] = 0x0000000000000b07; + // -> 0000000000000000000010110000011100000000000000000000101100000111 + + int expected_pos[] = { WORD_SIZE + 2, 2 * WORD_SIZE }; + u32 expected_bitmap[][2] = { { 0x00000b07, 0x00000003 }, + { 0x0, 0x00000b04 } }; + + // Loop to consume all suffixes + int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2; + while (pos != len) + { + hicn_uword curr_bitmap[2] = { 0 }; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos, + len, max_suffixes); + + EXPECT_EQ (pos, expected_pos[i]); + EXPECT_EQ (curr_bitmap[0], expected_bitmap[i][0]); + EXPECT_EQ (curr_bitmap[1], expected_bitmap[i][1]); + i++; + } +} + +TEST_F (InterestManifestTest, SerializeDeserialize) +{ +#if hicn_uword_bits == 64 +#define F(x) hicn_host_to_net_64 (x) +#elif hicn_uword_bits == 32 +#define F(x) hicn_host_to_net_32 (x) +#else +#error "Unrecognized architecture" +#endif + + auto header = reinterpret_cast<interest_manifest_header_t *> (buffer); + interest_manifest_init (header, 0); + + for (const auto &v : values) + { + interest_manifest_add_suffix (header, v); + } + + EXPECT_EQ (header->n_suffixes, n_suffixes); + + // Save bitmap + memcpy (bitmap_saved, header->request_bitmap, sizeof (bitmap_saved)); + + // Serialize manifest + interest_manifest_serialize (header); + + // If architecture is little endian, bytes should be now swapped + EXPECT_THAT (header->n_suffixes, ::testing::Eq (hicn_host_to_net_32 ( + n_suffixes) /* 0x14000000 */)); + + for (unsigned i = 0; i < BITMAP_SIZE; i++) + { + EXPECT_THAT (header->request_bitmap[i], + ::testing::Eq (F (bitmap_saved[i]))); + } + + hicn_name_suffix_t *suffix = (hicn_name_suffix_t *) (header + 1); + for (unsigned i = 0; i < n_suffixes; i++) + { + if (i == 0) + { + EXPECT_THAT (*(suffix + i), ::testing::Eq (hicn_name_suffix_t (0))); + } + else + { + EXPECT_THAT (*(suffix + i), + ::testing::Eq (hicn_host_to_net_32 (values[i - 1]))); + } + } + + // Deserialize manifest + interest_manifest_deserialize (header); + + // Bytes should now be as before + EXPECT_THAT (header->n_suffixes, ::testing::Eq (n_suffixes)); + + int i = 0; + unsigned long pos; + interest_manifest_foreach_suffix (header, suffix, pos) + { + if (pos == 0) + { + EXPECT_THAT (*suffix, ::testing::Eq (hicn_name_suffix_t (0))); + } + else + { + EXPECT_THAT (*suffix, ::testing::Eq (values[i])); + i++; + } + } +} + +TEST_F (InterestManifestTest, ForEach) +{ + unsigned long pos; + hicn_name_suffix_t *suffix = nullptr; + auto header = reinterpret_cast<interest_manifest_header_t *> (buffer); + interest_manifest_init (header, 0); + + for (const auto &v : values) + { + interest_manifest_add_suffix (header, v); + } + + // Iterate over interest manifest. bBbitmap should be all 1, we should be + // able to iterate over all suffixes. + interest_manifest_foreach_suffix (header, suffix, pos) + { + if (pos == 0) + { + EXPECT_EQ (*suffix, hicn_name_suffix_t (0)); + } + else + { + EXPECT_EQ (*suffix, values[pos - 1]); + } + } + + std::set<uint32_t> set_values (values.begin (), values.end ()); + + // Unset few bitmap positions + interest_manifest_del_suffix (header, 5 + 1); + set_values.erase (values[5]); + + interest_manifest_del_suffix (header, 6 + 1); + set_values.erase (values[6]); + + interest_manifest_del_suffix (header, 12 + 1); + set_values.erase (values[12]); + + interest_manifest_del_suffix (header, 17 + 1); + set_values.erase (values[17]); + + // Iterate over interest manifest and remove elements in manifest from set. + // The set should be empty at the end. + interest_manifest_foreach_suffix (header, suffix, pos) + { + if (pos > 0) + { + EXPECT_TRUE (set_values.find (*suffix) != set_values.end ()) + << "The value was " << *suffix; + set_values.erase (*suffix); + } + } + + EXPECT_TRUE (set_values.empty ()); +}
\ No newline at end of file diff --git a/lib/src/test/test_ip_address.cc b/lib/src/test/test_ip_address.cc new file mode 100644 index 000000000..1a7efb603 --- /dev/null +++ b/lib/src/test/test_ip_address.cc @@ -0,0 +1,73 @@ +/* + * 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 <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/ip_address.h> +} + +#define DEFAULT_SIZE 10 + +class IPAddressTest : public ::testing::Test +{ +protected: + IPAddressTest () {} + + virtual ~IPAddressTest () {} +}; + +TEST_F (IPAddressTest, IPAddressGetBit) +{ + hicn_ip_address_t a_0, a_1, a_1_0, a_1_1, a_1_48, a_1_49, a_1_63, a_1_64, + a_1_127; + + hicn_ip_address_pton ("0::0", &a_0); + hicn_ip_address_pton ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &a_1); + + hicn_ip_address_pton ("8000::0", &a_1_0); + hicn_ip_address_pton ("4000::0", &a_1_1); + hicn_ip_address_pton ("0:0:0:8000::0", &a_1_48); + hicn_ip_address_pton ("0:0:0:4000::0", &a_1_49); + hicn_ip_address_pton ("0:0:0:1::0", &a_1_63); + hicn_ip_address_pton ("0::8000:0:0:0", &a_1_64); + hicn_ip_address_pton ("0::1", &a_1_127); + +#if 0 + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_0, i), 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1, i), 1); +#endif + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_0, i), (i == 0) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_1, i), (i == 1) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_48, i), (i == 48) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_49, i), (i == 49) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_63, i), (i == 63) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_64, i), (i == 64) ? 1 : 0); + for (unsigned i = 0; i < 128; i++) + EXPECT_EQ (hicn_ip_address_get_bit (&a_1_127, i), (i == 127) ? 1 : 0); +} diff --git a/lib/src/test/test_khash.cc b/lib/src/test/test_khash.cc new file mode 100644 index 000000000..da6b62071 --- /dev/null +++ b/lib/src/test/test_khash.cc @@ -0,0 +1,179 @@ +/* + * 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 <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#include <hicn/util/khash.h> +} + +KHASH_MAP_INIT_INT (int, unsigned char) + +typedef struct +{ + unsigned key; + unsigned char val; +} int_unpack_t; + +typedef struct +{ + unsigned key; + unsigned char val; +} __attribute__ ((__packed__)) int_packed_t; + +#define hash_eq(a, b) ((a).key == (b).key) +#define hash_func(a) ((a).key) + +KHASH_INIT (iun, int_unpack_t, char, 0, hash_func, hash_eq) +KHASH_INIT (ipk, int_packed_t, char, 0, hash_func, hash_eq) + +class KHashTest : public ::testing::Test +{ +protected: + KHashTest () {} + + virtual ~KHashTest () + { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + virtual void + SetUp () + { + khash = kh_init (int); + } + + virtual void + TearDown () + { + kh_destroy (int, khash); + } + khash_t (int) * khash; +}; + +TEST_F (KHashTest, KhashIntSize) +{ + int ret; + int k; + int size = kh_size (khash); + + EXPECT_EQ (size, 0); + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 10; + } + size = kh_size (khash); + EXPECT_EQ (size, 1); +} + +TEST_F (KHashTest, KhashIntPut) +{ + int ret; + int k; + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 10; + } + int size = kh_size (khash); + EXPECT_EQ (size, 1); + k = kh_put (int, khash, 20, &ret); + if (ret == 1) + { + kh_val (khash, k) = 20; + } + size = kh_size (khash); + EXPECT_EQ (size, 2); +} + +TEST_F (KHashTest, KhashCheckValue) +{ + int ret; + int k; + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 100; + } + k = kh_put (int, khash, 20, &ret); + if (ret == 1) + { + kh_val (khash, k) = 200; + } + + k = kh_put (int, khash, 10, &ret); + int val = -1; + if (!ret) + val = kh_val (khash, k); + EXPECT_EQ (val, 100); + + k = kh_put (int, khash, 20, &ret); + val = -1; + if (!ret) + val = kh_val (khash, k); + EXPECT_EQ (val, 200); +} + +// Check that there are no collisions in case of same key hash +typedef struct +{ + int x; +} Key; +#define hash_key(key) 1 // Hash is always 1 to simulate collisions +#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions +KHASH_INIT (test_map, const Key *, unsigned, 1, hash_key, key_hash_eq); + +TEST_F (KHashTest, Collisions) +{ + int ret; + khiter_t k; + + kh_test_map_t *map = kh_init (test_map); + Key key1 = { .x = 10 }; + Key key2 = { .x = 11 }; + + k = kh_put_test_map (map, &key1, &ret); + ASSERT_EQ (ret, 1); + kh_val (map, k) = 15u; + + k = kh_put_test_map (map, &key2, &ret); + ASSERT_EQ (ret, 1); + kh_val (map, k) = 27u; + + k = kh_get_test_map (map, &key1); + ASSERT_NE (k, kh_end (map)); + unsigned val = kh_val (map, k); + EXPECT_EQ (val, 15u); + + k = kh_get_test_map (map, &key2); + ASSERT_NE (k, kh_end (map)); + val = kh_val (map, k); + EXPECT_EQ (val, 27u); + + kh_destroy_test_map (map); +} diff --git a/lib/src/test/test_name.cc b/lib/src/test/test_name.cc new file mode 100644 index 000000000..0cf160f70 --- /dev/null +++ b/lib/src/test/test_name.cc @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2021-2022 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/name.h> +#include <hicn/common.h> +#include <hicn/error.h> +} + +class NameTest : public ::testing::Test +{ +protected: + const char *ipv6_prefix = "b001::abcd:1234:abcd:1234"; + const char *ipv4_prefix = "12.13.14.15"; + const uint32_t suffix = 12345; + + NameTest () : name_{}, name4_{}, name6_{} + { + ipv6_prefix_bytes = {}; + int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6); + EXPECT_EQ (rc, 1); + + ipv4_prefix_bytes = {}; + rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4); + EXPECT_EQ (rc, 1); + + rc = hicn_name_create (ipv4_prefix, suffix, &name4_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_name_create (ipv6_prefix, suffix, &name6_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + } + + virtual ~NameTest () {} + + void + nameHashTest (const char *prefix) + { + // Create 2 names + uint32_t suffix = 13579; + hicn_name_t name_a, name_b; + int rc = hicn_name_create (prefix, suffix, &name_a); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_name_create (prefix, suffix, &name_b); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // The hash should be equal, with and without considering the suffix + uint32_t hash_a, hash_b; + hash_a = hicn_name_get_hash (&name_a); + hash_b = hicn_name_get_hash (&name_b); + EXPECT_EQ (hash_a, hash_b); + + hash_a = hicn_name_get_prefix_hash (&name_a); + hash_b = hicn_name_get_prefix_hash (&name_b); + EXPECT_EQ (hash_a, hash_b); + + // Now let's change the suffix + rc = hicn_name_set_suffix (&name_a, 97531); + // They should result equal if we do not consider the suffix + hash_a = hicn_name_get_prefix_hash (&name_a); + hash_b = hicn_name_get_prefix_hash (&name_b); + EXPECT_EQ (hash_a, hash_b); + + // And different if we consider it + hash_a = hicn_name_get_hash (&name_a); + hash_b = hicn_name_get_hash (&name_b); + EXPECT_NE (hash_a, hash_b); + } + + void + nameCopyTest (const char *prefix) + { + uint32_t suffix = 13579; + hicn_name_t name_a, name_b; + int rc = hicn_name_create (prefix, suffix, &name_a); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_name_copy (&name_b, &name_a); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_name_compare (&name_a, &name_b, 1); + EXPECT_EQ (rc, 0); + } + + void + nameCompareTest (const char *prefix) + { + // Create 2 names + uint32_t suffix = 13579; + hicn_name_t name_a, name_b; + int rc = hicn_name_create (prefix, suffix, &name_a); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_name_create (prefix, suffix, &name_b); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // They should be equal, with and without considering the suffix + rc = hicn_name_compare (&name_a, &name_b, 1); + EXPECT_EQ (rc, 0); + rc = hicn_name_compare (&name_a, &name_b, 0); + EXPECT_EQ (rc, 0); + + // Now let's change the suffix + rc = hicn_name_set_suffix (&name_a, 97531); + // They should result equal if we do not consider the suffix + rc = hicn_name_compare (&name_a, &name_b, 0); + EXPECT_EQ (rc, 0); + // And different if we consider the suffix + rc = hicn_name_compare (&name_a, &name_b, 1); + EXPECT_NE (rc, 0); + } + + void + nameFromIpPrefixTest (const hicn_ip_prefix_t &hicn_ip_prefix) + { + uint32_t suffix = 54321; + hicn_name_t name; + int rc = hicn_name_create_from_ip_prefix (&hicn_ip_prefix, suffix, &name); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = memcmp (hicn_ip_prefix.address.v6.as_u8, name.prefix.v6.as_u8, + sizeof (name.prefix.v6)); + EXPECT_EQ (rc, 0); + EXPECT_EQ (suffix, name.suffix); + } + + void + nameToIpPrefixTest (const char *prefix) + { + uint32_t suffix = 54321; + hicn_name_t name; + int rc = hicn_name_create (prefix, suffix, &name); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Get family + int family; + rc = hicn_name_get_family (&name, &family); + + hicn_ip_prefix_t hicn_ip_prefix; + rc = hicn_name_to_hicn_ip_prefix (&name, &hicn_ip_prefix); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hicn_ip_prefix.family, family); + rc = hicn_ip_address_cmp (&hicn_ip_prefix.address, &name.prefix); + EXPECT_EQ (rc, 0); + } + + hicn_name_t name_, name4_, name6_; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; +}; + +/** + * Name Initialization + */ +TEST_F (NameTest, NameInitialization) +{ + EXPECT_TRUE (_is_unspec (&name_)); + uint32_t suffix = 12345; + + // Initialize ipv6 name + hicn_name_t name6; + int rc = hicn_name_create (ipv6_prefix, suffix, &name6); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check name is correctly created + rc = hicn_ip_address_cmp (&name6.prefix, &ipv6_prefix_bytes); + EXPECT_EQ (rc, 0); + EXPECT_EQ (name6.suffix, suffix); + + // Initialize ipv4 name + hicn_name_t name4; + rc = hicn_name_create (ipv4_prefix, suffix, &name4); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check name is correctly created + rc = hicn_ip_address_cmp (&name4.prefix, &ipv4_prefix_bytes); + EXPECT_EQ (name4.prefix.pad[0], 0UL); + EXPECT_EQ (name4.prefix.pad[1], 0UL); + EXPECT_EQ (name4.prefix.pad[2], 0UL); + EXPECT_EQ (rc, 0); + EXPECT_EQ (name4.suffix, suffix); + + // Try also to reuse previously initialized name + rc = hicn_name_create (ipv4_prefix, suffix, &name6); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check name is correctly created + rc = hicn_ip_address_cmp (&name6.prefix, &ipv4_prefix_bytes); + EXPECT_EQ (name6.prefix.pad[0], 0UL); + EXPECT_EQ (name6.prefix.pad[1], 0UL); + EXPECT_EQ (name6.prefix.pad[2], 0UL); + EXPECT_EQ (rc, 0); + EXPECT_EQ (name6.suffix, suffix); +} + +/** + * Name from ip prefix + */ +TEST_F (NameTest, NameFromIpPrefix6) +{ + hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET6, + .address = {}, + .len = 64 }; + + hicn_ip_prefix.address.v6.as_u64[0] = ipv6_prefix_bytes.v6.as_u64[0]; + hicn_ip_prefix.address.v6.as_u64[1] = ipv6_prefix_bytes.v6.as_u64[1]; + + nameFromIpPrefixTest (hicn_ip_prefix); +} + +TEST_F (NameTest, NameFromIpPrefix4) +{ + hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET, + .address = {}, + .len = 64 }; + hicn_ip_prefix.address.v4.as_u32 = ipv4_prefix_bytes.v4.as_u32; + hicn_ip_prefix.address.pad[0] = 0; + hicn_ip_prefix.address.pad[1] = 0; + hicn_ip_prefix.address.pad[2] = 0; + nameFromIpPrefixTest (hicn_ip_prefix); +} + +TEST_F (NameTest, NameCompare6) { nameCompareTest (ipv6_prefix); } + +TEST_F (NameTest, NameCompare4) { nameCompareTest (ipv4_prefix); } + +TEST_F (NameTest, NameHash6) { nameHashTest (ipv6_prefix); } + +TEST_F (NameTest, NameHash4) { nameHashTest (ipv4_prefix); } + +TEST_F (NameTest, NameEmpty) +{ + int rc = hicn_name_empty (&name_); + EXPECT_EQ (rc, 1); + + name_.prefix.v6 = ipv6_prefix_bytes.v6; + rc = hicn_name_empty (&name_); + EXPECT_EQ (rc, 0); +} + +TEST_F (NameTest, NameCopy6) { nameCopyTest (ipv6_prefix); } + +TEST_F (NameTest, NameCopy4) { nameCopyTest (ipv4_prefix); } + +TEST_F (NameTest, NameCopyToDestination) +{ + ipv4_address_t dst4; + ipv6_address_t dst6; + + // Copy names to destination + int rc = hicn_name_copy_prefix_to_destination (dst4.as_u8, &name4_); + EXPECT_EQ (rc, 0); + rc = hicn_name_copy_prefix_to_destination (dst6.as_u8, &name6_); + EXPECT_EQ (rc, 0); + + // Check copy succeeded + EXPECT_TRUE (dst4.as_u32 == name4_.prefix.v4.as_u32); + EXPECT_TRUE (dst6.as_u64[0] == name6_.prefix.v6.as_u64[0]); + EXPECT_TRUE (dst6.as_u64[1] == name6_.prefix.v6.as_u64[1]); +} + +TEST_F (NameTest, SetGetSuffix) +{ + uint32_t suffix2 = 55555, suffix_ret; + + // Check if suffix is correct + int rc = hicn_name_get_seq_number (&name6_, &suffix_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (suffix, suffix_ret); + + // Set new suffix + rc = hicn_name_set_suffix (&name6_, suffix2); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check suffix was set + rc = hicn_name_get_seq_number (&name6_, &suffix_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (suffix2, suffix_ret); +} + +TEST_F (NameTest, NameToSockAddr) +{ + struct sockaddr_in saddr4; + struct sockaddr_in6 saddr6; + + int rc = + hicn_name_to_sockaddr_address (&name6_, (struct sockaddr *) (&saddr6)); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = memcmp (name6_.prefix.v6.as_u8, saddr6.sin6_addr.s6_addr, + sizeof (name6_.prefix.v6)); + EXPECT_EQ (rc, 0); + + rc = hicn_name_to_sockaddr_address (&name4_, (struct sockaddr *) (&saddr4)); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (name4_.prefix.v4.as_u32, saddr4.sin_addr.s_addr); +} + +TEST_F (NameTest, NameToIpPrefix) +{ + nameToIpPrefixTest (ipv4_prefix); + nameToIpPrefixTest (ipv6_prefix); +} + +TEST_F (NameTest, NameNToP) +{ + char dst[128]; + + // V6 + int rc = hicn_name_ntop (&name6_, dst, 128); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Build expected name + std::stringstream expected6; + expected6 << ipv6_prefix << "|" << suffix; + + rc = strcmp (dst, expected6.str ().c_str ()); + EXPECT_EQ (rc, 0); + + // V4 + rc = hicn_name_ntop (&name4_, dst, 128); + std::stringstream expected4; + expected4 << ipv4_prefix << "|" << suffix; + + rc = strcmp (dst, expected4.str ().c_str ()); + EXPECT_EQ (rc, 0); +} + +class PrefixTest : public ::testing::Test +{ +protected: + PrefixTest () {} + + virtual ~PrefixTest () {} +}; + +#define HICN_PREFIX(P, STR) \ + hicn_prefix_t P; \ + hicn_ip_prefix_t _##P; \ + EXPECT_EQ (hicn_ip_prefix_pton (STR, &_##P), 0); \ + EXPECT_EQ (hicn_prefix_create_from_ip_prefix (&_##P, &P), 0); + +TEST_F (PrefixTest, PrefixClear) +{ + HICN_PREFIX (hp_all, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"); + + for (unsigned i = 0; i < 127; i++) + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1); + + hicn_prefix_truncate (&hp_all, 127); + EXPECT_EQ (hicn_prefix_get_len (&hp_all), 127); + + for (unsigned i = 0; i < 126; i++) + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1) << "bit[" << i << "] != 1"; + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 127), 0); + + hicn_prefix_truncate (&hp_all, 126); + EXPECT_EQ (hicn_prefix_get_len (&hp_all), 126); + + for (unsigned i = 0; i < 125; i++) + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, i), 1); + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 0); + EXPECT_EQ (_hicn_prefix_get_bit (&hp_all, 127), 0); +} + +TEST_F (PrefixTest, PrefixClear2) +{ + HICN_PREFIX (hp_all, "b002::3"); + + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 125), 0); + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 1); + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 127), 1); + + hicn_prefix_truncate (&hp_all, 127); + EXPECT_EQ (hicn_prefix_get_len (&hp_all), 127); + + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 125), 0); + EXPECT_EQ (hicn_prefix_get_bit (&hp_all, 126), 1); + EXPECT_EQ (_hicn_prefix_get_bit (&hp_all, 127), 0); +} + +TEST_F (PrefixTest, PrefixLPM) +{ + HICN_PREFIX (b007, "b007::/64"); + HICN_PREFIX (b009, "b009::/64"); + + EXPECT_EQ (hicn_prefix_lpm (&b007, &b009), (uint32_t) 12); + + HICN_PREFIX (pfx, "1122:3344:5566:7788:9900:aabb:ccdd:eeff/128"); + EXPECT_EQ (hicn_prefix_lpm (&pfx, &pfx), (uint32_t) 128); +} diff --git a/lib/src/test/test_new_header.cc b/lib/src/test/test_new_header.cc new file mode 100644 index 000000000..c936b6910 --- /dev/null +++ b/lib/src/test/test_new_header.cc @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2021-2022 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/name.h> +#include <hicn/common.h> +#include <hicn/error.h> +#include <hicn/packet.h> + +#include "../protocol/ah.h" +#include "../protocol/new.h" +} + +class NewHeaderTest : public ::testing::Test +{ +protected: + const char *ipv6_prefix = "b001::abcd:1234:abcd:1234"; + const char *ipv4_prefix = "12.13.14.15"; + const uint32_t suffix = 12345; + + NewHeaderTest (hicn_packet_format_t format) + : buffer_ (new uint8_t[NEW_HDRLEN]), + format_ (format), name_{}, name4_{}, name6_{} + { + + int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6); + EXPECT_EQ (rc, 1); + + rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4); + EXPECT_EQ (rc, 1); + + rc = hicn_name_create (ipv4_prefix, suffix, &name4_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_name_create (ipv6_prefix, suffix, &name6_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + } + + NewHeaderTest () : NewHeaderTest (HICN_PACKET_FORMAT_NEW) {} + + virtual ~NewHeaderTest () { delete[] buffer_; } + + void + checkCommon () + { + // Initialize header + hicn_packet_set_format (&pkbuf_, format_); + // pkbuf_set_type (&pkbuf_, HICN_PACKET_TYPE_UNDEFINED); + int rc = hicn_packet_init_header (&pkbuf_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + auto new_hdr = (_new_header_t *) buffer_; + + // Check fields + EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL); + EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL); + EXPECT_EQ (new_hdr->suffix, 0UL); + EXPECT_EQ (new_hdr->lifetime, 0UL); + EXPECT_EQ (new_hdr->path_label, 0UL); + EXPECT_EQ (new_hdr->payload_len, 0UL); + EXPECT_EQ (_get_new_header_version (new_hdr), 0x9); + EXPECT_EQ (new_hdr->flags, 0); + } + + virtual void + SetUp () override + { + checkCommon (); + } + + uint8_t *buffer_; + hicn_packet_buffer_t pkbuf_; + hicn_packet_format_t format_; + hicn_name_t name_, name4_, name6_; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; +}; + +#if 0 +class NewHeaderAHTest : public NewHeaderTest +{ +protected: + NewHeaderAHTest () : NewHeaderTest (NEW_HDRLEN + AH_HDRLEN, HF_NEW_AH) {} + + virtual void + SetUp () override + { + auto new_hdr = &header_->protocol.newhdr; + checkCommon (new_hdr); + EXPECT_NE (new_hdr->flags, 0); + } +}; + +/** + * Header Initialization + */ +TEST_F (NewHeaderTest, GetFormat) +{ + // Get format from existing packet + hicn_format_t format; + int rc = hicn_packet_get_format (header_, &format); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check it corresponds to the new header format + EXPECT_EQ (format, HF_NEW); +} + +TEST_F (NewHeaderAHTest, GetFormat) +{ + // Get format from existing packet + hicn_format_t format; + int rc = hicn_packet_get_format (header_, &format); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Check it corresponds to the new header format + EXPECT_EQ (format, HF_NEW_AH); +} + +/** + * @brief Checksum functions are not required, but we keep them for + * compatibility. + */ +TEST_F (NewHeaderTest, Checksum) +{ + // Get format from existing packet + int rc = hicn_packet_compute_checksum (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_compute_header_checksum (format_, header_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_check_integrity_no_payload (format_, header_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (NewHeaderAHTest, Checksum) +{ + // Get format from existing packet + int rc = hicn_packet_compute_checksum (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_compute_header_checksum (format_, header_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_check_integrity_no_payload (format_, header_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (NewHeaderTest, GetHeaderLengthFromFormat) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, NEW_HDRLEN); +} + +TEST_F (NewHeaderAHTest, GetHeaderLengthFromFormat) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN); +} + +TEST_F (NewHeaderTest, GetHeaderLength) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length (format_, header_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, NEW_HDRLEN); +} + +TEST_F (NewHeaderAHTest, GetHeaderLength) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length (format_, header_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN); +} + +TEST_F (NewHeaderTest, SetGetPayloadLength) +{ + // Get format from existing packet + std::size_t payload_len = 1000, payload_len_ret; + int rc = hicn_packet_set_payload_length (format_, header_, payload_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (payload_len, payload_len_ret); +} + +TEST_F (NewHeaderAHTest, SetGetPayloadLength) +{ + // Get format from existing packet + std::size_t payload_len = 1000, payload_len_ret; + int rc = hicn_packet_set_payload_length (format_, header_, payload_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (payload_len, payload_len_ret); +} + +TEST_F (NewHeaderTest, SetGetName) +{ + // Get v6 name and set it to new_header + hicn_name_t name_ret; + int rc = hicn_packet_set_name (format_, header_, &name6_, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_name (format_, header_, &name_ret, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_name_compare (&name6_, &name_ret, 1); + EXPECT_EQ (rc, 0); +} + +TEST_F (NewHeaderTest, SetGetLocator) +{ + // This function does nothing but it is set for compatibility + hicn_ip_address_t locator; + memset (&locator, 0, sizeof (locator)); + locator.v6.as_u8[15] = 1; + int rc = hicn_packet_set_interest (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_set_locator (format_, header_, &locator, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_locator (format_, header_, &locator, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (NewHeaderTest, SetGetSignatureSize) +{ + // No AH, so we should get an error + // FixMe no error raised here + size_t signature_size = 128; + int rc = hicn_packet_set_signature_size (format_, header_, signature_size); + (void) rc; + // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Same for hicn_packet_get_signature_size + rc = hicn_packet_get_signature_size (format_, header_, &signature_size); + // EXPECT_NE (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (NewHeaderAHTest, SetGetSignatureSize) +{ + // No AH, so we should get an error + size_t signature_size = 128, signature_size_ret; + int rc = hicn_packet_set_signature_size (format_, header_, signature_size); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Same for hicn_packet_get_signature_size + rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (signature_size, signature_size_ret); +} + +TEST_F (NewHeaderTest, IsInterestIsData) +{ + // Mark packet as interest + int rc = hicn_packet_set_interest (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + int ret; + rc = hicn_packet_is_interest (format_, header_, &ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (ret, 1); + + // Mark packet as data + rc = hicn_packet_set_data (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_is_interest (format_, header_, &ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (ret, 0); +} + +TEST_F (NewHeaderTest, SetGetLifetime) +{ + // Lifetime + u32 lifetime = 20000, lifetime_ret; // 20 sec. + int rc = hicn_packet_set_lifetime (format_, header_, lifetime); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (lifetime, lifetime_ret); +} + +TEST_F (NewHeaderAHTest, SetGetLifetime) +{ + // Lifetime + u32 lifetime = 20000, lifetime_ret; // 20 sec. + int rc = hicn_packet_set_lifetime (format_, header_, lifetime); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (lifetime, lifetime_ret); +} + +TEST_F (NewHeaderTest, SetGetPayloadType) +{ + // Lifetime + hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret; + int rc = hicn_packet_set_payload_type (format_, header_, payload_type); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (payload_type, payload_type_ret); + + payload_type = HPT_DATA; + + rc = hicn_packet_set_payload_type (format_, header_, payload_type); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (payload_type, payload_type_ret); +} +#endif diff --git a/lib/src/test/test_pool.cc b/lib/src/test/test_pool.cc new file mode 100644 index 000000000..cbb5ce068 --- /dev/null +++ b/lib/src/test/test_pool.cc @@ -0,0 +1,209 @@ +/* + * 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 <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/pool.h> +} + +/* + * TODO + * - test max_size + */ + +#define DEFAULT_SIZE 10 + +class PoolTest : public ::testing::Test +{ +protected: + PoolTest () {} + virtual ~PoolTest () {} + + int *pool; +}; + +TEST_F (PoolTest, PoolAllocation) +{ + int rc; + + pool_init (pool, DEFAULT_SIZE, 0); + + size_t pool_size = next_pow2 (DEFAULT_SIZE); + + EXPECT_EQ (pool_get_alloc_size (pool), pool_size); + + /* Check that free indices and bitmaps are correctly initialize */ + off_t *fi = pool_get_free_indices (pool); + EXPECT_EQ (vector_len (fi), pool_size); + EXPECT_EQ (fi[0], (long) (pool_size - 1)); + EXPECT_EQ (fi[pool_size - 1], 0); + + /* The allocated size of the underlying vector should be the next power of + * two + */ + EXPECT_EQ (vector_get_alloc_size (fi), pool_size); + + bitmap_t *fb = pool_get_free_bitmap (pool); + EXPECT_TRUE (bitmap_is_set (fb, 0)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size - 2)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size - 1)); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size)); + + /* Getting elements from the pool should correctly update the free indices + * and bitmap */ + int *elt; + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), pool_size - 1); + EXPECT_TRUE (bitmap_is_unset (fb, 0)); + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), pool_size - 2); + EXPECT_TRUE (bitmap_is_unset (fb, 1)); + + for (unsigned i = 0; i < pool_size - 4; i++) + { + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + } + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), 1UL); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 2)); + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), 0UL); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 1)); + + /* + * Getting elements within the allocated range should not have triggered a + * resize + */ + EXPECT_EQ (pool_len (pool), pool_size); + + /* + * Getting elements once the allocated range has been exceeded should + * trigger a resize + */ + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + + EXPECT_EQ (pool_get_alloc_size (pool), pool_size * 2); + + EXPECT_EQ (pool_len (pool), pool_size + 1); + + /* + * Doubling the size, we should have again pool_size elements free, minus 1 + */ + EXPECT_EQ (pool_get_free_indices_size (pool), pool_size - 1); + + /* + * NOTE: this is wrong as there has been a realloc and the old fi + * pointer is now invalid + */ + // EXPECT_EQ(vector_len(fi), pool_size - 1); + + /* And the bitmap should also be correctly modified */ + fb = pool_get_free_bitmap (pool); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size)); + + /* Check that surrounding values are also correct */ + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 1)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size + 1)); + + /* Setting elements after should through */ + + /* Check that free indices and bitmaps are correctly updated */ + + pool_free (pool); +} + +TEST_F (PoolTest, PoolPut) +{ + pool_init (pool, DEFAULT_SIZE, 0); + + int *elt; + pool_get (pool, elt); + *elt = 10; + pool_put (pool, elt); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetForceBitmapRealloc) +{ + const int N = 64; + int *elts[N]; + int *elt = NULL; + pool_init (pool, N, 0); + + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + pool_get (pool, elt); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetAfterReleasing) +{ + int *elt1 = NULL, *elt2 = NULL, *tmp = NULL; + pool_init (pool, DEFAULT_SIZE, 0); + + // If two elements are requested... + off_t id1 = pool_get (pool, elt1); + pool_get (pool, tmp); + + // ...and the first one is released... + pool_put (pool, elt1); + + // ...requesting a new one should return + // the first one (that was freed) + off_t id2 = pool_get (pool, elt2); + EXPECT_EQ (id1, id2); + EXPECT_EQ (elt1, elt2); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetMultipleElementsAfterReleasing) +{ + const int N = 2; + int *elts[N]; + pool_init (pool, N, 0); + + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + for (int i = 0; i < N; i++) + pool_put (pool, elts[i]); + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + + pool_free (pool); +} diff --git a/lib/src/test/test_ring.cc b/lib/src/test/test_ring.cc new file mode 100644 index 000000000..f0b0371e8 --- /dev/null +++ b/lib/src/test/test_ring.cc @@ -0,0 +1,104 @@ +/* + * 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 <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/ring.h> +} + +#define DEFAULT_SIZE 10UL + +class RingTest : public ::testing::Test +{ +protected: + RingTest () { ring_init (ring, DEFAULT_SIZE); } + virtual ~RingTest () { ring_free (ring); } + + int *ring = NULL; +}; + +/* TEST: Ring allocation and initialization */ +TEST_F (RingTest, RingAddOne) +{ + int val = -1; + /* Allocated size should be the next power of two */ + EXPECT_EQ (ring_get_size (ring), 0UL); + ring_add_value (ring, 1); + EXPECT_EQ (ring_get_size (ring), 1UL); + ring_get (ring, 0, &val); + EXPECT_EQ (val, 1); + EXPECT_EQ (ring_get_size (ring), 1UL); + ring_advance (ring, 1); + EXPECT_EQ (ring_get_size (ring), 0UL); +} + +TEST_F (RingTest, RingAddMany) +{ + size_t i = 0; + int val = -1; + size_t count = 0; + + /* Allocated size should be the next power of two */ + EXPECT_EQ (ring_get_size (ring), 0UL); + for (unsigned i = 0; i < DEFAULT_SIZE; i++) + ring_add_value (ring, i); + EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, 1, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, 1UL); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE + 1, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + // Drop one + ring_add_value (ring, DEFAULT_SIZE); + EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, { + EXPECT_EQ (val, (int) (i + 1)); // all values shoud be shifted + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + ring_advance (ring, DEFAULT_SIZE); + EXPECT_EQ (ring_get_size (ring), 0UL); +} diff --git a/lib/src/test/test_slab.cc b/lib/src/test/test_slab.cc new file mode 100644 index 000000000..15deff3c1 --- /dev/null +++ b/lib/src/test/test_slab.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2022 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/util/slab.h> +} + +class SlabTest : public ::testing::Test +{ +protected: + SlabTest () {} + virtual ~SlabTest () { slab_free (slab); } + + slab_t *slab; +}; + +typedef struct +{ + int index; + int val; +} element_t; + +TEST_F (SlabTest, SlabCreateAndGetSingleChunk) +{ + slab = slab_create (element_t, 16); + ASSERT_NE (slab, nullptr); + + element_t *e = slab_get (element_t, slab); + ASSERT_NE (e, nullptr); + slab_put (slab, e); +} + +TEST_F (SlabTest, SlabGetChunks) +{ + slab = slab_create (element_t, 2); + + // Force creation of multiple blocks (since initial size is only 2) + for (int i = 0; i < 100; i++) + { + element_t *e = slab_get (element_t, slab); + EXPECT_NE (e, nullptr); + } +} + +TEST_F (SlabTest, SlabGetAndPutChunksNoResize) +{ + constexpr int NUM_ELEMENTS = 64; + element_t *elements[NUM_ELEMENTS]; + for (int i = 0; i < NUM_ELEMENTS; i++) + elements[i] = NULL; + + // Initial size=NUM_ELEMENTS, only one block will be created + slab = slab_create (element_t, NUM_ELEMENTS); + + for (int i = 0; i < NUM_ELEMENTS; i++) + { + elements[i] = slab_get (element_t, slab); + EXPECT_NE (elements[i], nullptr); + } + + // Release all chunks + for (int i = 0; i < NUM_ELEMENTS; i++) + slab_put (slab, elements[i]); +} + +TEST_F (SlabTest, SlabGetAndPutChunks) +{ + constexpr int NUM_ELEMENTS = 100; + element_t *elements[NUM_ELEMENTS]; + for (int i = 0; i < NUM_ELEMENTS; i++) + elements[i] = NULL; + + // Initial size=2 while NUM_ELEMENTS=100, to force creation of multiple + // blocks + slab = slab_create (sizeof (element_t), 2); + + for (int i = 0; i < NUM_ELEMENTS; i++) + { + elements[i] = slab_get (element_t, slab); + EXPECT_NE (elements[i], nullptr); + } + + // Release all chunks + for (int i = 0; i < NUM_ELEMENTS; i++) + slab_put (slab, elements[i]); +} + +TEST_F (SlabTest, SlabGetAndPutSomeChunks) +{ + slab = slab_create (element_t, 2); + + constexpr int NUM_ELEMENTS = 100; + element_t *elements[NUM_ELEMENTS]; + for (int i = 0; i < NUM_ELEMENTS; i++) + elements[i] = NULL; + + // Get chunks... + for (int i = 0; i < NUM_ELEMENTS; i++) + { + elements[i] = slab_get (element_t, slab); + EXPECT_NE (elements[i], nullptr); + + // ...and return only some of them + if (i % 5 == 0) + slab_put (slab, elements[i]); + } +} + +TEST_F (SlabTest, SlabGetSameChunkTwice) +{ + slab = slab_create (element_t, 1); + + // Get chunk and update it before returning it + element_t *e = slab_get (element_t, slab); + ASSERT_NE (e, nullptr); + element_t *prev = e; + e->index = 2; + e->val = 3; + slab_put (slab, e); + + // Get a chunk again: it should return the previous one + // without wiping its memory + e = slab_get (element_t, slab); + ASSERT_NE (e, nullptr); + EXPECT_EQ (e, prev); + EXPECT_EQ (e->index, 2); + EXPECT_EQ (e->val, 3); + + // Try to get an additional chunk: it should return a new chunk + // (different from previous one) + e = slab_get (element_t, slab); + EXPECT_NE (e, prev); +}
\ No newline at end of file diff --git a/lib/src/test/test_udp_header.cc b/lib/src/test/test_udp_header.cc new file mode 100644 index 000000000..2856c8ebf --- /dev/null +++ b/lib/src/test/test_udp_header.cc @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2021-2022 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/name.h> +#include <hicn/common.h> +#include <hicn/error.h> +#include <hicn/packet.h> + +#include "../protocol/ah.h" +#include "../protocol/ipv6.h" +#include "../protocol/udp.h" +#include "../protocol/new.h" +} + +class UdpHeaderTest : public ::testing::Test +{ +protected: + const char *ipv6_prefix = "b001::abcd:1234:abcd:1234"; + const char *ipv4_prefix = "12.13.14.15"; + const uint32_t suffix = 12345; + + UdpHeaderTest (size_t hdr_size, hicn_packet_format_t format) + : buffer_ (new uint8_t[hdr_size]), hdr_size_ (hdr_size), + format_ (format), name_{}, name4_{}, name6_{} + { + int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6); + EXPECT_EQ (rc, 1); + + rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4); + EXPECT_EQ (rc, 1); + + rc = hicn_name_create (ipv4_prefix, suffix, &name4_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_name_create (ipv6_prefix, suffix, &name6_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + } + + UdpHeaderTest () + : UdpHeaderTest (NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, + HICN_PACKET_FORMAT_IPV6_UDP) + { + } + + virtual ~UdpHeaderTest () { delete[] buffer_; } + + // checked everytime we build the packet... + void + checkCommon () + { + /* Initialize packet buffer headers */ + hicn_packet_set_format (&pkbuf_, format_); + hicn_packet_set_type (&pkbuf_, HICN_PACKET_TYPE_INTEREST); + hicn_packet_set_buffer (&pkbuf_, buffer_, hdr_size_, 0); + int rc = hicn_packet_init_header (&pkbuf_, 0); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + auto ip6_hdr = (_ipv6_header_t *) buffer_; + + // Check fields + EXPECT_EQ (ip6_hdr->saddr.as_u64[0], 0UL); + EXPECT_EQ (ip6_hdr->saddr.as_u64[1], 0UL); + EXPECT_EQ (ip6_hdr->daddr.as_u64[0], 0UL); + EXPECT_EQ (ip6_hdr->daddr.as_u64[1], 0UL); + EXPECT_EQ (ip6_hdr->nxt, IPPROTO_UDP); + + _udp_header_t *udp_hdr = (_udp_header_t *) (ip6_hdr + 1); + EXPECT_EQ (udp_hdr->src_port, 0UL); + EXPECT_EQ (udp_hdr->dst_port, 0UL); + EXPECT_EQ (udp_hdr->checksum, 0UL); + // EXPECT_EQ (ntohs (udp_hdr->length), NEW_HDRLEN + AH_HDRLEN); + + _new_header_t *new_hdr = (_new_header_t *) (udp_hdr + 1); + EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL); + EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL); + EXPECT_EQ (new_hdr->suffix, 0UL); + EXPECT_EQ (new_hdr->lifetime, 0UL); + EXPECT_EQ (new_hdr->path_label, 0UL); + EXPECT_EQ (new_hdr->payload_len, 0UL); + EXPECT_EQ (_get_new_header_version (new_hdr), 0x9); + } + + virtual void + SetUp () override + { + checkCommon (); + } + + uint8_t *buffer_; + size_t hdr_size_; + hicn_packet_buffer_t pkbuf_; + hicn_packet_format_t format_; + hicn_name_t name_, name4_, name6_; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; +}; + +class UdpHeaderAHTest : public UdpHeaderTest +{ +protected: + UdpHeaderAHTest () + : UdpHeaderTest (AH_HDRLEN + NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, + HICN_PACKET_FORMAT_IPV6_UDP_AH) + { + } +}; + +/** + * Header Initialization + */ +TEST_F (UdpHeaderTest, GetFormat) +{ + hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_); + EXPECT_EQ (format, HICN_PACKET_FORMAT_IPV6_UDP); +} + +TEST_F (UdpHeaderAHTest, GetFormat) +{ + // Get format from existing packet + hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_); + + // Check it corresponds to the new header format + EXPECT_EQ (format, HICN_PACKET_FORMAT_IPV6_UDP_AH); +} + +#if 0 + +// /** +// * @brief Checksum functions are not required, but we keep them for +// * compatibility. +// */ +// TEST_F (NewHeaderTest, Checksum) +// { +// // Get format from existing packet +// int rc = hicn_packet_compute_checksum (format_, header_); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + +// rc = hicn_packet_compute_header_checksum (format_, header_, 0); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + +// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +// } + +// TEST_F (NewHeaderAHTest, Checksum) +// { +// // Get format from existing packet +// int rc = hicn_packet_compute_checksum (format_, header_); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + +// rc = hicn_packet_compute_header_checksum (format_, header_, 0); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + +// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0); +// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +// } + +TEST_F (UdpHeaderTest, GetHeaderLengthFromFormat) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN); +} + +TEST_F (UdpHeaderAHTest, GetHeaderLengthFromFormat) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN); +} + +TEST_F (UdpHeaderTest, GetHeaderLength) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length (format_, header_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN); +} + +TEST_F (UdpHeaderAHTest, GetHeaderLength) +{ + // Get format from existing packet + std::size_t hdr_len; + int rc = hicn_packet_get_header_length (format_, header_, &hdr_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN); +} + +TEST_F (UdpHeaderTest, SetGetPayloadLength) +{ + // Get format from existing packet + std::size_t payload_len = 1000, payload_len_ret; + int rc = hicn_packet_set_payload_length (format_, header_, payload_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (payload_len, payload_len_ret); +} + +TEST_F (UdpHeaderAHTest, SetGetPayloadLength) +{ + // Get format from existing packet + std::size_t payload_len = 1000, payload_len_ret; + int rc = hicn_packet_set_payload_length (format_, header_, payload_len); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (payload_len, payload_len_ret); +} + +TEST_F (UdpHeaderTest, SetGetName) +{ + // Get v6 name and set it to new_header + hicn_name_t name_ret; + + int rc = hicn_packet_set_interest (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_set_name (format_, header_, &name6_, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_name (format_, header_, &name_ret, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_name_compare (&name6_, &name_ret, 1); + EXPECT_EQ (rc, 0); +} + +TEST_F (UdpHeaderTest, SetGetLocator) +{ + // This function does nothing but it is set for compatibility + hicn_ip_address_t locator; + memset (&locator, 0, sizeof (locator)); + locator.v6.as_u8[15] = 1; + int rc = hicn_packet_set_interest (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_set_locator (format_, header_, &locator, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_locator (format_, header_, &locator, 1); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (UdpHeaderTest, SetGetSignatureSize) +{ + // No AH, so we should get an error + // FixMe no error raised here + size_t signature_size = 128; + int rc = hicn_packet_set_signature_size (format_, header_, signature_size); + (void) rc; + // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Same for hicn_packet_get_signature_size + rc = hicn_packet_get_signature_size (format_, header_, &signature_size); + // EXPECT_NE (rc, HICN_LIB_ERROR_NONE); +} + +TEST_F (UdpHeaderAHTest, SetGetSignatureSize) +{ + // No AH, so we should get an error + size_t signature_size = 128, signature_size_ret; + int rc = hicn_packet_set_signature_size (format_, header_, signature_size); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + // Same for hicn_packet_get_signature_size + rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (signature_size, signature_size_ret); +} + +TEST_F (UdpHeaderTest, IsInterestIsData) +{ + // Mark packet as interest + int rc = hicn_packet_set_interest (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + int ret; + rc = hicn_packet_is_interest (format_, header_, &ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (ret, 1); + + // Mark packet as data + rc = hicn_packet_set_data (format_, header_); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_is_interest (format_, header_, &ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + EXPECT_EQ (ret, 0); +} + +TEST_F (UdpHeaderTest, SetGetLifetime) +{ + // Lifetime + u32 lifetime = 20000, lifetime_ret; // 20 sec. + int rc = hicn_packet_set_lifetime (format_, header_, lifetime); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (lifetime, lifetime_ret); +} + +TEST_F (UdpHeaderAHTest, SetGetLifetime) +{ + // Lifetime + u32 lifetime = 20000, lifetime_ret; // 20 sec. + int rc = hicn_packet_set_lifetime (format_, header_, lifetime); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (lifetime, lifetime_ret); +} + +TEST_F (UdpHeaderTest, SetGetPayloadType) +{ + // Lifetime + hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret; + int rc = hicn_packet_set_payload_type (format_, header_, payload_type); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (payload_type, payload_type_ret); + + payload_type = HPT_DATA; + + rc = hicn_packet_set_payload_type (format_, header_, payload_type); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret); + EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + + EXPECT_EQ (payload_type, payload_type_ret); +} +#endif diff --git a/lib/src/test/test_validation.cc b/lib/src/test/test_validation.cc new file mode 100644 index 000000000..091f26d65 --- /dev/null +++ b/lib/src/test/test_validation.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/validation.h> +} + +static constexpr int BUF_SIZE = 10; + +class ValidationTest : public ::testing::Test +{ +}; + +TEST_F (ValidationTest, SymbolicName) +{ + const char symbolic_name_correct[BUF_SIZE] = "conn0"; + const char symbolic_name_empty[BUF_SIZE] = ""; + const char symbolic_name_wrong[BUF_SIZE] = "1conn0"; + + EXPECT_TRUE (is_symbolic_name (symbolic_name_correct, BUF_SIZE)); + EXPECT_FALSE (is_symbolic_name (symbolic_name_empty, BUF_SIZE)); + EXPECT_FALSE (is_symbolic_name (symbolic_name_wrong, BUF_SIZE)); +} + +TEST_F (ValidationTest, Number) +{ + const char number_correct[BUF_SIZE] = "123"; + const char number_empty[BUF_SIZE] = ""; + const char number_wrong[BUF_SIZE] = "a123"; + const char number_wrong_2[BUF_SIZE] = "12T3"; + const char number_wrong_3[BUF_SIZE] = "a"; + const char number_wrong_negative[BUF_SIZE] = "-123"; + + EXPECT_TRUE (is_number (number_correct, BUF_SIZE)); + EXPECT_FALSE (is_number (number_empty, BUF_SIZE)); + EXPECT_FALSE (is_number (number_wrong, BUF_SIZE)); + EXPECT_FALSE (is_number (number_wrong_2, BUF_SIZE)); + EXPECT_FALSE (is_number (number_wrong_3, BUF_SIZE)); + EXPECT_FALSE (is_number (number_wrong_negative, BUF_SIZE)); +}
\ No newline at end of file diff --git a/lib/src/test/test_vector.cc b/lib/src/test/test_vector.cc new file mode 100644 index 000000000..88b0bb7cf --- /dev/null +++ b/lib/src/test/test_vector.cc @@ -0,0 +1,254 @@ +/* + * 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 <gtest/gtest.h> + +extern "C" +{ +#include <hicn/util/vector.h> +} + +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); +}
\ No newline at end of file |