diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/plans/all.fmf b/plans/all.fmf new file mode 100644 index 0000000..228c87e --- /dev/null +++ b/plans/all.fmf @@ -0,0 +1,23 @@ +summary: Run gating tests +discover: + how: fmf + dist-git-source: true + dist-git-type: centos +prepare: + - how: install + package: + - dnf-plugins-core + - https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + - how: shell + script: /usr/bin/crb enable + - how: install + package: + - jq + - jq-devel + - gcc + - wget + - how: shell + script: dnf config-manager --disable epel* + +execute: + how: tmt diff --git a/tests/jqtests.sh b/tests/jqtests.sh deleted file mode 100755 index 525e19d..0000000 --- a/tests/jqtests.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -die () { - echo "$1" >&2 - exit 1 -} - -# link jq binary. This make the tests to use -# installed binary instead of compiled one -cd source || die "missing source directory" -rm -f jq tests/*.log 2>/dev/null -ln -s /usr/bin/jq || die "failed to link jq binary" - -# run the tests -# List of tests is taken from Makefile -TESTS="tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test" - -for t in $TESTS; do - echo -n "Test $t ... " - ./${t} >"${t}.log" 2>&1 - RET=$? - if [ $RET = 0 ]; then - echo "ok" - else - echo "failed" - cat "${t}.log" - die "Test ${t} failed" - fi -done -exit 0 diff --git a/tests/performance/jqspeed.sh b/tests/performance/jqspeed.sh new file mode 100755 index 0000000..9840c2d --- /dev/null +++ b/tests/performance/jqspeed.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +export LC_ALL=C + +stress_jq() { + `which time` -p -f '%e\n' bash -c 'for i in `seq 1 1000` ; do echo '"'"'{"foo":"bar"}'"'"' | jq '"'"'has("bar")'"'"' > /dev/null ; done' 2>&1 | cut -d. -f1 +} + +FAIL=0 +TIME=`stress_jq` +echo -n "Test jqspeed ... " +if [ $TIME -gt 8 ] ; then + echo "failed" + FAIL=1 +else + echo "ok" +fi + +echo "Runtime: ${TIME}s " +exit $FAIL diff --git a/tests/performance/main.fmf b/tests/performance/main.fmf new file mode 100644 index 0000000..b1a8e27 --- /dev/null +++ b/tests/performance/main.fmf @@ -0,0 +1,6 @@ +summary: Run jq performance/speed test +require: + - jq + - which + - time +test: ./jqspeed.sh diff --git a/tests/pkgs-yum4.yml b/tests/pkgs-yum4.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/provision.fmf b/tests/provision.fmf new file mode 100644 index 0000000..62a6eba --- /dev/null +++ b/tests/provision.fmf @@ -0,0 +1,5 @@ +--- + +standard-inventory-qcow2: + qemu: + m: 2G diff --git a/tests/segfault/jqsegfault.sh b/tests/segfault/jqsegfault.sh new file mode 100755 index 0000000..96369c9 --- /dev/null +++ b/tests/segfault/jqsegfault.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +FAIL=0 + +# Test for segfault in multithreaded environment +gcc -o test_segfault test_segfault_with_multithreaded_env.c -lpthread -ljq && \ +./test_segfault +RET=$? + +echo -n "Test jqsegfault ... " + +if [ $RET != 0 ]; then + echo "failed" + FAIL=1 +else + echo "ok" +fi + +exit $FAIL diff --git a/tests/segfault/main.fmf b/tests/segfault/main.fmf new file mode 100644 index 0000000..9b2850d --- /dev/null +++ b/tests/segfault/main.fmf @@ -0,0 +1,8 @@ +summary: Run segfault threads test +require: + - wget + - dnf-utils + - gcc + - jq + - jq-devel +test: ./jqsegfault.sh diff --git a/tests/segfault/test_segfault_with_multithreaded_env.c b/tests/segfault/test_segfault_with_multithreaded_env.c new file mode 100644 index 0000000..c8e2622 --- /dev/null +++ b/tests/segfault/test_segfault_with_multithreaded_env.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +int my_jq_parse(jq_state *jq, struct jv_parser *parser) +{ + int rv = 0; + jv value; + + value = jv_parser_next(parser); + while (jv_is_valid(value)) { + jq_start(jq, value, 0); + jv result; + + while (jv_is_valid(result = jq_next(jq))) { + jv dumped = jv_dump_string(result, 0); + const char *str = jv_string_value(dumped); + printf("dumped: %s\n", str); + } + + jv_free(result); + value = jv_parser_next(parser); + } + + if (jv_invalid_has_msg(jv_copy(value))) { + jv msg = jv_invalid_get_msg(value); + printf("invalid: %s\n", jv_string_value(msg)); + jv_free(msg); + rv = 1; + } else { + jv_free(value); + } + + return rv; +} + +void *run(void *not_used) { + int rv; + jq_state *jq; + const char *prg = ".data"; + + jq = jq_init(); + printf("jq_init jq: %p prg: %s\n", jq, prg); + if (jq_compile(jq, prg) == 0) { + jq_teardown(&jq); + return NULL; + } + printf("compiled\n"); + + struct jv_parser *parser = jv_parser_new(0); + const char *buf = "{ \"data\": 1 }"; + jv_parser_set_buf(parser, buf, strlen(buf), 0); + rv = my_jq_parse(jq, parser); + if (rv != 0) { + printf("my_jq_parse failed!\n"); + } + + jv_parser_free(parser); + jq_teardown(&jq); + return NULL; +} + +#define THREADS 2 +/* calling run() twice works fine */ +/* calling them in threads causes core-dump */ +int main (int argc, char *argv[]) +{ + pthread_t threads[THREADS]; + int createerror; + int a; + + memset(&threads, 0, sizeof(threads)); + for (a = 0; a < THREADS; ++a) { + // sleep(1); // < if you want to run threads sequentionally + createerror = pthread_create(&threads[a], NULL, run, NULL); + if (createerror) { + printf("create thread error %d\n", a); + } + } + for(a = 0; a < THREADS; ++a) { + if (threads[a] != 0) { + pthread_join(threads[a], NULL); + } + } + + return 0; +} diff --git a/tests/tests.yml b/tests/tests.yml index efb1b65..f2f5ccc 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -10,10 +10,18 @@ - classic required_packages: - jq + - gcc + - wget + - jq-devel - valgrind - rubygem-rake tests: - - jqtests: - dir: . + - upstream: + dir: upstream run: ./jqtests.sh - save-files: ["source/tests/*.log"] + - segfault: + dir: segfault + run: ./jqsegfault.sh + - performance: + dir: performance + run: ./jqspeed.sh diff --git a/tests/upstream/jqtests.sh b/tests/upstream/jqtests.sh new file mode 100755 index 0000000..3c859f5 --- /dev/null +++ b/tests/upstream/jqtests.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +die () { + echo "$1" >&2 + exit 1 +} + +# If source not found, download it with dnf +if [ ! -d ./source ]; then + # Extract source from srpm + dnf download --source jq && \ + rpm2cpio jq*.rpm|cpio -id && \ + mkdir source && \ + tar -zxf jq-*.tar.gz -C source --strip-components=1 + if [ $? != 0 ]; then + echo "Failed to download upstream tests" + exit 1 + fi +fi + +pushd ./source || die "missing source directory" +rm -f jq tests/*.log 2>/dev/null +ln -s /usr/bin/jq || die "failed to link jq binary" + +FAIL=0 + +# run the tests +# List of tests is taken from Makefile +TESTS="tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test" + +for t in $TESTS; do + echo -n "Test $t ... " + ./${t} >"${t}.log" 2>&1 + RET=$? + if [ $RET = 0 ]; then + echo "ok" + else + echo "failed" + echo "-------------------- ${t}.log start -----------------------------" + cat "${t}.log" + echo "-------------------- ${t}.log end -----------------------------" + FAIL=1 + fi +done + +popd # exit SOURCE_DIR + +exit $FAIL diff --git a/tests/upstream/main.fmf b/tests/upstream/main.fmf new file mode 100644 index 0000000..bed862c --- /dev/null +++ b/tests/upstream/main.fmf @@ -0,0 +1,11 @@ +summary: Run jq gating tests +require: + - wget + - dnf-utils + - gcc + - jq + - jq-devel + - valgrind + - diffutils +test: ./jqtests.sh +duration: 30m