blob: c392960979165857f9efef690c34bd4c6fa6ba0b [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fbl/unique_fd.h>
#include <zxtest/zxtest.h>
#include "predicates.h"
TEST(MemFDTest, Smoke) {
fbl::unique_fd fd(memfd_create(nullptr, 0));
EXPECT_TRUE(fd.is_valid());
constexpr char payload[] = "abc";
EXPECT_EQ(write(fd.get(), payload, sizeof(payload)), ssize_t(sizeof(payload)));
char buffer[sizeof(payload) + 1] = {};
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), 0), ssize_t(sizeof(payload)));
EXPECT_STREQ(buffer, payload);
}
TEST(MemFDTest, UnsupportedOps) {
fbl::unique_fd fd(memfd_create(nullptr, 0));
EXPECT_TRUE(fd.is_valid());
ASSERT_EQ(bind(fd.get(), nullptr, 0), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(connect(fd.get(), nullptr, 0), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(listen(fd.get(), 0), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(accept(fd.get(), nullptr, nullptr), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(getsockname(fd.get(), nullptr, nullptr), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(getpeername(fd.get(), nullptr, nullptr), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(getsockopt(fd.get(), 0, 0, nullptr, nullptr), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(setsockopt(fd.get(), 0, 0, nullptr, 0), -1);
ASSERT_ERRNO(ENOTSOCK);
ASSERT_EQ(shutdown(fd.get(), 0), -1);
ASSERT_ERRNO(ENOTSOCK);
}
TEST(MemFDTest, SeekPastEnd) {
fbl::unique_fd fd(memfd_create(nullptr, 0));
EXPECT_TRUE(fd.is_valid());
constexpr char payload1[] = "abc";
EXPECT_EQ(write(fd.get(), payload1, sizeof(payload1)), ssize_t(sizeof(payload1)));
ASSERT_EQ(10543, lseek(fd.get(), 10543, SEEK_SET));
constexpr char payload2[] = "xyz";
EXPECT_EQ(write(fd.get(), payload2, sizeof(payload2)), ssize_t(sizeof(payload2)));
char buffer[std::max(sizeof(payload1), sizeof(payload2)) + 1] = {};
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), 10543), ssize_t(sizeof(payload2)));
EXPECT_STREQ(buffer, payload2);
}
TEST(MemFDTest, Truncate) {
fbl::unique_fd fd;
ASSERT_TRUE(fd = fbl::unique_fd(memfd_create(nullptr, 0)), "%s", strerror(errno));
constexpr off_t len = 10544;
EXPECT_SUCCESS(ftruncate(fd.get(), len));
constexpr char payload1[] = "xyz";
ASSERT_EQ(lseek(fd.get(), -sizeof(payload1), SEEK_END), len - ssize_t(sizeof(payload1)), "%s",
strerror(errno));
EXPECT_EQ(write(fd.get(), payload1, sizeof(payload1)), ssize_t(sizeof(payload1)), "%s",
strerror(errno));
ASSERT_EQ(lseek(fd.get(), -5014, SEEK_CUR), len - 5014, "%s", strerror(errno));
constexpr char payload2[] = "abc";
EXPECT_EQ(write(fd.get(), payload2, sizeof(payload2)), ssize_t(sizeof(payload2)), "%s",
strerror(errno));
char buffer[std::max(sizeof(payload1), sizeof(payload2)) + 1] = {};
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), len - 5014), ssize_t(sizeof(buffer)), "%s",
strerror(errno));
EXPECT_STREQ(buffer, payload2);
memset(buffer, 0, sizeof(buffer));
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), len - sizeof(payload1)),
ssize_t(sizeof(payload1)), "%s", strerror(errno));
EXPECT_STREQ(buffer, payload1);
EXPECT_SUCCESS(ftruncate(fd.get(), len - 5014));
EXPECT_SUCCESS(ftruncate(fd.get(), len));
memset(buffer, 0, sizeof(buffer));
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), 5530), ssize_t(sizeof(buffer)), "%s",
strerror(errno));
char zeros[sizeof(buffer)] = {};
EXPECT_EQ(memcmp(buffer, zeros, sizeof(buffer)), 0);
memset(buffer, 0, sizeof(buffer));
EXPECT_EQ(pread(fd.get(), buffer, sizeof(buffer), len - sizeof(payload1)),
ssize_t(sizeof(payload1)), "%s", strerror(errno));
EXPECT_EQ(memcmp(buffer, zeros, sizeof(payload1)), 0);
}
TEST(MemFDTest, MMap) {
const size_t kSize = 256;
fbl::unique_fd fd(memfd_create(nullptr, 0));
EXPECT_TRUE(fd.is_valid());
EXPECT_EQ(0, ftruncate(fd.get(), kSize));
constexpr char payload[] = "abc";
EXPECT_EQ(write(fd.get(), payload, sizeof(payload)), ssize_t(sizeof(payload)));
void* ptr = mmap(nullptr, kSize, PROT_READ, MAP_SHARED, fd.get(), 0u);
EXPECT_NE(MAP_FAILED, ptr);
char buffer[sizeof(payload) + 1] = {};
memcpy(buffer, ptr, sizeof(buffer));
EXPECT_STREQ(payload, buffer);
ASSERT_EQ(0, munmap(ptr, kSize));
}