blob: a50936916893416ee49dc76cf7a03eff45a96df0 [file]
// Copyright 2026 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/fxcrt/span_io.h"
#include <stdio.h>
#include <string>
#include <string_view>
#include "build/build_config.h"
#include "core/fxcrt/span.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/utils/file_util.h"
#if BUILDFLAG(IS_POSIX)
#include <fcntl.h>
#include <unistd.h>
#endif
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
TEST(Spanread, ReadNormal) {
pdfium::ScopedFILE scoped_f(tmpfile());
FILE* f = scoped_f.get();
ASSERT_TRUE(f);
const char kData[] = "hello world";
ASSERT_EQ(UNSAFE_BUFFERS(fwrite(kData, 1, sizeof(kData), f)), sizeof(kData));
rewind(f);
char buffer[100];
pdfium::span<char> read_span = fxcrt::spanread(buffer, f);
EXPECT_EQ(read_span.size(), sizeof(kData));
EXPECT_STREQ(read_span.data(), kData);
}
TEST(Spanread, ReadTruncated) {
pdfium::ScopedFILE scoped_f(tmpfile());
FILE* f = scoped_f.get();
ASSERT_TRUE(f);
const char kData[] = "hello world";
ASSERT_EQ(UNSAFE_BUFFERS(fwrite(kData, 1, sizeof(kData), f)), sizeof(kData));
rewind(f);
char buffer[5];
pdfium::span<char> read_span = fxcrt::spanread(buffer, f);
EXPECT_EQ(read_span.size(), 5u);
EXPECT_EQ(std::string_view(read_span.data(), read_span.size()), "hello");
}
TEST(Spanread, ReadEmpty) {
pdfium::ScopedFILE scoped_f(tmpfile());
FILE* f = scoped_f.get();
ASSERT_TRUE(f);
pdfium::span<char> empty_span;
pdfium::span<char> read_span = fxcrt::spanread(empty_span, f);
EXPECT_TRUE(read_span.empty());
}
TEST(Spanwrite, WriteNormal) {
pdfium::ScopedFILE scoped_f(tmpfile());
FILE* f = scoped_f.get();
ASSERT_TRUE(f);
const char kData[] = "hello world";
// Also test that raw array is acceptable (implicit conversion).
EXPECT_EQ(fxcrt::spanwrite(kData, f), sizeof(kData));
rewind(f);
char buffer[100];
size_t read = UNSAFE_BUFFERS(fread(buffer, 1, sizeof(kData), f));
EXPECT_EQ(read, sizeof(kData));
EXPECT_STREQ(buffer, kData);
}
TEST(Spanwrite, WriteEmpty) {
pdfium::ScopedFILE scoped_f(tmpfile());
FILE* f = scoped_f.get();
ASSERT_TRUE(f);
pdfium::span<const char> empty_span;
EXPECT_EQ(fxcrt::spanwrite(empty_span, f), 0u);
}
#if BUILDFLAG(IS_POSIX)
TEST(SpanreadFD, ReadNormal) {
std::string path = testing::TempDir() + "/pdfium_span_unittest_XXXXXX";
pdfium::ScopedFD scoped_fd(mkstemp(path.data()));
int fd = scoped_fd.get();
ASSERT_GE(fd, 0);
const char kData[] = "hello world";
ASSERT_EQ(write(fd, kData, sizeof(kData)),
static_cast<ssize_t>(sizeof(kData)));
lseek(fd, 0, SEEK_SET);
char buffer[100];
pdfium::span<char> read_span = fxcrt::spanread(buffer, fd);
EXPECT_EQ(read_span.size(), sizeof(kData));
EXPECT_STREQ(read_span.data(), kData);
unlink(path.c_str());
}
TEST(SpanreadFD, ReadEmpty) {
std::string path = testing::TempDir() + "/pdfium_span_unittest_XXXXXX";
pdfium::ScopedFD scoped_fd(mkstemp(path.data()));
int fd = scoped_fd.get();
ASSERT_GE(fd, 0);
pdfium::span<char> empty_span;
pdfium::span<char> read_span = fxcrt::spanread(empty_span, fd);
EXPECT_TRUE(read_span.empty());
unlink(path.c_str());
}
TEST(SpanwriteFD, WriteNormal) {
std::string path = testing::TempDir() + "/pdfium_span_unittest_XXXXXX";
pdfium::ScopedFD scoped_fd(mkstemp(path.data()));
int fd = scoped_fd.get();
ASSERT_GE(fd, 0);
const char kData[] = "hello world";
EXPECT_EQ(fxcrt::spanwrite(kData, fd), sizeof(kData));
lseek(fd, 0, SEEK_SET);
char buffer[100];
ssize_t bytes_read = read(fd, buffer, sizeof(kData));
EXPECT_EQ(bytes_read, static_cast<ssize_t>(sizeof(kData)));
EXPECT_STREQ(buffer, kData);
unlink(path.c_str());
}
TEST(SpanwriteFD, WriteEmpty) {
std::string path = testing::TempDir() + "/pdfium_span_unittest_XXXXXX";
pdfium::ScopedFD scoped_fd(mkstemp(path.data()));
int fd = scoped_fd.get();
ASSERT_GE(fd, 0);
pdfium::span<const char> empty_span;
EXPECT_EQ(fxcrt::spanwrite(empty_span, fd), 0u);
unlink(path.c_str());
}
#endif // BUILDFLAG(IS_POSIX)
#if BUILDFLAG(IS_WIN)
TEST(SpanreadWin, ReadNormal) {
std::string path = testing::TempDir() + "/pdfium_span_win_unittest.tmp";
std::wstring wpath(path.begin(), path.end());
pdfium::ScopedHandle scoped_handle(::CreateFileW(
wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr));
HANDLE handle = scoped_handle.get();
ASSERT_NE(handle, INVALID_HANDLE_VALUE);
const char kData[] = "hello world";
DWORD bytes_written = 0;
ASSERT_TRUE(
::WriteFile(handle, kData, sizeof(kData), &bytes_written, nullptr));
ASSERT_EQ(bytes_written, sizeof(kData));
// Seek to beginning
ASSERT_NE(::SetFilePointer(handle, 0, nullptr, FILE_BEGIN),
INVALID_SET_FILE_POINTER);
char buffer[100];
pdfium::span<char> read_span = fxcrt::spanread(buffer, handle);
EXPECT_EQ(read_span.size(), sizeof(kData));
EXPECT_STREQ(read_span.data(), kData);
}
TEST(SpanreadWin, ReadEmpty) {
std::string path = testing::TempDir() + "/pdfium_span_win_unittest.tmp";
std::wstring wpath(path.begin(), path.end());
pdfium::ScopedHandle scoped_handle(::CreateFileW(
wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr));
HANDLE handle = scoped_handle.get();
ASSERT_NE(handle, INVALID_HANDLE_VALUE);
pdfium::span<char> empty_span;
pdfium::span<char> read_span = fxcrt::spanread(empty_span, handle);
EXPECT_TRUE(read_span.empty());
}
TEST(SpanwriteWin, WriteNormal) {
std::string path = testing::TempDir() + "/pdfium_span_win_unittest.tmp";
std::wstring wpath(path.begin(), path.end());
pdfium::ScopedHandle scoped_handle(::CreateFileW(
wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr));
HANDLE handle = scoped_handle.get();
ASSERT_NE(handle, INVALID_HANDLE_VALUE);
const char kData[] = "hello world";
EXPECT_EQ(fxcrt::spanwrite(kData, handle), sizeof(kData));
// Seek to beginning
ASSERT_NE(::SetFilePointer(handle, 0, nullptr, FILE_BEGIN),
INVALID_SET_FILE_POINTER);
char buffer[100];
DWORD bytes_read = 0;
ASSERT_TRUE(::ReadFile(handle, buffer, sizeof(kData), &bytes_read, nullptr));
EXPECT_EQ(bytes_read, sizeof(kData));
EXPECT_STREQ(buffer, kData);
}
TEST(SpanwriteWin, WriteEmpty) {
std::string path = testing::TempDir() + "/pdfium_span_win_unittest.tmp";
std::wstring wpath(path.begin(), path.end());
pdfium::ScopedHandle scoped_handle(::CreateFileW(
wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr));
HANDLE handle = scoped_handle.get();
ASSERT_NE(handle, INVALID_HANDLE_VALUE);
pdfium::span<const char> empty_span;
EXPECT_EQ(fxcrt::spanwrite(empty_span, handle), 0u);
}
#endif // BUILDFLAG(IS_WIN)