Skip to content

Commit

Permalink
Add multi-threaded tests
Browse files Browse the repository at this point in the history
Output gets garbeled a bit, but we only care for the result which is
`Tests OK/NOP/FAIL: 50/0/0`.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
  • Loading branch information
sjaeckel committed Mar 14, 2024
1 parent a40ebda commit 887b799
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ jobs:
# Build with small stack-size
- { BUILDOPTIONS: '--with-cc=gcc --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-multilib' }
- { BUILDOPTIONS: '--with-cc=clang-10 --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 gcc-multilib' }
- { BUILDOPTIONS: '--with-cc=gcc --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE --multithread', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-multilib' }
- { BUILDOPTIONS: '--with-cc=clang-10 --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE --multithread', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 gcc-multilib' }

# Test "autotuning", the automatic evaluation and setting of the Toom-Cook cut-offs.
#- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --cflags=-DMP_16BIT --limit-valgrind --make-option=tune'
Expand Down
68 changes: 57 additions & 11 deletions demo/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2455,12 +2455,39 @@ static int test_mp_pack_unpack(void)
#define ONLY_PUBLIC_API_C
#endif

#if !defined(LTM_TEST_MULTITHREAD) || !defined(MP_SMALL_STACK_SIZE)
#define SINGLE_THREADED_C
typedef unsigned long int pthread_t;
extern int pthread_create(pthread_t *, const void *, void *(*)(void *), void *);
extern int pthread_join(pthread_t, void **);
#else
#define MULTI_THREADED_C
#include <pthread.h>
#endif

struct test_fn {
const char *name;
int (*fn)(void);
};

struct thread_info {
pthread_t thread_id;
const struct test_fn *t;
int ret;
};

static void *run(void *arg)
{
struct thread_info *tinfo = arg;

tinfo->ret = tinfo->t->fn();

return arg;
}

static int unit_tests(int argc, char **argv)
{
static const struct {
const char *name;
int (*fn)(void);
} test[] = {
static const struct test_fn test[] = {
#define T0(n) { #n, test_##n }
#define T1(n, o) { #n, MP_HAS(o) ? test_##n : NULL }
#define T2(n, o1, o2) { #n, (MP_HAS(o1) && MP_HAS(o2)) ? test_##n : NULL }
Expand Down Expand Up @@ -2522,31 +2549,50 @@ static int unit_tests(int argc, char **argv)
#undef T2
#undef T1
};
struct thread_info test_threads[sizeof(test)/sizeof(test[0])], *res;
unsigned long i, ok, fail, nop;
uint64_t t;
int j;
int j = -1;
ok = fail = nop = 0;

t = (uint64_t)time(NULL);
printf("SEED: 0x%" PRIx64 "\n\n", t);
s_mp_rand_jenkins_init(t);
mp_rand_source(s_mp_rand_jenkins);

if (MP_HAS(MULTI_THREADED)) {
printf("Multi-threading enabled\n\n");
DO(mp_warray_init(sizeof(test) / sizeof(test[0]), 1));
/* we ignore the fact that jenkings is not thread safe */
for (i = 0; i < (sizeof(test) / sizeof(test[0])); ++i) {
test_threads[i].t = &test[i];
EXPECT(pthread_create(&test_threads[i].thread_id, NULL, run, &test_threads[i]) == 0);
}
}

for (i = 0; i < (sizeof(test) / sizeof(test[0])); ++i) {
if (argc > 1) {
for (j = 1; j < argc; ++j) {
if (strstr(test[i].name, argv[j]) != NULL) {
break;
if (MP_HAS(SINGLE_THREADED)) {
if (argc > 1) {
for (j = 1; j < argc; ++j) {
if (strstr(test[i].name, argv[j]) != NULL) {
break;
}
}
if (j == argc) continue;
}
if (j == argc) continue;

if (test[i].fn)
j = test[i].fn();
} else if (MP_HAS(MULTI_THREADED)) {
EXPECT(pthread_join(test_threads[i].thread_id, (void **)&res) == 0);
j = res->ret;
}
printf("TEST %s\n", test[i].name);

if (test[i].fn == NULL) {
nop++;
printf("NOP %s\n\n", test[i].name);
} else if (test[i].fn() == EXIT_SUCCESS) {
} else if (j == EXIT_SUCCESS) {
ok++;
printf("\n");
} else {
Expand Down
37 changes: 22 additions & 15 deletions testme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ All other options will be tested with all MP_xBIT configurations.
runtime and may trigger the 30 minutes
timeout.
--multithread Run tests in multi-threaded mode (via pthread).
Godmode:
--all Choose all architectures and gcc and clang
Expand Down Expand Up @@ -128,7 +130,7 @@ _make()
echo -ne " Compile $1 $2"
suffix=$(echo ${1}${2} | tr ' ' '_')
_fixup_cflags "$1"
CC="$1" CFLAGS="$2 $TEST_CFLAGS" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log
CC="$1" CFLAGS="$2 $TEST_CFLAGS" LFLAGS="$4" LDFLAGS="$5" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log
errcnt=$(wc -l < gcc_errors_${suffix}.log)
if [[ ${errcnt} -gt 1 ]]; then
echo " failed"
Expand All @@ -148,10 +150,10 @@ _runtest()
# "make tune" will run "tune_it.sh" automatically, hence "autotune", but it cannot
# get switched off without some effort, so we just let it run twice for testing purposes
echo -e "\rRun autotune $1 $2"
_make "$1" "$2" ""
_make "$1" "$2" "" "$3" "$4"
$_timeout $TUNE_CMD > test_${suffix}.log || _die "running autotune" $?
else
_make "$1" "$2" "test"
_make "$1" "$2" "test" "$3" "$4"
echo -e "\rRun test $1 $2"
$_timeout ./test > test_${suffix}.log || _die "running tests" $?
fi
Expand All @@ -171,13 +173,13 @@ echo "MAKE_OPTIONS = \"$MAKE_OPTIONS\""
if [[ "$MAKE_OPTIONS" =~ "tune" ]]
then
echo "autotune branch"
_make "$1" "$2" ""
_make "$1" "$2" "" "$3" "$4"
# The shell used for /bin/sh is DASH 0.5.7-4ubuntu1 on the author's machine which fails valgrind, so
# we just run on instance of etc/tune with the same options as in etc/tune_it.sh
echo -e "\rRun etc/tune $1 $2 once inside valgrind"
$_timeout $VALGRIND_BIN $VALGRIND_OPTS $TUNE_CMD > test_${suffix}.log || _die "running etc/tune" $?
else
_make "$1" "$2" "test"
_make "$1" "$2" "test" "$3" "$4"
echo -e "\rRun test $1 $2 inside valgrind"
$_timeout $VALGRIND_BIN $VALGRIND_OPTS ./test > test_${suffix}.log || _die "running tests" $?
fi
Expand Down Expand Up @@ -301,6 +303,11 @@ do
--symbols)
CHECK_SYMBOLS="1"
;;
--multithread)
CFLAGS="$CFLAGS -DLTM_TEST_MULTITHREAD"
LFLAGS="$LFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
;;
--all)
COMPILERS="gcc clang"
ARCHFLAGS="-m64 -m32 -mx32"
Expand Down Expand Up @@ -376,9 +383,9 @@ then
_banner "$CC"
if [[ "$VALGRIND_BIN" != "" ]]
then
_runvalgrind "$CC" ""
_runvalgrind "$CC" "" "$LFLAGS" "$LDFLAGS"
else
_runtest "$CC" ""
_runtest "$CC" "" "$LFLAGS" "$LDFLAGS"
fi
_exit
fi
Expand All @@ -398,9 +405,9 @@ _banner
if [[ "$TEST_VS_MTEST" != "" ]]
then
make clean > /dev/null
_make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent"
_make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent" "$LFLAGS" "$LDFLAGS"
echo
_make "gcc" "$MTEST_RAND" "mtest"
_make "gcc" "$MTEST_RAND" "mtest" "$LFLAGS" "$LDFLAGS"
echo
echo "Run test vs. mtest for $TEST_VS_MTEST iterations"
_timeout=""
Expand Down Expand Up @@ -429,15 +436,15 @@ do
fi
if [[ "$VALGRIND_BIN" != "" ]]
then
_runvalgrind "$i" "$a $CFLAGS"
_runvalgrind "$i" "$a $CFLAGS" "$LFLAGS" "$LDFLAGS"
[ "$WITH_LOW_MP" != "1" ] && continue
_runvalgrind "$i" "$a -DMP_16BIT $CFLAGS"
_runvalgrind "$i" "$a -DMP_32BIT $CFLAGS"
_runvalgrind "$i" "$a -DMP_16BIT $CFLAGS" "$LFLAGS" "$LDFLAGS"
_runvalgrind "$i" "$a -DMP_32BIT $CFLAGS" "$LFLAGS" "$LDFLAGS"
else
_runtest "$i" "$a $CFLAGS"
_runtest "$i" "$a $CFLAGS" "$LFLAGS" "$LDFLAGS"
[ "$WITH_LOW_MP" != "1" ] && continue
_runtest "$i" "$a -DMP_16BIT $CFLAGS"
_runtest "$i" "$a -DMP_32BIT $CFLAGS"
_runtest "$i" "$a -DMP_16BIT $CFLAGS" "$LFLAGS" "$LDFLAGS"
_runtest "$i" "$a -DMP_32BIT $CFLAGS" "$LFLAGS" "$LDFLAGS"
fi
done
done
Expand Down

0 comments on commit 887b799

Please sign in to comment.