Files
llvm-project/lldb/unittests/Host/FileTest.cpp
satyanarayana reddy janga 14321cc482 [lldb] Fix missing return in NativeFile::SeekFromEnd stream path (#188596)
The stream path in NativeFile::SeekFromEnd was missing a `return result`
statement after the fseek block, causing it to fall through to the error
handler which overwrites the error status with "invalid file handle"
even on success. Both SeekFromStart and SeekFromCurrent correctly return
after their stream blocks.

while no active callers to this function, It is still worth fixing this.
2026-03-26 13:28:15 -07:00

120 lines
3.8 KiB
C++

//===-- FileTest.cpp ------------------------------------------------------===//
//
// 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 "lldb/Host/File.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "gtest/gtest.h"
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#endif
using namespace lldb;
using namespace lldb_private;
TEST(File, GetWaitableHandleFileno) {
const auto *Info = testing::UnitTest::GetInstance()->current_test_info();
llvm::SmallString<128> name;
int fd;
llvm::sys::fs::createTemporaryFile(llvm::Twine(Info->test_case_name()) + "-" +
Info->name(),
"test", fd, name);
llvm::FileRemover remover(name);
ASSERT_GE(fd, 0);
FILE *stream = fdopen(fd, "r");
ASSERT_TRUE(stream);
NativeFile file(stream, File::eOpenOptionReadWrite, true);
#ifdef _WIN32
EXPECT_EQ(file.GetWaitableHandle(), (HANDLE)_get_osfhandle(fd));
#else
EXPECT_EQ(file.GetWaitableHandle(), (file_t)fd);
#endif
}
TEST(File, GetStreamFromDescriptor) {
const auto *Info = testing::UnitTest::GetInstance()->current_test_info();
llvm::SmallString<128> name;
int fd;
llvm::sys::fs::createTemporaryFile(llvm::Twine(Info->test_case_name()) + "-" +
Info->name(),
"test", fd, name);
llvm::FileRemover remover(name);
ASSERT_GE(fd, 0);
NativeFile file(fd, File::eOpenOptionWriteOnly, true);
ASSERT_TRUE(file.IsValid());
FILE *stream = file.GetStream();
ASSERT_TRUE(stream != NULL);
EXPECT_EQ(file.GetDescriptor(), fd);
#ifdef _WIN32
EXPECT_EQ(file.GetWaitableHandle(), (HANDLE)_get_osfhandle(fd));
#else
EXPECT_EQ(file.GetWaitableHandle(), (file_t)fd);
#endif
}
TEST(File, SeekFromEndStream) {
const auto *Info = testing::UnitTest::GetInstance()->current_test_info();
llvm::SmallString<128> name;
int fd;
llvm::sys::fs::createTemporaryFile(llvm::Twine(Info->test_case_name()) + "-" +
Info->name(),
"test", fd, name);
llvm::FileRemover remover(name);
ASSERT_GE(fd, 0);
FILE *stream = fdopen(fd, "w+");
ASSERT_TRUE(stream);
// Write some data so the file has a known size.
const char data[] = "0123456789";
ASSERT_EQ(fwrite(data, 1, sizeof(data) - 1, stream), sizeof(data) - 1);
ASSERT_EQ(fflush(stream), 0);
// Use the stream-based NativeFile to exercise the stream path in
// SeekFromEnd. Before the fix, the stream path was missing a return
// statement, causing the error to be incorrectly set to "invalid file
// handle".
NativeFile file(stream, File::eOpenOptionReadWrite, true);
Status error;
off_t result = file.SeekFromEnd(-5, &error);
EXPECT_TRUE(error.Success());
EXPECT_EQ(result, 0); // fseek returns 0 on success
}
TEST(File, ReadOnlyModeNotWritable) {
const auto *Info = testing::UnitTest::GetInstance()->current_test_info();
llvm::SmallString<128> name;
int fd;
llvm::sys::fs::createTemporaryFile(llvm::Twine(Info->test_case_name()) + "-" +
Info->name(),
"test", fd, name);
llvm::FileRemover remover(name);
ASSERT_GE(fd, 0);
NativeFile file(fd, File::eOpenOptionReadOnly, true);
ASSERT_TRUE(file.IsValid());
llvm::StringLiteral buf = "Hello World";
size_t bytes_written = buf.size();
Status error = file.Write(buf.data(), bytes_written);
EXPECT_EQ(error.Fail(), true);
}