blob: d9fbff9af42a5bf2c7e8fa67fb53772606fb1f42 [file]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Integration test for program_invocation_name.
///
//===----------------------------------------------------------------------===//
#include "src/__support/CPP/string_view.h"
#include "src/errno/program_invocation_name.h"
#include "src/errno/program_invocation_short_name.h"
#include "src/unistd/execve.h"
#include "test/IntegrationTest/test.h"
TEST_MAIN(int argc, char **argv, char **envp) {
ASSERT_TRUE(argc >= 1);
ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name != nullptr);
ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_short_name != nullptr);
ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name == argv[0]);
LIBC_NAMESPACE::cpp::string_view arg1 = argc > 1 ? argv[1] : "";
if (arg1 == "reexec1") {
// Step 1: Executed with an absolute path containing slashes.
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
"/known/path/to/invocation_name");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
"invocation_name");
ASSERT_EQ(argc, 3);
const char *self_path = argv[2];
char *const child_argv[] = {
const_cast<char *>("./relative/path/to/invocation_name"),
const_cast<char *>("reexec2"),
const_cast<char *>(self_path),
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
}
if (arg1 == "reexec2") {
// Step 2: Executed with a relative path containing slashes.
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
"./relative/path/to/invocation_name");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
"invocation_name");
ASSERT_EQ(argc, 3);
const char *self_path = argv[2];
char *const child_argv[] = {
const_cast<char *>(""),
const_cast<char *>("reexec3"),
const_cast<char *>(self_path),
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
}
if (arg1 == "reexec3") {
// Step 3: Executed with an empty string.
ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name ==
LIBC_NAMESPACE::program_invocation_short_name);
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name, "");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name, "");
ASSERT_EQ(argc, 3);
const char *self_path = argv[2];
char *const child_argv[] = {
const_cast<char *>("/known/path/to/dir/"),
const_cast<char *>("reexec4"),
const_cast<char *>(self_path),
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
}
if (arg1 == "reexec4") {
// Step 4: Executed with a path ending in a slash.
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
"/known/path/to/dir/");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name, "");
ASSERT_EQ(argc, 3);
const char *self_path = argv[2];
char *const child_argv[] = {
const_cast<char *>("invocation_name_no_slash"),
const_cast<char *>("reexec5"),
const_cast<char *>(self_path),
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
}
if (arg1 == "reexec5") {
// Step 5: Executed with a path without slashes.
ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name ==
LIBC_NAMESPACE::program_invocation_short_name);
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
"invocation_name_no_slash");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
"invocation_name_no_slash");
ASSERT_EQ(argc, 3);
const char *self_path = argv[2];
char *const child_argv[] = {
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
}
if (argc == 1 && LIBC_NAMESPACE::cpp::string_view(argv[0]) == "") {
// Step 6: Executed with an empty (zero-length) argv. The kernel adds an
// empty string for argv[0].
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name, "");
ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name, "");
return 0;
}
// Step 0: Initial run. Re-exec self with known argv[0] values.
const char *self_path = argv[0];
char *const child_argv[] = {
const_cast<char *>("/known/path/to/invocation_name"),
const_cast<char *>("reexec1"),
const_cast<char *>(self_path),
nullptr,
};
LIBC_NAMESPACE::execve(self_path, child_argv, envp);
ASSERT_TRUE(false);
return 1;
}