Extend fork test

This patch extends the fork test with explicit checks for the cloned
content of the heap and RW segment as well as the seek position of an
open file descriptor. It adds the new libports/run/fork.run script
that exercises the fork mechanism implemented by the libc. It is based
on noux_fork.run, which tests the mechansim provided by noux. The
test program has been moved from ports to libports.

Issue #3478
This commit is contained in:
Norman Feske 2019-08-13 16:16:56 +02:00 committed by Christian Helmuth
parent 65f75589e9
commit 581785a48f
5 changed files with 163 additions and 78 deletions

View File

@ -0,0 +1,37 @@
build { core init test/fork }
create_boot_directory
install_config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="CPU"/>
<service name="PD"/>
</parent-provides>
<start name="test-fork" caps="300">
<resource name="RAM" quantum="1G"/>
<config>
<arg value="name_of_executeable"/>
<libc stdin="/null" stdout="/log" stderr="/log">
<fd id="3" path="/seek_test" readable="yes" seek="5"/>
</libc>
<vfs>
<null/> <log/>
<inline name="seek_test">0123456789</inline>
</vfs>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
</config>
}
build_boot_image {
core init ld.lib.so libc.lib.so vfs.lib.so libm.lib.so posix.lib.so test-fork
}
append qemu_args " -nographic "
run_genode_until "--- parent done ---.*\n" 20
run_genode_until "child.*exited.*\n" 5 [output_spawn_id]

View File

@ -1,4 +1,4 @@
TARGET = test-noux_fork
TARGET = test-fork
SRC_CC = test.cc
LIBS = posix

View File

@ -0,0 +1,121 @@
/*
* \brief Simple fork test
* \author Norman Feske
* \date 2012-02-14
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
enum { MAX_COUNT = 100 };
int main(int, char **argv)
{
printf("--- test-fork started ---\n");
enum { MSG_SIZE = 100 };
static char message_in_rw_segment[MSG_SIZE];
char const * const message_about_rw_segment = "message stored in rw segment";
strncpy(message_in_rw_segment, message_about_rw_segment, MSG_SIZE);
char * const message_on_heap = (char *)malloc(MSG_SIZE);
char const * const message_about_heap = "message stored on the heap";
strncpy(message_on_heap, message_about_heap, MSG_SIZE - 1);
enum { ARGV0_SIZE = 100 };
static char parent_argv0[ARGV0_SIZE];
strncpy(parent_argv0, argv[0], ARGV0_SIZE - 1);
pid_t fork_ret = fork();
if (fork_ret < 0) {
printf("Error: fork returned %d, errno=%d\n", fork_ret, errno);
return -1;
}
printf("pid %d: fork returned %d\n", getpid(), fork_ret);
/* child */
if (fork_ret == 0) {
printf("pid %d: child says hello\n", getpid());
/*
* Validate that the child's heap and RW segment correspond to the
* the state of the parent.
*/
printf("RW segment: %s\n", message_in_rw_segment);
if (strcmp(message_in_rw_segment, message_about_rw_segment)) {
printf("Error: unexpected content of the child's RW segment\n");
return -1;
}
printf("argv0: %s\n", argv[0]);
if (!argv[0] || strcmp(argv[0], parent_argv0)) {
printf("Error: unexpected content of the child's args buffer\n");
return -1;
}
printf("heap: %s\n", message_on_heap);
if (strcmp(message_on_heap, message_about_heap)) {
printf("Error: unexpected content on the child's heap\n");
return -1;
}
{
char c = 0;
if (read(3, &c, 1) == 1) {
printf("read character '%c' from FD 3\n", c);
if (c != '5') {
printf("Error: read unexpected value from FD 3\n");
return -1;
}
}
}
pid_t fork_ret = fork();
if (fork_ret < 0) {
printf("Error: fork returned %d, errno=%d\n", fork_ret, errno);
return -1;
}
printf("pid %d: fork returned %d\n", getpid(), fork_ret);
/* grand child */
if (fork_ret == 0) {
printf("pid %d: grand child says hello\n", getpid());
for (int k = 0; k < MAX_COUNT; k++) {
printf("pid %d: grand child k = %d\n", getpid(), k);
}
return 0;
};
for (int j = 0; j < MAX_COUNT; j++) {
printf("pid %d: child j = %d\n", getpid(), j);
}
if (fork_ret != 0) {
printf("pid %d: child waits for grand-child exit\n", getpid());
waitpid(fork_ret, nullptr, 0);
}
return 0;
}
printf("pid %d: parent received child pid %d, starts counting...\n",
getpid(), fork_ret);
for (int i = 0; i < MAX_COUNT; ) {
printf("pid %d: parent i = %d\n", getpid(), i++);
}
printf("pid %d: parent waits for child exit\n", getpid());
waitpid(fork_ret, nullptr, 0);
printf("--- parent done ---\n");
return 0;
}

View File

@ -1,6 +1,6 @@
build {
core init timer server/log_terminal noux lib/libc_noux
test/noux_fork
test/fork
}
create_boot_directory
@ -34,9 +34,9 @@ install_config {
<config verbose="yes" stdin="/null" stdout="/log" stderr="/log">
<fstab>
<null/> <log/>
<rom name="test-noux_fork" />
<rom name="test-fork" />
</fstab>
<start name="test-noux_fork"> </start>
<start name="test-fork"> </start>
</config>
</start>
</config>
@ -44,7 +44,7 @@ install_config {
build_boot_image {
core init timer log_terminal noux ld.lib.so libc.lib.so vfs.lib.so libm.lib.so
libc_noux.lib.so posix.lib.so test-noux_fork
libc_noux.lib.so posix.lib.so test-fork
}
append qemu_args " -nographic "

View File

@ -1,73 +0,0 @@
/*
* \brief Simple fork test
* \author Norman Feske
* \date 2012-02-14
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
enum { MAX_COUNT = 1000 };
int main(int, char **)
{
printf("--- test-noux_fork started ---\n");
pid_t fork_ret = fork();
if (fork_ret < 0) {
printf("Error: fork returned %d, errno=%d\n", fork_ret, errno);
return -1;
}
printf("pid %d: fork returned %d\n", getpid(), fork_ret);
/* child */
if (fork_ret == 0) {
printf("pid %d: child says hello\n", getpid());
pid_t fork_ret = fork();
if (fork_ret < 0) {
printf("Error: fork returned %d, errno=%d\n", fork_ret, errno);
return -1;
}
printf("pid %d: fork returned %d\n", getpid(), fork_ret);
/* grand child */
if (fork_ret == 0) {
printf("pid %d: grand child says hello\n", getpid());
for (int k = 0; k < MAX_COUNT; k++) {
printf("pid %d: grand child k = %d\n", getpid(), k);
}
return 0;
};
for (int j = 0; j < MAX_COUNT; j++) {
printf("pid %d: child j = %d\n", getpid(), j);
}
if (fork_ret != 0) {
printf("pid %d: child waits for grand-child exit\n", getpid());
waitpid(fork_ret, nullptr, 0);
}
return 0;
}
printf("pid %d: parent received child pid %d, starts counting...\n",
getpid(), fork_ret);
for (int i = 0; i < MAX_COUNT; ) {
printf("pid %d: parent i = %d\n", getpid(), i++);
}
printf("pid %d: parent waits for child exit\n", getpid());
waitpid(fork_ret, nullptr, 0);
printf("--- parent done ---\n");
return 0;
}