uboot/test/lib/string.c
<<
>>
Prefs
   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 <log.h>
  15#include <test/lib.h>
  16#include <test/test.h>
  17#include <test/ut.h>
  18
  19/* Xor mask used for marking memory regions */
  20#define MASK 0xA5
  21/* Number of different alignment values */
  22#define SWEEP 16
  23/* Allow for copying up to 32 bytes */
  24#define BUFLEN (SWEEP + 33)
  25
  26#define TEST_STR        "hello"
  27
  28/**
  29 * init_buffer() - initialize buffer
  30 *
  31 * The buffer is filled with incrementing values xor'ed with the mask.
  32 *
  33 * @buf:        buffer
  34 * @mask:       xor mask
  35 */
  36static void init_buffer(u8 buf[], u8 mask)
  37{
  38        int i;
  39
  40        for (i = 0; i < BUFLEN; ++i)
  41                buf[i] = i ^ mask;
  42}
  43
  44/**
  45 * test_memset() - test result of memset()
  46 *
  47 * @uts:        unit test state
  48 * @buf:        buffer
  49 * @mask:       value set by memset()
  50 * @offset:     relative start of region changed by memset() in buffer
  51 * @len:        length of region changed by memset()
  52 * Return:      0 = success, 1 = failure
  53 */
  54static int test_memset(struct unit_test_state *uts, u8 buf[], u8 mask,
  55                       int offset, int len)
  56{
  57        int i;
  58
  59        for (i = 0; i < BUFLEN; ++i) {
  60                if (i < offset || i >= offset + len) {
  61                        ut_asserteq(i, buf[i]);
  62                } else {
  63                        ut_asserteq(mask, buf[i]);
  64                }
  65        }
  66        return 0;
  67}
  68
  69/**
  70 * lib_memset() - unit test for memset()
  71 *
  72 * Test memset() with varied alignment and length of the changed buffer.
  73 *
  74 * @uts:        unit test state
  75 * Return:      0 = success, 1 = failure
  76 */
  77static int lib_memset(struct unit_test_state *uts)
  78{
  79        u8 buf[BUFLEN];
  80        int offset, len;
  81        void *ptr;
  82
  83        for (offset = 0; offset <= SWEEP; ++offset) {
  84                for (len = 1; len < BUFLEN - SWEEP; ++len) {
  85                        init_buffer(buf, 0);
  86                        ptr = memset(buf + offset, MASK, len);
  87                        ut_asserteq_ptr(buf + offset, (u8 *)ptr);
  88                        if (test_memset(uts, buf, MASK, offset, len)) {
  89                                debug("%s: failure %d, %d\n",
  90                                      __func__, offset, len);
  91                                return CMD_RET_FAILURE;
  92                        }
  93                }
  94        }
  95        return 0;
  96}
  97
  98LIB_TEST(lib_memset, 0);
  99
 100/**
 101 * test_memmove() - test result of memcpy() or memmove()
 102 *
 103 * @uts:        unit test state
 104 * @buf:        buffer
 105 * @mask:       xor mask used to initialize source buffer
 106 * @offset1:    relative start of copied region in source buffer
 107 * @offset2:    relative start of copied region in destination buffer
 108 * @len:        length of region changed by memset()
 109 * Return:      0 = success, 1 = failure
 110 */
 111static int test_memmove(struct unit_test_state *uts, u8 buf[], u8 mask,
 112                        int offset1, int offset2, int len)
 113{
 114        int i;
 115
 116        for (i = 0; i < BUFLEN; ++i) {
 117                if (i < offset2 || i >= offset2 + len) {
 118                        ut_asserteq(i, buf[i]);
 119                } else {
 120                        ut_asserteq((i + offset1 - offset2) ^ mask, buf[i]);
 121                }
 122        }
 123        return 0;
 124}
 125
 126/**
 127 * lib_memcpy() - unit test for memcpy()
 128 *
 129 * Test memcpy() with varied alignment and length of the copied buffer.
 130 *
 131 * @uts:        unit test state
 132 * Return:      0 = success, 1 = failure
 133 */
 134static int lib_memcpy(struct unit_test_state *uts)
 135{
 136        u8 buf1[BUFLEN];
 137        u8 buf2[BUFLEN];
 138        int offset1, offset2, len;
 139        void *ptr;
 140
 141        init_buffer(buf1, MASK);
 142
 143        for (offset1 = 0; offset1 <= SWEEP; ++offset1) {
 144                for (offset2 = 0; offset2 <= SWEEP; ++offset2) {
 145                        for (len = 1; len < BUFLEN - SWEEP; ++len) {
 146                                init_buffer(buf2, 0);
 147                                ptr = memcpy(buf2 + offset2, buf1 + offset1,
 148                                             len);
 149                                ut_asserteq_ptr(buf2 + offset2, (u8 *)ptr);
 150                                if (test_memmove(uts, buf2, MASK, offset1,
 151                                                 offset2, len)) {
 152                                        debug("%s: failure %d, %d, %d\n",
 153                                              __func__, offset1, offset2, len);
 154                                        return CMD_RET_FAILURE;
 155                                }
 156                        }
 157                }
 158        }
 159        return 0;
 160}
 161
 162LIB_TEST(lib_memcpy, 0);
 163
 164/**
 165 * lib_memmove() - unit test for memmove()
 166 *
 167 * Test memmove() with varied alignment and length of the copied buffer.
 168 *
 169 * @uts:        unit test state
 170 * Return:      0 = success, 1 = failure
 171 */
 172static int lib_memmove(struct unit_test_state *uts)
 173{
 174        u8 buf[BUFLEN];
 175        int offset1, offset2, len;
 176        void *ptr;
 177
 178        for (offset1 = 0; offset1 <= SWEEP; ++offset1) {
 179                for (offset2 = 0; offset2 <= SWEEP; ++offset2) {
 180                        for (len = 1; len < BUFLEN - SWEEP; ++len) {
 181                                init_buffer(buf, 0);
 182                                ptr = memmove(buf + offset2, buf + offset1,
 183                                              len);
 184                                ut_asserteq_ptr(buf + offset2, (u8 *)ptr);
 185                                if (test_memmove(uts, buf, 0, offset1, offset2,
 186                                                 len)) {
 187                                        debug("%s: failure %d, %d, %d\n",
 188                                              __func__, offset1, offset2, len);
 189                                        return CMD_RET_FAILURE;
 190                                }
 191                        }
 192                }
 193        }
 194        return 0;
 195}
 196
 197LIB_TEST(lib_memmove, 0);
 198
 199/** lib_memdup() - unit test for memdup() */
 200static int lib_memdup(struct unit_test_state *uts)
 201{
 202        char buf[BUFLEN];
 203        size_t len;
 204        char *p, *q;
 205
 206        /* Zero size should do nothing */
 207        p = memdup(NULL, 0);
 208        ut_assertnonnull(p);
 209        free(p);
 210
 211        p = memdup(buf, 0);
 212        ut_assertnonnull(p);
 213        free(p);
 214
 215        strcpy(buf, TEST_STR);
 216        len = sizeof(TEST_STR);
 217        p = memdup(buf, len);
 218        ut_asserteq_mem(p, buf, len);
 219
 220        q = memdup(p, len);
 221        ut_asserteq_mem(q, buf, len);
 222        free(q);
 223        free(p);
 224
 225        return 0;
 226}
 227LIB_TEST(lib_memdup, 0);
 228