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.
120 lines
3.8 KiB
C++
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);
|
|
}
|