aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-11-02 15:28:23 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-11-02 15:28:23 +0200
commitd127146846f4d6561e15000d1469b715dafdb627 (patch)
tree2ee7d7512023df0dc25f0bd51da1c378ebb1a400 /tests
parent4ce6aa975be40286465cd9ac6a669ff5a95fe5a1 (diff)
downloadkmi-d127146846f4d6561e15000d1469b715dafdb627.tar.gz
kmi-d127146846f4d6561e15000d1469b715dafdb627.zip
initial exec support
Diffstat (limited to 'tests')
-rw-r--r--tests/common/cpio.h99
-rw-r--r--tests/common/printf.h6
-rw-r--r--tests/common/start.h3
-rw-r--r--tests/common/string.c510
-rw-r--r--tests/common/string.h26
-rw-r--r--tests/dangling_shmem/source.mk3
-rw-r--r--tests/exec/exec.c16
-rw-r--r--tests/exec/init.c38
-rw-r--r--tests/exec/source.mk1
-rw-r--r--tests/fork/source.mk2
-rwxr-xr-xtests/scripts/gen-prog32
-rwxr-xr-xtests/scripts/gen-simple25
-rw-r--r--tests/scripts/makefile8
-rw-r--r--tests/shmem/source.mk3
14 files changed, 725 insertions, 47 deletions
diff --git a/tests/common/cpio.h b/tests/common/cpio.h
new file mode 100644
index 0000000..708ce18
--- /dev/null
+++ b/tests/common/cpio.h
@@ -0,0 +1,99 @@
+#include <kmi/utils.h>
+
+/** GNU cpio, POSIX 'newc' format header. */
+struct __packed cpio_header {
+ /** Magic bytes. */
+ char c_magic[6];
+
+ /** File inode. */
+ char c_ino[8];
+
+ /** File type and permissions. */
+ char c_mode[8];
+
+ /** User ID. */
+ char c_uid[8];
+
+ /** Group ID. */
+ char c_gid[8];
+
+ /** Number of links to this file. */
+ char c_nlink[8];
+
+ /** Modification time. */
+ char c_mtime[8];
+
+ /** Size of file. */
+ char c_filesize[8];
+
+ /** Device major. */
+ char c_devmajor[8];
+
+ /** Device minor. */
+ char c_devminor[8];
+
+ /** Block device major. */
+ char c_rdevmajor[8];
+
+ /** Block device minor. */
+ char c_rdevminor[8];
+
+ /** Length of filename. */
+ char c_namesize[8];
+
+ /** CRC check. */
+ char c_check[8];
+};
+
+/**
+ * Get next file in archive.
+ * Does not check for out of bounds.
+ *
+ * @param cp Pointer to current file header.
+ * @return Pointer to next file header.
+ */
+static inline struct cpio_header *cpio_next_entry(struct cpio_header *cp)
+{
+ size_t blen = align_up(sizeof(struct cpio_header)
+ + convnum(cp->c_namesize, 8, 16), 4);
+ size_t tlen = align_up(convnum(cp->c_filesize, 8, 16), 4);
+
+ return (struct cpio_header *)(((char *)cp) + blen + tlen);
+}
+
+/**
+ * Get file with name in archive.
+ *
+ * @param c Pointer to initrd.
+ * @param fname Filename to look for.
+ * @param fname_len Length of filename.
+ * @return Pointer to corresponding file header if found, \c NULL otherwise.
+ */
+static inline struct cpio_header *cpio_find_file(const char *c,
+ const char *fname,
+ size_t fname_len)
+{
+ struct cpio_header *cp = (struct cpio_header *)c;
+ for (; cp; cp = cpio_next_entry(cp)) {
+ size_t namelen = convnum(cp->c_namesize, 8, 16);
+ if (namelen == 0)
+ return NULL;
+
+ if (namelen < fname_len)
+ continue;
+
+
+ char *name = (char *)(cp + 1);
+ if (strcmp(name, "TRAILER!!!") == 0)
+ return NULL;
+
+ if (fname[0] != '/')
+ name += namelen - (fname_len + 1); /* match ending */
+
+ if (strncmp(name, fname, fname_len) == 0)
+ return cp;
+ }
+
+ printf("???\n");
+ return NULL;
+}
diff --git a/tests/common/printf.h b/tests/common/printf.h
index b6e50e5..e1b3b43 100644
--- a/tests/common/printf.h
+++ b/tests/common/printf.h
@@ -1,8 +1,8 @@
-#ifndef KMI_PRINTF_H
-#define KMI_PRINTF_H
+#ifndef KMI_TESTS__PRINTF_H
+#define KMI_TESTS__PRINTF_H
#include <kmi/attrs.h>
int printf(const char *fmt, ...) __printf;
-#endif /* KMI_PRINTF_H */
+#endif /* KMI_TESTS_PRINTF_H */
diff --git a/tests/common/start.h b/tests/common/start.h
index 3a49686..923d9ab 100644
--- a/tests/common/start.h
+++ b/tests/common/start.h
@@ -1,7 +1,8 @@
#ifndef KMI_START_H
#define KMI_START_H
-#define UNUSED(x) (void)x
+#include <kmi/utils.h>
+
#define START(pid, tid, d0, d1, d2, d3)\
void _start(sys_arg_t pid, sys_arg_t tid,\
sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
diff --git a/tests/common/string.c b/tests/common/string.c
new file mode 100644
index 0000000..e1519b0
--- /dev/null
+++ b/tests/common/string.c
@@ -0,0 +1,510 @@
+/* copied straight from the kernel */
+#include <common/string.h>
+#include <kmi/utils.h>
+#include <kmi/types.h>
+
+char *strcpy(char * restrict dst, const char * restrict src)
+{
+ const char *s1 = src;
+ char *s2 = dst;
+
+ while (*s1)
+ *(s2++) = *(s1++);
+
+ return dst;
+}
+
+char *strncpy(char * restrict dst, const char * restrict src, size_t num)
+{
+ const char *s1 = src;
+ char *s2 = dst;
+
+ /* copy s1 into s2 */
+ while (num-- && *s1)
+ *(s2++) = *(s1++);
+
+ /* the previous loop always overshoots by one */
+ num++;
+
+ /* pad with zeroes if num is not yet zero */
+ while (num--)
+ *(s2++) = 0;
+
+ return dst;
+}
+
+char *strcat(char * restrict dst, const char * restrict src)
+{
+ const char *s1 = src;
+ size_t l1 = strlen(s1);
+ char *s2 = dst + l1;
+
+ while (*s1)
+ *(s2++) = *(s1++);
+
+ /* append null character */
+ *s2 = 0;
+
+ return dst;
+}
+
+char *strncat(char * restrict dst, const char * restrict src, size_t num)
+{
+ const char *s1 = src;
+ size_t l1 = strlen(s1);
+ char *s2 = dst + l1;
+
+ while (num-- && *s1)
+ *(s2++) = *(s1++);
+
+ /* append null character */
+ *s2 = 0;
+
+ return dst;
+}
+
+int strcmp(const char *str1, const char *str2)
+{
+ const char *s1 = (const char *)str1;
+ const char *s2 = (const char *)str2;
+
+ while ((*(s1++) == *(s2++)) && *s1 && *s2)
+ ;
+
+ return (int)(s1[-1] - s2[-1]);
+}
+
+int strncmp(const char *str1, const char *str2, size_t num)
+{
+ const char *s1 = (const char *)str1;
+ const char *s2 = (const char *)str2;
+
+ while ((*(s1++) == *(s2++)) && *s1 && *s2 && --num)
+ ;
+
+ return (int)(s1[-1] - s2[-1]);
+}
+
+char *strchr(const char *str, int chr)
+{
+ const char *s1 = str;
+ ssize_t num = strlen(s1);
+
+ while (num-- && *(s1++) != chr)
+ ;
+
+ if (num < 0)
+ return 0;
+
+ return (char *)(s1 - 1);
+}
+
+char *strtok(char * restrict str, const char * restrict delims)
+{
+ static char *cont = 0;
+ const char *s1 = str;
+
+ if (!s1)
+ s1 = cont;
+
+ if (!s1)
+ return 0;
+
+ s1 = strpbrk(s1, delims);
+
+ if (!s1)
+ cont = 0;
+ else
+ cont = (char *)s1 + 1;
+
+ return (char *)s1;
+}
+
+/* should probably test out these functions somehwere, blergh */
+char *strstr(const char *str1, const char *str2)
+{
+ /* boyer-moore-horspool */
+ char table[256] = { 0 };
+ size_t sl = strlen(str1);
+ size_t pl = strlen(str2);
+
+ const unsigned char *s1 = (const unsigned char *)str1;
+ const unsigned char *haystack = (const unsigned char *)s1;
+ const unsigned char *needle = (const unsigned char *)str2;
+
+ for (size_t i = 0; i < 256; ++i)
+ table[i] = pl;
+
+ /* generate deltas */
+ for (size_t i = 0; i < pl - 1; ++i)
+ table[needle[i]] = pl - i - 1;
+
+ size_t skip = 0;
+ while (sl - skip >= pl) {
+ s1 = &haystack[skip];
+
+ if (!memcmp(s1, needle, pl))
+ return (char *)s1;
+
+ skip += table[haystack[skip + pl - 1]];
+ }
+
+ return 0;
+}
+
+char *strrchr(const char *str, int chr)
+{
+ ssize_t num = strlen(str);
+ const char *s1 = (str + num) - 1;
+
+ while (num-- && *(s1--) != chr)
+ ;
+
+ if (num < 0)
+ return 0;
+
+ return (char *)(s1 + 1);
+}
+
+char *strpbrk(const char *str1, const char *str2)
+{
+ size_t i = strcspn(str1, str2);
+
+ if (!i)
+ return 0;
+
+ return (char *)(str1 + i);
+}
+
+size_t strcspn(const char *str1, const char *str2)
+{
+ char table[256] = { 0 };
+ const unsigned char *s1 = (const unsigned char *)str1;
+ const unsigned char *s2 = (const unsigned char *)s1;
+ const unsigned char *t1 = (const unsigned char *)str2;
+
+ /* populate table */
+ while (*(t1++))
+ table[*t1] = 1;
+
+ for (;;) {
+ if (table[*(s2++)])
+ break;
+ }
+
+ /* the for loop overshoots by one */
+ return (size_t)(s2 - s1) - 1;
+}
+
+size_t strspn(const char *str1, const char *str2)
+{
+ char table[256] = { 0 };
+ const unsigned char *s1 = (const unsigned char *)str1;
+ const unsigned char *s2 = (const unsigned char *)s1;
+ const unsigned char *t1 = (const unsigned char *)str2;
+
+ /* populate table */
+ while (*(t1++))
+ table[*t1] = 1;
+
+ for (;;) {
+ if (!table[*(s2++)])
+ break;
+ }
+
+ /* the for loop overshoots by one */
+ return (size_t)(s2 - s1) - 1;
+}
+
+size_t strlen(const char *str)
+{
+ const char *s1 = str;
+ while (*(s1++))
+ ;
+
+ /* the loop overshoots by one */
+ return (size_t)(s1 - str) - 1;
+}
+
+/* not a macro */
+size_t strnlen(const char *str, size_t num)
+{
+ const char *s1 = str;
+ while (num-- && *(s1++))
+ ;
+
+ return (size_t)(s1 - str) - 1;
+}
+
+void *memchr(const void *ptr, int val, size_t num)
+{
+ const char *p1 = (char *)ptr;
+ ssize_t n = num;
+ char c = (char)val;
+
+ while (n-- && *(p1++) != c)
+ ;
+
+ if (n < 0)
+ return 0;
+
+ return (void *)(p1 - 1);
+}
+
+/** @defgroup group1 Optimized specializations
+ *
+ * The two most used memory operations get their special optimized versions for
+ * aligned manipulations, which is what the vast majority of our huge operations
+ * like page zeroing are.
+ *
+ * @{
+ */
+
+/** How many longs per iteration we want to process. An address and size must be
+ * aligned to MAGIC_NUMBER * sizeof(long) bytes. */
+#define MAGIC_NUMBER 8
+
+/**
+ * Optimized version of memcpy() for big regions.
+ * All parameters must be aligned to MAGIC_NUMBER * sizeof(long).
+ *
+ * @param dst Destination to copy to.
+ * @param src Source to copy from.
+ * @param num Number of bytes to copy.
+ * @return dst
+ */
+static inline void *__aligned_memcpy(long *restrict dst,
+ const long *restrict src, size_t num)
+{
+ size_t count = num / sizeof(long);
+ for (size_t i = 0; i < count; i += MAGIC_NUMBER) {
+ dst[i + 0] = src[i + 0];
+ dst[i + 1] = src[i + 1];
+ dst[i + 2] = src[i + 2];
+ dst[i + 3] = src[i + 3];
+ dst[i + 4] = src[i + 4];
+ dst[i + 5] = src[i + 5];
+ dst[i + 6] = src[i + 6];
+ dst[i + 7] = src[i + 7];
+ /* would be kind of cool if there was some kind of forced unrolling,
+ * as we need to do MAGIC_NUMBER of steps, preferably even with
+ * optimizations disabled. For now I guess just be careful that
+ * MAGIC_NUMBER matches the number of steps within loop */
+ }
+
+ return dst;
+}
+
+/**
+ * Optimized version of memset() for big regions.
+ * \p ptr and \p num must be aligned to MAGIC_NUMBER * sizeof(long).
+ *
+ * @param ptr Destination to write to.
+ * @param value Value (converted to unsigned char) to write.
+ * @param num Number of bytes to write.
+ * @return ptr
+ */
+static inline void *__aligned_memset(long *ptr, int value, size_t num)
+{
+ long bits = 0;
+ for (size_t i = 0; i < sizeof(long) / sizeof(unsigned char); ++i)
+ bits |= ((unsigned char)value) << i * CHAR_BIT;
+
+ size_t count = num / sizeof(long);
+ for (size_t i = 0; i < count; i += MAGIC_NUMBER) {
+ ptr[i + 0] = bits;
+ ptr[i + 1] = bits;
+ ptr[i + 2] = bits;
+ ptr[i + 3] = bits;
+ ptr[i + 4] = bits;
+ ptr[i + 5] = bits;
+ ptr[i + 6] = bits;
+ ptr[i + 7] = bits;
+ }
+
+ return ptr;
+}
+
+/** @} */
+
+void *memcpy(void * restrict dst, const void * restrict src,
+ size_t num)
+{
+
+ if (is_aligned((uintptr_t)dst, sizeof(long) * MAGIC_NUMBER)
+ && is_aligned((uintptr_t)src, sizeof(long) * MAGIC_NUMBER)
+ && is_aligned(num, sizeof(long) * MAGIC_NUMBER))
+ return __aligned_memcpy(dst, src, num);
+
+ const char *m1 = (const char *)src;
+ char *m2 = (char *)dst;
+
+ while (num--)
+ *(m2++) = *(m1++);
+
+ return dst;
+}
+
+void *memset(void *ptr, int value, size_t num)
+{
+ if (is_aligned((uintptr_t)ptr, sizeof(long) * MAGIC_NUMBER)
+ && is_aligned(num, sizeof(long) * MAGIC_NUMBER))
+ return __aligned_memset(ptr, value, num);
+
+ char *p = ptr;
+ char c = value;
+
+ while (num--)
+ *(p++) = c;
+
+ return ptr;
+}
+
+
+void *memmove(void *dst, const void *src, size_t num)
+{
+ const char *m1 = (const char *)src;
+ char *m2 = (char *)dst;
+
+ m1 += num;
+ m2 += num;
+
+ /* doesn't really take into account aliasing yet */
+ while (num--)
+ *(--m2) = *(--m1);
+
+ return dst;
+}
+
+int memcmp(const void *ptr1, const void *ptr2, size_t num)
+{
+ const char *p1 = (const char *)ptr1;
+ const char *p2 = (const char *)ptr2;
+
+ while ((*(p1++) == *(p2++)) && --num)
+ ;
+
+ return (int)(p1[-1] - p2[-1]);
+}
+
+/**
+ * Convert ASCII hex character to integer.
+ * Allows both upper- and lowercase letters.
+ *
+ * @param c Character to convert.
+ * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc.
+ * \c -1 if conversion failed.
+ */
+static int __hexval(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ if (c >= 'a' && c <= 'f')
+ return 10 + c - 'a';
+
+ if (c >= 'A' && c <= 'F')
+ return 10 + c - 'A';
+
+ return -1;
+}
+
+/**
+ * Convert string assumed to represent hex
+ * value to corresponding pointer.
+ *
+ * @param s String to convert to value.
+ * @return Corresponding pointer value.
+ */
+static uintptr_t __hexuintptr(const char *s)
+{
+ uintptr_t res = 0;
+ int val = 0;
+ while ((val = __hexval(*(s++))) != -1) {
+ res *= 16;
+ res += val;
+ }
+
+ return res;
+}
+
+/**
+ * Convert ASCII decimal character to integer.
+ *
+ * @param c Character to convert.
+ * @return Corresponding integer value. That is, '1' => 1, '2' => 2, etc.
+ * \c -1 if conversion failed.
+ */
+static int __decval(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ return -1;
+}
+
+/**
+ * Convert string assumed to represent decimal
+ * value to corresponding pointer.
+ *
+ * @param s String to convert to value.
+ * @return Corresponding pointer value.
+ */
+static uintptr_t __decuintptr(const char *s)
+{
+ uintptr_t res = 0;
+ int val = 0;
+ while ((val = __decval(*(s++))) != -1) {
+ res *= 10;
+ res += val;
+ }
+
+ return res;
+}
+
+static int __octval(char c)
+{
+ if (c >= '0' && c <= '7')
+ return c - '0';
+
+ return -1;
+}
+
+static uintptr_t __octuintptr(const char *s)
+{
+ uintptr_t res = 0;
+ int val = 0;
+ while ((val = __octval(*(s++))) != -1) {
+ res *= 8;
+ res += val;
+ }
+
+ return res;
+}
+
+uintptr_t strtouintptr(const char *s)
+{
+ if (!s)
+ return 0;
+
+ if (s[0] == 0)
+ return 0;
+
+ if (s[0] == '0') {
+ if (s[1] == 0)
+ return 0;
+
+ if (s[1] == 'x' || s[1] == 'X')
+ return __hexuintptr(s + 2);
+
+ return __octuintptr(s + 1);
+ }
+
+ if (s[0] == '-')
+ return -__decuintptr(s + 1);
+
+ if (s[0] == '+')
+ return __decuintptr(s + 1);
+
+ return __decuintptr(s);
+}
diff --git a/tests/common/string.h b/tests/common/string.h
new file mode 100644
index 0000000..9a6dbeb
--- /dev/null
+++ b/tests/common/string.h
@@ -0,0 +1,26 @@
+#ifndef KMI_TESTS_STRING_H
+#define KMI_TESTS_STRING_H
+
+#include <kmi/types.h>
+
+char *strcpy(char * restrict dst, const char * restrict src);
+char *strncpy(char * restrict dst, const char * restrict src, size_t num);
+char *strncat(char * restrict dst, const char * restrict src, size_t num);
+int strcmp(const char *str1, const char *str2);
+int strncmp(const char *str1, const char *str2, size_t num);
+char *strchr(const char *str, int chr);
+char *strtok(char * restrict str, const char * restrict delims);
+char *strstr(const char *str1, const char *str2);
+char *strrchr(const char *str, int chr);
+char *strpbrk(const char *str1, const char *str2);
+size_t strspn(const char *str1, const char *str2);
+size_t strcspn(const char *str1, const char *str2);
+size_t strlen(const char *str);
+size_t strnlen(const char *str, size_t num);
+void *memset(void *ptr, int value, size_t num);
+void *memchr(const void *ptr, int val, size_t num);
+void *memcpy(void * restrict dst, const void * restrict src, size_t num);
+void *memmove(void *dst, const void *src, size_t num);
+int memcmp(const void *ptr1, const void *ptr2, size_t num);
+uintptr_t strtouintptr(const char *s);
+#endif /* KMI_TESTS_STRING_H */
diff --git a/tests/dangling_shmem/source.mk b/tests/dangling_shmem/source.mk
index 2ecd7a6..35785ed 100644
--- a/tests/dangling_shmem/source.mk
+++ b/tests/dangling_shmem/source.mk
@@ -1,2 +1 @@
-DO != ./scripts/gen-prog -n dangling_shmem -p init init.c
-DO != ./scripts/gen-simple -n dangling_shmem -p init
+TESTS += dangling_shmem
diff --git a/tests/exec/exec.c b/tests/exec/exec.c
new file mode 100644
index 0000000..4f92b27
--- /dev/null
+++ b/tests/exec/exec.c
@@ -0,0 +1,16 @@
+#include <common/test.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(d2);
+ UNUSED(d3);
+
+ printf("pid = %ld, tid = %ld, d0 = %ld, d1 = %ld\n",
+ pid, tid, d0, d1);
+
+ check(pid == 0, "unexpected pid for exec\n");
+ check(tid == 2, "unexpected tid for exec\n");
+ check(d0 == SYS_USER_SPAWNED, "unexpected d0 for exec\n");
+ check(d1 == 2, "unexpected d1 for exec\n");
+ ok();
+}
diff --git a/tests/exec/init.c b/tests/exec/init.c
new file mode 100644
index 0000000..d56337d
--- /dev/null
+++ b/tests/exec/init.c
@@ -0,0 +1,38 @@
+#include <common/test.h>
+#include <common/cpio.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ check(pid == 0, "illegal pid for init\n");
+ id_t our_id = 0;
+ printf("forking\n");
+ id_t new_id = sys_fork(&our_id);
+ check(new_id >= 0, "error from fork\n");
+
+ if (new_id == 0) {
+ printf("hello from child with pid %ld\n", (long int)our_id);
+ printf("finding exec in cpio archive %lx...\n", d2);
+ struct cpio_header *cp = cpio_find_file((const void *)d2,
+ "exec", sizeof("exec") - 1);
+
+ check(cp, "couldn't find exec?\n");
+ long name_len = convnum(cp->c_namesize, 8, 16);
+ uintptr_t exec = (uintptr_t)(cp) + align_up(sizeof(struct cpio_header) + name_len, 4);
+ printf("found exec at %lx\n", exec);
+
+ printf("doing exec...\n");
+ sys_exec(exec, 0);
+ error("exec failed\n");
+ }
+
+ printf("hello from parent\n");
+ sys_swap(new_id);
+ check(0, "failed swapping to child\n");
+}
diff --git a/tests/exec/source.mk b/tests/exec/source.mk
new file mode 100644
index 0000000..fdd3d0e
--- /dev/null
+++ b/tests/exec/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-simple -n exec -p init -p exec
diff --git a/tests/fork/source.mk b/tests/fork/source.mk
index e78d467..8e067b7 100644
--- a/tests/fork/source.mk
+++ b/tests/fork/source.mk
@@ -1 +1 @@
-TEST += fork
+TESTS += fork
diff --git a/tests/scripts/gen-prog b/tests/scripts/gen-prog
deleted file mode 100755
index 6e99f37..0000000
--- a/tests/scripts/gen-prog
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-NAME=
-PROG=
-while getopts "n:p:" opt; do
- case "$opt" in
- n) NAME="$OPTARG";;
- p) PROG="$OPTARG";;
- *) echo "unrecognised options -$OPTARG" >&2; exit 1;
- esac
-done
-
-shift $((OPTIND - 1))
-
-# create all subdirectories
-mkdir -p $(echo "${@}" | tr ' ' '\n' | sed "s|[^/]*$||;s|^|build/$NAME|" | uniq)
-
-for s in ${@}
-do
- obj="build/${NAME}/${s%.*}.o"
- dep="${obj}.d"
-
- echo "${NAME}_OBJS += ${obj}" >> tests.mk
- echo "${dep}:" >> tests.mk
- echo "-include ${dep}" >> tests.mk
- echo "${obj}: $NAME/${s} \$(COMMON)" >> tests.mk
- echo " \$(COMPILE_TEST) -c $NAME/${s} -o ${obj}" >> tests.mk
-done
-
-echo "build/${NAME}/$PROG: \$(${NAME}_OBJS) \$(COMMON)" >> tests.mk
-echo " \$(COMPILE_TEST) \$(${NAME}_OBJS) \$(COMMON) \
- -o build/${NAME}/$PROG" >> tests.mk
diff --git a/tests/scripts/gen-simple b/tests/scripts/gen-simple
index a942fb3..fe2d7a4 100755
--- a/tests/scripts/gen-simple
+++ b/tests/scripts/gen-simple
@@ -10,6 +10,8 @@ while getopts "n:p:" opt; do
esac
done
+mkdir -p "build/$NAME"
+
if [ -z "$NAME" ]; then
echo "No name given for tests" >&2; exit 2;
fi
@@ -18,13 +20,28 @@ if [ -z "$PROGS" ]; then
echo "No programs to add to initrd" >&2; exit 3;
fi
-echo "build/$NAME/initrd: build/$NAME/init \$(COMMON) \$(KMI)" >> tests.mk
-echo " echo build/$NAME/init | \$(GEN_INITRD) build/$NAME/initrd" >> tests.mk
+for p in $PROGS
+do
+ dep="build/${NAME}/${p}.d"
+
+ echo "${NAME}_PROGS += build/${NAME}/${p}" >> tests.mk
+ echo "${dep}:" >> tests.mk
+ echo "-include ${dep}" >> tests.mk
+ echo "build/${NAME}/${p}: $NAME/$p.c \$(COMMON)" >> tests.mk
+ echo " \$(COMPILE_TEST) $NAME/${p}.c \$(COMMON) \\" >> tests.mk
+ echo " -o build/${NAME}/${p}" >> tests.mk
+done
+
+echo "build/$NAME/initrd: \$(${NAME}_PROGS) \$(COMMON) \$(KMI)" >> tests.mk
+echo " for p in \$(${NAME}_PROGS); do \\" >> tests.mk
+echo " echo \$\$p; \\" >> tests.mk
+echo " done | \$(GEN_INITRD) build/$NAME/initrd" >> tests.mk
+
echo "reports/$NAME/log: build/$NAME/initrd" >> tests.mk
echo " mkdir -p reports/$NAME" >> tests.mk
echo " rm -f reports/$NAME/*" >> tests.mk
-echo " timeout --foreground 30s \$(QEMU) \
- build/$NAME/initrd > reports/$NAME/log" >> tests.mk
+echo " timeout --foreground 30s \$(QEMU) \\" >> tests.mk
+echo " build/$NAME/initrd > reports/$NAME/log" >> tests.mk
echo "TESTS += $NAME" >> tests.mk
echo ".PHONY: $NAME" >> tests.mk
diff --git a/tests/scripts/makefile b/tests/scripts/makefile
index ed2b2b4..63150b1 100644
--- a/tests/scripts/makefile
+++ b/tests/scripts/makefile
@@ -15,7 +15,8 @@ OBFLAGS := -ffreestanding -nostdlib -std=c17 -g -O2
INCLUDEFLAGS := -I ../include -I.
WARNFLAGS := -Wall -Wextra
DEPFLAGS = -MT $@ -MMD -MP -MF $@.d
-COMPILE_TEST = $(COMPILER) $(WARNFLAGS) $(INCLUDEFLAGS) $(DEPFLAGS) $(OBFLAGS) $(ARCH_FLAGS)
+COMPILE_TEST = $(COMPILER) $(WARNFLAGS) $(INCLUDEFLAGS) \
+ $(DEPFLAGS) $(OBFLAGS) $(ARCH_FLAGS)
GEN_INITRD := cpio -H newc -o >
QEMU := qemu-system-$(ARCH) -machine virt -kernel ../kmi.bin \
@@ -27,11 +28,14 @@ QEMU := qemu-system-$(ARCH) -machine virt -kernel ../kmi.bin \
-initrd
KMI := ../kmi.bin
-COMMON := build/printf.o
+COMMON := build/printf.o build/string.o
build/printf.o: common/printf.c $(KMI)
$(COMPILE_TEST) -c common/printf.c -o build/printf.o
+build/string.o: common/string.c $(KMI)
+ $(COMPILE_TEST) -c common/string.c -o build/string.o
+
include tests.mk
.PHONY: check
diff --git a/tests/shmem/source.mk b/tests/shmem/source.mk
index da84808..0fd9bee 100644
--- a/tests/shmem/source.mk
+++ b/tests/shmem/source.mk
@@ -1,2 +1 @@
-DO != ./scripts/gen-prog -n shmem -p init init.c
-DO != ./scripts/gen-simple -n shmem -p init
+TESTS += shmem