108 changes: 108 additions & 0 deletions libc/test/src/__support/CPP/stringview_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,111 @@ TEST(LlvmLibcStringViewTest, FindLastOf) {
ASSERT_EQ(Empty1.find_last_of('a', 0), string_view::npos);
ASSERT_EQ(Empty1.find_last_of('a', 123), string_view::npos);
}

TEST(LlvmLibcStringViewTest, FindFirstNotOf) {
string_view Tmp("abada");

EXPECT_EQ(Tmp.find_first_not_of('a'), size_t(1));
EXPECT_EQ(Tmp.find_first_not_of('a', 123), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('a', 5), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('a', 4), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('a', 3), size_t(3));
EXPECT_EQ(Tmp.find_first_not_of('a', 2), size_t(3));
EXPECT_EQ(Tmp.find_first_not_of('a', 1), size_t(1));
EXPECT_EQ(Tmp.find_first_not_of('a', 0), size_t(1));

EXPECT_EQ(Tmp.find_first_not_of('b'), size_t(0));
EXPECT_EQ(Tmp.find_first_not_of('b', 123), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('b', 5), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('b', 4), size_t(4));
EXPECT_EQ(Tmp.find_first_not_of('b', 3), size_t(3));
EXPECT_EQ(Tmp.find_first_not_of('b', 2), size_t(2));
EXPECT_EQ(Tmp.find_first_not_of('b', 1), size_t(2));
EXPECT_EQ(Tmp.find_first_not_of('b', 0), size_t(0));

EXPECT_EQ(Tmp.find_first_not_of('d'), size_t(0));
EXPECT_EQ(Tmp.find_first_not_of('d', 123), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('d', 5), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('d', 4), size_t(4));
EXPECT_EQ(Tmp.find_first_not_of('d', 3), size_t(4));
EXPECT_EQ(Tmp.find_first_not_of('d', 2), size_t(2));
EXPECT_EQ(Tmp.find_first_not_of('d', 1), size_t(1));
EXPECT_EQ(Tmp.find_first_not_of('d', 0), size_t(0));

EXPECT_EQ(Tmp.find_first_not_of('e'), size_t(0));
EXPECT_EQ(Tmp.find_first_not_of('e', 123), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('e', 5), string_view::npos);
EXPECT_EQ(Tmp.find_first_not_of('e', 4), size_t(4));
EXPECT_EQ(Tmp.find_first_not_of('e', 3), size_t(3));
EXPECT_EQ(Tmp.find_first_not_of('e', 2), size_t(2));
EXPECT_EQ(Tmp.find_first_not_of('e', 1), size_t(1));
EXPECT_EQ(Tmp.find_first_not_of('e', 0), size_t(0));

string_view Empty;
EXPECT_EQ(Empty.find_first_not_of('a'), string_view::npos);
EXPECT_EQ(Empty.find_first_not_of('a', 0), string_view::npos);
EXPECT_EQ(Empty.find_first_not_of('a', 123), string_view::npos);

string_view Empty1("");
EXPECT_EQ(Empty1.find_first_not_of('a'), string_view::npos);
EXPECT_EQ(Empty1.find_first_not_of('a', 0), string_view::npos);
EXPECT_EQ(Empty1.find_first_not_of('a', 123), string_view::npos);

string_view Full("aaaaaaa");
EXPECT_EQ(Full.find_first_not_of('a'), string_view::npos);
EXPECT_EQ(Full.find_first_not_of('a', 0), string_view::npos);
EXPECT_EQ(Full.find_first_not_of('a', 123), string_view::npos);

EXPECT_EQ(Full.find_first_not_of('b'), size_t(0));
EXPECT_EQ(Full.find_first_not_of('b', 0), size_t(0));
EXPECT_EQ(Full.find_first_not_of('b', 123), string_view::npos);
}

