51 changes: 51 additions & 0 deletions libc/test/integration/src/spawn/posix_spawn_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===-- Unittests for posix_spawn -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "test_binary_properties.h"

#include "src/spawn/posix_spawn.h"
#include "src/spawn/posix_spawn_file_actions_addopen.h"
#include "src/spawn/posix_spawn_file_actions_destroy.h"
#include "src/spawn/posix_spawn_file_actions_init.h"
#include "src/sys/wait/waitpid.h"
#include "utils/IntegrationTest/test.h"

#include <fcntl.h>
#include <spawn.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/wait.h>

char arg0[] = "libc_posix_spawn_test_binary";
char *argv[] = {
arg0,
nullptr,
};

void spawn_and_wait_for_normal_exit(char **envp) {
pid_t cpid;
posix_spawn_file_actions_t file_actions;
ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_init(&file_actions), 0);
__llvm_libc::posix_spawn_file_actions_addopen(
&file_actions, CHILD_FD, "testdata/posix_spawn.test", O_RDONLY, 0);
ASSERT_EQ(
__llvm_libc::posix_spawn(&cpid, arg0, &file_actions, nullptr, argv, envp),
0);
ASSERT_TRUE(cpid > 0);
int status;
ASSERT_EQ(__llvm_libc::waitpid(cpid, &status, 0), cpid);
ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_destroy(&file_actions), 0);
ASSERT_TRUE(WIFEXITED(status));
int exit_status = WEXITSTATUS(status);
ASSERT_EQ(exit_status, 0);
}

TEST_MAIN(int argc, char **argv, char **envp) {
spawn_and_wait_for_normal_exit(envp);
return 0;
}
22 changes: 22 additions & 0 deletions libc/test/integration/src/spawn/posix_spawn_test_binary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "test_binary_properties.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
if (argc != 1)
return 5;
constexpr size_t bufsize = sizeof(TEXT);
char buf[bufsize];
ssize_t readsize = bufsize - 1;
ssize_t len = read(CHILD_FD, buf, readsize);
if (len != readsize) {
return 1;
}
buf[readsize] = '\0'; // Null terminator
if (close(CHILD_FD) != 0)
return 2;
if (strcmp(buf, TEXT) != 0)
return 3;
return 0;
}
15 changes: 15 additions & 0 deletions libc/test/integration/src/spawn/test_binary_properties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//===-- Common definitions shared between test binary and test --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H
#define LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H

constexpr int CHILD_FD = 10;
constexpr char TEXT[] = "Hello, posix_spawn";

#endif // LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H
1 change: 1 addition & 0 deletions libc/test/integration/src/spawn/testdata/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
file(GENERATE OUTPUT posix_spawn.test CONTENT "Hello, posix_spawn")
4 changes: 3 additions & 1 deletion libc/utils/IntegrationTest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_header_library(
add_object_library(
test
SRCS
test.cpp
HDRS
test.h
DEPENDS
Expand Down
32 changes: 32 additions & 0 deletions libc/utils/IntegrationTest/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- Simple malloc and free for use with integration tests -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <stddef.h>
#include <stdint.h>

// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
// various other parts of the libc. Since SCUDO development does not use
// LLVM libc build rules, it is very hard to keep track or pull all that SCUDO
// requires. Hence, as a work around for this problem, we use a simple allocator
// which just hands out continuous blocks from a statically allocated chunk of
// memory.

static uint8_t memory[16384];
static uint8_t *ptr = memory;

extern "C" {

void *malloc(size_t s) {
void *mem = ptr;
ptr += s;
return mem;
}

void free(void *) {}

} // extern "C"