forked from OSchip/llvm-project
[libc] add strerror
Strerror maps error numbers to strings. Additionally, a utility for mapping errors to strings was added so that it could be reused for perror and similar. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D134074
This commit is contained in:
parent
41f3602dfa
commit
42bcb35c0f
|
@ -57,6 +57,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
# string.h entrypoints that depend on malloc
|
||||
libc.src.string.strdup
|
||||
libc.src.string.strndup
|
||||
libc.src.string.strerror
|
||||
|
||||
# inttypes.h entrypoints
|
||||
libc.src.inttypes.imaxabs
|
||||
|
|
|
@ -72,6 +72,19 @@ add_header_library(
|
|||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
|
||||
add_object_library(
|
||||
error_to_string
|
||||
HDRS
|
||||
error_to_string.h
|
||||
SRCS
|
||||
error_to_string.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.src.__support.CPP.string_view
|
||||
libc.src.__support.CPP.stringstream
|
||||
)
|
||||
|
||||
add_header_library(
|
||||
integer_operations
|
||||
HDRS
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
//===-- Implementation of a class for mapping errors to strings -----------===//
|
||||
//
|
||||
// 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 "src/__support/error_to_string.h"
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/CPP/stringstream.h"
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace internal {
|
||||
|
||||
constexpr size_t max_buff_size() {
|
||||
constexpr size_t unknown_str_len = sizeof("Unknown error");
|
||||
constexpr size_t max_num_len =
|
||||
__llvm_libc::IntegerToString::dec_bufsize<int>();
|
||||
// the buffer should be able to hold "Unknown error" + ' ' + num_str
|
||||
return (unknown_str_len + 1 + max_num_len) * sizeof(char);
|
||||
}
|
||||
|
||||
// This is to hold error strings that have to be custom built. It may be
|
||||
// rewritten on every call to strerror (or other error to string function).
|
||||
constexpr size_t BUFFER_SIZE = max_buff_size();
|
||||
thread_local char error_buffer[BUFFER_SIZE];
|
||||
|
||||
struct ErrMsgMapping {
|
||||
int err_num;
|
||||
cpp::string_view err_msg;
|
||||
|
||||
public:
|
||||
constexpr ErrMsgMapping(int num, const char *msg)
|
||||
: err_num(num), err_msg(msg) {
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr ErrMsgMapping raw_err_array[] = {
|
||||
ErrMsgMapping(0, "Success"),
|
||||
ErrMsgMapping(EPERM, "Operation not permitted"),
|
||||
ErrMsgMapping(ENOENT, "No such file or directory"),
|
||||
ErrMsgMapping(ESRCH, "No such process"),
|
||||
ErrMsgMapping(EINTR, "Interrupted system call"),
|
||||
ErrMsgMapping(EIO, "Input/output error"),
|
||||
ErrMsgMapping(ENXIO, "No such device or address"),
|
||||
ErrMsgMapping(E2BIG, "Argument list too long"),
|
||||
ErrMsgMapping(ENOEXEC, "Exec format error"),
|
||||
ErrMsgMapping(EBADF, "Bad file descriptor"),
|
||||
ErrMsgMapping(ECHILD, "No child processes"),
|
||||
ErrMsgMapping(EAGAIN, "Resource temporarily unavailable"),
|
||||
ErrMsgMapping(ENOMEM, "Cannot allocate memory"),
|
||||
ErrMsgMapping(EACCES, "Permission denied"),
|
||||
ErrMsgMapping(EFAULT, "Bad address"),
|
||||
ErrMsgMapping(ENOTBLK, "Block device required"),
|
||||
ErrMsgMapping(EBUSY, "Device or resource busy"),
|
||||
ErrMsgMapping(EEXIST, "File exists"),
|
||||
ErrMsgMapping(EXDEV, "Invalid cross-device link"),
|
||||
ErrMsgMapping(ENODEV, "No such device"),
|
||||
ErrMsgMapping(ENOTDIR, "Not a directory"),
|
||||
ErrMsgMapping(EISDIR, "Is a directory"),
|
||||
ErrMsgMapping(EINVAL, "Invalid argument"),
|
||||
ErrMsgMapping(ENFILE, "Too many open files in system"),
|
||||
ErrMsgMapping(EMFILE, "Too many open files"),
|
||||
ErrMsgMapping(ENOTTY, "Inappropriate ioctl for device"),
|
||||
ErrMsgMapping(ETXTBSY, "Text file busy"),
|
||||
ErrMsgMapping(EFBIG, "File too large"),
|
||||
ErrMsgMapping(ENOSPC, "No space left on device"),
|
||||
ErrMsgMapping(ESPIPE, "Illegal seek"),
|
||||
ErrMsgMapping(EROFS, "Read-only file system"),
|
||||
ErrMsgMapping(EMLINK, "Too many links"),
|
||||
ErrMsgMapping(EPIPE, "Broken pipe"),
|
||||
ErrMsgMapping(EDOM, "Numerical argument out of domain"),
|
||||
ErrMsgMapping(ERANGE, "Numerical result out of range"),
|
||||
ErrMsgMapping(EDEADLK, "Resource deadlock avoided"),
|
||||
ErrMsgMapping(ENAMETOOLONG, "File name too long"),
|
||||
ErrMsgMapping(ENOLCK, "No locks available"),
|
||||
ErrMsgMapping(ENOSYS, "Function not implemented"),
|
||||
ErrMsgMapping(ENOTEMPTY, "Directory not empty"),
|
||||
ErrMsgMapping(ELOOP, "Too many levels of symbolic links"),
|
||||
// No error for 41. Would be EWOULDBLOCK
|
||||
ErrMsgMapping(ENOMSG, "No message of desired type"),
|
||||
ErrMsgMapping(EIDRM, "Identifier removed"),
|
||||
ErrMsgMapping(ECHRNG, "Channel number out of range"),
|
||||
ErrMsgMapping(EL2NSYNC, "Level 2 not synchronized"),
|
||||
ErrMsgMapping(EL3HLT, "Level 3 halted"),
|
||||
ErrMsgMapping(EL3RST, "Level 3 reset"),
|
||||
ErrMsgMapping(ELNRNG, "Link number out of range"),
|
||||
ErrMsgMapping(EUNATCH, "Protocol driver not attached"),
|
||||
ErrMsgMapping(ENOCSI, "No CSI structure available"),
|
||||
ErrMsgMapping(EL2HLT, "Level 2 halted"),
|
||||
ErrMsgMapping(EBADE, "Invalid exchange"),
|
||||
ErrMsgMapping(EBADR, "Invalid request descriptor"),
|
||||
ErrMsgMapping(EXFULL, "Exchange full"),
|
||||
ErrMsgMapping(ENOANO, "No anode"),
|
||||
ErrMsgMapping(EBADRQC, "Invalid request code"),
|
||||
ErrMsgMapping(EBADSLT, "Invalid slot"),
|
||||
// No error for 58. Would be EDEADLOCK.
|
||||
ErrMsgMapping(EBFONT, "Bad font file format"),
|
||||
ErrMsgMapping(ENOSTR, "Device not a stream"),
|
||||
ErrMsgMapping(ENODATA, "No data available"),
|
||||
ErrMsgMapping(ETIME, "Timer expired"),
|
||||
ErrMsgMapping(ENOSR, "Out of streams resources"),
|
||||
ErrMsgMapping(ENONET, "Machine is not on the network"),
|
||||
ErrMsgMapping(ENOPKG, "Package not installed"),
|
||||
ErrMsgMapping(EREMOTE, "Object is remote"),
|
||||
ErrMsgMapping(ENOLINK, "Link has been severed"),
|
||||
ErrMsgMapping(EADV, "Advertise error"),
|
||||
ErrMsgMapping(ESRMNT, "Srmount error"),
|
||||
ErrMsgMapping(ECOMM, "Communication error on send"),
|
||||
ErrMsgMapping(EPROTO, "Protocol error"),
|
||||
ErrMsgMapping(EMULTIHOP, "Multihop attempted"),
|
||||
ErrMsgMapping(EDOTDOT, "RFS specific error"),
|
||||
ErrMsgMapping(EBADMSG, "Bad message"),
|
||||
ErrMsgMapping(EOVERFLOW, "Value too large for defined data type"),
|
||||
ErrMsgMapping(ENOTUNIQ, "Name not unique on network"),
|
||||
ErrMsgMapping(EBADFD, "File descriptor in bad state"),
|
||||
ErrMsgMapping(EREMCHG, "Remote address changed"),
|
||||
ErrMsgMapping(ELIBACC, "Can not access a needed shared library"),
|
||||
ErrMsgMapping(ELIBBAD, "Accessing a corrupted shared library"),
|
||||
ErrMsgMapping(ELIBSCN, ".lib section in a.out corrupted"),
|
||||
ErrMsgMapping(ELIBMAX, "Attempting to link in too many shared libraries"),
|
||||
ErrMsgMapping(ELIBEXEC, "Cannot exec a shared library directly"),
|
||||
ErrMsgMapping(EILSEQ, "Invalid or incomplete multibyte or wide character"),
|
||||
ErrMsgMapping(ERESTART, "Interrupted system call should be restarted"),
|
||||
ErrMsgMapping(ESTRPIPE, "Streams pipe error"),
|
||||
ErrMsgMapping(EUSERS, "Too many users"),
|
||||
ErrMsgMapping(ENOTSOCK, "Socket operation on non-socket"),
|
||||
ErrMsgMapping(EDESTADDRREQ, "Destination address required"),
|
||||
ErrMsgMapping(EMSGSIZE, "Message too long"),
|
||||
ErrMsgMapping(EPROTOTYPE, "Protocol wrong type for socket"),
|
||||
ErrMsgMapping(ENOPROTOOPT, "Protocol not available"),
|
||||
ErrMsgMapping(EPROTONOSUPPORT, "Protocol not supported"),
|
||||
ErrMsgMapping(ESOCKTNOSUPPORT, "Socket type not supported"),
|
||||
ErrMsgMapping(ENOTSUP, "Operation not supported"),
|
||||
ErrMsgMapping(EPFNOSUPPORT, "Protocol family not supported"),
|
||||
ErrMsgMapping(EAFNOSUPPORT, "Address family not supported by protocol"),
|
||||
ErrMsgMapping(EADDRINUSE, "Address already in use"),
|
||||
ErrMsgMapping(EADDRNOTAVAIL, "Cannot assign requested address"),
|
||||
ErrMsgMapping(ENETDOWN, "Network is down"),
|
||||
ErrMsgMapping(ENETUNREACH, "Network is unreachable"),
|
||||
ErrMsgMapping(ENETRESET, "Network dropped connection on reset"),
|
||||
ErrMsgMapping(ECONNABORTED, "Software caused connection abort"),
|
||||
ErrMsgMapping(ECONNRESET, "Connection reset by peer"),
|
||||
ErrMsgMapping(ENOBUFS, "No buffer space available"),
|
||||
ErrMsgMapping(EISCONN, "Transport endpoint is already connected"),
|
||||
ErrMsgMapping(ENOTCONN, "Transport endpoint is not connected"),
|
||||
ErrMsgMapping(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
|
||||
ErrMsgMapping(ETOOMANYREFS, "Too many references: cannot splice"),
|
||||
ErrMsgMapping(ETIMEDOUT, "Connection timed out"),
|
||||
ErrMsgMapping(ECONNREFUSED, "Connection refused"),
|
||||
ErrMsgMapping(EHOSTDOWN, "Host is down"),
|
||||
ErrMsgMapping(EHOSTUNREACH, "No route to host"),
|
||||
ErrMsgMapping(EALREADY, "Operation already in progress"),
|
||||
ErrMsgMapping(EINPROGRESS, "Operation now in progress"),
|
||||
ErrMsgMapping(ESTALE, "Stale file handle"),
|
||||
ErrMsgMapping(EUCLEAN, "Structure needs cleaning"),
|
||||
ErrMsgMapping(ENOTNAM, "Not a XENIX named type file"),
|
||||
ErrMsgMapping(ENAVAIL, "No XENIX semaphores available"),
|
||||
ErrMsgMapping(EISNAM, "Is a named type file"),
|
||||
ErrMsgMapping(EREMOTEIO, "Remote I/O error"),
|
||||
ErrMsgMapping(EDQUOT, "Disk quota exceeded"),
|
||||
ErrMsgMapping(ENOMEDIUM, "No medium found"),
|
||||
ErrMsgMapping(EMEDIUMTYPE, "Wrong medium type"),
|
||||
ErrMsgMapping(ECANCELED, "Operation canceled"),
|
||||
ErrMsgMapping(ENOKEY, "Required key not available"),
|
||||
ErrMsgMapping(EKEYEXPIRED, "Key has expired"),
|
||||
ErrMsgMapping(EKEYREVOKED, "Key has been revoked"),
|
||||
ErrMsgMapping(EKEYREJECTED, "Key was rejected by service"),
|
||||
ErrMsgMapping(EOWNERDEAD, "Owner died"),
|
||||
ErrMsgMapping(ENOTRECOVERABLE, "State not recoverable"),
|
||||
ErrMsgMapping(ERFKILL, "Operation not possible due to RF-kill"),
|
||||
ErrMsgMapping(EHWPOISON, "Memory page has hardware error"),
|
||||
};
|
||||
|
||||
constexpr size_t total_str_len(const ErrMsgMapping *array, size_t len) {
|
||||
size_t total = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
// add 1 for the null terminator.
|
||||
total += array[i].err_msg.size() + 1;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
// Since the StringMappings array is a map from error numbers to their
|
||||
// corresponding strings, we have to have an array large enough we can use the
|
||||
// error numbers as indexes. Thankfully there are 132 errors in the above list
|
||||
// (41 and 58 are skipped) and the highest number is 133. If other platforms use
|
||||
// different error numbers, then this number may need to be adjusted.
|
||||
// Also if negative numbers or particularly large numbers are used, then the
|
||||
// array should be turned into a proper hashmap.
|
||||
constexpr size_t ERR_ARRAY_SIZE = 134;
|
||||
|
||||
class ErrorMapper {
|
||||
|
||||
// const char *StringMappings[ERR_ARRAY_SIZE] = {""};
|
||||
int err_offsets[ERR_ARRAY_SIZE] = {-1};
|
||||
char string_array[total_str_len(
|
||||
raw_err_array, sizeof(raw_err_array) / sizeof(ErrMsgMapping))] = {'\0'};
|
||||
|
||||
public:
|
||||
constexpr ErrorMapper() {
|
||||
cpp::string_view string_mappings[ERR_ARRAY_SIZE] = {""};
|
||||
for (size_t i = 0; i < (sizeof(raw_err_array) / sizeof(ErrMsgMapping)); ++i)
|
||||
string_mappings[raw_err_array[i].err_num] = raw_err_array[i].err_msg;
|
||||
|
||||
size_t string_array_index = 0;
|
||||
for (size_t cur_err = 0; cur_err < ERR_ARRAY_SIZE; ++cur_err) {
|
||||
if (string_mappings[cur_err].size() != 0) {
|
||||
err_offsets[cur_err] = string_array_index;
|
||||
// No need to replace with proper strcpy, this is evaluated at compile
|
||||
// time.
|
||||
for (size_t i = 0; i < string_mappings[cur_err].size() + 1;
|
||||
++i, ++string_array_index) {
|
||||
string_array[string_array_index] = string_mappings[cur_err][i];
|
||||
}
|
||||
} else {
|
||||
err_offsets[cur_err] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpp::string_view get_str(int err_num) const {
|
||||
if (err_num >= 0 && static_cast<size_t>(err_num) < ERR_ARRAY_SIZE &&
|
||||
err_offsets[err_num] != -1) {
|
||||
return const_cast<char *>(string_array + err_offsets[err_num]);
|
||||
} else {
|
||||
// if the buffer can't hold "Unknown error" + ' ' + num_str, then just
|
||||
// return "Unknown error".
|
||||
if (BUFFER_SIZE <
|
||||
(sizeof("Unknown error") + 1 + IntegerToString::dec_bufsize<int>()))
|
||||
return const_cast<char *>("Unknown error");
|
||||
|
||||
cpp::StringStream buffer_stream({error_buffer, BUFFER_SIZE});
|
||||
buffer_stream << "Unknown error" << ' ' << err_num << '\0';
|
||||
return buffer_stream.str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr ErrorMapper error_mapper;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
cpp::string_view get_error_string(int err_num) {
|
||||
return internal::error_mapper.get_str(err_num);
|
||||
}
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,21 @@
|
|||
//===-- Definition of a class for mapping errors to strings -----*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/integer_to_string.h"
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_SUPPORT_ERROR_TO_STRING
|
||||
#define LLVM_LIBC_SRC_SUPPORT_ERROR_TO_STRING
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
cpp::string_view get_error_string(int err_num);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SUPPORT_ERROR_TO_STRING
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/CPP/optional.h"
|
||||
#include "src/__support/CPP/span.h"
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/CPP/type_traits.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
@ -45,9 +45,9 @@ namespace __llvm_libc {
|
|||
// auto str = IntegerToString::convert<30>(a, b30buf);
|
||||
class IntegerToString {
|
||||
static cpp::string_view convert_uintmax(uintmax_t uval,
|
||||
cpp::span<char> &buffer,
|
||||
bool lowercase,
|
||||
const uint8_t conv_base) {
|
||||
cpp::span<char> &buffer,
|
||||
bool lowercase,
|
||||
const uint8_t conv_base) {
|
||||
const char a = lowercase ? 'a' : 'A';
|
||||
|
||||
size_t len = 0;
|
||||
|
@ -68,8 +68,8 @@ class IntegerToString {
|
|||
}
|
||||
|
||||
static cpp::string_view convert_intmax(intmax_t val, cpp::span<char> &buffer,
|
||||
bool lowercase,
|
||||
const uint8_t conv_base) {
|
||||
bool lowercase,
|
||||
const uint8_t conv_base) {
|
||||
if (val >= 0)
|
||||
return convert_uintmax(uintmax_t(val), buffer, lowercase, conv_base);
|
||||
uintmax_t uval = uintmax_t(-val);
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
cpp::enable_if_t<2 <= BASE && BASE <= 36 && cpp::is_integral_v<T>,
|
||||
int> = 0>
|
||||
static cpp::optional<cpp::string_view> convert(T val, cpp::span<char> buffer,
|
||||
bool lowercase = true) {
|
||||
bool lowercase = true) {
|
||||
if (buffer.size() < bufsize<BASE, T>())
|
||||
return cpp::optional<cpp::string_view>();
|
||||
if (cpp::is_signed_v<T>)
|
||||
|
@ -155,7 +155,7 @@ public:
|
|||
|
||||
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
|
||||
static cpp::optional<cpp::string_view> hex(T val, cpp::span<char> buffer,
|
||||
bool lowercase = true) {
|
||||
bool lowercase = true) {
|
||||
return convert<16>(val, buffer, lowercase);
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,17 @@ add_entrypoint_object(
|
|||
libc.include.stdlib
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strerror
|
||||
SRCS
|
||||
strerror.cpp
|
||||
HDRS
|
||||
strerror.h
|
||||
DEPENDS
|
||||
libc.src.__support.error_to_string
|
||||
libc.src.__support.CPP.span
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strlcat
|
||||
SRCS
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of strerror ----------------------------------------===//
|
||||
//
|
||||
// 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 "src/string/strerror.h"
|
||||
#include "src/__support/CPP/span.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/error_to_string.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, strerror, (int err_num)) {
|
||||
return const_cast<char *>(get_error_string(err_num).data());
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for strerror ----------------------*- 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 LLVM_LIBC_SRC_STRING_STRERROR_H
|
||||
#define LLVM_LIBC_SRC_STRING_STRERROR_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *strerror(int errnum);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRING_STRERROR_H
|
|
@ -18,7 +18,7 @@ namespace testing {
|
|||
|
||||
namespace internal {
|
||||
|
||||
extern "C" const char *strerror(int);
|
||||
extern "C" char *strerror(int);
|
||||
|
||||
template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
|
||||
T ExpectedReturn;
|
||||
|
|
|
@ -123,6 +123,16 @@ add_libc_unittest(
|
|||
libc.src.string.strdup
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strerror_test
|
||||
SUITE
|
||||
libc_string_unittests
|
||||
SRCS
|
||||
strerror_test.cpp
|
||||
DEPENDS
|
||||
libc.src.string.strerror
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strlcat_test
|
||||
SUITE
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
//===-- Unittests for strerror --------------------------------------------===//
|
||||
//
|
||||
// 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 "src/string/strerror.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcStrErrorTest, KnownErrors) {
|
||||
ASSERT_STREQ(__llvm_libc::strerror(0), "Success");
|
||||
|
||||
const char *message_array[] = {
|
||||
"Success",
|
||||
"Operation not permitted",
|
||||
"No such file or directory",
|
||||
"No such process",
|
||||
"Interrupted system call",
|
||||
"Input/output error",
|
||||
"No such device or address",
|
||||
"Argument list too long",
|
||||
"Exec format error",
|
||||
"Bad file descriptor",
|
||||
"No child processes",
|
||||
"Resource temporarily unavailable",
|
||||
"Cannot allocate memory",
|
||||
"Permission denied",
|
||||
"Bad address",
|
||||
"Block device required",
|
||||
"Device or resource busy",
|
||||
"File exists",
|
||||
"Invalid cross-device link",
|
||||
"No such device",
|
||||
"Not a directory",
|
||||
"Is a directory",
|
||||
"Invalid argument",
|
||||
"Too many open files in system",
|
||||
"Too many open files",
|
||||
"Inappropriate ioctl for device",
|
||||
"Text file busy",
|
||||
"File too large",
|
||||
"No space left on device",
|
||||
"Illegal seek",
|
||||
"Read-only file system",
|
||||
"Too many links",
|
||||
"Broken pipe",
|
||||
"Numerical argument out of domain",
|
||||
"Numerical result out of range",
|
||||
"Resource deadlock avoided",
|
||||
"File name too long",
|
||||
"No locks available",
|
||||
"Function not implemented",
|
||||
"Directory not empty",
|
||||
"Too many levels of symbolic links",
|
||||
"Unknown error 41", // Unknown
|
||||
"No message of desired type",
|
||||
"Identifier removed",
|
||||
"Channel number out of range",
|
||||
"Level 2 not synchronized",
|
||||
"Level 3 halted",
|
||||
"Level 3 reset",
|
||||
"Link number out of range",
|
||||
"Protocol driver not attached",
|
||||
"No CSI structure available",
|
||||
"Level 2 halted",
|
||||
"Invalid exchange",
|
||||
"Invalid request descriptor",
|
||||
"Exchange full",
|
||||
"No anode",
|
||||
"Invalid request code",
|
||||
"Invalid slot",
|
||||
"Unknown error 58", // Unknown
|
||||
"Bad font file format",
|
||||
"Device not a stream",
|
||||
"No data available",
|
||||
"Timer expired",
|
||||
"Out of streams resources",
|
||||
"Machine is not on the network",
|
||||
"Package not installed",
|
||||
"Object is remote",
|
||||
"Link has been severed",
|
||||
"Advertise error",
|
||||
"Srmount error",
|
||||
"Communication error on send",
|
||||
"Protocol error",
|
||||
"Multihop attempted",
|
||||
"RFS specific error",
|
||||
"Bad message",
|
||||
"Value too large for defined data type",
|
||||
"Name not unique on network",
|
||||
"File descriptor in bad state",
|
||||
"Remote address changed",
|
||||
"Can not access a needed shared library",
|
||||
"Accessing a corrupted shared library",
|
||||
".lib section in a.out corrupted",
|
||||
"Attempting to link in too many shared libraries",
|
||||
"Cannot exec a shared library directly",
|
||||
"Invalid or incomplete multibyte or wide character",
|
||||
"Interrupted system call should be restarted",
|
||||
"Streams pipe error",
|
||||
"Too many users",
|
||||
"Socket operation on non-socket",
|
||||
"Destination address required",
|
||||
"Message too long",
|
||||
"Protocol wrong type for socket",
|
||||
"Protocol not available",
|
||||
"Protocol not supported",
|
||||
"Socket type not supported",
|
||||
"Operation not supported",
|
||||
"Protocol family not supported",
|
||||
"Address family not supported by protocol",
|
||||
"Address already in use",
|
||||
"Cannot assign requested address",
|
||||
"Network is down",
|
||||
"Network is unreachable",
|
||||
"Network dropped connection on reset",
|
||||
"Software caused connection abort",
|
||||
"Connection reset by peer",
|
||||
"No buffer space available",
|
||||
"Transport endpoint is already connected",
|
||||
"Transport endpoint is not connected",
|
||||
"Cannot send after transport endpoint shutdown",
|
||||
"Too many references: cannot splice",
|
||||
"Connection timed out",
|
||||
"Connection refused",
|
||||
"Host is down",
|
||||
"No route to host",
|
||||
"Operation already in progress",
|
||||
"Operation now in progress",
|
||||
"Stale file handle",
|
||||
"Structure needs cleaning",
|
||||
"Not a XENIX named type file",
|
||||
"No XENIX semaphores available",
|
||||
"Is a named type file",
|
||||
"Remote I/O error",
|
||||
"Disk quota exceeded",
|
||||
"No medium found",
|
||||
"Wrong medium type",
|
||||
"Operation canceled",
|
||||
"Required key not available",
|
||||
"Key has expired",
|
||||
"Key has been revoked",
|
||||
"Key was rejected by service",
|
||||
"Owner died",
|
||||
"State not recoverable",
|
||||
"Operation not possible due to RF-kill",
|
||||
"Memory page has hardware error",
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < (sizeof(message_array) / sizeof(char *)); ++i) {
|
||||
EXPECT_STREQ(__llvm_libc::strerror(i), message_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStrErrorTest, UnknownErrors) {
|
||||
ASSERT_STREQ(__llvm_libc::strerror(-1), "Unknown error -1");
|
||||
ASSERT_STREQ(__llvm_libc::strerror(134), "Unknown error 134");
|
||||
ASSERT_STREQ(__llvm_libc::strerror(2147483647), "Unknown error 2147483647");
|
||||
ASSERT_STREQ(__llvm_libc::strerror(-2147483648), "Unknown error -2147483648");
|
||||
}
|
Loading…
Reference in New Issue