TEST(LlvmLibcStringViewTest, Contains) {
string_view Empty;
for (char c = 'a'; c < 'z'; ++c)
EXPECT_FALSE(Empty.contains(c));

string_view Tmp("abada");
EXPECT_TRUE(Tmp.contains('a'));
EXPECT_TRUE(Tmp.contains('b'));
EXPECT_FALSE(Tmp.contains('c'));
EXPECT_TRUE(Tmp.contains('d'));
EXPECT_FALSE(Tmp.contains('e'));

EXPECT_TRUE(Tmp.substr(1).contains('a'));
EXPECT_TRUE(Tmp.substr(1).contains('b'));
EXPECT_FALSE(Tmp.substr(1).contains('c'));
EXPECT_TRUE(Tmp.substr(1).contains('d'));
EXPECT_FALSE(Tmp.substr(1).contains('e'));

EXPECT_TRUE(Tmp.substr(2).contains('a'));
EXPECT_FALSE(Tmp.substr(2).contains('b'));
EXPECT_FALSE(Tmp.substr(2).contains('c'));
EXPECT_TRUE(Tmp.substr(2).contains('d'));
EXPECT_FALSE(Tmp.substr(2).contains('e'));

EXPECT_TRUE(Tmp.substr(3).contains('a'));
EXPECT_FALSE(Tmp.substr(3).contains('b'));
EXPECT_FALSE(Tmp.substr(3).contains('c'));
EXPECT_TRUE(Tmp.substr(3).contains('d'));
EXPECT_FALSE(Tmp.substr(3).contains('e'));

EXPECT_TRUE(Tmp.substr(4).contains('a'));
EXPECT_FALSE(Tmp.substr(4).contains('b'));
EXPECT_FALSE(Tmp.substr(4).contains('c'));
EXPECT_FALSE(Tmp.substr(4).contains('d'));
EXPECT_FALSE(Tmp.substr(4).contains('e'));

EXPECT_FALSE(Tmp.substr(5).contains('a'));
EXPECT_FALSE(Tmp.substr(5).contains('b'));
EXPECT_FALSE(Tmp.substr(5).contains('c'));
EXPECT_FALSE(Tmp.substr(5).contains('d'));
EXPECT_FALSE(Tmp.substr(5).contains('e'));

EXPECT_FALSE(Tmp.substr(6).contains('a'));
EXPECT_FALSE(Tmp.substr(6).contains('b'));
EXPECT_FALSE(Tmp.substr(6).contains('c'));
EXPECT_FALSE(Tmp.substr(6).contains('d'));
EXPECT_FALSE(Tmp.substr(6).contains('e'));
}
20 changes: 20 additions & 0 deletions libc/test/src/sys/mman/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,23 @@ add_libc_unittest(
libc.src.unistd.sysconf
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
shm_test
SUITE
libc_sys_mman_unittests
SRCS
shm_test.cpp
DEPENDS
libc.include.sys_mman
libc.include.sys_syscall
libc.src.errno.errno
libc.src.sys.mman.shm_open
libc.src.sys.mman.shm_unlink
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
libc.src.unistd.ftruncate
libc.src.unistd.close
libc.src.__support.OSUtil.osutil
libc.test.UnitTest.ErrnoSetterMatcher
)
77 changes: 77 additions & 0 deletions libc/test/src/sys/mman/linux/shm_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===-- Unittests for shm_open/shm_unlink ---------------------------------===//
//
// 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/OSUtil/syscall.h"
#include "src/sys/mman/mmap.h"
#include "src/sys/mman/munmap.h"
#include "src/sys/mman/shm_open.h"
#include "src/sys/mman/shm_unlink.h"
#include "src/unistd/close.h"
#include "src/unistd/ftruncate.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/LibcTest.h"
#include <asm-generic/fcntl.h>
#include <sys/syscall.h>

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
// since shm_open/shm_unlink are wrappers around open/unlink, we only focus on
// testing basic cases and name conversions.

TEST(LlvmLibcShmTest, Basic) {
const char *name = "/test_shm_open";
int fd;
ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
returns(GE(0)).with_errno(EQ(0)));

// check that FD_CLOEXEC is set by default.
// TODO: use fcntl when implemented.
// https://github.com/llvm/llvm-project/issues/84968
long flag = LIBC_NAMESPACE::syscall_impl(SYS_fcntl, fd, F_GETFD);
ASSERT_GE(static_cast<int>(flag), 0);
EXPECT_NE(static_cast<int>(flag) & FD_CLOEXEC, 0);

// allocate space using ftruncate
ASSERT_THAT(LIBC_NAMESPACE::ftruncate(fd, 4096), Succeeds());
// map the shared memory
void *addr = LIBC_NAMESPACE::mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
ASSERT_NE(addr, MAP_FAILED);
// just write random data to the shared memory
char data[] = "Despite its name, LLVM has little to do with traditional "
"virtual machines.";
for (size_t i = 0; i < sizeof(data); ++i)
static_cast<char *>(addr)[i] = data[i];

// close fd does not affect the mapping
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
for (size_t i = 0; i < sizeof(data); ++i)
EXPECT_EQ(static_cast<char *>(addr)[i], data[i]);

// unmap the shared memory
ASSERT_THAT(LIBC_NAMESPACE::munmap(addr, 4096), Succeeds());
// remove the shared memory
ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());
}

TEST(LlvmLibcShmTest, NameConversion) {
const char *name = "////test_shm_open";
int fd;
ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
returns(GE(0)).with_errno(EQ(0)));
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::shm_open("/123/123", O_CREAT | O_RDWR, 0666),
Fails(EINVAL));

ASSERT_THAT(LIBC_NAMESPACE::shm_open("/.", O_CREAT | O_RDWR, 0666),
Fails(EINVAL));

ASSERT_THAT(LIBC_NAMESPACE::shm_open("/..", O_CREAT | O_RDWR, 0666),
Fails(EINVAL));
}