1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de> 4 * 5 * Unit tests for memory functions 6 * 7 * The architecture dependent implementations run through different lines of 8 * code depending on the alignment and length of memory regions copied or set. 9 * This has to be considered in testing. 10 */ 11 12 #include <common.h> 13 #include <command.h> 14 #include <test/lib.h> 15 #include <test/test.h> 16 #include <test/ut.h> 17 18 /* Xor mask used for marking memory regions */ 19 #define MASK 0xA5 20 /* Number of different alignment values */ 21 #define SWEEP 16 22 /* Allow for copying up to 32 bytes */ 23 #define BUFLEN (SWEEP + 33) 24 25 /** 26 * init_buffer() - initialize buffer 27 * 28 * The buffer is filled with incrementing values xor'ed with the mask. 29 * 30 * @buf: buffer 31 * @mask: xor mask 32 */ 33 static void init_buffer(u8 buf[], u8 mask) 34 { 35 int i; 36 37 for (i = 0; i < BUFLEN; ++i) 38 buf[i] = i ^ mask; 39 } 40 41 /** 42 * test_memset() - test result of memset() 43 * 44 * @uts: unit test state 45 * @buf: buffer 46 * @mask: value set by memset() 47 * @offset: relative start of region changed by memset() in buffer 48 * @len: length of region changed by memset() 49 * Return: 0 = success, 1 = failure 50 */ 51 static int test_memset(struct unit_test_state *uts, u8 buf[], u8 mask, 52 int offset, int len) 53 { 54 int i; 55 56 for (i = 0; i < BUFLEN; ++i) { 57 if (i < offset || i >= offset + len) { 58 ut_asserteq(i, buf[i]); 59 } else { 60 ut_asserteq(mask, buf[i]); 61 } 62 } 63 return 0; 64 } 65 66 /** 67 * lib_memset() - unit test for memset() 68 * 69 * Test memset() with varied alignment and length of the changed buffer. 70 * 71 * @uts: unit test state 72 * Return: 0 = success, 1 = failure 73 */ 74 static int lib_memset(struct unit_test_state *uts) 75 { 76 u8 buf[BUFLEN]; 77 int offset, len; 78 void *ptr; 79 80 for (offset = 0; offset <= SWEEP; ++offset) { 81 for (len = 1; len < BUFLEN - SWEEP; ++len) { 82 init_buffer(buf, 0); 83 ptr = memset(buf + offset, MASK, len); 84 ut_asserteq_ptr(buf + offset, (u8 *)ptr); 85 if (test_memset(uts, buf, MASK, offset, len)) { 86 debug("%s: failure %d, %d\n", 87 __func__, offset, len); 88 return CMD_RET_FAILURE; 89 } 90 } 91 } 92 return 0; 93 } 94 95 LIB_TEST(lib_memset, 0); 96 97 /** 98 * test_memmove() - test result of memcpy() or memmove() 99 * 100 * @uts: unit test state 101 * @buf: buffer 102 * @mask: xor mask used to initialize source buffer 103 * @offset1: relative start of copied region in source buffer 104 * @offset2: relative start of copied region in destination buffer 105 * @len: length of region changed by memset() 106 * Return: 0 = success, 1 = failure 107 */ 108 static int test_memmove(struct unit_test_state *uts, u8 buf[], u8 mask, 109 int offset1, int offset2, int len) 110 { 111 int i; 112 113 for (i = 0; i < BUFLEN; ++i) { 114 if (i < offset2 || i >= offset2 + len) { 115 ut_asserteq(i, buf[i]); 116 } else { 117 ut_asserteq((i + offset1 - offset2) ^ mask, buf[i]); 118 } 119 } 120 return 0; 121 } 122 123 /** 124 * lib_memcpy() - unit test for memcpy() 125 * 126 * Test memcpy() with varied alignment and length of the copied buffer. 127 * 128 * @uts: unit test state 129 * Return: 0 = success, 1 = failure 130 */ 131 static int lib_memcpy(struct unit_test_state *uts) 132 { 133 u8 buf1[BUFLEN]; 134 u8 buf2[BUFLEN]; 135 int offset1, offset2, len; 136 void *ptr; 137 138 init_buffer(buf1, MASK); 139 140 for (offset1 = 0; offset1 <= SWEEP; ++offset1) { 141 for (offset2 = 0; offset2 <= SWEEP; ++offset2) { 142 for (len = 1; len < BUFLEN - SWEEP; ++len) { 143 init_buffer(buf2, 0); 144 ptr = memcpy(buf2 + offset2, buf1 + offset1, 145 len); 146 ut_asserteq_ptr(buf2 + offset2, (u8 *)ptr); 147 if (test_memmove(uts, buf2, MASK, offset1, 148 offset2, len)) { 149 debug("%s: failure %d, %d, %d\n", 150 __func__, offset1, offset2, len); 151 return CMD_RET_FAILURE; 152 } 153 } 154 } 155 } 156 return 0; 157 } 158 159 LIB_TEST(lib_memcpy, 0); 160 161 /** 162 * lib_memmove() - unit test for memmove() 163 * 164 * Test memmove() with varied alignment and length of the copied buffer. 165 * 166 * @uts: unit test state 167 * Return: 0 = success, 1 = failure 168 */ 169 static int lib_memmove(struct unit_test_state *uts) 170 { 171 u8 buf[BUFLEN]; 172 int offset1, offset2, len; 173 void *ptr; 174 175 for (offset1 = 0; offset1 <= SWEEP; ++offset1) { 176 for (offset2 = 0; offset2 <= SWEEP; ++offset2) { 177 for (len = 1; len < BUFLEN - SWEEP; ++len) { 178 init_buffer(buf, 0); 179 ptr = memmove(buf + offset2, buf + offset1, 180 len); 181 ut_asserteq_ptr(buf + offset2, (u8 *)ptr); 182 if (test_memmove(uts, buf, 0, offset1, offset2, 183 len)) { 184 debug("%s: failure %d, %d, %d\n", 185 __func__, offset1, offset2, len); 186 return CMD_RET_FAILURE; 187 } 188 } 189 } 190 } 191 return 0; 192 } 193 194 LIB_TEST(lib_memmove, 0); 195