Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0abbfd8 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

selftests/powerpc: Add test for strlen()



This patch adds a test for strlen()

string.c contains a copy of strlen() from lib/string.c

The test first tests the correctness of strlen() by comparing
the result with libc strlen(). It tests all cases of alignment.

It them tests the duration of an aligned strlen() on a 4 bytes string,
on a 16 bytes string and on a 256 bytes string.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
[mpe: Drop change log from copy of string.c]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 1bb07b59
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ EXTRA_SOURCES := ../harness.c

build_32bit = $(shell if ($(CC) $(CFLAGS) -m32 -o /dev/null memcmp.c >/dev/null 2>&1) then echo "1"; fi)

TEST_GEN_PROGS := memcmp_64
TEST_GEN_PROGS := memcmp_64 strlen

$(OUTPUT)/memcmp_64: memcmp.c
$(OUTPUT)/memcmp_64: CFLAGS += -m64 -maltivec
@@ -18,6 +18,8 @@ $(OUTPUT)/memcmp_32: CFLAGS += -m32
TEST_GEN_PROGS += memcmp_32
endif

$(OUTPUT)/strlen: strlen.c string.c

ASFLAGS = $(CFLAGS)

include ../../lib.mk
+21 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copied from linux/lib/string.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

#include <stddef.h>

/**
 * strlen - Find the length of a string
 * @s: The string to be sized
 */
size_t test_strlen(const char *s)
{
	const char *sc;

	for (sc = s; *sc != '\0'; ++sc)
		/* nothing */;
	return sc - s;
}
+127 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "utils.h"

#define SIZE 256
#define ITERATIONS 1000
#define ITERATIONS_BENCH 100000

int test_strlen(const void *s);

/* test all offsets and lengths */
static void test_one(char *s)
{
	unsigned long offset;

	for (offset = 0; offset < SIZE; offset++) {
		int x, y;
		unsigned long i;

		y = strlen(s + offset);
		x = test_strlen(s + offset);

		if (x != y) {
			printf("strlen() returned %d, should have returned %d (%p offset %ld)\n", x, y, s, offset);

			for (i = offset; i < SIZE; i++)
				printf("%02x ", s[i]);
			printf("\n");
		}
	}
}

static void bench_test(char *s)
{
	struct timespec ts_start, ts_end;
	int i;

	clock_gettime(CLOCK_MONOTONIC, &ts_start);

	for (i = 0; i < ITERATIONS_BENCH; i++)
		test_strlen(s);

	clock_gettime(CLOCK_MONOTONIC, &ts_end);

	printf("len %3.3d : time = %.6f\n", test_strlen(s), ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9);
}

static int testcase(void)
{
	char *s;
	unsigned long i;

	s = memalign(128, SIZE);
	if (!s) {
		perror("memalign");
		exit(1);
	}

	srandom(1);

	memset(s, 0, SIZE);
	for (i = 0; i < SIZE; i++) {
		char c;

		do {
			c = random() & 0x7f;
		} while (!c);
		s[i] = c;
		test_one(s);
	}

	for (i = 0; i < ITERATIONS; i++) {
		unsigned long j;

		for (j = 0; j < SIZE; j++) {
			char c;

			do {
				c = random() & 0x7f;
			} while (!c);
			s[j] = c;
		}
		for (j = 0; j < sizeof(long); j++) {
			s[SIZE - 1 - j] = 0;
			test_one(s);
		}
	}

	for (i = 0; i < SIZE; i++) {
		char c;

		do {
			c = random() & 0x7f;
		} while (!c);
		s[i] = c;
	}

	bench_test(s);

	s[16] = 0;
	bench_test(s);

	s[8] = 0;
	bench_test(s);

	s[4] = 0;
	bench_test(s);

	s[3] = 0;
	bench_test(s);

	s[2] = 0;
	bench_test(s);

	s[1] = 0;
	bench_test(s);

	return 0;
}

int main(void)
{
	return test_harness(testcase, "strlen");
}