diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/test/unit/lib/util | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
34 files changed, 5876 insertions, 0 deletions
diff --git a/src/spdk/test/unit/lib/util/Makefile b/src/spdk/test/unit/lib/util/Makefile new file mode 100644 index 000000000..221715725 --- /dev/null +++ b/src/spdk/test/unit/lib/util/Makefile @@ -0,0 +1,45 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk + +DIRS-y = base64.c bit_array.c cpuset.c crc16.c crc32_ieee.c crc32c.c dif.c \ + iov.c math.c pipe.c string.c + +.PHONY: all clean $(DIRS-y) + +all: $(DIRS-y) +clean: $(DIRS-y) + +include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk diff --git a/src/spdk/test/unit/lib/util/base64.c/.gitignore b/src/spdk/test/unit/lib/util/base64.c/.gitignore new file mode 100644 index 000000000..a5b175236 --- /dev/null +++ b/src/spdk/test/unit/lib/util/base64.c/.gitignore @@ -0,0 +1 @@ +base64_ut diff --git a/src/spdk/test/unit/lib/util/base64.c/Makefile b/src/spdk/test/unit/lib/util/base64.c/Makefile new file mode 100644 index 000000000..c0d91c076 --- /dev/null +++ b/src/spdk/test/unit/lib/util/base64.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = base64_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/base64.c/base64_ut.c b/src/spdk/test/unit/lib/util/base64.c/base64_ut.c new file mode 100644 index 000000000..b1f70561c --- /dev/null +++ b/src/spdk/test/unit/lib/util/base64.c/base64_ut.c @@ -0,0 +1,381 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/base64.c" + +char text_A[] = "FZB3"; +uint8_t raw_A[] = {0x15, 0x90, 0x77}; +char text_B[] = "AbC/1+c="; +char text_urlsafe_B[] = "AbC_1-c="; +uint8_t raw_B[] = {0x01, 0xB0, 0xBF, 0xD7, 0xE7}; +char text_C[] = "AbC/1+cC"; +char text_urlsafe_C[] = "AbC_1-cC"; +uint8_t raw_C[] = {0x01, 0xB0, 0xBF, 0xD7, 0xE7, 0x02}; +char text_D[] = "AbC/1w=="; +char text_urlsafe_D[] = "AbC_1w=="; +uint8_t raw_D[] = {0x01, 0xB0, 0xBF, 0xD7}; +char text_E[] = "AbC12==="; +char text_F[] = "AbCd112"; +char text_G[] = "AbCd12"; +char text_H[] = "AbC12"; +char text_I[] = "AQu/1+cCCBUnOBFWv+HzoL3BOVUBItP2mRDdqhnxAtIT4hD1wbQ30Ylm8R+7khPS";//64 bytes +char text_urlsafe_I[] = + "AQu_1-cCCBUnOBFWv-HzoL3BOVUBItP2mRDdqhnxAtIT4hD1wbQ30Ylm8R-7khPS";//64 bytes +uint8_t raw_I[] = {0x01, 0x0B, 0xBF, 0xD7, 0xE7, 0x02, 0x08, 0x15, 0x27, 0x38, 0x11, 0x56, 0xBF, 0xE1, 0xF3, 0xA0, + 0xBD, 0xC1, 0x39, 0x55, 0x01, 0x22, 0xD3, 0xF6, 0x99, 0x10, 0xDD, 0xAA, 0x19, 0xF1, 0x02, 0xD2, + 0x13, 0xE2, 0x10, 0xF5, 0xC1, 0xB4, 0x37, 0xD1, 0x89, 0x66, 0xF1, 0x1F, 0xBB, 0x92, 0x13, 0xD2 + }; +char text_J[] = + "AQu/1+cCCBUnOBFWv+HzoL3BOVUBItP2mRDdqhnxAtIT4hD1wbQ30Ylm8R+7khPSvcE5VecCCBUZ8QLiEPVm8b3BOVUBItP2GfEC4hD1ZvE5VQEi0/aJZvEfu5LiEPUTvcE5VQEi0/YZEQ=="; +char text_urlsafe_J[] = + "AQu_1-cCCBUnOBFWv-HzoL3BOVUBItP2mRDdqhnxAtIT4hD1wbQ30Ylm8R-7khPSvcE5VecCCBUZ8QLiEPVm8b3BOVUBItP2GfEC4hD1ZvE5VQEi0_aJZvEfu5LiEPUTvcE5VQEi0_YZEQ=="; +uint8_t raw_J[] = {0x01, 0x0B, 0xBF, 0xD7, 0xE7, 0x02, 0x08, 0x15, 0x27, 0x38, 0x11, 0x56, 0xBF, 0xE1, 0xF3, 0xA0, + 0xBD, 0xC1, 0x39, 0x55, 0x01, 0x22, 0xD3, 0xF6, 0x99, 0x10, 0xDD, 0xAA, 0x19, 0xF1, 0x02, 0xD2, + 0x13, 0xE2, 0x10, 0xF5, 0xC1, 0xB4, 0x37, 0xD1, 0x89, 0x66, 0xF1, 0x1F, 0xBB, 0x92, 0x13, 0xD2, + 0xBD, 0xC1, 0x39, 0x55, 0xE7, 0x02, 0x08, 0x15, 0x19, 0xF1, 0x02, 0xE2, 0x10, 0xF5, 0x66, 0xF1, + 0xBD, 0xC1, 0x39, 0x55, 0x01, 0x22, 0xD3, 0xF6, 0x19, 0xF1, 0x02, 0xE2, 0x10, 0xF5, 0x66, 0xF1, + 0x39, 0x55, 0x01, 0x22, 0xD3, 0xF6, 0x89, 0x66, 0xF1, 0x1F, 0xBB, 0x92, 0xE2, 0x10, 0xF5, 0x13, + 0xBD, 0xC1, 0x39, 0x55, 0x01, 0x22, 0xD3, 0xF6, 0x19, 0x11 + }; + +static void +test_base64_get_encoded_strlen(void) +{ + uint32_t raw_lens[4] = {8, 9, 10, 11}; + uint32_t text_strlens[4] = {12, 12, 16, 16}; + uint32_t text_strlen; + int i; + + for (i = 0; i < 4; i++) { + text_strlen = spdk_base64_get_encoded_strlen(raw_lens[i]); + CU_ASSERT_EQUAL(text_strlen, text_strlens[i]); + } +} + +static void +test_base64_get_decoded_len(void) +{ + uint32_t text_strlens[4] = {8, 10, 11, 12}; + uint32_t raw_lens[4] = {6, 7, 8, 9}; + uint32_t bin_len; + int i; + + for (i = 0; i < 4; i++) { + bin_len = spdk_base64_get_decoded_len(text_strlens[i]); + CU_ASSERT_EQUAL(bin_len, raw_lens[i]); + } +} + +static void +test_base64_encode(void) +{ + char text[200]; + int ret; + + ret = spdk_base64_encode(text, raw_A, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_A) == 0); + CU_ASSERT_EQUAL(strlen(text), strlen(text_A)); + + ret = spdk_base64_encode(text, raw_B, sizeof(raw_B)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_B) == 0); + CU_ASSERT_EQUAL(strlen(text), strlen(text_B)); + + ret = spdk_base64_encode(text, raw_C, sizeof(raw_C)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_C) == 0); + + ret = spdk_base64_encode(text, raw_D, sizeof(raw_D)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_D) == 0); + + ret = spdk_base64_encode(text, raw_I, sizeof(raw_I)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_I) == 0); + + ret = spdk_base64_encode(text, raw_J, sizeof(raw_J)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_J) == 0); + + ret = spdk_base64_encode(NULL, raw_A, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_encode(text, NULL, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_encode(text, raw_A, 0); + CU_ASSERT_EQUAL(ret, -EINVAL); +} + +static void +test_base64_decode(void) +{ + char raw_buf[200]; + void *raw = (void *)raw_buf; + size_t raw_len; + int ret; + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_A); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_A)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_A); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_A)); + CU_ASSERT(memcmp(raw, raw_A, sizeof(raw_A)) == 0); + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_B); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_B)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_B); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_B)); + CU_ASSERT(memcmp(raw, raw_B, sizeof(raw_B)) == 0); + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_C); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_C)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_C); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_C)); + CU_ASSERT(memcmp(raw, raw_C, sizeof(raw_C)) == 0); + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_D); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_D)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_D); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_D)); + CU_ASSERT(memcmp(raw, raw_D, sizeof(raw_D)) == 0); + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_I); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_I)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_I); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_I)); + CU_ASSERT(memcmp(raw, raw_I, sizeof(raw_I)) == 0); + + /* len */ + ret = spdk_base64_decode(NULL, &raw_len, text_J); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_J)); + + /* decode */ + ret = spdk_base64_decode(raw, &raw_len, text_J); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_J)); + CU_ASSERT(memcmp(raw, raw_J, sizeof(raw_J)) == 0); + + ret = spdk_base64_decode(raw, &raw_len, text_E); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_decode(raw, &raw_len, text_F); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_decode(raw, &raw_len, text_G); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_decode(raw, &raw_len, text_H); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_decode(raw, &raw_len, NULL); + CU_ASSERT_EQUAL(ret, -EINVAL); +} + +static void +test_base64_urlsafe_encode(void) +{ + char text[200]; + int ret; + + ret = spdk_base64_urlsafe_encode(text, raw_A, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_A) == 0); + CU_ASSERT_EQUAL(strlen(text), strlen(text_A)); + + ret = spdk_base64_urlsafe_encode(text, raw_B, sizeof(raw_B)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_urlsafe_B) == 0); + CU_ASSERT_EQUAL(strlen(text), strlen(text_urlsafe_B)); + + ret = spdk_base64_urlsafe_encode(text, raw_C, sizeof(raw_C)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_urlsafe_C) == 0); + + ret = spdk_base64_urlsafe_encode(text, raw_D, sizeof(raw_D)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_urlsafe_D) == 0); + + ret = spdk_base64_urlsafe_encode(text, raw_I, sizeof(raw_I)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_urlsafe_I) == 0); + + ret = spdk_base64_urlsafe_encode(text, raw_J, sizeof(raw_J)); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT(strcmp(text, text_urlsafe_J) == 0); + + ret = spdk_base64_urlsafe_encode(NULL, raw_A, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_encode(text, NULL, sizeof(raw_A)); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_encode(text, raw_A, 0); + CU_ASSERT_EQUAL(ret, -EINVAL); +} + +static void +test_base64_urlsafe_decode(void) +{ + char raw_buf[200]; + void *raw = (void *)raw_buf; + size_t raw_len = 0; + int ret; + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_A); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_A)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_A); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_A)); + CU_ASSERT(memcmp(raw, raw_A, sizeof(raw_A)) == 0); + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_B); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_B)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_B); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_B)); + CU_ASSERT(memcmp(raw, raw_B, sizeof(raw_B)) == 0); + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_C); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_C)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_C); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_C)); + CU_ASSERT(memcmp(raw, raw_C, sizeof(raw_C)) == 0); + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_D); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_D)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_D); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_D)); + CU_ASSERT(memcmp(raw, raw_D, sizeof(raw_D)) == 0); + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_I); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_I)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_I); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_I)); + CU_ASSERT(memcmp(raw, raw_I, sizeof(raw_I)) == 0); + + /* len */ + ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_J); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_J)); + + /* decode */ + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_J); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_EQUAL(raw_len, sizeof(raw_J)); + CU_ASSERT(memcmp(raw, raw_J, sizeof(raw_J)) == 0); + + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_E); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_F); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_G); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_H); + CU_ASSERT_EQUAL(ret, -EINVAL); + ret = spdk_base64_urlsafe_decode(raw, &raw_len, NULL); + CU_ASSERT_EQUAL(ret, -EINVAL); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("base64", NULL, NULL); + + CU_ADD_TEST(suite, test_base64_get_encoded_strlen); + CU_ADD_TEST(suite, test_base64_get_decoded_len); + CU_ADD_TEST(suite, test_base64_encode); + CU_ADD_TEST(suite, test_base64_decode); + CU_ADD_TEST(suite, test_base64_urlsafe_encode); + CU_ADD_TEST(suite, test_base64_urlsafe_decode); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/bit_array.c/.gitignore b/src/spdk/test/unit/lib/util/bit_array.c/.gitignore new file mode 100644 index 000000000..24300cdb3 --- /dev/null +++ b/src/spdk/test/unit/lib/util/bit_array.c/.gitignore @@ -0,0 +1 @@ +bit_array_ut diff --git a/src/spdk/test/unit/lib/util/bit_array.c/Makefile b/src/spdk/test/unit/lib/util/bit_array.c/Makefile new file mode 100644 index 000000000..281001af8 --- /dev/null +++ b/src/spdk/test/unit/lib/util/bit_array.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = bit_array_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/bit_array.c/bit_array_ut.c b/src/spdk/test/unit/lib/util/bit_array.c/bit_array_ut.c new file mode 100644 index 000000000..5b19b409b --- /dev/null +++ b/src/spdk/test/unit/lib/util/bit_array.c/bit_array_ut.c @@ -0,0 +1,376 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/bit_array.c" +#include "common/lib/test_env.c" + +static void +test_1bit(void) +{ + struct spdk_bit_array *ba; + + ba = spdk_bit_array_create(1); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 1); + + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == UINT32_MAX); + + /* Set bit 0 */ + CU_ASSERT(spdk_bit_array_set(ba, 0) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == true); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == 0); + + /* Clear bit 0 */ + spdk_bit_array_clear(ba, 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == UINT32_MAX); + + spdk_bit_array_free(&ba); + CU_ASSERT(ba == NULL); +} + +static void +test_64bit(void) +{ + struct spdk_bit_array *ba; + + ba = spdk_bit_array_create(64); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 64); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_get(ba, 63) == false); + CU_ASSERT(spdk_bit_array_get(ba, 64) == false); + CU_ASSERT(spdk_bit_array_get(ba, 1000) == false); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == UINT32_MAX); + + /* Set bit 1 */ + CU_ASSERT(spdk_bit_array_set(ba, 1) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_get(ba, 1) == true); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == 1); + + /* Set bit 63 (1 still set) */ + CU_ASSERT(spdk_bit_array_set(ba, 63) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_get(ba, 1) == true); + CU_ASSERT(spdk_bit_array_get(ba, 63) == true); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == 1); + + /* Clear bit 1 (63 still set) */ + spdk_bit_array_clear(ba, 1); + CU_ASSERT(spdk_bit_array_get(ba, 1) == false); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == 63); + + /* Clear bit 63 (no bits set) */ + spdk_bit_array_clear(ba, 63); + CU_ASSERT(spdk_bit_array_get(ba, 63) == false); + CU_ASSERT(spdk_bit_array_find_first_set(ba, 0) == UINT32_MAX); + + spdk_bit_array_free(&ba); +} + +static void +test_find(void) +{ + struct spdk_bit_array *ba; + uint32_t i; + + ba = spdk_bit_array_create(256); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 256); + + /* Set all bits */ + for (i = 0; i < 256; i++) { + CU_ASSERT(spdk_bit_array_set(ba, i) == 0); + } + + /* Verify that find_first_set and find_first_clear work for each starting position */ + for (i = 0; i < 256; i++) { + CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == i); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == UINT32_MAX); + } + CU_ASSERT(spdk_bit_array_find_first_set(ba, 256) == UINT32_MAX); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == UINT32_MAX); + + /* Clear bits 0 through 31 */ + for (i = 0; i < 32; i++) { + spdk_bit_array_clear(ba, i); + } + + for (i = 0; i < 32; i++) { + CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == 32); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == i); + } + + for (i = 32; i < 256; i++) { + CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == i); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == UINT32_MAX); + } + + /* Clear bit 255 */ + spdk_bit_array_clear(ba, 255); + + for (i = 0; i < 32; i++) { + CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == 32); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == i); + } + + for (i = 32; i < 255; i++) { + CU_ASSERT(spdk_bit_array_find_first_set(ba, i) == i); + CU_ASSERT(spdk_bit_array_find_first_clear(ba, i) == 255); + } + + CU_ASSERT(spdk_bit_array_find_first_clear(ba, 256) == UINT32_MAX); + + spdk_bit_array_free(&ba); +} + +static void +test_resize(void) +{ + struct spdk_bit_array *ba; + + /* Start with a 0 bit array */ + ba = spdk_bit_array_create(0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_set(ba, 0) == -EINVAL); + spdk_bit_array_clear(ba, 0); + + /* Increase size to 1 bit */ + SPDK_CU_ASSERT_FATAL(spdk_bit_array_resize(&ba, 1) == 0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 1); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_set(ba, 0) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == true); + + /* Increase size to 2 bits */ + SPDK_CU_ASSERT_FATAL(spdk_bit_array_resize(&ba, 2) == 0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 2); + CU_ASSERT(spdk_bit_array_get(ba, 1) == false); + CU_ASSERT(spdk_bit_array_set(ba, 1) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 1) == true); + + /* Shrink size back to 1 bit */ + SPDK_CU_ASSERT_FATAL(spdk_bit_array_resize(&ba, 1) == 0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 1); + CU_ASSERT(spdk_bit_array_get(ba, 0) == true); + CU_ASSERT(spdk_bit_array_get(ba, 1) == false); + + /* Increase size to 65 bits */ + SPDK_CU_ASSERT_FATAL(spdk_bit_array_resize(&ba, 65) == 0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 65); + CU_ASSERT(spdk_bit_array_get(ba, 0) == true); + CU_ASSERT(spdk_bit_array_get(ba, 1) == false); + CU_ASSERT(spdk_bit_array_set(ba, 64) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 64) == true); + + /* Shrink size back to 0 bits */ + SPDK_CU_ASSERT_FATAL(spdk_bit_array_resize(&ba, 0) == 0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_capacity(ba) == 0); + CU_ASSERT(spdk_bit_array_get(ba, 0) == false); + CU_ASSERT(spdk_bit_array_get(ba, 1) == false); + + spdk_bit_array_free(&ba); +} + +static void +test_errors(void) +{ + /* Passing NULL to resize should fail. */ + CU_ASSERT(spdk_bit_array_resize(NULL, 0) == -EINVAL); + + /* Passing NULL to free is a no-op. */ + spdk_bit_array_free(NULL); +} + +static void +test_count(void) +{ + struct spdk_bit_array *ba; + uint32_t i; + + /* 0-bit array should have 0 bits set and 0 bits clear */ + ba = spdk_bit_array_create(0); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_count_set(ba) == 0); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 0); + spdk_bit_array_free(&ba); + + /* 1-bit array */ + ba = spdk_bit_array_create(1); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_count_set(ba) == 0); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 1); + spdk_bit_array_set(ba, 0); + CU_ASSERT(spdk_bit_array_count_set(ba) == 1); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 0); + spdk_bit_array_free(&ba); + + /* 65-bit array */ + ba = spdk_bit_array_create(65); + SPDK_CU_ASSERT_FATAL(ba != NULL); + CU_ASSERT(spdk_bit_array_count_set(ba) == 0); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 65); + spdk_bit_array_set(ba, 0); + CU_ASSERT(spdk_bit_array_count_set(ba) == 1); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 64); + spdk_bit_array_set(ba, 5); + CU_ASSERT(spdk_bit_array_count_set(ba) == 2); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 63); + spdk_bit_array_set(ba, 13); + CU_ASSERT(spdk_bit_array_count_set(ba) == 3); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 62); + spdk_bit_array_clear(ba, 0); + CU_ASSERT(spdk_bit_array_count_set(ba) == 2); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 63); + for (i = 0; i < 65; i++) { + spdk_bit_array_set(ba, i); + } + CU_ASSERT(spdk_bit_array_count_set(ba) == 65); + CU_ASSERT(spdk_bit_array_count_clear(ba) == 0); + for (i = 0; i < 65; i++) { + spdk_bit_array_clear(ba, i); + CU_ASSERT(spdk_bit_array_count_set(ba) == 65 - i - 1); + CU_ASSERT(spdk_bit_array_count_clear(ba) == i + 1); + } + spdk_bit_array_free(&ba); +} + +#define TEST_MASK_SIZE 128 +#define TEST_BITS_NUM (TEST_MASK_SIZE * 8 - 3) +static void +test_mask_store_load(void) +{ + struct spdk_bit_array *ba; + uint8_t mask[TEST_MASK_SIZE] = { 0 }; + uint32_t i; + + ba = spdk_bit_array_create(TEST_BITS_NUM); + + /* Check if stored mask is consistent with bit array mask */ + spdk_bit_array_set(ba, 0); + spdk_bit_array_set(ba, TEST_BITS_NUM / 2); + spdk_bit_array_set(ba, TEST_BITS_NUM - 1); + + spdk_bit_array_store_mask(ba, mask); + + for (i = 0; i < TEST_BITS_NUM; i++) { + if (i == 0 || i == TEST_BITS_NUM / 2 || i == TEST_BITS_NUM - 1) { + CU_ASSERT((mask[i / 8] & (1U << (i % 8)))); + } else { + CU_ASSERT(!(mask[i / 8] & (1U << (i % 8)))); + } + } + + /* Check if loaded mask is consistent with bit array mask */ + memset(mask, 0, TEST_MASK_SIZE); + mask[0] = 1; + mask[TEST_MASK_SIZE - 1] = 1U << 4; + + spdk_bit_array_load_mask(ba, mask); + + CU_ASSERT(spdk_bit_array_get(ba, 0)); + CU_ASSERT(spdk_bit_array_get(ba, TEST_BITS_NUM - 1)); + + spdk_bit_array_clear(ba, 0); + spdk_bit_array_clear(ba, TEST_BITS_NUM - 1); + + for (i = 0; i < TEST_BITS_NUM; i++) { + CU_ASSERT(!spdk_bit_array_get(ba, i)); + } + + spdk_bit_array_free(&ba); +} + +static void +test_mask_clear(void) +{ + struct spdk_bit_array *ba; + uint32_t i; + + ba = spdk_bit_array_create(TEST_BITS_NUM); + + for (i = 0; i < TEST_BITS_NUM; i++) { + spdk_bit_array_set(ba, i); + } + + spdk_bit_array_clear_mask(ba); + + for (i = 0; i < TEST_BITS_NUM; i++) { + CU_ASSERT(!spdk_bit_array_get(ba, i)); + } + + spdk_bit_array_free(&ba); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("bit_array", NULL, NULL); + + CU_ADD_TEST(suite, test_1bit); + CU_ADD_TEST(suite, test_64bit); + CU_ADD_TEST(suite, test_find); + CU_ADD_TEST(suite, test_resize); + CU_ADD_TEST(suite, test_errors); + CU_ADD_TEST(suite, test_count); + CU_ADD_TEST(suite, test_mask_store_load); + CU_ADD_TEST(suite, test_mask_clear); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/cpuset.c/.gitignore b/src/spdk/test/unit/lib/util/cpuset.c/.gitignore new file mode 100644 index 000000000..2ca1a2d36 --- /dev/null +++ b/src/spdk/test/unit/lib/util/cpuset.c/.gitignore @@ -0,0 +1 @@ +cpuset_ut diff --git a/src/spdk/test/unit/lib/util/cpuset.c/Makefile b/src/spdk/test/unit/lib/util/cpuset.c/Makefile new file mode 100644 index 000000000..6b2374935 --- /dev/null +++ b/src/spdk/test/unit/lib/util/cpuset.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = cpuset_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/cpuset.c/cpuset_ut.c b/src/spdk/test/unit/lib/util/cpuset.c/cpuset_ut.c new file mode 100644 index 000000000..3630c5cbd --- /dev/null +++ b/src/spdk/test/unit/lib/util/cpuset.c/cpuset_ut.c @@ -0,0 +1,262 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" +#include "spdk/cpuset.h" + +#include "spdk_cunit.h" + +#include "util/cpuset.c" + +static int +cpuset_check_range(struct spdk_cpuset *core_mask, uint32_t min, uint32_t max, bool isset) +{ + uint32_t core; + for (core = min; core <= max; core++) { + if (isset != spdk_cpuset_get_cpu(core_mask, core)) { + return -1; + } + } + return 0; +} + +static void +test_cpuset(void) +{ + uint32_t cpu; + struct spdk_cpuset *set = spdk_cpuset_alloc(); + + SPDK_CU_ASSERT_FATAL(set != NULL); + CU_ASSERT(spdk_cpuset_count(set) == 0); + + /* Set cpu 0 */ + spdk_cpuset_set_cpu(set, 0, true); + CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true); + CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 1, false) == 0); + CU_ASSERT(spdk_cpuset_count(set) == 1); + + /* Set last cpu (cpu 0 already set) */ + spdk_cpuset_set_cpu(set, SPDK_CPUSET_SIZE - 1, true); + CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true); + CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); + CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0); + CU_ASSERT(spdk_cpuset_count(set) == 2); + + /* Clear cpu 0 (last cpu already set) */ + spdk_cpuset_set_cpu(set, 0, false); + CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == false); + CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0); + CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); + CU_ASSERT(spdk_cpuset_count(set) == 1); + + /* Set middle cpu (last cpu already set) */ + cpu = (SPDK_CPUSET_SIZE - 1) / 2; + spdk_cpuset_set_cpu(set, cpu, true); + CU_ASSERT(spdk_cpuset_get_cpu(set, cpu) == true); + CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); + CU_ASSERT(cpuset_check_range(set, 1, cpu - 1, false) == 0); + CU_ASSERT(cpuset_check_range(set, cpu + 1, SPDK_CPUSET_SIZE - 2, false) == 0); + CU_ASSERT(spdk_cpuset_count(set) == 2); + + /* Set all cpus */ + for (cpu = 0; cpu < SPDK_CPUSET_SIZE; cpu++) { + spdk_cpuset_set_cpu(set, cpu, true); + } + CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, true) == 0); + CU_ASSERT(spdk_cpuset_count(set) == SPDK_CPUSET_SIZE); + + /* Clear all cpus */ + spdk_cpuset_zero(set); + CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, false) == 0); + CU_ASSERT(spdk_cpuset_count(set) == 0); + + spdk_cpuset_free(set); +} + +static void +test_cpuset_parse(void) +{ + int rc; + struct spdk_cpuset *core_mask; + char buf[1024]; + + core_mask = spdk_cpuset_alloc(); + SPDK_CU_ASSERT_FATAL(core_mask != NULL); + + /* Only core 0 should be set */ + rc = spdk_cpuset_parse(core_mask, "0x1"); + CU_ASSERT(rc >= 0); + CU_ASSERT(cpuset_check_range(core_mask, 0, 0, true) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 1, SPDK_CPUSET_SIZE - 1, false) == 0); + + /* Only core 1 should be set */ + rc = spdk_cpuset_parse(core_mask, "[1]"); + CU_ASSERT(rc >= 0); + CU_ASSERT(cpuset_check_range(core_mask, 0, 0, false) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 1, 1, true) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 2, SPDK_CPUSET_SIZE - 1, false) == 0); + + /* Set cores 0-10,12,128-254 */ + rc = spdk_cpuset_parse(core_mask, "[0-10,12,128-254]"); + CU_ASSERT(rc >= 0); + CU_ASSERT(cpuset_check_range(core_mask, 0, 10, true) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 11, 11, false) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 12, 12, true) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 13, 127, false) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 128, 254, true) == 0); + CU_ASSERT(cpuset_check_range(core_mask, 255, SPDK_CPUSET_SIZE - 1, false) == 0); + + /* Set all cores */ + snprintf(buf, sizeof(buf), "[0-%d]", SPDK_CPUSET_SIZE - 1); + rc = spdk_cpuset_parse(core_mask, buf); + CU_ASSERT(rc >= 0); + CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); + + /* Null parameters not allowed */ + rc = spdk_cpuset_parse(core_mask, NULL); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(NULL, "[1]"); + CU_ASSERT(rc < 0); + + /* Wrong formated core lists */ + rc = spdk_cpuset_parse(core_mask, ""); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "["); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "[]"); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "[10--11]"); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "[11-10]"); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "[10-11,]"); + CU_ASSERT(rc < 0); + + rc = spdk_cpuset_parse(core_mask, "[,10-11]"); + CU_ASSERT(rc < 0); + + /* Out of range value */ + snprintf(buf, sizeof(buf), "[%d]", SPDK_CPUSET_SIZE + 1); + rc = spdk_cpuset_parse(core_mask, buf); + CU_ASSERT(rc < 0); + + /* Overflow value (UINT64_MAX * 10) */ + rc = spdk_cpuset_parse(core_mask, "[184467440737095516150]"); + CU_ASSERT(rc < 0); + + spdk_cpuset_free(core_mask); +} + +static void +test_cpuset_fmt(void) +{ + int i; + uint32_t lcore; + struct spdk_cpuset *core_mask = spdk_cpuset_alloc(); + const char *hex_mask; + char hex_mask_ref[SPDK_CPUSET_SIZE / 4 + 1]; + + /* Clear coremask. hex_mask should be "0" */ + spdk_cpuset_zero(core_mask); + hex_mask = spdk_cpuset_fmt(core_mask); + SPDK_CU_ASSERT_FATAL(hex_mask != NULL); + CU_ASSERT(strcmp("0", hex_mask) == 0); + + /* Set coremask 0x51234. Result should be "51234" */ + spdk_cpuset_zero(core_mask); + spdk_cpuset_set_cpu(core_mask, 2, true); + spdk_cpuset_set_cpu(core_mask, 4, true); + spdk_cpuset_set_cpu(core_mask, 5, true); + spdk_cpuset_set_cpu(core_mask, 9, true); + spdk_cpuset_set_cpu(core_mask, 12, true); + spdk_cpuset_set_cpu(core_mask, 16, true); + spdk_cpuset_set_cpu(core_mask, 18, true); + hex_mask = spdk_cpuset_fmt(core_mask); + SPDK_CU_ASSERT_FATAL(hex_mask != NULL); + CU_ASSERT(strcmp("51234", hex_mask) == 0); + + /* Set all cores */ + spdk_cpuset_zero(core_mask); + CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, false) == 0); + + for (lcore = 0; lcore < SPDK_CPUSET_SIZE; lcore++) { + spdk_cpuset_set_cpu(core_mask, lcore, true); + } + for (i = 0; i < SPDK_CPUSET_SIZE / 4; i++) { + hex_mask_ref[i] = 'f'; + } + hex_mask_ref[SPDK_CPUSET_SIZE / 4] = '\0'; + + /* Check data before format */ + CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); + + hex_mask = spdk_cpuset_fmt(core_mask); + SPDK_CU_ASSERT_FATAL(hex_mask != NULL); + CU_ASSERT(strcmp(hex_mask_ref, hex_mask) == 0); + + /* Check data integrity after format */ + CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); + + spdk_cpuset_free(core_mask); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("cpuset", NULL, NULL); + + CU_ADD_TEST(suite, test_cpuset); + CU_ADD_TEST(suite, test_cpuset_parse); + CU_ADD_TEST(suite, test_cpuset_fmt); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/crc16.c/.gitignore b/src/spdk/test/unit/lib/util/crc16.c/.gitignore new file mode 100644 index 000000000..d026adf09 --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc16.c/.gitignore @@ -0,0 +1 @@ +crc16_ut diff --git a/src/spdk/test/unit/lib/util/crc16.c/Makefile b/src/spdk/test/unit/lib/util/crc16.c/Makefile new file mode 100644 index 000000000..339146be5 --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc16.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = crc16_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/crc16.c/crc16_ut.c b/src/spdk/test/unit/lib/util/crc16.c/crc16_ut.c new file mode 100644 index 000000000..03e6c65cd --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc16.c/crc16_ut.c @@ -0,0 +1,104 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/crc16.c" + +static void +test_crc16_t10dif(void) +{ + uint16_t crc; + char buf[] = "123456789"; + + crc = spdk_crc16_t10dif(0, buf, strlen(buf)); + CU_ASSERT(crc == 0xd0db); +} + +static void +test_crc16_t10dif_seed(void) +{ + uint16_t crc = 0; + char buf1[] = "1234"; + char buf2[] = "56789"; + + crc = spdk_crc16_t10dif(crc, buf1, strlen(buf1)); + crc = spdk_crc16_t10dif(crc, buf2, strlen(buf2)); + CU_ASSERT(crc == 0xd0db); +} + +static void +test_crc16_t10dif_copy(void) +{ + uint16_t crc1 = 0, crc2; + char buf1[] = "1234"; + char buf2[] = "56789"; + char *buf3 = calloc(1, strlen(buf1) + strlen(buf2) + 1); + SPDK_CU_ASSERT_FATAL(buf3 != NULL); + + crc1 = spdk_crc16_t10dif_copy(crc1, buf3, buf1, strlen(buf1)); + crc1 = spdk_crc16_t10dif_copy(crc1, buf3 + strlen(buf1), buf2, strlen(buf2)); + CU_ASSERT(crc1 == 0xd0db); + + crc2 = spdk_crc16_t10dif(0, buf3, strlen(buf3)); + CU_ASSERT(crc2 == 0xd0db); + + free(buf3); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("crc16", NULL, NULL); + + CU_ADD_TEST(suite, test_crc16_t10dif); + CU_ADD_TEST(suite, test_crc16_t10dif_seed); + CU_ADD_TEST(suite, test_crc16_t10dif_copy); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/crc32_ieee.c/.gitignore b/src/spdk/test/unit/lib/util/crc32_ieee.c/.gitignore new file mode 100644 index 000000000..40a85a93f --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32_ieee.c/.gitignore @@ -0,0 +1 @@ +crc32_ieee_ut diff --git a/src/spdk/test/unit/lib/util/crc32_ieee.c/Makefile b/src/spdk/test/unit/lib/util/crc32_ieee.c/Makefile new file mode 100644 index 000000000..6b976721c --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32_ieee.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = crc32_ieee_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/crc32_ieee.c/crc32_ieee_ut.c b/src/spdk/test/unit/lib/util/crc32_ieee.c/crc32_ieee_ut.c new file mode 100644 index 000000000..2187438bf --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32_ieee.c/crc32_ieee_ut.c @@ -0,0 +1,74 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/crc32.c" +#include "util/crc32_ieee.c" + +static void +test_crc32_ieee(void) +{ + uint32_t crc; + char buf[] = "Hello world!"; + + crc = 0xFFFFFFFFu; + crc = spdk_crc32_ieee_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x1b851995); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("crc32_ieee", NULL, NULL); + + CU_ADD_TEST(suite, test_crc32_ieee); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/crc32c.c/.gitignore b/src/spdk/test/unit/lib/util/crc32c.c/.gitignore new file mode 100644 index 000000000..55bedec7f --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32c.c/.gitignore @@ -0,0 +1 @@ +crc32c_ut diff --git a/src/spdk/test/unit/lib/util/crc32c.c/Makefile b/src/spdk/test/unit/lib/util/crc32c.c/Makefile new file mode 100644 index 000000000..4f1cc0e4b --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32c.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = crc32c_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/crc32c.c/crc32c_ut.c b/src/spdk/test/unit/lib/util/crc32c.c/crc32c_ut.c new file mode 100644 index 000000000..6313d7bf6 --- /dev/null +++ b/src/spdk/test/unit/lib/util/crc32c.c/crc32c_ut.c @@ -0,0 +1,145 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/crc32.c" +#include "util/crc32c.c" + +static void +test_crc32c(void) +{ + uint32_t crc; + char buf[1024]; + + /* Verify a string's CRC32-C value against the known correct result. */ + snprintf(buf, sizeof(buf), "%s", "Hello world!"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x7b98e751); + + /* + * The main loop of the optimized CRC32-C implementation processes data in 8-byte blocks, + * followed by a loop to handle the 0-7 trailing bytes. + * Test all buffer sizes from 0 to 7 in order to hit all possible trailing byte counts. + */ + + /* 0-byte buffer should not modify CRC at all, so final result should be ~0 ^ ~0 == 0 */ + snprintf(buf, sizeof(buf), "%s", ""); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0); + + /* 1-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "1"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x90F599E3); + + /* 2-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "12"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x7355C460); + + /* 3-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "123"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x107B2FB2); + + /* 4-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "1234"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0xF63AF4EE); + + /* 5-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "12345"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x18D12335); + + /* 6-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "123456"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x41357186); + + /* 7-byte buffer */ + snprintf(buf, sizeof(buf), "%s", "1234567"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x124297EA); + + /* Test a buffer of exactly 8 bytes (one block in the main CRC32-C loop). */ + snprintf(buf, sizeof(buf), "%s", "12345678"); + crc = 0xFFFFFFFFu; + crc = spdk_crc32c_update(buf, strlen(buf), crc); + crc ^= 0xFFFFFFFFu; + CU_ASSERT(crc == 0x6087809A); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("crc32c", NULL, NULL); + + CU_ADD_TEST(suite, test_crc32c); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/dif.c/.gitignore b/src/spdk/test/unit/lib/util/dif.c/.gitignore new file mode 100644 index 000000000..040b296b7 --- /dev/null +++ b/src/spdk/test/unit/lib/util/dif.c/.gitignore @@ -0,0 +1 @@ +dif_ut diff --git a/src/spdk/test/unit/lib/util/dif.c/Makefile b/src/spdk/test/unit/lib/util/dif.c/Makefile new file mode 100644 index 000000000..714928236 --- /dev/null +++ b/src/spdk/test/unit/lib/util/dif.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = dif_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/dif.c/dif_ut.c b/src/spdk/test/unit/lib/util/dif.c/dif_ut.c new file mode 100644 index 000000000..0b069b189 --- /dev/null +++ b/src/spdk/test/unit/lib/util/dif.c/dif_ut.c @@ -0,0 +1,2669 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/dif.c" + +#define DATA_PATTERN(offset) ((uint8_t)(0xAB + (offset))) +#define GUARD_SEED 0xCD + +static int +ut_data_pattern_generate(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks) +{ + struct _dif_sgl sgl; + uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i; + uint8_t *buf; + + _dif_sgl_init(&sgl, iovs, iovcnt); + + if (!_dif_sgl_is_valid(&sgl, block_size * num_blocks)) { + return -1; + } + + offset_blocks = 0; + data_offset = 0; + + while (offset_blocks < num_blocks) { + offset_in_block = 0; + while (offset_in_block < block_size) { + _dif_sgl_get_buf(&sgl, (void *)&buf, &buf_len); + if (offset_in_block < block_size - md_size) { + buf_len = spdk_min(buf_len, + block_size - md_size - offset_in_block); + for (i = 0; i < buf_len; i++) { + buf[i] = DATA_PATTERN(data_offset + i); + } + data_offset += buf_len; + } else { + buf_len = spdk_min(buf_len, block_size - offset_in_block); + memset(buf, 0, buf_len); + } + _dif_sgl_advance(&sgl, buf_len); + offset_in_block += buf_len; + } + offset_blocks++; + } + + return 0; +} + +static int +ut_data_pattern_verify(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks) +{ + struct _dif_sgl sgl; + uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i; + uint8_t *buf; + + _dif_sgl_init(&sgl, iovs, iovcnt); + + if (!_dif_sgl_is_valid(&sgl, block_size * num_blocks)) { + return -1; + } + + offset_blocks = 0; + data_offset = 0; + + while (offset_blocks < num_blocks) { + offset_in_block = 0; + while (offset_in_block < block_size) { + _dif_sgl_get_buf(&sgl, (void *)&buf, &buf_len); + + if (offset_in_block < block_size - md_size) { + buf_len = spdk_min(buf_len, + block_size - md_size - offset_in_block); + for (i = 0; i < buf_len; i++) { + if (buf[i] != DATA_PATTERN(data_offset + i)) { + return -1; + } + } + data_offset += buf_len; + } else { + buf_len = spdk_min(buf_len, block_size - offset_in_block); + } + _dif_sgl_advance(&sgl, buf_len); + offset_in_block += buf_len; + } + offset_blocks++; + } + + return 0; +} + +static void +_iov_alloc_buf(struct iovec *iov, uint32_t len) +{ + iov->iov_base = calloc(1, len); + iov->iov_len = len; + SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL); +} + +static void +_iov_free_buf(struct iovec *iov) +{ + free(iov->iov_base); +} + +static void +_iov_set_buf(struct iovec *iov, uint8_t *buf, uint32_t buf_len) +{ + iov->iov_base = buf; + iov->iov_len = buf_len; +} + +static bool +_iov_check(struct iovec *iov, void *iov_base, uint32_t iov_len) +{ + return (iov->iov_base == iov_base && iov->iov_len == iov_len); +} + +static void +_dif_generate_and_verify(struct iovec *iov, + uint32_t block_size, uint32_t md_size, bool dif_loc, + enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t ref_tag, uint32_t e_ref_tag, + uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag, + bool expect_pass) +{ + struct spdk_dif_ctx ctx = {}; + uint32_t guard_interval; + uint16_t guard = 0; + int rc; + + rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1); + CU_ASSERT(rc == 0); + + guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true); + + ctx.dif_type = dif_type; + ctx.dif_flags = dif_flags; + ctx.init_ref_tag = ref_tag; + ctx.app_tag = app_tag; + + if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval); + } + + _dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx); + + ctx.init_ref_tag = e_ref_tag; + ctx.apptag_mask = apptag_mask; + ctx.app_tag = e_app_tag; + + rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL); + CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0)); + + rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1); + CU_ASSERT(rc == 0); +} + +static void +dif_generate_and_verify_test(void) +{ + struct iovec iov; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iov, 4096 + 128); + + /* Positive cases */ + + /* The case that DIF is contained in the first 8 bytes of metadata. */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, true, + SPDK_DIF_TYPE1, dif_flags, + 22, 22, + 0x22, 0xFFFF, 0x22, + true); + + /* The case that DIF is contained in the last 8 bytes of metadata. */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE1, dif_flags, + 22, 22, + 0x22, 0xFFFF, 0x22, + true); + + /* Negative cases */ + + /* Reference tag doesn't match. */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE1, dif_flags, + 22, 23, + 0x22, 0xFFFF, 0x22, + false); + + /* Application tag doesn't match. */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE1, dif_flags, + 22, 22, + 0x22, 0xFFFF, 0x23, + false); + + _iov_free_buf(&iov); +} + +static void +dif_disable_check_test(void) +{ + struct iovec iov; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iov, 4096 + 128); + + /* The case that DIF check is disabled when the Application Tag is 0xFFFF for + * Type 1. DIF check is disabled and pass is expected. + */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE1, dif_flags, + 22, 22, + 0xFFFF, 0xFFFF, 0x22, + true); + + /* The case that DIF check is not disabled when the Application Tag is 0xFFFF but + * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and + * fail is expected. + */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE3, dif_flags, + 22, 22, + 0xFFFF, 0xFFFF, 0x22, + false); + + /* The case that DIF check is disabled when the Application Tag is 0xFFFF and + * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and + * pass is expected. + */ + _dif_generate_and_verify(&iov, + 4096 + 128, 128, false, + SPDK_DIF_TYPE3, dif_flags, + 0xFFFFFFFF, 22, + 0xFFFF, 0xFFFF, 0x22, + true); + + _iov_free_buf(&iov); +} + +static void +dif_sec_512_md_0_error_test(void) +{ + struct spdk_dif_ctx ctx = {}; + int rc; + + /* Metadata size is 0. */ + rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0, 0); + CU_ASSERT(rc != 0); +} + +static void +dif_guard_seed_test(void) +{ + struct iovec iov; + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct spdk_dif *dif; + uint16_t guard; + int rc; + + _iov_alloc_buf(&iov, 512 + 8); + + memset(iov.iov_base, 0, 512 + 8); + + dif = (struct spdk_dif *)(iov.iov_base + 512); + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 1, &ctx); + CU_ASSERT(rc == 0); + + /* Guard should be zero if the block is all zero and seed is not added. */ + guard = from_be16(&dif->guard); + CU_ASSERT(guard == 0); + + rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 1, &ctx); + CU_ASSERT(rc == 0); + + /* Guard should not be zero if the block is all zero but seed is added. */ + guard = from_be16(&dif->guard); + CU_ASSERT(guard != 0); + + rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + _iov_free_buf(&iov); +} + +static void +dif_generate_and_verify(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) +{ + struct spdk_dif_ctx ctx = {}; + int rc; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, + init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT(rc == 0); +} + +static void +dif_disable_sec_512_md_8_single_iov_test(void) +{ + struct iovec iov; + + _iov_alloc_buf(&iov, 512 + 8); + + dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0); + + _iov_free_buf(&iov); +} + +static void +dif_sec_512_md_8_prchk_0_single_iov_test(void) +{ + struct iovec iov; + + _iov_alloc_buf(&iov, 512 + 8); + + dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); + + _iov_free_buf(&iov); +} + +static void +dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void) +{ + struct iovec iovs[4]; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1)); + num_blocks += i + 1; + } + + dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, + 0, 22, 0xFFFF, 0x22); + + dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22); + + dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22); + + dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dif_sec_4096_md_128_prchk_7_multi_iovs_test(void) +{ + struct iovec iovs[4]; + int i, num_blocks; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1)); + num_blocks += i + 1; + } + + dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void) +{ + struct iovec iovs[2]; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 512); + _iov_alloc_buf(&iovs[1], 8); + + dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void) +{ + struct iovec iovs[2]; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 256); + _iov_alloc_buf(&iovs[1], 264); + + dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void) +{ + struct iovec iovs[2]; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 513); + _iov_alloc_buf(&iovs[1], 7); + + dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void) +{ + struct iovec iovs[2]; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 515); + _iov_alloc_buf(&iovs[1], 5); + + dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void) +{ + struct iovec iovs[2]; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 518); + _iov_alloc_buf(&iovs[1], 2); + + dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void) +{ + struct iovec iovs[9]; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][255:0] */ + _iov_alloc_buf(&iovs[0], 256); + + /* data[0][511:256], guard[0][0] */ + _iov_alloc_buf(&iovs[1], 256 + 1); + + /* guard[0][1], apptag[0][0] */ + _iov_alloc_buf(&iovs[2], 1 + 1); + + /* apptag[0][1], reftag[0][0] */ + _iov_alloc_buf(&iovs[3], 1 + 1); + + /* reftag[0][3:1], data[1][255:0] */ + _iov_alloc_buf(&iovs[4], 3 + 256); + + /* data[1][511:256], guard[1][0] */ + _iov_alloc_buf(&iovs[5], 256 + 1); + + /* guard[1][1], apptag[1][0] */ + _iov_alloc_buf(&iovs[6], 1 + 1); + + /* apptag[1][1], reftag[1][0] */ + _iov_alloc_buf(&iovs[7], 1 + 1); + + /* reftag[1][3:1] */ + _iov_alloc_buf(&iovs[8], 3); + + dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags, + 22, 0xFFFF, 0x22); + + for (i = 0; i < 9; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void) +{ + struct iovec iovs[11]; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][1000:0] */ + _iov_alloc_buf(&iovs[0], 1000); + + /* data[0][3095:1000], guard[0][0] */ + _iov_alloc_buf(&iovs[1], 3096 + 1); + + /* guard[0][1], apptag[0][0] */ + _iov_alloc_buf(&iovs[2], 1 + 1); + + /* apptag[0][1], reftag[0][0] */ + _iov_alloc_buf(&iovs[3], 1 + 1); + + /* reftag[0][3:1], ignore[0][59:0] */ + _iov_alloc_buf(&iovs[4], 3 + 60); + + /* ignore[119:60], data[1][3050:0] */ + _iov_alloc_buf(&iovs[5], 60 + 3051); + + /* data[1][4095:3050], guard[1][0] */ + _iov_alloc_buf(&iovs[6], 1045 + 1); + + /* guard[1][1], apptag[1][0] */ + _iov_alloc_buf(&iovs[7], 1 + 1); + + /* apptag[1][1], reftag[1][0] */ + _iov_alloc_buf(&iovs[8], 1 + 1); + + /* reftag[1][3:1], ignore[1][9:0] */ + _iov_alloc_buf(&iovs[9], 3 + 10); + + /* ignore[1][127:9] */ + _iov_alloc_buf(&iovs[10], 118); + + dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags, + 22, 0xFFFF, 0x22); + dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags, + 22, 0xFFFF, 0x22); + + for (i = 0; i < 11; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +_dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags, bool dif_loc) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + uint32_t inject_offset = 0, dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, + SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk); + CU_ASSERT(rc != 0); + if (inject_flags == SPDK_DIF_DATA_ERROR) { + CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); + } else { + CU_ASSERT(inject_flags == err_blk.err_type); + } + CU_ASSERT(inject_offset == err_blk.err_offset); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) || + (rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR))); +} + +static void +dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags) +{ + /* The case that DIF is contained in the first 8 bytes of metadata. */ + _dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks, + inject_flags, true); + + /* The case that DIF is contained in the last 8 bytes of metadata. */ + _dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks, + inject_flags, false); +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) +{ + struct iovec iovs[4]; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1)); + num_blocks += i + 1; + } + + dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_DATA_ERROR); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void) +{ + struct iovec iovs[2]; + + _iov_alloc_buf(&iovs[0], 4096); + _iov_alloc_buf(&iovs[1], 128); + + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void) +{ + struct iovec iovs[2]; + + _iov_alloc_buf(&iovs[0], 2048); + _iov_alloc_buf(&iovs[1], 2048 + 128); + + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void) +{ + struct iovec iovs[2]; + + _iov_alloc_buf(&iovs[0], 4096 + 1); + _iov_alloc_buf(&iovs[1], 127); + + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void) +{ + struct iovec iovs[2]; + + _iov_alloc_buf(&iovs[0], 4096 + 3); + _iov_alloc_buf(&iovs[1], 125); + + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void) +{ + struct iovec iovs[2]; + + _iov_alloc_buf(&iovs[0], 4096 + 6); + _iov_alloc_buf(&iovs[1], 122); + + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); + dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); +} + +static void +dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) +{ + struct spdk_dif_ctx ctx = {}; + int rc; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, + init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks); + CU_ASSERT(rc == 0); +} + +static void +dif_copy_sec_512_md_8_prchk_0_single_iov(void) +{ + struct iovec iov, bounce_iov; + + _iov_alloc_buf(&iov, 512 * 4); + _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); + + dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, + false, SPDK_DIF_TYPE1, 0, 0, 0, 0); + dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, + true, SPDK_DIF_TYPE1, 0, 0, 0, 0); + + _iov_free_buf(&iov); + _iov_free_buf(&bounce_iov); +} + +static void +dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) +{ + struct iovec iovs[4], bounce_iov; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 512 * (i + 1)); + num_blocks += i + 1; + } + + _iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks); + + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, + false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22); + + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, + false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22); + + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, + false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22); + + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, + false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&bounce_iov); +} + +static void +dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void) +{ + struct iovec iovs[4], bounce_iov; + uint32_t dif_flags; + int i, num_blocks; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); + num_blocks += i + 1; + } + + _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); + + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, + false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); + dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, + true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&bounce_iov); +} + +static void +dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void) +{ + struct iovec iovs[2], bounce_iov; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 256); + _iov_alloc_buf(&iovs[1], 256); + + _iov_alloc_buf(&bounce_iov, 512 + 8); + + dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1, + false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); + _iov_free_buf(&bounce_iov); +} + +static void +dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) +{ + struct iovec iovs[6], bounce_iov; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][255:0] */ + _iov_alloc_buf(&iovs[0], 256); + + /* data[0][511:256], data[1][255:0] */ + _iov_alloc_buf(&iovs[1], 256 + 256); + + /* data[1][382:256] */ + _iov_alloc_buf(&iovs[2], 128); + + /* data[1][383] */ + _iov_alloc_buf(&iovs[3], 1); + + /* data[1][510:384] */ + _iov_alloc_buf(&iovs[4], 126); + + /* data[1][511], data[2][511:0], data[3][511:0] */ + _iov_alloc_buf(&iovs[5], 1 + 512 * 2); + + _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); + + dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4, + true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); + + for (i = 0; i < 6; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&bounce_iov); +} + +static void +_dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags, bool dif_loc) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + uint32_t inject_offset = 0, dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags, + 88, 0xFFFF, 0x88, 0, GUARD_SEED); + SPDK_CU_ASSERT_FATAL(rc == 0); + + rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk); + CU_ASSERT(rc != 0); + if (inject_flags == SPDK_DIF_DATA_ERROR) { + CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); + } else { + CU_ASSERT(inject_flags == err_blk.err_type); + } + CU_ASSERT(inject_offset == err_blk.err_offset); +} + +static void +dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags) +{ + /* The case that DIF is contained in the first 8 bytes of metadata. */ + _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, + block_size, md_size, num_blocks, + inject_flags, true); + + /* The case that DIF is contained in the last 8 bytes of metadata. */ + _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, + block_size, md_size, num_blocks, + inject_flags, false); +} + +static void +dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) +{ + struct iovec iovs[4], bounce_iov; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); + num_blocks += i + 1; + } + + _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + num_blocks, SPDK_DIF_GUARD_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + num_blocks, SPDK_DIF_APPTAG_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + num_blocks, SPDK_DIF_REFTAG_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + num_blocks, SPDK_DIF_DATA_ERROR); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&bounce_iov); +} + +static void +dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) +{ + struct iovec iovs[4], bounce_iov; + int i; + + _iov_alloc_buf(&iovs[0], 2048); + _iov_alloc_buf(&iovs[1], 2048); + _iov_alloc_buf(&iovs[2], 1); + _iov_alloc_buf(&iovs[3], 4095); + + _iov_alloc_buf(&bounce_iov, (4096 + 128) * 2); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + 2, SPDK_DIF_GUARD_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + 2, SPDK_DIF_APPTAG_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + 2, SPDK_DIF_REFTAG_ERROR); + + dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, + 2, SPDK_DIF_DATA_ERROR); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&bounce_iov); +} + +static void +dix_sec_512_md_0_error(void) +{ + struct spdk_dif_ctx ctx; + int rc; + + rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0, 0); + CU_ASSERT(rc != 0); +} + +static void +dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) +{ + struct spdk_dif_ctx ctx; + int rc; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, + init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks); + CU_ASSERT(rc == 0); +} + +static void +dix_sec_512_md_8_prchk_0_single_iov(void) +{ + struct iovec iov, md_iov; + + _iov_alloc_buf(&iov, 512 * 4); + _iov_alloc_buf(&md_iov, 8 * 4); + + dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); + dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0); + + _iov_free_buf(&iov); + _iov_free_buf(&md_iov); +} + +static void +dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) +{ + struct iovec iovs[4], md_iov; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 512 * (i + 1)); + num_blocks += i + 1; + } + _iov_alloc_buf(&md_iov, 8 * num_blocks); + + dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, + 0, 22, 0xFFFF, 0x22); + + dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22); + + dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22); + + dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static void +dix_sec_4096_md_128_prchk_7_multi_iovs(void) +{ + struct iovec iovs[4], md_iov; + uint32_t dif_flags; + int i, num_blocks; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); + num_blocks += i + 1; + } + _iov_alloc_buf(&md_iov, 128 * num_blocks); + + dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static void +dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void) +{ + struct iovec iovs[2], md_iov; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + _iov_alloc_buf(&iovs[0], 256); + _iov_alloc_buf(&iovs[1], 256); + _iov_alloc_buf(&md_iov, 8); + + dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + _iov_free_buf(&iovs[0]); + _iov_free_buf(&iovs[1]); + _iov_free_buf(&md_iov); +} + +static void +dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) +{ + struct iovec iovs[6], md_iov; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][255:0] */ + _iov_alloc_buf(&iovs[0], 256); + + /* data[0][511:256], data[1][255:0] */ + _iov_alloc_buf(&iovs[1], 256 + 256); + + /* data[1][382:256] */ + _iov_alloc_buf(&iovs[2], 128); + + /* data[1][383] */ + _iov_alloc_buf(&iovs[3], 1); + + /* data[1][510:384] */ + _iov_alloc_buf(&iovs[4], 126); + + /* data[1][511], data[2][511:0], data[3][511:0] */ + _iov_alloc_buf(&iovs[5], 1 + 512 * 2); + + _iov_alloc_buf(&md_iov, 8 * 4); + + dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22); + + for (i = 0; i < 6; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static void +_dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags, bool dif_loc) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + uint32_t inject_offset = 0, dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags, + 88, 0xFFFF, 0x88, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset); + CU_ASSERT(rc == 0); + + rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk); + CU_ASSERT(rc != 0); + + if (inject_flags == SPDK_DIF_DATA_ERROR) { + CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); + } else { + CU_ASSERT(inject_flags == err_blk.err_type); + } + CU_ASSERT(inject_offset == err_blk.err_offset); +} + +static void +dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + uint32_t inject_flags) +{ + /* The case that DIF is contained in the first 8 bytes of metadata. */ + _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, + inject_flags, true); + + /* The case that DIF is contained in the last 8 bytes of metadata. */ + _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, + inject_flags, false); +} + +static void +dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) +{ + struct iovec iovs[4], md_iov; + int i, num_blocks; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); + num_blocks += i + 1; + } + + _iov_alloc_buf(&md_iov, 128 * num_blocks); + + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static void +dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) +{ + struct iovec iovs[4], md_iov; + int i; + + _iov_alloc_buf(&iovs[0], 2048); + _iov_alloc_buf(&iovs[1], 2048); + _iov_alloc_buf(&iovs[2], 1); + _iov_alloc_buf(&iovs[3], 4095); + + _iov_alloc_buf(&md_iov, 128 * 2); + + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR); + dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static int +ut_readv(uint32_t read_base, uint32_t read_len, struct iovec *iovs, int iovcnt) +{ + int i; + uint32_t j, offset; + uint8_t *buf; + + offset = 0; + for (i = 0; i < iovcnt; i++) { + buf = iovs[i].iov_base; + for (j = 0; j < iovs[i].iov_len; j++, offset++) { + if (offset >= read_len) { + return offset; + } + buf[j] = DATA_PATTERN(read_base + offset); + } + } + + return offset; +} + +static void +set_md_interleave_iovs_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct iovec iov1, iov2, dif_iovs[4] = {}; + uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0; + uint8_t *buf1, *buf2; + int rc; + + dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + /* The first data buffer: + * - Create iovec array to Leave a space for metadata for each block + * - Split vectored read and so creating iovec array is done before every vectored read. + */ + buf1 = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf1 != NULL); + _iov_set_buf(&iov1, buf1, (4096 + 128) * 4); + + data_offset = 0; + data_len = 4096 * 4; + + /* 1st read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 4096 * 4); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true); + + read_len = ut_readv(data_offset, 1024, dif_iovs, 4); + CU_ASSERT(read_len == 1024); + + rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 2nd read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 3072 + 4096 * 3); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true); + + read_len = ut_readv(data_offset, 3071, dif_iovs, 4); + CU_ASSERT(read_len == 3071); + + rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 3rd read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 1 + 4096 * 3); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true); + + read_len = ut_readv(data_offset, 1 + 4096 * 2 + 512, dif_iovs, 4); + CU_ASSERT(read_len == 1 + 4096 * 2 + 512); + + rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 4th read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 1); + CU_ASSERT(mapped_len == 3584); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true); + + read_len = ut_readv(data_offset, 3584, dif_iovs, 1); + CU_ASSERT(read_len == 3584); + + rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + CU_ASSERT(data_offset == 4096 * 4); + data_len -= read_len; + CU_ASSERT(data_len == 0); + + /* The second data buffer: + * - Set data pattern with a space for metadata for each block. + */ + buf2 = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf2 != NULL); + _iov_set_buf(&iov2, buf2, (4096 + 128) * 4); + + rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4); + CU_ASSERT(rc == 0); + rc = spdk_dif_generate(&iov2, 1, 4, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* Compare the first and the second data buffer by byte. */ + rc = memcmp(buf1, buf2, (4096 + 128) * 4); + CU_ASSERT(rc == 0); + + free(buf1); + free(buf2); +} + +static void +set_md_interleave_iovs_split_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct iovec iovs1[7], iovs2[7], dif_iovs[8] = {}; + uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0; + int rc, i; + + dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + /* The first SGL data buffer: + * - Create iovec array to leave a space for metadata for each block + * - Split vectored read and so creating iovec array is done before every vectored read. + */ + _iov_alloc_buf(&iovs1[0], 512 + 8 + 128); + _iov_alloc_buf(&iovs1[1], 128); + _iov_alloc_buf(&iovs1[2], 256 + 8); + _iov_alloc_buf(&iovs1[3], 100); + _iov_alloc_buf(&iovs1[4], 412 + 5); + _iov_alloc_buf(&iovs1[5], 3 + 300); + _iov_alloc_buf(&iovs1[6], 212 + 8); + + data_offset = 0; + data_len = 512 * 4; + + /* 1st read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 8); + CU_ASSERT(mapped_len == 512 * 4); + CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base, 512) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true); + CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true); + CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true); + CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true); + CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true); + + read_len = ut_readv(data_offset, 128, dif_iovs, 8); + CU_ASSERT(read_len == 128); + + rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 2nd read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 8); + CU_ASSERT(mapped_len == 384 + 512 * 3); + CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 128, 384) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true); + CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true); + CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true); + CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true); + CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true); + + read_len = ut_readv(data_offset, 383, dif_iovs, 8); + CU_ASSERT(read_len == 383); + + rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 3rd read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 8); + CU_ASSERT(mapped_len == 1 + 512 * 3); + CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 511, 1) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true); + CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true); + CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true); + CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true); + CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true); + + read_len = ut_readv(data_offset, 1 + 512 * 2 + 128, dif_iovs, 8); + CU_ASSERT(read_len == 1 + 512 * 2 + 128); + + rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + data_len -= read_len; + + /* 4th read */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, + data_offset, data_len, &mapped_len, &ctx); + CU_ASSERT(rc == 2); + CU_ASSERT(mapped_len == 384); + CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[5].iov_base + 3 + 128, 172) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[6].iov_base, 212) == true); + + read_len = ut_readv(data_offset, 384, dif_iovs, 8); + CU_ASSERT(read_len == 384); + + rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + data_offset += read_len; + CU_ASSERT(data_offset == 512 * 4); + data_len -= read_len; + CU_ASSERT(data_len == 0); + + /* The second SGL data buffer: + * - Set data pattern with a space for metadata for each block. + */ + _iov_alloc_buf(&iovs2[0], 512 + 8 + 128); + _iov_alloc_buf(&iovs2[1], 128); + _iov_alloc_buf(&iovs2[2], 256 + 8); + _iov_alloc_buf(&iovs2[3], 100); + _iov_alloc_buf(&iovs2[4], 412 + 5); + _iov_alloc_buf(&iovs2[5], 3 + 300); + _iov_alloc_buf(&iovs2[6], 212 + 8); + + rc = ut_data_pattern_generate(iovs2, 7, 512 + 8, 8, 4); + CU_ASSERT(rc == 0); + rc = spdk_dif_generate(iovs2, 7, 4, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs1, 7, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs2, 7, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* Compare the first and the second SGL data buffer by byte. */ + for (i = 0; i < 7; i++) { + rc = memcmp(iovs1[i].iov_base, iovs2[i].iov_base, + iovs1[i].iov_len); + CU_ASSERT(rc == 0); + } + + for (i = 0; i < 7; i++) { + _iov_free_buf(&iovs1[i]); + _iov_free_buf(&iovs2[i]); + } +} + +static void +dif_generate_stream_test(void) +{ + struct iovec iov; + struct spdk_dif_ctx ctx; + struct spdk_dif_error err_blk; + uint32_t dif_flags; + int rc; + + _iov_alloc_buf(&iov, (512 + 8) * 5); + + rc = ut_data_pattern_generate(&iov, 1, 512 + 8, 8, 5); + CU_ASSERT(rc == 0); + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, dif_flags, + 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 0, 511, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 511, 1, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 512, 256, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 768, 512, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 1280, 1024, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 2304, 256, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate_stream(&iov, 1, 2560, 512, &ctx); + CU_ASSERT(rc == -ERANGE); + + rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(&iov, 1, 512 + 8, 8, 5); + CU_ASSERT(rc == 0); + + _iov_free_buf(&iov); +} + +static void +set_md_interleave_iovs_alignment_test(void) +{ + struct iovec iovs[3], dif_iovs[5] = {}; + uint32_t mapped_len = 0; + int rc; + struct spdk_dif_ctx ctx; + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + 0, 0, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + /* The case that buffer size is smaller than necessary. */ + _iov_set_buf(&iovs[0], (uint8_t *)0xDEADBEEF, 1024); + _iov_set_buf(&iovs[1], (uint8_t *)0xFEEDBEEF, 1024); + _iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 24); + + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 2048, &mapped_len, &ctx); + CU_ASSERT(rc == -ERANGE); + + /* The folllowing are the normal cases. */ + _iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 32); + + /* data length is less than a data block size. */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 500, &mapped_len, &ctx); + CU_ASSERT(rc == 1); + CU_ASSERT(mapped_len == 500); + CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xDEADBEEF, 500) == true); + + /* Pass enough number of iovecs */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 500, 1000, &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 1000); + CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], (void *)(0xFEEDBEEF + 16), 476) == true); + + /* Pass iovecs smaller than necessary */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 3, iovs, 3, 500, 1000, &mapped_len, &ctx); + CU_ASSERT(rc == 3); + CU_ASSERT(mapped_len == 524); + CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true); + + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 1500, 500, &mapped_len, &ctx); + CU_ASSERT(rc == 2); + CU_ASSERT(mapped_len == 500); + CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xFEEDBEEF + 492), 36) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xFEEDBEEF + 536), 464) == true); + + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 2000, 48, &mapped_len, &ctx); + CU_ASSERT(rc == 2); + CU_ASSERT(mapped_len == 48); + CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xFEEDBEEF + 1000, 24) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], (void *)0xC0FFEE, 24) == true); +} + +static void +_dif_generate_split_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct iovec iov; + uint8_t *buf1, *buf2; + struct _dif_sgl sgl; + uint16_t guard = 0, prev_guard; + uint32_t dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_flags, 0, 0, 0, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + buf1 = calloc(1, 4096 + 128); + SPDK_CU_ASSERT_FATAL(buf1 != NULL); + _iov_set_buf(&iov, buf1, 4096 + 128); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + guard = GUARD_SEED; + prev_guard = GUARD_SEED; + + guard = _dif_generate_split(&sgl, 0, 1000, guard, 0, &ctx); + CU_ASSERT(sgl.iov_offset == 1000); + CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf1, 1000)); + + prev_guard = guard; + + guard = _dif_generate_split(&sgl, 1000, 3000, guard, 0, &ctx); + CU_ASSERT(sgl.iov_offset == 4000); + CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf1 + 1000, 3000)); + + guard = _dif_generate_split(&sgl, 4000, 96 + 128, guard, 0, &ctx); + CU_ASSERT(guard == GUARD_SEED); + CU_ASSERT(sgl.iov_offset == 0); + CU_ASSERT(sgl.iovcnt == 0); + + rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + rc = dif_verify(&sgl, 1, &ctx, NULL); + CU_ASSERT(rc == 0); + + buf2 = calloc(1, 4096 + 128); + SPDK_CU_ASSERT_FATAL(buf2 != NULL); + _iov_set_buf(&iov, buf2, 4096 + 128); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + dif_generate(&sgl, 1, &ctx); + + rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + rc = dif_verify(&sgl, 1, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = memcmp(buf1, buf2, 4096 + 128); + CU_ASSERT(rc == 0); + + free(buf1); + free(buf2); +} + +static void +set_md_interleave_iovs_multi_segments_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct iovec iov1 = {}, iov2 = {}, dif_iovs[4] = {}; + uint32_t dif_check_flags, data_len, read_len, data_offset, read_offset, mapped_len = 0; + uint8_t *buf1, *buf2; + int rc; + + dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + /* The first data buffer: + * - Data buffer is split into multi data segments + * - For each data segment, + * - Create iovec array to Leave a space for metadata for each block + * - Split vectored read and so creating iovec array is done before every vectored read. + */ + buf1 = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf1 != NULL); + _iov_set_buf(&iov1, buf1, (4096 + 128) * 4); + + /* 1st data segment */ + data_offset = 0; + data_len = 1024; + + spdk_dif_ctx_set_data_offset(&ctx, data_offset); + + read_offset = 0; + + /* 1st read in 1st data segment */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + read_offset, data_len - read_offset, + &mapped_len, &ctx); + CU_ASSERT(rc == 1); + CU_ASSERT(mapped_len == 1024); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 1024) == true); + + read_len = ut_readv(data_offset + read_offset, 1024, dif_iovs, 4); + CU_ASSERT(read_len == 1024); + + rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + read_offset += read_len; + CU_ASSERT(read_offset == data_len); + + /* 2nd data segment */ + data_offset += data_len; + data_len = 3072 + 4096 * 2 + 512; + + spdk_dif_ctx_set_data_offset(&ctx, data_offset); + _iov_set_buf(&iov1, buf1 + 1024, 3072 + 128 + (4096 + 128) * 3 + 512); + + read_offset = 0; + + /* 1st read in 2nd data segment */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + read_offset, data_len - read_offset, + &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 3072 + 4096 * 2 + 512); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true); + + read_len = ut_readv(data_offset + read_offset, 3071, dif_iovs, 4); + CU_ASSERT(read_len == 3071); + + rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + read_offset += read_len; + + /* 2nd read in 2nd data segment */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + read_offset, data_len - read_offset, + &mapped_len, &ctx); + CU_ASSERT(rc == 4); + CU_ASSERT(mapped_len == 1 + 4096 * 2 + 512); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true); + CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true); + CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true); + + read_len = ut_readv(data_offset + read_offset, 1 + 4096 * 2 + 512, dif_iovs, 4); + CU_ASSERT(read_len == 1 + 4096 * 2 + 512); + + rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + read_offset += read_len; + CU_ASSERT(read_offset == data_len); + + /* 3rd data segment */ + data_offset += data_len; + data_len = 3584; + + spdk_dif_ctx_set_data_offset(&ctx, data_offset); + _iov_set_buf(&iov1, buf1 + (4096 + 128) * 3 + 512, 3584 + 128); + + read_offset = 0; + + /* 1st read in 3rd data segment */ + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, + read_offset, data_len - read_offset, + &mapped_len, &ctx); + CU_ASSERT(rc == 1); + CU_ASSERT(mapped_len == 3584); + CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true); + + read_len = ut_readv(data_offset + read_offset, 3584, dif_iovs, 1); + CU_ASSERT(read_len == 3584); + + rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx); + CU_ASSERT(rc == 0); + + read_offset += read_len; + CU_ASSERT(read_offset == data_len); + data_offset += data_len; + CU_ASSERT(data_offset == 4096 * 4); + + spdk_dif_ctx_set_data_offset(&ctx, 0); + _iov_set_buf(&iov1, buf1, (4096 + 128) * 4); + + /* The second data buffer: + * - Set data pattern with a space for metadata for each block. + */ + buf2 = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf2 != NULL); + _iov_set_buf(&iov2, buf2, (4096 + 128) * 4); + + rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov2, 1, 4, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* Compare the first and the second data buffer by byte. */ + rc = memcmp(buf1, buf2, (4096 + 128) * 4); + CU_ASSERT(rc == 0); + + free(buf1); + free(buf2); +} + +static void +_dif_verify_split_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct iovec iov; + uint8_t *buf; + struct _dif_sgl sgl; + uint16_t guard = 0, prev_guard = 0; + uint32_t dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_flags, 0, 0, 0, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + buf = calloc(1, 4096 + 128); + SPDK_CU_ASSERT_FATAL(buf != NULL); + _iov_set_buf(&iov, buf, 4096 + 128); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + dif_generate(&sgl, 1, &ctx); + + _dif_sgl_init(&sgl, &iov, 1); + + guard = GUARD_SEED; + prev_guard = GUARD_SEED; + + rc = _dif_verify_split(&sgl, 0, 1000, &guard, 0, &ctx, &err_blk); + CU_ASSERT(rc == 0); + CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf, 1000)); + CU_ASSERT(sgl.iov_offset == 1000); + + prev_guard = guard; + + rc = _dif_verify_split(&sgl, 1000, 3000, &guard, 0, &ctx, &err_blk); + CU_ASSERT(rc == 0); + CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf + 1000, 3000)); + CU_ASSERT(sgl.iov_offset == 4000); + + rc = _dif_verify_split(&sgl, 4000, 96 + 128, &guard, 0, &ctx, &err_blk); + CU_ASSERT(rc == 0); + CU_ASSERT(guard == GUARD_SEED); + CU_ASSERT(sgl.iov_offset == 0); + CU_ASSERT(sgl.iovcnt == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + rc = dif_verify(&sgl, 1, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + free(buf); +} + +static void +dif_verify_stream_multi_segments_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct iovec iov = {}; + uint8_t *buf; + uint32_t dif_flags; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + buf = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf != NULL); + _iov_set_buf(&iov, buf, (4096 + 128) * 4); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 4, &ctx); + CU_ASSERT(rc == 0); + + /* 1st data segment */ + _iov_set_buf(&iov, buf, 1024); + spdk_dif_ctx_set_data_offset(&ctx, 0); + + rc = spdk_dif_verify_stream(&iov, 1, 0, 1024, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* 2nd data segment */ + _iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512); + spdk_dif_ctx_set_data_offset(&ctx, 1024); + + rc = spdk_dif_verify_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* 3rd data segment */ + _iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128); + spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3); + + rc = spdk_dif_verify_stream(&iov, 1, 0, 3584, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* verify all data segments once */ + _iov_set_buf(&iov, buf, (4096 + 128) * 4); + spdk_dif_ctx_set_data_offset(&ctx, 0); + + rc = spdk_dif_verify(&iov, 1, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 4); + CU_ASSERT(rc == 0); + + free(buf); +} + +#define UT_CRC32C_XOR 0xffffffffUL + +static void +update_crc32c_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct iovec iovs[7]; + uint32_t crc32c1, crc32c2, crc32c3, crc32c4; + uint32_t dif_flags; + int i, rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + dif_flags, 0, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + /* data[0][255:0] */ + _iov_alloc_buf(&iovs[0], 256); + + /* data[0][511:256], md[0][0] */ + _iov_alloc_buf(&iovs[1], 256 + 1); + + /* md[0][4:1] */ + _iov_alloc_buf(&iovs[2], 4); + + /* md[0][7:5], data[1][122:0] */ + _iov_alloc_buf(&iovs[3], 3 + 123); + + /* data[1][511:123], md[1][5:0] */ + _iov_alloc_buf(&iovs[4], 389 + 6); + + /* md[1][7:6], data[2][511:0], md[2][7:0], data[3][431:0] */ + _iov_alloc_buf(&iovs[5], 2 + 512 + 8 + 432); + + /* data[3][511:432], md[3][7:0] */ + _iov_alloc_buf(&iovs[6], 80 + 8); + + rc = ut_data_pattern_generate(iovs, 7, 512 + 8, 8, 4); + CU_ASSERT(rc == 0); + + crc32c1 = UT_CRC32C_XOR; + + rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c1, &ctx); + CU_ASSERT(rc == 0); + + /* Test if DIF doesn't affect CRC for split case. */ + rc = spdk_dif_generate(iovs, 7, 4, &ctx); + CU_ASSERT(rc == 0); + + crc32c2 = UT_CRC32C_XOR; + + rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c2, &ctx); + CU_ASSERT(rc == 0); + + CU_ASSERT(crc32c1 == crc32c2); + + for (i = 0; i < 7; i++) { + _iov_free_buf(&iovs[i]); + } + + /* Test if CRC is same regardless of splitting. */ + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 512 + 8); + } + + rc = ut_data_pattern_generate(iovs, 4, 512 + 8, 8, 4); + CU_ASSERT(rc == 0); + + crc32c3 = UT_CRC32C_XOR; + + rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c3, &ctx); + CU_ASSERT(rc == 0); + + CU_ASSERT(crc32c1 == crc32c3); + + /* Test if DIF doesn't affect CRC for non-split case. */ + rc = spdk_dif_generate(iovs, 4, 4, &ctx); + CU_ASSERT(rc == 0); + + crc32c4 = UT_CRC32C_XOR; + + rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c4, &ctx); + CU_ASSERT(rc == 0); + + CU_ASSERT(crc32c1 == crc32c4); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +_dif_update_crc32c_split_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct iovec iov; + uint8_t *buf; + struct _dif_sgl sgl; + uint32_t dif_flags, crc32c, prev_crc32c; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_flags, 0, 0, 0, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + buf = calloc(1, 4096 + 128); + SPDK_CU_ASSERT_FATAL(buf != NULL); + _iov_set_buf(&iov, buf, 4096 + 128); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1); + CU_ASSERT(rc == 0); + + _dif_sgl_init(&sgl, &iov, 1); + + dif_generate(&sgl, 1, &ctx); + + _dif_sgl_init(&sgl, &iov, 1); + + crc32c = _dif_update_crc32c_split(&sgl, 0, 1000, UT_CRC32C_XOR, &ctx); + CU_ASSERT(crc32c == spdk_crc32c_update(buf, 1000, UT_CRC32C_XOR)); + + prev_crc32c = crc32c; + + crc32c = _dif_update_crc32c_split(&sgl, 1000, 3000, prev_crc32c, &ctx); + CU_ASSERT(crc32c == spdk_crc32c_update(buf + 1000, 3000, prev_crc32c)); + + prev_crc32c = crc32c; + + crc32c = _dif_update_crc32c_split(&sgl, 4000, 96 + 128, prev_crc32c, &ctx); + CU_ASSERT(crc32c == spdk_crc32c_update(buf + 4000, 96, prev_crc32c)); + + CU_ASSERT(crc32c == spdk_crc32c_update(buf, 4096, UT_CRC32C_XOR)); + + free(buf); +} + +static void +dif_update_crc32c_stream_multi_segments_test(void) +{ + struct spdk_dif_ctx ctx = {}; + struct iovec iov = {}; + uint8_t *buf; + uint32_t dif_flags, crc32c1, crc32c2; + int rc; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, + dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + buf = calloc(1, (4096 + 128) * 4); + SPDK_CU_ASSERT_FATAL(buf != NULL); + _iov_set_buf(&iov, buf, (4096 + 128) * 4); + + rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 4, &ctx); + CU_ASSERT(rc == 0); + + crc32c1 = UT_CRC32C_XOR; + crc32c2 = UT_CRC32C_XOR; + + /* 1st data segment */ + _iov_set_buf(&iov, buf, 1024); + spdk_dif_ctx_set_data_offset(&ctx, 0); + + rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 1024, &crc32c1, &ctx); + CU_ASSERT(rc == 0); + + /* 2nd data segment */ + _iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512); + spdk_dif_ctx_set_data_offset(&ctx, 1024); + + rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &crc32c1, &ctx); + CU_ASSERT(rc == 0); + + /* 3rd data segment */ + _iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128); + spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3); + + rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3584, &crc32c1, &ctx); + CU_ASSERT(rc == 0); + + /* Update CRC32C for all data segments once */ + _iov_set_buf(&iov, buf, (4096 + 128) * 4); + spdk_dif_ctx_set_data_offset(&ctx, 0); + + rc = spdk_dif_update_crc32c(&iov, 1, 4, &crc32c2, &ctx); + CU_ASSERT(rc == 0); + + CU_ASSERT(crc32c1 == crc32c2); + + free(buf); +} + +static void +get_range_with_md_test(void) +{ + struct spdk_dif_ctx ctx = {}; + uint32_t buf_offset, buf_len; + int rc; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, 0, 0, 0, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + spdk_dif_get_range_with_md(0, 2048, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 0); + CU_ASSERT(buf_len == 2048); + + spdk_dif_get_range_with_md(2048, 4096, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 2048); + CU_ASSERT(buf_len == 4096 + 128); + + spdk_dif_get_range_with_md(4096, 10240, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 4096 + 128); + CU_ASSERT(buf_len == 10240 + 256); + + spdk_dif_get_range_with_md(10240, 2048, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 10240 + 256); + CU_ASSERT(buf_len == 2048 + 128); + + buf_len = spdk_dif_get_length_with_md(6144, &ctx); + CU_ASSERT(buf_len == 6144 + 128); +} + +static void +dif_generate_remap_and_verify(struct iovec *iovs, int iovcnt, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t init_ref_tag, uint32_t remapped_init_ref_tag, + uint16_t apptag_mask, uint16_t app_tag) +{ + struct spdk_dif_ctx ctx = {}; + int rc; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, + init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag); + + rc = spdk_dif_remap_ref_tag(iovs, iovcnt, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, + remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); + CU_ASSERT(rc == 0); +} + +static void +dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test(void) +{ + struct iovec iovs[4]; + int i, num_blocks; + uint32_t dif_flags; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1)); + num_blocks += i + 1; + } + + dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, + dif_flags, 22, 99, 0xFFFF, 0x22); + + dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, true, SPDK_DIF_TYPE1, + dif_flags, 22, 99, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test(void) +{ + struct iovec iovs[11]; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][1000:0] */ + _iov_alloc_buf(&iovs[0], 1000); + + /* data[0][3095:1000], guard[0][0] */ + _iov_alloc_buf(&iovs[1], 3096 + 1); + + /* guard[0][1], apptag[0][0] */ + _iov_alloc_buf(&iovs[2], 1 + 1); + + /* apptag[0][1], reftag[0][0] */ + _iov_alloc_buf(&iovs[3], 1 + 1); + + /* reftag[0][3:1], ignore[0][59:0] */ + _iov_alloc_buf(&iovs[4], 3 + 60); + + /* ignore[119:60], data[1][3050:0] */ + _iov_alloc_buf(&iovs[5], 60 + 3051); + + /* data[1][4095:3050], guard[1][0] */ + _iov_alloc_buf(&iovs[6], 1045 + 1); + + /* guard[1][1], apptag[1][0] */ + _iov_alloc_buf(&iovs[7], 1 + 1); + + /* apptag[1][1], reftag[1][0] */ + _iov_alloc_buf(&iovs[8], 1 + 1); + + /* reftag[1][3:1], ignore[1][9:0] */ + _iov_alloc_buf(&iovs[9], 3 + 10); + + /* ignore[1][127:9] */ + _iov_alloc_buf(&iovs[10], 118); + + dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags, + 22, 99, 0xFFFF, 0x22); + dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags, + 22, 99, 0xFFFF, 0x22); + + for (i = 0; i < 11; i++) { + _iov_free_buf(&iovs[i]); + } +} + +static void +dix_generate_remap_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, + uint32_t block_size, uint32_t md_size, uint32_t num_blocks, + bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, + uint32_t init_ref_tag, uint32_t remapped_init_ref_tag, + uint16_t apptag_mask, uint16_t app_tag) +{ + struct spdk_dif_ctx ctx; + int rc; + + rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, + init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); + CU_ASSERT(rc == 0); + + spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag); + + rc = spdk_dix_remap_ref_tag(md_iov, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, + remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL); + CU_ASSERT(rc == 0); + + rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks); + CU_ASSERT(rc == 0); +} + +static void +dix_sec_4096_md_128_prchk_7_multi_iovs_remap(void) +{ + struct iovec iovs[4], md_iov; + uint32_t dif_flags; + int i, num_blocks; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + num_blocks = 0; + + for (i = 0; i < 4; i++) { + _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); + num_blocks += i + 1; + } + _iov_alloc_buf(&md_iov, 128 * num_blocks); + + dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1, + dif_flags, 22, 99, 0xFFFF, 0x22); + dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1, + dif_flags, 22, 99, 0xFFFF, 0x22); + + for (i = 0; i < 4; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +static void +dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap(void) +{ + struct iovec iovs[6], md_iov; + uint32_t dif_flags; + int i; + + dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | + SPDK_DIF_FLAGS_REFTAG_CHECK; + + /* data[0][255:0] */ + _iov_alloc_buf(&iovs[0], 256); + + /* data[0][511:256], data[1][255:0] */ + _iov_alloc_buf(&iovs[1], 256 + 256); + + /* data[1][382:256] */ + _iov_alloc_buf(&iovs[2], 128); + + /* data[1][383] */ + _iov_alloc_buf(&iovs[3], 1); + + /* data[1][510:384] */ + _iov_alloc_buf(&iovs[4], 126); + + /* data[1][511], data[2][511:0], data[3][511:0] */ + _iov_alloc_buf(&iovs[5], 1 + 512 * 2); + + _iov_alloc_buf(&md_iov, 8 * 4); + + dix_generate_remap_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, + dif_flags, 22, 99, 0xFFFF, 0x22); + + for (i = 0; i < 6; i++) { + _iov_free_buf(&iovs[i]); + } + _iov_free_buf(&md_iov); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("dif", NULL, NULL); + + CU_ADD_TEST(suite, dif_generate_and_verify_test); + CU_ADD_TEST(suite, dif_disable_check_test); + CU_ADD_TEST(suite, dif_sec_512_md_0_error_test); + CU_ADD_TEST(suite, dif_guard_seed_test); + CU_ADD_TEST(suite, dif_disable_sec_512_md_8_single_iov_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_single_iov_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test); + CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test); + CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_single_iov); + CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs); + CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_7_multi_iovs); + CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data); + CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits); + CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test); + CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test); + CU_ADD_TEST(suite, dix_sec_512_md_0_error); + CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_single_iov); + CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs); + CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs); + CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_split_data); + CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits); + CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test); + CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test); + CU_ADD_TEST(suite, set_md_interleave_iovs_test); + CU_ADD_TEST(suite, set_md_interleave_iovs_split_test); + CU_ADD_TEST(suite, dif_generate_stream_test); + CU_ADD_TEST(suite, set_md_interleave_iovs_alignment_test); + CU_ADD_TEST(suite, _dif_generate_split_test); + CU_ADD_TEST(suite, set_md_interleave_iovs_multi_segments_test); + CU_ADD_TEST(suite, _dif_verify_split_test); + CU_ADD_TEST(suite, dif_verify_stream_multi_segments_test); + CU_ADD_TEST(suite, update_crc32c_test); + CU_ADD_TEST(suite, _dif_update_crc32c_split_test); + CU_ADD_TEST(suite, dif_update_crc32c_stream_multi_segments_test); + CU_ADD_TEST(suite, get_range_with_md_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test); + CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test); + CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_remap); + CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/iov.c/.gitignore b/src/spdk/test/unit/lib/util/iov.c/.gitignore new file mode 100644 index 000000000..94d8d9621 --- /dev/null +++ b/src/spdk/test/unit/lib/util/iov.c/.gitignore @@ -0,0 +1 @@ +iov_ut diff --git a/src/spdk/test/unit/lib/util/iov.c/Makefile b/src/spdk/test/unit/lib/util/iov.c/Makefile new file mode 100644 index 000000000..c7b4ccd5a --- /dev/null +++ b/src/spdk/test/unit/lib/util/iov.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = iov_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/iov.c/iov_ut.c b/src/spdk/test/unit/lib/util/iov.c/iov_ut.c new file mode 100644 index 000000000..248ab91ff --- /dev/null +++ b/src/spdk/test/unit/lib/util/iov.c/iov_ut.c @@ -0,0 +1,249 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/iov.c" + +static int +_check_val(void *buf, size_t len, uint8_t val) +{ + size_t i; + uint8_t *data = buf; + + for (i = 0; i < len; i++) { + if (data[i] != val) { + return -1; + } + } + + return 0; +} + +static void +test_single_iov(void) +{ + struct iovec siov[1]; + struct iovec diov[1]; + uint8_t sdata[64]; + uint8_t ddata[64]; + ssize_t rc; + + /* Simplest cases- 1 element in each iovec. */ + + /* Same size. */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + siov[0].iov_base = sdata; + siov[0].iov_len = sizeof(sdata); + diov[0].iov_base = ddata; + diov[0].iov_len = sizeof(ddata); + + rc = spdk_iovcpy(siov, 1, diov, 1); + CU_ASSERT(rc == sizeof(sdata)); + CU_ASSERT(_check_val(ddata, 64, 1) == 0); + + /* Source smaller than dest */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + siov[0].iov_base = sdata; + siov[0].iov_len = 48; + diov[0].iov_base = ddata; + diov[0].iov_len = sizeof(ddata); + + rc = spdk_iovcpy(siov, 1, diov, 1); + CU_ASSERT(rc == 48); + CU_ASSERT(_check_val(ddata, 48, 1) == 0); + CU_ASSERT(_check_val(&ddata[48], 16, 0) == 0); + + /* Dest smaller than source */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + siov[0].iov_base = sdata; + siov[0].iov_len = sizeof(sdata); + diov[0].iov_base = ddata; + diov[0].iov_len = 48; + + rc = spdk_iovcpy(siov, 1, diov, 1); + CU_ASSERT(rc == 48); + CU_ASSERT(_check_val(ddata, 48, 1) == 0); + CU_ASSERT(_check_val(&ddata[48], 16, 0) == 0); +} + +static void +test_simple_iov(void) +{ + struct iovec siov[4]; + struct iovec diov[4]; + uint8_t sdata[64]; + uint8_t ddata[64]; + ssize_t rc; + int i; + + /* Simple cases with 4 iov elements */ + + /* Same size. */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + for (i = 0; i < 4; i++) { + siov[i].iov_base = sdata + (16 * i); + siov[i].iov_len = 16; + diov[i].iov_base = ddata + (16 * i); + diov[i].iov_len = 16; + } + + rc = spdk_iovcpy(siov, 4, diov, 4); + CU_ASSERT(rc == sizeof(sdata)); + CU_ASSERT(_check_val(ddata, 64, 1) == 0); + + /* Source smaller than dest */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + for (i = 0; i < 4; i++) { + siov[i].iov_base = sdata + (8 * i); + siov[i].iov_len = 8; + diov[i].iov_base = ddata + (16 * i); + diov[i].iov_len = 16; + } + + rc = spdk_iovcpy(siov, 4, diov, 4); + CU_ASSERT(rc == 32); + CU_ASSERT(_check_val(ddata, 32, 1) == 0); + CU_ASSERT(_check_val(&ddata[32], 32, 0) == 0); + + /* Dest smaller than source */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + for (i = 0; i < 4; i++) { + siov[i].iov_base = sdata + (16 * i); + siov[i].iov_len = 16; + diov[i].iov_base = ddata + (8 * i); + diov[i].iov_len = 8; + } + + rc = spdk_iovcpy(siov, 4, diov, 4); + CU_ASSERT(rc == 32); + CU_ASSERT(_check_val(ddata, 32, 1) == 0); + CU_ASSERT(_check_val(&ddata[32], 32, 0) == 0); +} + +static void +test_complex_iov(void) +{ + struct iovec siov[4]; + struct iovec diov[4]; + uint8_t sdata[64]; + uint8_t ddata[64]; + ssize_t rc; + int i; + + /* More source elements */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + for (i = 0; i < 4; i++) { + siov[i].iov_base = sdata + (16 * i); + siov[i].iov_len = 16; + } + diov[0].iov_base = ddata; + diov[0].iov_len = sizeof(ddata); + + rc = spdk_iovcpy(siov, 4, diov, 1); + CU_ASSERT(rc == sizeof(sdata)); + CU_ASSERT(_check_val(ddata, 64, 1) == 0); + + /* More dest elements */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + for (i = 0; i < 4; i++) { + diov[i].iov_base = ddata + (16 * i); + diov[i].iov_len = 16; + } + siov[0].iov_base = sdata; + siov[0].iov_len = sizeof(sdata); + + rc = spdk_iovcpy(siov, 1, diov, 4); + CU_ASSERT(rc == sizeof(sdata)); + CU_ASSERT(_check_val(ddata, 64, 1) == 0); + + /* Build one by hand that's really terrible */ + memset(sdata, 1, sizeof(sdata)); + memset(ddata, 0, sizeof(ddata)); + siov[0].iov_base = sdata; + siov[0].iov_len = 1; + siov[1].iov_base = siov[0].iov_base + siov[0].iov_len; + siov[1].iov_len = 13; + siov[2].iov_base = siov[1].iov_base + siov[1].iov_len; + siov[2].iov_len = 6; + siov[3].iov_base = siov[2].iov_base + siov[2].iov_len; + siov[3].iov_len = 44; + + diov[0].iov_base = ddata; + diov[0].iov_len = 31; + diov[1].iov_base = diov[0].iov_base + diov[0].iov_len; + diov[1].iov_len = 9; + diov[2].iov_base = diov[1].iov_base + diov[1].iov_len; + diov[2].iov_len = 1; + diov[3].iov_base = diov[2].iov_base + diov[2].iov_len; + diov[3].iov_len = 23; + + rc = spdk_iovcpy(siov, 4, diov, 4); + CU_ASSERT(rc == 64); + CU_ASSERT(_check_val(ddata, 64, 1) == 0); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("iov", NULL, NULL); + + CU_ADD_TEST(suite, test_single_iov); + CU_ADD_TEST(suite, test_simple_iov); + CU_ADD_TEST(suite, test_complex_iov); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/math.c/.gitignore b/src/spdk/test/unit/lib/util/math.c/.gitignore new file mode 100644 index 000000000..e51846f2b --- /dev/null +++ b/src/spdk/test/unit/lib/util/math.c/.gitignore @@ -0,0 +1 @@ +math_ut diff --git a/src/spdk/test/unit/lib/util/math.c/Makefile b/src/spdk/test/unit/lib/util/math.c/Makefile new file mode 100644 index 000000000..e8b20c6be --- /dev/null +++ b/src/spdk/test/unit/lib/util/math.c/Makefile @@ -0,0 +1,39 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk + +TEST_FILE = math_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/math.c/math_ut.c b/src/spdk/test/unit/lib/util/math.c/math_ut.c new file mode 100644 index 000000000..66e063e12 --- /dev/null +++ b/src/spdk/test/unit/lib/util/math.c/math_ut.c @@ -0,0 +1,81 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/math.c" + +static void +test_serial_number_arithmetic(void) +{ + CU_ASSERT(spdk_sn32_add(0, 1) == 1); + CU_ASSERT(spdk_sn32_add(1, 1) == 2); + CU_ASSERT(spdk_sn32_add(1, 2) == 3); + CU_ASSERT(spdk_sn32_add(1, UINT32_MAX) == 0); + CU_ASSERT(spdk_sn32_add(UINT32_MAX, UINT32_MAX) == UINT32_MAX - 1); + CU_ASSERT(spdk_sn32_gt(1, 0) == true); + CU_ASSERT(spdk_sn32_gt(2, 1) == true); + CU_ASSERT(spdk_sn32_gt(UINT32_MAX, UINT32_MAX - 1) == true); + CU_ASSERT(spdk_sn32_gt(0, UINT32_MAX) == true); + CU_ASSERT(spdk_sn32_gt(100, UINT32_MAX - 100) == true); + CU_ASSERT(spdk_sn32_lt(1, 0) == false); + CU_ASSERT(spdk_sn32_lt(2, 1) == false); + CU_ASSERT(spdk_sn32_lt(UINT32_MAX, UINT32_MAX - 1) == false); + CU_ASSERT(spdk_sn32_lt(0, UINT32_MAX) == false); + CU_ASSERT(spdk_sn32_lt(100, UINT32_MAX - 100) == false); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("math", NULL, NULL); + + CU_ADD_TEST(suite, test_serial_number_arithmetic); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/pipe.c/.gitignore b/src/spdk/test/unit/lib/util/pipe.c/.gitignore new file mode 100644 index 000000000..493aa5572 --- /dev/null +++ b/src/spdk/test/unit/lib/util/pipe.c/.gitignore @@ -0,0 +1 @@ +pipe_ut diff --git a/src/spdk/test/unit/lib/util/pipe.c/Makefile b/src/spdk/test/unit/lib/util/pipe.c/Makefile new file mode 100644 index 000000000..99592cfb4 --- /dev/null +++ b/src/spdk/test/unit/lib/util/pipe.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = pipe_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/pipe.c/pipe_ut.c b/src/spdk/test/unit/lib/util/pipe.c/pipe_ut.c new file mode 100644 index 000000000..8ac76dfe9 --- /dev/null +++ b/src/spdk/test/unit/lib/util/pipe.c/pipe_ut.c @@ -0,0 +1,653 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/pipe.c" +#include "common/lib/test_env.c" + +static void +test_create_destroy(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + spdk_pipe_destroy(pipe); +} + +static void +test_write_get_buffer(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + struct iovec iovs[2]; + int rc; + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + /* Get some available memory. */ + rc = spdk_pipe_writer_get_buffer(pipe, 5, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 5); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get 0 bytes. */ + rc = spdk_pipe_writer_get_buffer(pipe, 0, iovs); + CU_ASSERT(rc == 0); + CU_ASSERT(iovs[0].iov_base == NULL); + CU_ASSERT(iovs[0].iov_len == 0); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get all available memory */ + rc = spdk_pipe_writer_get_buffer(pipe, 9, iovs); + CU_ASSERT(rc == 9); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 9); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get the full size of the data buffer backing the pipe, which isn't allowed */ + rc = spdk_pipe_writer_get_buffer(pipe, 10, iovs); + CU_ASSERT(rc == 9); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 9); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Advance the write pointer 7 bytes in. */ + pipe->write = 7; + + /* Get all of the available memory. */ + rc = spdk_pipe_writer_get_buffer(pipe, 2, iovs); + CU_ASSERT(rc == 2); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 2); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more than the available memory */ + rc = spdk_pipe_writer_get_buffer(pipe, 3, iovs); + CU_ASSERT(rc == 2); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 2); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Advance the read pointer 3 bytes in. */ + pipe->read = 3; + + /* Get all of the available memory. */ + rc = spdk_pipe_writer_get_buffer(pipe, 5, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 3); + CU_ASSERT(iovs[1].iov_base == mem); + CU_ASSERT(iovs[1].iov_len == 2); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 3); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more than the available memory */ + rc = spdk_pipe_writer_get_buffer(pipe, 6, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 3); + CU_ASSERT(iovs[1].iov_base == mem); + CU_ASSERT(iovs[1].iov_len == 2); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 3); + + memset(iovs, 0, sizeof(iovs)); + + /* Advance the read pointer past the write pointer */ + pipe->read = 9; + + /* Get all of the available memory. */ + rc = spdk_pipe_writer_get_buffer(pipe, 1, iovs); + CU_ASSERT(rc == 1); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 1); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 9); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more than the available memory */ + rc = spdk_pipe_writer_get_buffer(pipe, 2, iovs); + CU_ASSERT(rc == 1); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 1); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 9); + + memset(iovs, 0, sizeof(iovs)); + + /* Fill the pipe */ + pipe->write = 8; + + /* Get data while the pipe is full */ + rc = spdk_pipe_writer_get_buffer(pipe, 1, iovs); + CU_ASSERT(rc == 0); + CU_ASSERT(iovs[0].iov_base == NULL); + CU_ASSERT(iovs[0].iov_len == 0); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 8); + CU_ASSERT(pipe->read == 9); + + spdk_pipe_destroy(pipe); +} + +static void +test_write_advance(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + int rc; + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + /* Advance half way through the pipe */ + rc = spdk_pipe_writer_advance(pipe, 5); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->write == 5); + CU_ASSERT(pipe->read == 0); + + pipe->write = 0; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_writer_advance(pipe, 9); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->write == 9); + CU_ASSERT(pipe->read == 0); + + pipe->write = 0; + + /* Advance beyond the end */ + rc = spdk_pipe_writer_advance(pipe, 10); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 0); + + /* Move the read pointer forward */ + pipe->write = 0; + pipe->read = 5; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_writer_advance(pipe, 4); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->write == 4); + CU_ASSERT(pipe->read == 5); + + pipe->write = 0; + pipe->read = 5; + + /* Advance beyond the end */ + rc = spdk_pipe_writer_advance(pipe, 5); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 5); + + /* Test wrap around */ + pipe->write = 7; + pipe->read = 3; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_writer_advance(pipe, 5); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->write == 2); + CU_ASSERT(pipe->read == 3); + + pipe->write = 7; + pipe->read = 3; + + /* Advance beyond the end */ + rc = spdk_pipe_writer_advance(pipe, 6); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->write == 7); + CU_ASSERT(pipe->read == 3); + + spdk_pipe_destroy(pipe); +} + +static void +test_read_get_buffer(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + struct iovec iovs[2]; + int rc; + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + /* Set the write pointer to the end, making all data available. */ + pipe->write = 9; + + /* Get half the available memory. */ + rc = spdk_pipe_reader_get_buffer(pipe, 5, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 5); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 9); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get 0 bytes. */ + rc = spdk_pipe_reader_get_buffer(pipe, 0, iovs); + CU_ASSERT(rc == 0); + CU_ASSERT(iovs[0].iov_base == NULL); + CU_ASSERT(iovs[0].iov_len == 0); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 9); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get all available memory */ + rc = spdk_pipe_reader_get_buffer(pipe, 9, iovs); + CU_ASSERT(rc == 9); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 9); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 9); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more bytes than exist */ + rc = spdk_pipe_reader_get_buffer(pipe, 10, iovs); + CU_ASSERT(rc == 9); + CU_ASSERT(iovs[0].iov_base == mem); + CU_ASSERT(iovs[0].iov_len == 9); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 9); + CU_ASSERT(pipe->read == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Advance the read pointer 5 bytes in. */ + pipe->read = 5; + pipe->write = 0; + + /* Get all of the available memory. */ + rc = spdk_pipe_reader_get_buffer(pipe, 5, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == (mem + 5)); + CU_ASSERT(iovs[0].iov_len == 5); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 5); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more than the available memory */ + rc = spdk_pipe_reader_get_buffer(pipe, 6, iovs); + CU_ASSERT(rc == 5); + CU_ASSERT(iovs[0].iov_base == (mem + 5)); + CU_ASSERT(iovs[0].iov_len == 5); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 0); + CU_ASSERT(pipe->read == 5); + + memset(iovs, 0, sizeof(iovs)); + + /* Invert the write and read pointers */ + pipe->read = 7; + pipe->write = 3; + + /* Get all of the available memory. */ + rc = spdk_pipe_reader_get_buffer(pipe, 6, iovs); + CU_ASSERT(rc == 6); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 3); + CU_ASSERT(iovs[1].iov_base == mem); + CU_ASSERT(iovs[1].iov_len == 3); + CU_ASSERT(pipe->write == 3); + CU_ASSERT(pipe->read == 7); + + memset(iovs, 0, sizeof(iovs)); + + /* Get more than the available memory */ + rc = spdk_pipe_reader_get_buffer(pipe, 7, iovs); + CU_ASSERT(rc == 6); + CU_ASSERT(iovs[0].iov_base == (mem + 7)); + CU_ASSERT(iovs[0].iov_len == 3); + CU_ASSERT(iovs[1].iov_base == mem); + CU_ASSERT(iovs[1].iov_len == 3); + CU_ASSERT(pipe->write == 3); + CU_ASSERT(pipe->read == 7); + + memset(iovs, 0, sizeof(iovs)); + + /* Empty the pipe */ + pipe->read = 8; + pipe->write = 8; + + /* Get data while the pipe is empty */ + rc = spdk_pipe_reader_get_buffer(pipe, 1, iovs); + CU_ASSERT(rc == 0); + CU_ASSERT(iovs[0].iov_base == NULL); + CU_ASSERT(iovs[0].iov_len == 0); + CU_ASSERT(iovs[1].iov_base == NULL); + CU_ASSERT(iovs[1].iov_len == 0); + CU_ASSERT(pipe->write == 8); + CU_ASSERT(pipe->read == 8); + + spdk_pipe_destroy(pipe); +} + +static void +test_read_advance(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + int rc; + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + pipe->read = 0; + pipe->write = 9; + + /* Advance half way through the pipe */ + rc = spdk_pipe_reader_advance(pipe, 5); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->read == 5); + CU_ASSERT(pipe->write == 9); + + pipe->read = 0; + pipe->write = 9; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_reader_advance(pipe, 9); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->read == 9); + CU_ASSERT(pipe->write == 9); + + pipe->read = 0; + pipe->write = 9; + + /* Advance beyond the end */ + rc = spdk_pipe_reader_advance(pipe, 10); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->read == 0); + CU_ASSERT(pipe->write == 9); + + /* Move the write pointer forward */ + pipe->read = 0; + pipe->write = 5; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_reader_advance(pipe, 5); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->write == 5); + CU_ASSERT(pipe->read == 5); + + pipe->read = 0; + pipe->write = 5; + + /* Advance beyond the end */ + rc = spdk_pipe_reader_advance(pipe, 6); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->read == 0); + CU_ASSERT(pipe->write == 5); + + /* Test wrap around */ + pipe->read = 7; + pipe->write = 3; + + /* Advance to the end of the pipe */ + rc = spdk_pipe_reader_advance(pipe, 6); + CU_ASSERT(rc == 0); + CU_ASSERT(pipe->read == 3); + CU_ASSERT(pipe->write == 3); + + pipe->read = 7; + pipe->write = 3; + + /* Advance beyond the end */ + rc = spdk_pipe_writer_advance(pipe, 7); + CU_ASSERT(rc == -EINVAL); + CU_ASSERT(pipe->read == 7); + CU_ASSERT(pipe->write == 3); + + spdk_pipe_destroy(pipe); +} + +static void +test_data(void) +{ + struct spdk_pipe *pipe; + uint8_t mem[10]; + struct iovec iovs[2]; + uint8_t *data; + int rc; + size_t i; + + memset(mem, 0, sizeof(mem)); + memset(iovs, 0, sizeof(iovs)); + + pipe = spdk_pipe_create(mem, sizeof(mem)); + SPDK_CU_ASSERT_FATAL(pipe != NULL); + + /* Place 1 byte in the pipe */ + rc = spdk_pipe_writer_get_buffer(pipe, 1, iovs); + CU_ASSERT(rc == 1); + CU_ASSERT(iovs[0].iov_base != NULL); + CU_ASSERT(iovs[0].iov_len == 1); + + memset(iovs[0].iov_base, 'A', 1); + + rc = spdk_pipe_writer_advance(pipe, 1); + CU_ASSERT(rc == 0); + + CU_ASSERT(mem[0] == 'A'); + CU_ASSERT(mem[1] == 0); + CU_ASSERT(mem[2] == 0); + CU_ASSERT(mem[3] == 0); + CU_ASSERT(mem[4] == 0); + CU_ASSERT(mem[5] == 0); + CU_ASSERT(mem[6] == 0); + CU_ASSERT(mem[7] == 0); + CU_ASSERT(mem[8] == 0); + CU_ASSERT(mem[9] == 0); + + memset(iovs, 0, sizeof(iovs)); + + /* Get 1 byte from the pipe */ + CU_ASSERT(spdk_pipe_reader_bytes_available(pipe) == 1); + rc = spdk_pipe_reader_get_buffer(pipe, 10, iovs); + CU_ASSERT(rc == 1); + + data = iovs[0].iov_base; + CU_ASSERT(*data = 'A'); + + spdk_pipe_reader_advance(pipe, 1); + + /* Put 9 more bytes in the pipe, so every byte has + * been written */ + rc = spdk_pipe_writer_get_buffer(pipe, 9, iovs); + CU_ASSERT(rc == 9); + CU_ASSERT(iovs[0].iov_len == 9); + CU_ASSERT(iovs[1].iov_len == 0); + + memset(iovs[0].iov_base, 'B', iovs[0].iov_len); + + rc = spdk_pipe_writer_advance(pipe, 9); + CU_ASSERT(rc == 0); + + CU_ASSERT(mem[0] == 'A'); + CU_ASSERT(mem[1] == 'B'); + CU_ASSERT(mem[2] == 'B'); + CU_ASSERT(mem[3] == 'B'); + CU_ASSERT(mem[4] == 'B'); + CU_ASSERT(mem[5] == 'B'); + CU_ASSERT(mem[6] == 'B'); + CU_ASSERT(mem[7] == 'B'); + CU_ASSERT(mem[8] == 'B'); + CU_ASSERT(mem[9] == 'B'); + + memset(iovs, 0, sizeof(iovs)); + + /* Get 7 bytes of the previously written 9. */ + CU_ASSERT(spdk_pipe_reader_bytes_available(pipe) == 9); + rc = spdk_pipe_reader_get_buffer(pipe, 7, iovs); + CU_ASSERT(rc == 7); + + CU_ASSERT(iovs[0].iov_len == 7); + data = iovs[0].iov_base; + for (i = 0; i < iovs[0].iov_len; i++) { + CU_ASSERT(data[i] == 'B'); + } + + spdk_pipe_reader_advance(pipe, 7); + + memset(iovs, 0, sizeof(iovs)); + + /* Put 1 more byte in the pipe, overwriting the original 'A' */ + rc = spdk_pipe_writer_get_buffer(pipe, 1, iovs); + CU_ASSERT(rc == 1); + CU_ASSERT(iovs[0].iov_len == 1); + CU_ASSERT(iovs[1].iov_len == 0); + + memset(iovs[0].iov_base, 'C', iovs[0].iov_len); + + rc = spdk_pipe_writer_advance(pipe, 1); + CU_ASSERT(rc == 0); + + CU_ASSERT(mem[0] == 'C'); + CU_ASSERT(mem[1] == 'B'); + CU_ASSERT(mem[2] == 'B'); + CU_ASSERT(mem[3] == 'B'); + CU_ASSERT(mem[4] == 'B'); + CU_ASSERT(mem[5] == 'B'); + CU_ASSERT(mem[6] == 'B'); + CU_ASSERT(mem[7] == 'B'); + CU_ASSERT(mem[8] == 'B'); + CU_ASSERT(mem[9] == 'B'); + + memset(iovs, 0, sizeof(iovs)); + + /* Get all of the data out of the pipe */ + CU_ASSERT(spdk_pipe_reader_bytes_available(pipe) == 3); + rc = spdk_pipe_reader_get_buffer(pipe, 3, iovs); + CU_ASSERT(rc == 3); + CU_ASSERT(iovs[0].iov_len == 2); + CU_ASSERT(iovs[1].iov_len == 1); + + data = iovs[0].iov_base; + CU_ASSERT(data[0] == 'B'); + CU_ASSERT(data[1] == 'B'); + data = iovs[1].iov_base; + CU_ASSERT(data[0] == 'C'); + + spdk_pipe_reader_advance(pipe, 3); + + spdk_pipe_destroy(pipe); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("pipe", NULL, NULL); + + CU_ADD_TEST(suite, test_create_destroy); + CU_ADD_TEST(suite, test_write_get_buffer); + CU_ADD_TEST(suite, test_write_advance); + CU_ADD_TEST(suite, test_read_get_buffer); + CU_ADD_TEST(suite, test_read_advance); + CU_ADD_TEST(suite, test_data); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} diff --git a/src/spdk/test/unit/lib/util/string.c/.gitignore b/src/spdk/test/unit/lib/util/string.c/.gitignore new file mode 100644 index 000000000..5d85d4d93 --- /dev/null +++ b/src/spdk/test/unit/lib/util/string.c/.gitignore @@ -0,0 +1 @@ +string_ut diff --git a/src/spdk/test/unit/lib/util/string.c/Makefile b/src/spdk/test/unit/lib/util/string.c/Makefile new file mode 100644 index 000000000..016fb07e9 --- /dev/null +++ b/src/spdk/test/unit/lib/util/string.c/Makefile @@ -0,0 +1,38 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) + +TEST_FILE = string_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/util/string.c/string_ut.c b/src/spdk/test/unit/lib/util/string.c/string_ut.c new file mode 100644 index 000000000..d61c62536 --- /dev/null +++ b/src/spdk/test/unit/lib/util/string.c/string_ut.c @@ -0,0 +1,407 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" + +#include "util/string.c" + +static void +test_parse_ip_addr(void) +{ + int rc; + char *host; + char *port; + char ip[255]; + + /* IPv4 */ + snprintf(ip, 255, "%s", "192.168.0.1"); + rc = spdk_parse_ip_addr(ip, &host, &port); + CU_ASSERT_EQUAL(rc, 0); + SPDK_CU_ASSERT_FATAL(host != NULL); + CU_ASSERT(strcmp(host, "192.168.0.1") == 0); + CU_ASSERT_EQUAL(strlen(host), 11); + CU_ASSERT_EQUAL(port, NULL); + + /* IPv4 with port */ + snprintf(ip, 255, "%s", "123.456.789.0:5520"); + rc = spdk_parse_ip_addr(ip, &host, &port); + CU_ASSERT_EQUAL(rc, 0); + SPDK_CU_ASSERT_FATAL(host != NULL); + CU_ASSERT(strcmp(host, "123.456.789.0") == 0); + CU_ASSERT_EQUAL(strlen(host), 13); + SPDK_CU_ASSERT_FATAL(port != NULL); + CU_ASSERT(strcmp(port, "5520") == 0); + CU_ASSERT_EQUAL(strlen(port), 4); + + /* IPv6 */ + snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + rc = spdk_parse_ip_addr(ip, &host, &port); + CU_ASSERT_EQUAL(rc, 0); + SPDK_CU_ASSERT_FATAL(host != NULL); + CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); + CU_ASSERT_EQUAL(strlen(host), 36); + CU_ASSERT_EQUAL(port, NULL); + + /* IPv6 with port */ + snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"); + rc = spdk_parse_ip_addr(ip, &host, &port); + CU_ASSERT_EQUAL(rc, 0); + SPDK_CU_ASSERT_FATAL(host != NULL); + CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); + CU_ASSERT_EQUAL(strlen(host), 36); + SPDK_CU_ASSERT_FATAL(port != NULL); + CU_ASSERT(strcmp(port, "443") == 0); + CU_ASSERT_EQUAL(strlen(port), 3); + + /* IPv6 dangling colon */ + snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:"); + rc = spdk_parse_ip_addr(ip, &host, &port); + CU_ASSERT_EQUAL(rc, 0); + SPDK_CU_ASSERT_FATAL(host != NULL); + CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); + CU_ASSERT_EQUAL(strlen(host), 36); + CU_ASSERT_EQUAL(port, NULL); +} + +static void +test_str_chomp(void) +{ + char s[1024]; + + /* One \n newline */ + snprintf(s, sizeof(s), "%s", "hello world\n"); + CU_ASSERT(spdk_str_chomp(s) == 1); + CU_ASSERT(strcmp(s, "hello world") == 0); + + /* One \r\n newline */ + snprintf(s, sizeof(s), "%s", "hello world\r\n"); + CU_ASSERT(spdk_str_chomp(s) == 2); + CU_ASSERT(strcmp(s, "hello world") == 0); + + /* No newlines */ + snprintf(s, sizeof(s), "%s", "hello world"); + CU_ASSERT(spdk_str_chomp(s) == 0); + CU_ASSERT(strcmp(s, "hello world") == 0); + + /* Two newlines */ + snprintf(s, sizeof(s), "%s", "hello world\n\n"); + CU_ASSERT(spdk_str_chomp(s) == 2); + CU_ASSERT(strcmp(s, "hello world") == 0); + + /* Empty string */ + snprintf(s, sizeof(s), "%s", ""); + CU_ASSERT(spdk_str_chomp(s) == 0); + CU_ASSERT(strcmp(s, "") == 0); + + /* One-character string with only \n */ + snprintf(s, sizeof(s), "%s", "\n"); + CU_ASSERT(spdk_str_chomp(s) == 1); + CU_ASSERT(strcmp(s, "") == 0); + + /* One-character string without a newline */ + snprintf(s, sizeof(s), "%s", "a"); + CU_ASSERT(spdk_str_chomp(s) == 0); + CU_ASSERT(strcmp(s, "a") == 0); +} + +static void +test_parse_capacity(void) +{ + char str[128]; + uint64_t cap; + int rc; + bool has_prefix = true; + + rc = spdk_parse_capacity("472", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 472); + CU_ASSERT(has_prefix == false); + + snprintf(str, sizeof(str), "%"PRIu64, UINT64_MAX); + rc = spdk_parse_capacity(str, &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == UINT64_MAX); + CU_ASSERT(has_prefix == false); + + rc = spdk_parse_capacity("12k", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 12 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("12K", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 12 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("12KB", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 12 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("100M", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 100 * 1024 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("128M", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 128 * 1024 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("4G", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 4ULL * 1024 * 1024 * 1024); + CU_ASSERT(has_prefix == true); + + rc = spdk_parse_capacity("100M 512k", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 100ULL * 1024 * 1024); + + rc = spdk_parse_capacity("12k8K", &cap, &has_prefix); + CU_ASSERT(rc == 0); + CU_ASSERT(cap == 12 * 1024); + CU_ASSERT(has_prefix == true); + + /* Non-number */ + rc = spdk_parse_capacity("G", &cap, &has_prefix); + CU_ASSERT(rc != 0); + + rc = spdk_parse_capacity("darsto", &cap, &has_prefix); + CU_ASSERT(rc != 0); +} + +static void +test_sprintf_append_realloc(void) +{ + char *str1, *str2, *str3, *str4; + + /* Test basic functionality. */ + str1 = spdk_sprintf_alloc("hello world\ngood morning\n" \ + "good afternoon\ngood evening\n"); + SPDK_CU_ASSERT_FATAL(str1 != NULL); + + str2 = spdk_sprintf_append_realloc(NULL, "hello world\n"); + SPDK_CU_ASSERT_FATAL(str2); + + str2 = spdk_sprintf_append_realloc(str2, "good morning\n"); + SPDK_CU_ASSERT_FATAL(str2); + + str2 = spdk_sprintf_append_realloc(str2, "good afternoon\n"); + SPDK_CU_ASSERT_FATAL(str2); + + str2 = spdk_sprintf_append_realloc(str2, "good evening\n"); + SPDK_CU_ASSERT_FATAL(str2); + + CU_ASSERT(strcmp(str1, str2) == 0); + + free(str1); + free(str2); + + /* Test doubling buffer size. */ + str3 = spdk_sprintf_append_realloc(NULL, "aaaaaaaaaa\n"); + str3 = spdk_sprintf_append_realloc(str3, "bbbbbbbbbb\n"); + str3 = spdk_sprintf_append_realloc(str3, "cccccccccc\n"); + + str4 = malloc(33 + 1); + memset(&str4[0], 'a', 10); + str4[10] = '\n'; + memset(&str4[11], 'b', 10); + str4[21] = '\n'; + memset(&str4[22], 'c', 10); + str4[32] = '\n'; + str4[33] = 0; + + CU_ASSERT(strcmp(str3, str4) == 0); + + free(str3); + free(str4); +} +static void +test_strtol(void) +{ + long int val; + + const char *val1 = "no_digits"; + /* LLONG_MIN - 1 */ + const char *val2 = "-9223372036854775809"; + /* LONG_MIN */ + const char *val3 = "-9223372036854775808"; + /* LONG_MIN + 1 */ + const char *val4 = "-9223372036854775807"; + /* LONG_MAX - 1 */ + const char *val5 = "9223372036854775806"; + /* LONG_MAX */ + const char *val6 = "9223372036854775807"; + /* LONG_MAX + 1 */ + const char *val7 = "9223372036854775808"; + /* digits + chars */ + const char *val8 = "10_is_ten"; + /* chars + digits */ + const char *val9 = "ten_is_10"; + /* all zeroes */ + const char *val10 = "00000000"; + /* leading minus sign, but not negative */ + const char *val11 = "-0"; + + val = spdk_strtol(val1, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtol(val2, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtol(val3, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtol(val4, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtol(val5, 10); + CU_ASSERT(val == LONG_MAX - 1); + + val = spdk_strtol(val6, 10); + CU_ASSERT(val == LONG_MAX); + + val = spdk_strtol(val7, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtol(val8, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtol(val9, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtol(val10, 10); + CU_ASSERT(val == 0); + + /* Invalid base */ + val = spdk_strtol(val10, 1); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtol(val11, 10); + CU_ASSERT(val == 0); +} + +static void +test_strtoll(void) +{ + long long int val; + + const char *val1 = "no_digits"; + /* LLONG_MIN - 1 */ + const char *val2 = "-9223372036854775809"; + /* LLONG_MIN */ + const char *val3 = "-9223372036854775808"; + /* LLONG_MIN + 1 */ + const char *val4 = "-9223372036854775807"; + /* LLONG_MAX - 1 */ + const char *val5 = "9223372036854775806"; + /* LLONG_MAX */ + const char *val6 = "9223372036854775807"; + /* LLONG_MAX + 1 */ + const char *val7 = "9223372036854775808"; + /* digits + chars */ + const char *val8 = "10_is_ten"; + /* chars + digits */ + const char *val9 = "ten_is_10"; + /* all zeroes */ + const char *val10 = "00000000"; + /* leading minus sign, but not negative */ + const char *val11 = "-0"; + + val = spdk_strtoll(val1, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtoll(val2, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtoll(val3, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtoll(val4, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtoll(val5, 10); + CU_ASSERT(val == LLONG_MAX - 1); + + val = spdk_strtoll(val6, 10); + CU_ASSERT(val == LLONG_MAX); + + val = spdk_strtoll(val7, 10); + CU_ASSERT(val == -ERANGE); + + val = spdk_strtoll(val8, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtoll(val9, 10); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtoll(val10, 10); + CU_ASSERT(val == 0); + + /* Invalid base */ + val = spdk_strtoll(val10, 1); + CU_ASSERT(val == -EINVAL); + + val = spdk_strtoll(val11, 10); + CU_ASSERT(val == 0); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + CU_set_error_action(CUEA_ABORT); + CU_initialize_registry(); + + suite = CU_add_suite("string", NULL, NULL); + + CU_ADD_TEST(suite, test_parse_ip_addr); + CU_ADD_TEST(suite, test_str_chomp); + CU_ADD_TEST(suite, test_parse_capacity); + CU_ADD_TEST(suite, test_sprintf_append_realloc); + CU_ADD_TEST(suite, test_strtol); + CU_ADD_TEST(suite, test_strtoll); + + CU_basic_set_mode(CU_BRM_VERBOSE); + + CU_basic_run_tests(); + + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} |