Message ID | 20230808141739.3110740-11-fufuyqqqqqq@gmail.com |
---|---|
State | New |
Headers | show |
Series | Native Library Calls | expand |
Yeqi Fu <fufuyqqqqqq@gmail.com> writes: > Introduce a new test for native calls to ensure their functionality. > The process involves cross-compiling the test cases, building them > as dynamically linked binaries, and running these binaries which > necessitates the addition of the appropriate interpreter prefix. > > Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com> > --- > tests/tcg/multiarch/Makefile.target | 17 +++++ > tests/tcg/multiarch/native/nativecall.c | 98 +++++++++++++++++++++++++ > 2 files changed, 115 insertions(+) > create mode 100644 tests/tcg/multiarch/native/nativecall.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index 43bddeaf21..5231df34ba 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -138,5 +138,22 @@ run-plugin-semiconsole-with-%: > TESTS += semihosting semiconsole > endif > > +nativecall: native/nativecall.c > + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) > + > +ifneq ($(LD_PREFIX),) > +ifneq ($(wildcard $(LIBNATIVE)),) > +run-nativecall: nativecall > + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no native library found") > +endif > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no elf interpreter prefix found") > +endif > +EXTRA_RUNS += run-nativecall > + > # Update TESTS > TESTS += $(MULTIARCH_TESTS) > diff --git a/tests/tcg/multiarch/native/nativecall.c b/tests/tcg/multiarch/native/nativecall.c > new file mode 100644 > index 0000000000..d3f6f49ed0 > --- /dev/null > +++ b/tests/tcg/multiarch/native/nativecall.c > @@ -0,0 +1,98 @@ > +#include <assert.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/mman.h> > + > +void compare_memory(const void *a, const void *b, size_t n) > +{ > + const unsigned char *p1 = a; > + const unsigned char *p2 = b; > + for (size_t i = 0; i < n; i++) { > + assert(p1[i] == p2[i]); > + } > +} > + > +void test_memcpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + memcpy(dest, src, 13); > + compare_memory(dest, src, 13); > +} As discussed earlier expanding the range of sizes involved will help get more coverage especially as routines are usually optimised to handle various alignments and block sizes. You can also use a --enable-gcov build and check how much coverage of your new code is hit by the test cases. > + > +void test_strncpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + strncpy(dest, src, 13); > + compare_memory(dest, src, 13); > +} > + > +void test_strcpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + strcpy(dest, src); > + compare_memory(dest, src, 13); > +} > + > +void test_strcat() > +{ > + char src[20] = "Hello, "; > + char dst[] = "world!"; > + char str[] = "Hello, world!"; > + strcat(src, dest); copy and paste fail here (dst/dest) means it doesn't compile. It's always good practice to make sure your tree passes a make check (or at least check-tcg in the user-mode case) to ensure no silly bugs are present. You can also create a gitlab account and take advantage of the CI. See this run for example: https://gitlab.com/stsquad/qemu/-/pipelines/959899240/failures > + compare_memory(src, str, 13); > +} > + > +void test_memcmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(memcmp(str1, str2, 3) == 0); > + assert(memcmp(str1, str3, 3) != 0); > +} > + > +void test_strncmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(strncmp(str1, str2, 2) == 0); > + assert(strncmp(str1, str3, 2) != 0); > +} > + > +void test_strcmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(strcmp(str1, str2) == 0); > + assert(strcmp(str1, str3) != 0); > +} > + > +void test_memset() > +{ > + char buffer[10]; > + memset(buffer, 'A', 10); > + int i; > + for (i = 0; i < 10; i++) { > + assert(buffer[i] == 'A'); > + } > +} > + > +int main() > +{ > + test_memset(); > + test_memcpy(); > + test_strncpy(); > + test_memcmp(); > + test_strncmp(); > + test_strcpy(); > + test_strcmp(); > + test_strcat(); > + > + return EXIT_SUCCESS; > +}
Yeqi Fu <fufuyqqqqqq@gmail.com> writes: > Introduce a new test for native calls to ensure their functionality. > The process involves cross-compiling the test cases, building them > as dynamically linked binaries, and running these binaries which > necessitates the addition of the appropriate interpreter prefix. > > Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com> > --- > tests/tcg/multiarch/Makefile.target | 17 +++++ > tests/tcg/multiarch/native/nativecall.c | 98 > +++++++++++++++++++++++++ Another thing I missed is putting the test in a subdir misses out the common logic: # Set search path for all sources VPATH += $(MULTIARCH_SRC) MULTIARCH_SRCS = $(notdir $(wildcard $(MULTIARCH_SRC)/*.c)) ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET)) VPATH += $(MULTIARCH_SRC)/linux MULTIARCH_SRCS += $(notdir $(wildcard $(MULTIARCH_SRC)/linux/*.c)) endif MULTIARCH_TESTS = $(MULTIARCH_SRCS:.c=) which as a result means things like: make build-tcg don't automatically build the tests (although it does get picked up at runtime). You can either move it out of the subdir or do something similar that the arm-compat-semi does, expand VPATH and use TESTS: modified tests/tcg/multiarch/Makefile.target @@ -138,13 +138,18 @@ run-plugin-semiconsole-with-%: TESTS += semihosting semiconsole endif -nativecall: native/nativecall.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) - ifneq ($(LD_PREFIX),) ifneq ($(wildcard $(LIBNATIVE)),) +VPATH += $(MULTIARCH_SRC)/native + +nativecall: nativecall.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) + run-nativecall: nativecall - $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass + $(LIBNATIVE) $<, "nativecall") + +TESTS += nativecall else run-nativecall: nativecall $(call skip-test, $<, "no native library found") @@ -153,7 +158,6 @@ else run-nativecall: nativecall $(call skip-test, $<, "no elf interpreter prefix found") endif -EXTRA_RUNS += run-nativecall > 2 files changed, 115 insertions(+) > create mode 100644 tests/tcg/multiarch/native/nativecall.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index 43bddeaf21..5231df34ba 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -138,5 +138,22 @@ run-plugin-semiconsole-with-%: > TESTS += semihosting semiconsole > endif > > +nativecall: native/nativecall.c > + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) > + > +ifneq ($(LD_PREFIX),) > +ifneq ($(wildcard $(LIBNATIVE)),) > +run-nativecall: nativecall > + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no native library found") > +endif > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no elf interpreter prefix found") > +endif > +EXTRA_RUNS += run-nativecall > + > # Update TESTS > TESTS += $(MULTIARCH_TESTS) > diff --git a/tests/tcg/multiarch/native/nativecall.c b/tests/tcg/multiarch/native/nativecall.c > new file mode 100644 > index 0000000000..d3f6f49ed0 > --- /dev/null > +++ b/tests/tcg/multiarch/native/nativecall.c > @@ -0,0 +1,98 @@ > +#include <assert.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/mman.h> > + > +void compare_memory(const void *a, const void *b, size_t n) > +{ > + const unsigned char *p1 = a; > + const unsigned char *p2 = b; > + for (size_t i = 0; i < n; i++) { > + assert(p1[i] == p2[i]); > + } > +} > + > +void test_memcpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + memcpy(dest, src, 13); > + compare_memory(dest, src, 13); > +} > + > +void test_strncpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + strncpy(dest, src, 13); > + compare_memory(dest, src, 13); > +} > + > +void test_strcpy() > +{ > + char src[] = "Hello, world!"; > + char dest[20]; > + strcpy(dest, src); > + compare_memory(dest, src, 13); > +} > + > +void test_strcat() > +{ > + char src[20] = "Hello, "; > + char dst[] = "world!"; > + char str[] = "Hello, world!"; > + strcat(src, dest); > + compare_memory(src, str, 13); > +} > + > +void test_memcmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(memcmp(str1, str2, 3) == 0); > + assert(memcmp(str1, str3, 3) != 0); > +} > + > +void test_strncmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(strncmp(str1, str2, 2) == 0); > + assert(strncmp(str1, str3, 2) != 0); > +} > + > +void test_strcmp() > +{ > + char str1[] = "abc"; > + char str2[] = "abc"; > + char str3[] = "def"; > + assert(strcmp(str1, str2) == 0); > + assert(strcmp(str1, str3) != 0); > +} > + > +void test_memset() > +{ > + char buffer[10]; > + memset(buffer, 'A', 10); > + int i; > + for (i = 0; i < 10; i++) { > + assert(buffer[i] == 'A'); > + } > +} > + > +int main() > +{ > + test_memset(); > + test_memcpy(); > + test_strncpy(); > + test_memcmp(); > + test_strncmp(); > + test_strcpy(); > + test_strcmp(); > + test_strcat(); > + > + return EXIT_SUCCESS; > +}
Yeqi Fu <fufuyqqqqqq@gmail.com> writes: > Introduce a new test for native calls to ensure their functionality. > The process involves cross-compiling the test cases, building them > as dynamically linked binaries, and running these binaries which > necessitates the addition of the appropriate interpreter prefix. > > Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com> > --- > tests/tcg/multiarch/Makefile.target | 17 +++++ > tests/tcg/multiarch/native/nativecall.c | 98 +++++++++++++++++++++++++ > 2 files changed, 115 insertions(+) > create mode 100644 tests/tcg/multiarch/native/nativecall.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index 43bddeaf21..5231df34ba 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -138,5 +138,22 @@ run-plugin-semiconsole-with-%: > TESTS += semihosting semiconsole > endif > > +nativecall: native/nativecall.c > + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) > + > +ifneq ($(LD_PREFIX),) > +ifneq ($(wildcard $(LIBNATIVE)),) > +run-nativecall: nativecall > + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no native library found") > +endif > +else > +run-nativecall: nativecall > + $(call skip-test, $<, "no elf interpreter prefix found") > +endif > +EXTRA_RUNS += run-nativecall > + Or indeed just expand VPATH and use TESTS instead of EXTRA_RUNS (which is for additional configurations of tests): modified tests/tcg/multiarch/Makefile.target @@ -138,13 +138,18 @@ run-plugin-semiconsole-with-%: TESTS += semihosting semiconsole endif -nativecall: native/nativecall.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) - ifneq ($(LD_PREFIX),) ifneq ($(wildcard $(LIBNATIVE)),) +VPATH += $(MULTIARCH_SRC)/native + +nativecall: nativecall.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) + run-nativecall: nativecall - $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass + $(LIBNATIVE) $<, "nativecall") + +TESTS += nativecall else run-nativecall: nativecall $(call skip-test, $<, "no native library found") @@ -153,7 +158,6 @@ else run-nativecall: nativecall $(call skip-test, $<, "no elf interpreter prefix found") endif -EXTRA_RUNS += run-nativecall
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 43bddeaf21..5231df34ba 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -138,5 +138,22 @@ run-plugin-semiconsole-with-%: TESTS += semihosting semiconsole endif +nativecall: native/nativecall.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out -static,$(LDFLAGS)) + +ifneq ($(LD_PREFIX),) +ifneq ($(wildcard $(LIBNATIVE)),) +run-nativecall: nativecall + $(call run-test,$<, $(QEMU) -L $(LD_PREFIX) --native-bypass $(LIBNATIVE) $<, "nativecall") +else +run-nativecall: nativecall + $(call skip-test, $<, "no native library found") +endif +else +run-nativecall: nativecall + $(call skip-test, $<, "no elf interpreter prefix found") +endif +EXTRA_RUNS += run-nativecall + # Update TESTS TESTS += $(MULTIARCH_TESTS) diff --git a/tests/tcg/multiarch/native/nativecall.c b/tests/tcg/multiarch/native/nativecall.c new file mode 100644 index 0000000000..d3f6f49ed0 --- /dev/null +++ b/tests/tcg/multiarch/native/nativecall.c @@ -0,0 +1,98 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> + +void compare_memory(const void *a, const void *b, size_t n) +{ + const unsigned char *p1 = a; + const unsigned char *p2 = b; + for (size_t i = 0; i < n; i++) { + assert(p1[i] == p2[i]); + } +} + +void test_memcpy() +{ + char src[] = "Hello, world!"; + char dest[20]; + memcpy(dest, src, 13); + compare_memory(dest, src, 13); +} + +void test_strncpy() +{ + char src[] = "Hello, world!"; + char dest[20]; + strncpy(dest, src, 13); + compare_memory(dest, src, 13); +} + +void test_strcpy() +{ + char src[] = "Hello, world!"; + char dest[20]; + strcpy(dest, src); + compare_memory(dest, src, 13); +} + +void test_strcat() +{ + char src[20] = "Hello, "; + char dst[] = "world!"; + char str[] = "Hello, world!"; + strcat(src, dest); + compare_memory(src, str, 13); +} + +void test_memcmp() +{ + char str1[] = "abc"; + char str2[] = "abc"; + char str3[] = "def"; + assert(memcmp(str1, str2, 3) == 0); + assert(memcmp(str1, str3, 3) != 0); +} + +void test_strncmp() +{ + char str1[] = "abc"; + char str2[] = "abc"; + char str3[] = "def"; + assert(strncmp(str1, str2, 2) == 0); + assert(strncmp(str1, str3, 2) != 0); +} + +void test_strcmp() +{ + char str1[] = "abc"; + char str2[] = "abc"; + char str3[] = "def"; + assert(strcmp(str1, str2) == 0); + assert(strcmp(str1, str3) != 0); +} + +void test_memset() +{ + char buffer[10]; + memset(buffer, 'A', 10); + int i; + for (i = 0; i < 10; i++) { + assert(buffer[i] == 'A'); + } +} + +int main() +{ + test_memset(); + test_memcpy(); + test_strncpy(); + test_memcmp(); + test_strncmp(); + test_strcpy(); + test_strcmp(); + test_strcat(); + + return EXIT_SUCCESS; +}
Introduce a new test for native calls to ensure their functionality. The process involves cross-compiling the test cases, building them as dynamically linked binaries, and running these binaries which necessitates the addition of the appropriate interpreter prefix. Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com> --- tests/tcg/multiarch/Makefile.target | 17 +++++ tests/tcg/multiarch/native/nativecall.c | 98 +++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 tests/tcg/multiarch/native/nativecall.c