Add a test for native calls to verify the functionality of native
functions. This requires cross-compiling test cases and building them
as dynamically linked binaries. Also, introduce necessary system
libraries in QEMU.

Signed-off-by: Yeqi Fu <fufuyqqq...@gmail.com>
---
 tests/tcg/multiarch/Makefile.target      |   9 +-
 tests/tcg/multiarch/native/nativecalls.c | 103 +++++++++++++++++++++++
 2 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/multiarch/native/nativecalls.c

diff --git a/tests/tcg/multiarch/Makefile.target 
b/tests/tcg/multiarch/Makefile.target
index 373db69648..c4ea7117c2 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -128,7 +128,14 @@ run-semiconsole: semiconsole
 run-plugin-semiconsole-with-%:
        $(call skip-test, $<, "MANUAL ONLY")
 
-TESTS += semihosting semiconsole
+nativecalls: native/nativecalls.c
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(filter-out 
-static,$(LDFLAGS))
+
+run-nativecalls: nativecalls
+       $(call run-test,$<, $(QEMU) -L /usr/$(subst -gcc,,$(CC)) 
--native-bypass $(SRC_PATH)/build/common-user/native/$(TARGET)/libnative.so $<, 
\
+       "native call")
+
+TESTS += semihosting semiconsole nativecalls
 endif
 
 # Update TESTS
diff --git a/tests/tcg/multiarch/native/nativecalls.c 
b/tests/tcg/multiarch/native/nativecalls.c
new file mode 100644
index 0000000000..2d4ddb3a8e
--- /dev/null
+++ b/tests/tcg/multiarch/native/nativecalls.c
@@ -0,0 +1,103 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.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_memcmp()
+{
+    char str1[] = "abc";
+    char str2[] = "abc";
+    char str3[] = "def";
+    assert(memcmp(str1, str2, 3) == 0);
+    assert(memcmp(str1, str3, 3) != 0);
+}
+
+void test_memset()
+{
+    char buffer[10];
+    memset(buffer, 'A', 10);
+    int i;
+    for (i = 0; i < 10; i++) {
+        assert(buffer[i] == 'A');
+    }
+}
+
+void test_strncpy()
+{
+    char src[] = "Hello, world!";
+    char dest[20];
+    strncpy(dest, src, 13);
+    compare_memory(dest, src, 13);
+}
+
+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_strcpy()
+{
+    char src[] = "Hello, world!";
+    char dest[20];
+    strcpy(dest, src);
+    compare_memory(dest, src, 13);
+}
+
+void test_strcmp()
+{
+    char str1[] = "abc";
+    char str2[] = "abc";
+    char str3[] = "def";
+    assert(strcmp(str1, str2) == 0);
+    assert(strcmp(str1, str3) != 0);
+}
+
+void test_memcpy_bad_addr()
+{
+    char src[] = "Hello, world!";
+    char *dst = (char *)0x1;
+    memcpy(dst, src, 13);
+}
+
+void test_memset_bad_addr()
+{
+    char *dst = (char *)0x1;
+    memset(dst, 'A', 10);
+}
+
+int main()
+{
+    test_memcpy();
+    test_memcmp();
+    test_memset();
+    test_strncpy();
+    test_strncmp();
+    test_strcpy();
+    test_strcmp();
+
+    test_memcpy_bad_addr();
+    test_memset_bad_addr();
+
+    return EXIT_SUCCESS;
+}
-- 
2.34.1


Reply via email to