| //===-- 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); |
| } |