summaryrefslogtreecommitdiffstats
path: root/src/spdk/test/unit/lib/util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/test/unit/lib/util
parentInitial commit. (diff)
downloadceph-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 '')
-rw-r--r--src/spdk/test/unit/lib/util/Makefile45
-rw-r--r--src/spdk/test/unit/lib/util/base64.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/base64.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/base64.c/base64_ut.c381
-rw-r--r--src/spdk/test/unit/lib/util/bit_array.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/bit_array.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/bit_array.c/bit_array_ut.c376
-rw-r--r--src/spdk/test/unit/lib/util/cpuset.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/cpuset.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/cpuset.c/cpuset_ut.c262
-rw-r--r--src/spdk/test/unit/lib/util/crc16.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/crc16.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/crc16.c/crc16_ut.c104
-rw-r--r--src/spdk/test/unit/lib/util/crc32_ieee.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/crc32_ieee.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/crc32_ieee.c/crc32_ieee_ut.c74
-rw-r--r--src/spdk/test/unit/lib/util/crc32c.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/crc32c.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/crc32c.c/crc32c_ut.c145
-rw-r--r--src/spdk/test/unit/lib/util/dif.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/dif.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/dif.c/dif_ut.c2669
-rw-r--r--src/spdk/test/unit/lib/util/iov.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/iov.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/iov.c/iov_ut.c249
-rw-r--r--src/spdk/test/unit/lib/util/math.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/math.c/Makefile39
-rw-r--r--src/spdk/test/unit/lib/util/math.c/math_ut.c81
-rw-r--r--src/spdk/test/unit/lib/util/pipe.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/pipe.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/pipe.c/pipe_ut.c653
-rw-r--r--src/spdk/test/unit/lib/util/string.c/.gitignore1
-rw-r--r--src/spdk/test/unit/lib/util/string.c/Makefile38
-rw-r--r--src/spdk/test/unit/lib/util/string.c/string_ut.c407
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;
+}