diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
commit | 74a628f776edb588bff8f8f5cc16eac947c9d631 (patch) | |
tree | dc32e010ac4902621e5a279bfeb48628f7f0e166 /unittests | |
parent | afed7be32164a598f8172282c249af7266c48b46 (diff) | |
download | src-74a628f776edb588bff8f8f5cc16eac947c9d631.tar.gz src-74a628f776edb588bff8f8f5cc16eac947c9d631.zip |
Vendor import of lldb trunk r300422:vendor/lldb/lldb-trunk-r300422
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=317027
svn path=/vendor/lldb/lldb-trunk-r300422/; revision=317028; tag=vendor/lldb/lldb-trunk-r300422
Diffstat (limited to 'unittests')
66 files changed, 1882 insertions, 153 deletions
diff --git a/unittests/Breakpoint/BreakpointIDTest.cpp b/unittests/Breakpoint/BreakpointIDTest.cpp index a449d40a335a..a84fa5439527 100644 --- a/unittests/Breakpoint/BreakpointIDTest.cpp +++ b/unittests/Breakpoint/BreakpointIDTest.cpp @@ -10,7 +10,7 @@ #include "gtest/gtest.h" #include "lldb/Breakpoint/BreakpointID.h" -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h" #include "llvm/ADT/StringRef.h" diff --git a/unittests/Breakpoint/CMakeLists.txt b/unittests/Breakpoint/CMakeLists.txt index ca1c282aaa66..e3715e55f0d7 100644 --- a/unittests/Breakpoint/CMakeLists.txt +++ b/unittests/Breakpoint/CMakeLists.txt @@ -1,3 +1,9 @@ add_lldb_unittest(LLDBBreakpointTests BreakpointIDTest.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + LINK_COMPONENTS + Support ) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index a865dbe244f8..f4c735e78e34 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -2,6 +2,7 @@ add_custom_target(LLDBUnitTests) set_target_properties(LLDBUnitTests PROPERTIES FOLDER "LLDB tests") include_directories(${LLDB_SOURCE_ROOT}) +include_directories(${LLDB_PROJECT_ROOT}) set(LLDB_GTEST_COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/gtest_common.h) if (MSVC) @@ -21,9 +22,17 @@ if (LLDB_BUILT_STANDALONE) endif() function(add_lldb_unittest test_name) + cmake_parse_arguments(ARG + "" + "" + "LINK_LIBS;LINK_COMPONENTS" + ${ARGN}) + + list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) + add_unittest(LLDBUnitTests ${test_name} - ${ARGN} + ${ARG_UNPARSED_ARGUMENTS} ) add_custom_command( @@ -31,9 +40,7 @@ function(add_lldb_unittest test_name) POST_BUILD COMMAND "${CMAKE_COMMAND}" -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/Inputs) - lldb_link_common_libs(${test_name} EXE) - target_link_libraries(${test_name} ${CLANG_USED_LIBS} ${LLDB_SYSTEM_LIBS}) - llvm_config(${test_name} ${LLVM_LINK_COMPONENTS}) + target_link_libraries(${test_name} ${ARG_LINK_LIBS} ${CLANG_USED_LIBS} ${LLDB_SYSTEM_LIBS}) endfunction() function(add_unittest_inputs test_name inputs) @@ -53,10 +60,17 @@ add_subdirectory(Expression) add_subdirectory(Host) add_subdirectory(Interpreter) add_subdirectory(Language) +add_subdirectory(ObjectFile) add_subdirectory(Platform) add_subdirectory(Process) add_subdirectory(ScriptInterpreter) +add_subdirectory(Signals) add_subdirectory(Symbol) add_subdirectory(SymbolFile) +add_subdirectory(Target) add_subdirectory(UnwindAssembly) add_subdirectory(Utility) + +if(LLDB_CAN_USE_DEBUGSERVER) + add_subdirectory(debugserver) +endif()
\ No newline at end of file diff --git a/unittests/Core/BroadcasterTest.cpp b/unittests/Core/BroadcasterTest.cpp index e3795822f9ac..1613d0806009 100644 --- a/unittests/Core/BroadcasterTest.cpp +++ b/unittests/Core/BroadcasterTest.cpp @@ -10,6 +10,7 @@ #include "gtest/gtest.h" #include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Event.h" #include "lldb/Core/Listener.h" #include "lldb/Host/Predicate.h" diff --git a/unittests/Core/CMakeLists.txt b/unittests/Core/CMakeLists.txt index 980bc5b9f9ae..73dd0d83fee3 100644 --- a/unittests/Core/CMakeLists.txt +++ b/unittests/Core/CMakeLists.txt @@ -2,9 +2,16 @@ add_lldb_unittest(LLDBCoreTests ArchSpecTest.cpp BroadcasterTest.cpp DataExtractorTest.cpp - ErrorTest.cpp ListenerTest.cpp ScalarTest.cpp + StateTest.cpp + StreamCallbackTest.cpp StructuredDataTest.cpp TimerTest.cpp + + LINK_LIBS + lldbCore + lldbHost + LINK_COMPONENTS + Support ) diff --git a/unittests/Core/DataExtractorTest.cpp b/unittests/Core/DataExtractorTest.cpp index d474e21dc0c3..213d5a7b43fd 100644 --- a/unittests/Core/DataExtractorTest.cpp +++ b/unittests/Core/DataExtractorTest.cpp @@ -7,16 +7,9 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif - #include "gtest/gtest.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataExtractor.h" using namespace lldb_private; diff --git a/unittests/Core/ScalarTest.cpp b/unittests/Core/ScalarTest.cpp index b79854f97ae3..3c4995c49086 100644 --- a/unittests/Core/ScalarTest.cpp +++ b/unittests/Core/ScalarTest.cpp @@ -7,20 +7,13 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif - #include "gtest/gtest.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Error.h" #include "lldb/Core/Scalar.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/Endian.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/StreamString.h" using namespace lldb_private; diff --git a/unittests/Core/StateTest.cpp b/unittests/Core/StateTest.cpp new file mode 100644 index 000000000000..76cdaac82055 --- /dev/null +++ b/unittests/Core/StateTest.cpp @@ -0,0 +1,21 @@ +//===-- StateTest.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/State.h" +#include "llvm/Support/FormatVariadic.h" +#include "gtest/gtest.h" + +using namespace lldb; +using namespace lldb_private; + +TEST(StateTest, Formatv) { + EXPECT_EQ("exited", llvm::formatv("{0}", eStateExited).str()); + EXPECT_EQ("stopped", llvm::formatv("{0}", eStateStopped).str()); + EXPECT_EQ("unknown", llvm::formatv("{0}", StateType(-1)).str()); +} diff --git a/unittests/Core/StreamCallbackTest.cpp b/unittests/Core/StreamCallbackTest.cpp new file mode 100644 index 000000000000..d3ccd0211a4e --- /dev/null +++ b/unittests/Core/StreamCallbackTest.cpp @@ -0,0 +1,28 @@ +//===-- StreamCallbackTest.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/StreamCallback.h" +#include "gtest/gtest.h" + +using namespace lldb; +using namespace lldb_private; + +static char test_baton; +static size_t callback_count = 0; +static void TestCallback(const char *data, void *baton) { + EXPECT_STREQ("Foobar", data); + EXPECT_EQ(&test_baton, baton); + ++callback_count; +} + +TEST(StreamCallbackTest, Callback) { + StreamCallback stream(TestCallback, &test_baton); + stream << "Foobar"; + EXPECT_EQ(1u, callback_count); +} diff --git a/unittests/Core/StructuredDataTest.cpp b/unittests/Core/StructuredDataTest.cpp index 8e10d571fbfa..cac330304179 100644 --- a/unittests/Core/StructuredDataTest.cpp +++ b/unittests/Core/StructuredDataTest.cpp @@ -10,7 +10,7 @@ #include "gtest/gtest.h" #include "lldb/Core/StructuredData.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Utility/StreamString.h" #include "llvm/Support/MachO.h" diff --git a/unittests/Core/TimerTest.cpp b/unittests/Core/TimerTest.cpp index d37d281f61af..7e7eeef0a361 100644 --- a/unittests/Core/TimerTest.cpp +++ b/unittests/Core/TimerTest.cpp @@ -7,16 +7,10 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when exceptions are disabled. -#include <eh.h> -#endif - #include "lldb/Core/Timer.h" #include "gtest/gtest.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Utility/StreamString.h" #include <thread> using namespace lldb_private; diff --git a/unittests/Editline/CMakeLists.txt b/unittests/Editline/CMakeLists.txt index eaa21c490d98..4f656f6cc350 100644 --- a/unittests/Editline/CMakeLists.txt +++ b/unittests/Editline/CMakeLists.txt @@ -1,3 +1,8 @@ add_lldb_unittest(EditlineTests EditlineTest.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbUtility ) diff --git a/unittests/Editline/EditlineTest.cpp b/unittests/Editline/EditlineTest.cpp index 55dae525ddc3..f4976a348198 100644 --- a/unittests/Editline/EditlineTest.cpp +++ b/unittests/Editline/EditlineTest.cpp @@ -19,11 +19,11 @@ #include "gtest/gtest.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/StringList.h" #include "lldb/Host/Editline.h" #include "lldb/Host/Pipe.h" -#include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Host/PseudoTerminal.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/StringList.h" namespace { const size_t TIMEOUT_MILLIS = 5000; diff --git a/unittests/Expression/CMakeLists.txt b/unittests/Expression/CMakeLists.txt index 04bad141170b..c0a701da4f3d 100644 --- a/unittests/Expression/CMakeLists.txt +++ b/unittests/Expression/CMakeLists.txt @@ -1,3 +1,7 @@ add_lldb_unittest(ExpressionTests GoParserTest.cpp + + LINK_LIBS + lldbCore + lldbPluginExpressionParserGo ) diff --git a/unittests/Expression/GoParserTest.cpp b/unittests/Expression/GoParserTest.cpp index de489e43ef22..710dc5e4e86f 100644 --- a/unittests/Expression/GoParserTest.cpp +++ b/unittests/Expression/GoParserTest.cpp @@ -8,19 +8,12 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif - #include <sstream> #include "gtest/gtest.h" #include "Plugins/ExpressionParser/Go/GoParser.h" -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h" using namespace lldb_private; diff --git a/unittests/Host/CMakeLists.txt b/unittests/Host/CMakeLists.txt index 4c20f820e3c8..3396f45da4f3 100644 --- a/unittests/Host/CMakeLists.txt +++ b/unittests/Host/CMakeLists.txt @@ -1,7 +1,21 @@ -add_lldb_unittest(HostTests +set (FILES FileSpecTest.cpp FileSystemTest.cpp SocketAddressTest.cpp SocketTest.cpp SymbolsTest.cpp +) + +if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + list(APPEND FILES + linux/HostTest.cpp + linux/SupportTest.cpp + ) +endif() + +add_lldb_unittest(HostTests + ${FILES} + LINK_LIBS + lldbCore + lldbHost ) diff --git a/unittests/Host/FileSpecTest.cpp b/unittests/Host/FileSpecTest.cpp index 55a66b3b37eb..cb6877e7b622 100644 --- a/unittests/Host/FileSpecTest.cpp +++ b/unittests/Host/FileSpecTest.cpp @@ -9,7 +9,7 @@ #include "gtest/gtest.h" -#include "lldb/Host/FileSpec.h" +#include "lldb/Utility/FileSpec.h" using namespace lldb_private; @@ -109,6 +109,28 @@ TEST(FileSpecTest, CopyByAppendingPathComponent) { EXPECT_STREQ("bar", fs.GetFilename().GetCString()); } +TEST(FileSpecTest, PrependPathComponent) { + FileSpec fs_posix("foo", false, FileSpec::ePathSyntaxPosix); + fs_posix.PrependPathComponent("/bar"); + EXPECT_STREQ("/bar/foo", fs_posix.GetCString()); + + FileSpec fs_posix_2("foo/bar", false, FileSpec::ePathSyntaxPosix); + fs_posix_2.PrependPathComponent("/baz"); + EXPECT_STREQ("/baz/foo/bar", fs_posix_2.GetCString()); + + FileSpec fs_windows("baz", false, FileSpec::ePathSyntaxWindows); + fs_windows.PrependPathComponent("F:\\bar"); + EXPECT_STREQ("F:\\bar\\baz", fs_windows.GetCString()); + + FileSpec fs_posix_root("bar", false, FileSpec::ePathSyntaxPosix); + fs_posix_root.PrependPathComponent("/"); + EXPECT_STREQ("/bar", fs_posix_root.GetCString()); + + FileSpec fs_windows_root("bar", false, FileSpec::ePathSyntaxWindows); + fs_windows_root.PrependPathComponent("F:\\"); + EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString()); +} + static void Compare(const FileSpec &one, const FileSpec &two, bool full_match, bool remove_backup_dots, bool result) { EXPECT_EQ(result, FileSpec::Equal(one, two, full_match, remove_backup_dots)) @@ -142,6 +164,7 @@ TEST(FileSpecTest, EqualDotsWindows) { {R"(C:/bar/baz)", R"(C:\foo\..\bar\baz)"}, {R"(C:\bar)", R"(C:\foo\..\bar)"}, {R"(C:\foo\bar)", R"(C:\foo\.\bar)"}, + {R"(C:\foo\bar)", R"(C:\foo\bar\.)"}, }; for(const auto &test: tests) { @@ -165,6 +188,7 @@ TEST(FileSpecTest, EqualDotsPosix) { {R"(/bar/baz)", R"(/foo/../bar/baz)"}, {R"(/bar)", R"(/foo/../bar)"}, {R"(/foo/bar)", R"(/foo/./bar)"}, + {R"(/foo/bar)", R"(/foo/bar/.)"}, }; for(const auto &test: tests) { @@ -283,4 +307,4 @@ TEST(FileSpecTest, FormatFileSpec) { EXPECT_EQ("foo", llvm::formatv("{0}", F).str()); EXPECT_EQ("foo", llvm::formatv("{0:F}", F).str()); EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str()); -}
\ No newline at end of file +} diff --git a/unittests/Host/SocketTest.cpp b/unittests/Host/SocketTest.cpp index 569a4404131e..7abb010a9089 100644 --- a/unittests/Host/SocketTest.cpp +++ b/unittests/Host/SocketTest.cpp @@ -7,13 +7,6 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif - #include <cstdio> #include <functional> #include <thread> @@ -203,17 +196,14 @@ TEST_F(SocketTest, TCPGetAddress) { } TEST_F(SocketTest, UDPConnect) { - Socket *socket_a; - Socket *socket_b; + Socket *socket; bool child_processes_inherit = false; auto error = UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, - socket_a, socket_b); + socket); - std::unique_ptr<Socket> a_up(socket_a); - std::unique_ptr<Socket> b_up(socket_b); + std::unique_ptr<Socket> socket_up(socket); EXPECT_TRUE(error.Success()); - EXPECT_TRUE(a_up->IsValid()); - EXPECT_TRUE(b_up->IsValid()); + EXPECT_TRUE(socket_up->IsValid()); } diff --git a/unittests/Host/linux/HostTest.cpp b/unittests/Host/linux/HostTest.cpp new file mode 100644 index 000000000000..36d3fd206dac --- /dev/null +++ b/unittests/Host/linux/HostTest.cpp @@ -0,0 +1,48 @@ +//===-- HostTest.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Process.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +namespace { +class HostTest : public testing::Test { +public: + static void SetUpTestCase() { HostInfo::Initialize(); } + static void TearDownTestCase() { HostInfo::Terminate(); } +}; +} // namespace + +TEST_F(HostTest, GetProcessInfo) { + ProcessInstanceInfo Info; + ASSERT_FALSE(Host::GetProcessInfo(0, Info)); + + ASSERT_TRUE(Host::GetProcessInfo(getpid(), Info)); + + ASSERT_TRUE(Info.ProcessIDIsValid()); + EXPECT_EQ(lldb::pid_t(getpid()), Info.GetProcessID()); + + ASSERT_TRUE(Info.ParentProcessIDIsValid()); + EXPECT_EQ(lldb::pid_t(getppid()), Info.GetParentProcessID()); + + ASSERT_TRUE(Info.EffectiveUserIDIsValid()); + EXPECT_EQ(geteuid(), Info.GetEffectiveUserID()); + + ASSERT_TRUE(Info.EffectiveGroupIDIsValid()); + EXPECT_EQ(getegid(), Info.GetEffectiveGroupID()); + + ASSERT_TRUE(Info.UserIDIsValid()); + EXPECT_EQ(geteuid(), Info.GetUserID()); + + ASSERT_TRUE(Info.GroupIDIsValid()); + EXPECT_EQ(getegid(), Info.GetGroupID()); +} diff --git a/unittests/Host/linux/SupportTest.cpp b/unittests/Host/linux/SupportTest.cpp new file mode 100644 index 000000000000..9b63084827af --- /dev/null +++ b/unittests/Host/linux/SupportTest.cpp @@ -0,0 +1,26 @@ +//===-- SupportTest.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/linux/Support.h" +#include "llvm/Support/Threading.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +TEST(Support, getProcFile_Pid) { + auto BufferOrError = getProcFile(getpid(), "maps"); + ASSERT_TRUE(BufferOrError); + ASSERT_TRUE(*BufferOrError); +} + +TEST(Support, getProcFile_Tid) { + auto BufferOrError = getProcFile(getpid(), llvm::get_threadid(), "comm"); + ASSERT_TRUE(BufferOrError); + ASSERT_TRUE(*BufferOrError); +} diff --git a/unittests/Interpreter/CMakeLists.txt b/unittests/Interpreter/CMakeLists.txt index 4078476bc75a..d884dee62ec5 100644 --- a/unittests/Interpreter/CMakeLists.txt +++ b/unittests/Interpreter/CMakeLists.txt @@ -1,5 +1,10 @@ add_lldb_unittest(InterpreterTests TestArgs.cpp + TestCompletion.cpp + + LINK_LIBS + lldbInterpreter + lldbUtilityMocks ) target_link_libraries(InterpreterTests diff --git a/unittests/Interpreter/TestArgs.cpp b/unittests/Interpreter/TestArgs.cpp index 9dcf09d54aea..2aeed0f542b1 100644 --- a/unittests/Interpreter/TestArgs.cpp +++ b/unittests/Interpreter/TestArgs.cpp @@ -169,6 +169,14 @@ TEST(ArgsTest, AppendArguments) { EXPECT_STREQ("4", args.GetArgumentAtIndex(3)); } +TEST(ArgsTest, GetArgumentArrayRef) { + Args args("foo bar"); + auto ref = args.GetArgumentArrayRef(); + ASSERT_EQ(2u, ref.size()); + EXPECT_STREQ("foo", ref[0]); + EXPECT_STREQ("bar", ref[1]); +} + TEST(ArgsTest, StringToBoolean) { bool success = false; EXPECT_TRUE(Args::StringToBoolean(llvm::StringRef("true"), false, nullptr)); diff --git a/unittests/Interpreter/TestCompletion.cpp b/unittests/Interpreter/TestCompletion.cpp new file mode 100644 index 000000000000..0548b93d6f72 --- /dev/null +++ b/unittests/Interpreter/TestCompletion.cpp @@ -0,0 +1,307 @@ +//===-- TestCompletion.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Utility/StringList.h" +#include "lldb/Utility/TildeExpressionResolver.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +#include "unittests/Utility/Mocks/MockTildeExpressionResolver.h" + +namespace fs = llvm::sys::fs; +namespace path = llvm::sys::path; +using namespace llvm; +using namespace lldb_private; + +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } + +namespace { + +class CompletionTest : public testing::Test { +protected: + /// Unique temporary directory in which all created filesystem entities must + /// be placed. It is removed at the end of the test suite. + static SmallString<128> BaseDir; + + static SmallString<128> OriginalWorkingDir; + + static SmallString<128> DirFoo; + static SmallString<128> DirFooA; + static SmallString<128> DirFooB; + static SmallString<128> DirFooC; + static SmallString<128> DirBar; + static SmallString<128> DirBaz; + static SmallString<128> DirTestFolder; + + static SmallString<128> FileAA; + static SmallString<128> FileAB; + static SmallString<128> FileAC; + static SmallString<128> FileFoo; + static SmallString<128> FileBar; + static SmallString<128> FileBaz; + + void SetUp() override { llvm::sys::fs::set_current_path(OriginalWorkingDir); } + + static void SetUpTestCase() { + llvm::sys::fs::current_path(OriginalWorkingDir); + + ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion", BaseDir)); + const char *DirNames[] = {"foo", "fooa", "foob", "fooc", + "bar", "baz", "test_folder"}; + const char *FileNames[] = {"aa1234.tmp", "ab1234.tmp", "ac1234.tmp", + "foo1234.tmp", "bar1234.tmp", "baz1234.tmp"}; + SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC, + &DirBar, &DirBaz, &DirTestFolder}; + for (auto Dir : llvm::zip(DirNames, Dirs)) { + auto &Path = *std::get<1>(Dir); + Path = BaseDir; + path::append(Path, std::get<0>(Dir)); + ASSERT_NO_ERROR(fs::create_directory(Path)); + } + + SmallString<128> *Files[] = {&FileAA, &FileAB, &FileAC, + &FileFoo, &FileBar, &FileBaz}; + for (auto File : llvm::zip(FileNames, Files)) { + auto &Path = *std::get<1>(File); + Path = BaseDir; + path::append(Path, std::get<0>(File)); + int FD; + ASSERT_NO_ERROR(fs::createUniqueFile(Path, FD, Path)); + ::close(FD); + } + } + + static void TearDownTestCase() { + ASSERT_NO_ERROR(fs::remove_directories(BaseDir)); + } + + static bool HasEquivalentFile(const Twine &Path, const StringList &Paths) { + for (size_t I = 0; I < Paths.GetSize(); ++I) { + if (fs::equivalent(Path, Paths[I])) + return true; + } + return false; + } + + static bool ContainsExactString(const Twine &Str, const StringList &Paths) { + SmallString<16> Storage; + StringRef Rendered = Str.toStringRef(Storage); + for (size_t I = 0; I < Paths.GetSize(); ++I) { + if (Paths[I] == Rendered) + return true; + } + return false; + } + + void DoDirCompletions(const Twine &Prefix, + StandardTildeExpressionResolver &Resolver, + StringList &Results) { + // When a partial name matches, it returns all matches. If it matches both + // a full name AND some partial names, it returns all of them. + uint32_t Count = + CommandCompletions::DiskDirectories(Prefix + "foo", Results, Resolver); + ASSERT_EQ(4u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirFoo, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooA, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooB, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooC, Results)); + + // If it matches only partial names, it still works as expected. + Count = CommandCompletions::DiskDirectories(Twine(Prefix) + "b", Results, + Resolver); + ASSERT_EQ(2u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirBar, Results)); + EXPECT_TRUE(HasEquivalentFile(DirBaz, Results)); + } +}; + +SmallString<128> CompletionTest::BaseDir; +SmallString<128> CompletionTest::OriginalWorkingDir; + +SmallString<128> CompletionTest::DirFoo; +SmallString<128> CompletionTest::DirFooA; +SmallString<128> CompletionTest::DirFooB; +SmallString<128> CompletionTest::DirFooC; +SmallString<128> CompletionTest::DirBar; +SmallString<128> CompletionTest::DirBaz; +SmallString<128> CompletionTest::DirTestFolder; + +SmallString<128> CompletionTest::FileAA; +SmallString<128> CompletionTest::FileAB; +SmallString<128> CompletionTest::FileAC; +SmallString<128> CompletionTest::FileFoo; +SmallString<128> CompletionTest::FileBar; +SmallString<128> CompletionTest::FileBaz; +} + +TEST_F(CompletionTest, DirCompletionAbsolute) { + // All calls to DiskDirectories() return only directories, even when + // there are files which also match. The tests below all check this + // by asserting an exact result count, and verifying against known + // folders. + + std::string Prefixes[] = {(Twine(BaseDir) + "/").str(), ""}; + + StandardTildeExpressionResolver Resolver; + StringList Results; + + // When a directory is specified that doesn't end in a slash, it searches + // for that directory, not items under it. + size_t Count = + CommandCompletions::DiskDirectories(BaseDir, Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(BaseDir, Results)); + + // When the same directory ends with a slash, it finds all children. + Count = CommandCompletions::DiskDirectories(Prefixes[0], Results, Resolver); + ASSERT_EQ(7u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirFoo, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooA, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooB, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooC, Results)); + EXPECT_TRUE(HasEquivalentFile(DirBar, Results)); + EXPECT_TRUE(HasEquivalentFile(DirBaz, Results)); + EXPECT_TRUE(HasEquivalentFile(DirTestFolder, Results)); + + DoDirCompletions(Twine(BaseDir) + "/", Resolver, Results); + llvm::sys::fs::set_current_path(BaseDir); + DoDirCompletions("", Resolver, Results); +} + +TEST_F(CompletionTest, FileCompletionAbsolute) { + // All calls to DiskFiles() return both files and directories The tests below + // all check this by asserting an exact result count, and verifying against + // known folders. + + StandardTildeExpressionResolver Resolver; + StringList Results; + // When an item is specified that doesn't end in a slash but exactly matches + // one item, it returns that item. + size_t Count = CommandCompletions::DiskFiles(Twine(BaseDir) + "/fooa", + Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirFooA, Results)); + + // The previous check verified a directory match. But it should work for + // files too. + Count = + CommandCompletions::DiskFiles(Twine(BaseDir) + "/aa", Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(FileAA, Results)); + + // When it ends with a slash, it should find all files and directories. + Count = + CommandCompletions::DiskFiles(Twine(BaseDir) + "/", Results, Resolver); + ASSERT_EQ(13u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirFoo, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooA, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooB, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooC, Results)); + EXPECT_TRUE(HasEquivalentFile(DirBar, Results)); + EXPECT_TRUE(HasEquivalentFile(DirBaz, Results)); + EXPECT_TRUE(HasEquivalentFile(DirTestFolder, Results)); + + EXPECT_TRUE(HasEquivalentFile(FileAA, Results)); + EXPECT_TRUE(HasEquivalentFile(FileAB, Results)); + EXPECT_TRUE(HasEquivalentFile(FileAC, Results)); + EXPECT_TRUE(HasEquivalentFile(FileFoo, Results)); + EXPECT_TRUE(HasEquivalentFile(FileBar, Results)); + EXPECT_TRUE(HasEquivalentFile(FileBaz, Results)); + + // When a partial name matches, it returns all file & directory matches. + Count = + CommandCompletions::DiskFiles(Twine(BaseDir) + "/foo", Results, Resolver); + ASSERT_EQ(5u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(HasEquivalentFile(DirFoo, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooA, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooB, Results)); + EXPECT_TRUE(HasEquivalentFile(DirFooC, Results)); + EXPECT_TRUE(HasEquivalentFile(FileFoo, Results)); +} + +TEST_F(CompletionTest, DirCompletionUsername) { + MockTildeExpressionResolver Resolver("James", BaseDir); + Resolver.AddKnownUser("Kirk", DirFooB); + Resolver.AddKnownUser("Lars", DirFooC); + Resolver.AddKnownUser("Jason", DirFoo); + Resolver.AddKnownUser("Larry", DirFooA); + + // Just resolving current user's home directory by itself should return the + // directory. + StringList Results; + size_t Count = CommandCompletions::DiskDirectories("~", Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(ContainsExactString(Twine("~") + path::get_separator(), Results)); + + // With a slash appended, it should return all items in the directory. + Count = CommandCompletions::DiskDirectories("~/", Results, Resolver); + ASSERT_EQ(7u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE( + ContainsExactString(Twine("~/foo") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~/fooa") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~/foob") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~/fooc") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~/bar") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~/baz") + path::get_separator(), Results)); + EXPECT_TRUE(ContainsExactString( + Twine("~/test_folder") + path::get_separator(), Results)); + + // With ~username syntax it should return one match if there is an exact + // match. + // It shouldn't translate to the actual directory, it should keep the form the + // user typed. + Count = CommandCompletions::DiskDirectories("~Lars", Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE( + ContainsExactString(Twine("~Lars") + path::get_separator(), Results)); + + // But with a username that is not found, no results are returned. + Count = CommandCompletions::DiskDirectories("~Dave", Results, Resolver); + ASSERT_EQ(0u, Count); + ASSERT_EQ(Count, Results.GetSize()); + + // And if there are multiple matches, it should return all of them. + Count = CommandCompletions::DiskDirectories("~La", Results, Resolver); + ASSERT_EQ(2u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE( + ContainsExactString(Twine("~Lars") + path::get_separator(), Results)); + EXPECT_TRUE( + ContainsExactString(Twine("~Larry") + path::get_separator(), Results)); +} diff --git a/unittests/Language/CPlusPlus/CMakeLists.txt b/unittests/Language/CPlusPlus/CMakeLists.txt index 6cad97cc6d3c..4882eafc8d85 100644 --- a/unittests/Language/CPlusPlus/CMakeLists.txt +++ b/unittests/Language/CPlusPlus/CMakeLists.txt @@ -1,3 +1,6 @@ add_lldb_unittest(LanguageCPlusPlusTests CPlusPlusLanguageTest.cpp + + LINK_LIBS + lldbPluginCPlusPlusLanguage ) diff --git a/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp b/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp index 26de31d52a33..8c7fade83759 100644 --- a/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp +++ b/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp @@ -6,35 +6,153 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - #include "gtest/gtest.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" using namespace lldb_private; -TEST(CPlusPlusLanguage, MethodName) { +TEST(CPlusPlusLanguage, MethodNameParsing) { struct TestCase { std::string input; std::string context, basename, arguments, qualifiers, scope_qualified_name; }; TestCase test_cases[] = { - {"foo::bar(baz)", "foo", "bar", "(baz)", "", "foo::bar"}, + {"main(int, char *[]) ", "", "main", "(int, char *[])", "", "main"}, + {"foo::bar(baz) const", "foo", "bar", "(baz)", "const", "foo::bar"}, + {"foo::~bar(baz)", "foo", "~bar", "(baz)", "", "foo::~bar"}, + {"a::b::c::d(e,f)", "a::b::c", "d", "(e,f)", "", "a::b::c::d"}, + {"void f(int)", "", "f", "(int)", "", "f"}, + + // Operators {"std::basic_ostream<char, std::char_traits<char> >& " "std::operator<<<std::char_traits<char> >" "(std::basic_ostream<char, std::char_traits<char> >&, char const*)", "std", "operator<<<std::char_traits<char> >", "(std::basic_ostream<char, std::char_traits<char> >&, char const*)", "", - "std::operator<<<std::char_traits<char> >"}}; + "std::operator<<<std::char_traits<char> >"}, + {"operator delete[](void*, clang::ASTContext const&, unsigned long)", "", + "operator delete[]", "(void*, clang::ASTContext const&, unsigned long)", + "", "operator delete[]"}, + {"llvm::Optional<clang::PostInitializer>::operator bool() const", + "llvm::Optional<clang::PostInitializer>", "operator bool", "()", "const", + "llvm::Optional<clang::PostInitializer>::operator bool"}, + {"(anonymous namespace)::FactManager::operator[](unsigned short)", + "(anonymous namespace)::FactManager", "operator[]", "(unsigned short)", + "", "(anonymous namespace)::FactManager::operator[]"}, + {"const int& std::map<int, pair<short, int>>::operator[](short) const", + "std::map<int, pair<short, int>>", "operator[]", "(short)", "const", + "std::map<int, pair<short, int>>::operator[]"}, + {"CompareInsn::operator()(llvm::StringRef, InsnMatchEntry const&)", + "CompareInsn", "operator()", "(llvm::StringRef, InsnMatchEntry const&)", + "", "CompareInsn::operator()"}, + {"llvm::Optional<llvm::MCFixupKind>::operator*() const &", + "llvm::Optional<llvm::MCFixupKind>", "operator*", "()", "const &", + "llvm::Optional<llvm::MCFixupKind>::operator*"}, + // Internal classes + {"operator<<(Cls, Cls)::Subclass::function()", + "operator<<(Cls, Cls)::Subclass", "function", "()", "", + "operator<<(Cls, Cls)::Subclass::function"}, + {"SAEC::checkFunction(context&) const::CallBack::CallBack(int)", + "SAEC::checkFunction(context&) const::CallBack", "CallBack", "(int)", "", + "SAEC::checkFunction(context&) const::CallBack::CallBack"}, + // Anonymous namespace + {"XX::(anonymous namespace)::anon_class::anon_func() const", + "XX::(anonymous namespace)::anon_class", "anon_func", "()", "const", + "XX::(anonymous namespace)::anon_class::anon_func"}, + + // Function pointers + {"string (*f(vector<int>&&))(float)", "", "f", "(vector<int>&&)", "", + "f"}, + {"void (*&std::_Any_data::_M_access<void (*)()>())()", "std::_Any_data", + "_M_access<void (*)()>", "()", "", + "std::_Any_data::_M_access<void (*)()>"}, + {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "", + "func1", "(int)", "", "func1"}, + + // Decltype + {"decltype(nullptr)&& std::forward<decltype(nullptr)>" + "(std::remove_reference<decltype(nullptr)>::type&)", + "std", "forward<decltype(nullptr)>", + "(std::remove_reference<decltype(nullptr)>::type&)", "", + "std::forward<decltype(nullptr)>"}, + + // Templates + {"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::" + "addPass<llvm::VP>(llvm::VP)", + "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>", "addPass<llvm::VP>", + "(llvm::VP)", "", + "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::" + "addPass<llvm::VP>"}, + {"void std::vector<Class, std::allocator<Class> >" + "::_M_emplace_back_aux<Class const&>(Class const&)", + "std::vector<Class, std::allocator<Class> >", + "_M_emplace_back_aux<Class const&>", "(Class const&)", "", + "std::vector<Class, std::allocator<Class> >::" + "_M_emplace_back_aux<Class const&>"}, + {"unsigned long llvm::countTrailingOnes<unsigned int>" + "(unsigned int, llvm::ZeroBehavior)", + "llvm", "countTrailingOnes<unsigned int>", + "(unsigned int, llvm::ZeroBehavior)", "", + "llvm::countTrailingOnes<unsigned int>"}, + {"std::enable_if<(10u)<(64), bool>::type llvm::isUInt<10u>(unsigned " + "long)", + "llvm", "isUInt<10u>", "(unsigned long)", "", "llvm::isUInt<10u>"}, + {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "", + "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>", "()", "", + "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>"}}; for (const auto &test : test_cases) { CPlusPlusLanguage::MethodName method(ConstString(test.input)); - EXPECT_TRUE(method.IsValid()); - EXPECT_EQ(test.context, method.GetContext()); - EXPECT_EQ(test.basename, method.GetBasename()); - EXPECT_EQ(test.arguments, method.GetArguments()); - EXPECT_EQ(test.qualifiers, method.GetQualifiers()); - EXPECT_EQ(test.scope_qualified_name, method.GetScopeQualifiedName()); + EXPECT_TRUE(method.IsValid()) << test.input; + if (method.IsValid()) { + EXPECT_EQ(test.context, method.GetContext().str()); + EXPECT_EQ(test.basename, method.GetBasename().str()); + EXPECT_EQ(test.arguments, method.GetArguments().str()); + EXPECT_EQ(test.qualifiers, method.GetQualifiers().str()); + EXPECT_EQ(test.scope_qualified_name, method.GetScopeQualifiedName()); + } + } +} + +TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) { + struct TestCase { + std::string input; + std::string context, basename; + }; + + TestCase test_cases[] = { + {"main", "", "main"}, + {"main ", "", "main"}, + {"foo01::bar", "foo01", "bar"}, + {"foo::~bar", "foo", "~bar"}, + {"std::vector<int>::push_back", "std::vector<int>", "push_back"}, + {"operator<<(Cls, Cls)::Subclass::function", + "operator<<(Cls, Cls)::Subclass", "function"}, + {"std::vector<Class, std::allocator<Class>>" + "::_M_emplace_back_aux<Class const&>", + "std::vector<Class, std::allocator<Class>>", + "_M_emplace_back_aux<Class const&>"}}; + + llvm::StringRef context, basename; + for (const auto &test : test_cases) { + EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier( + test.input.c_str(), context, basename)); + EXPECT_EQ(test.context, context.str()); + EXPECT_EQ(test.basename, basename.str()); } + + EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier("void", context, + basename)); + EXPECT_FALSE( + CPlusPlusLanguage::ExtractContextAndIdentifier("321", context, basename)); + EXPECT_FALSE( + CPlusPlusLanguage::ExtractContextAndIdentifier("", context, basename)); + EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( + "selector:", context, basename)); + EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( + "selector:otherField:", context, basename)); + EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( + "abc::", context, basename)); } diff --git a/unittests/ObjectFile/CMakeLists.txt b/unittests/ObjectFile/CMakeLists.txt new file mode 100644 index 000000000000..8a98a9e34e51 --- /dev/null +++ b/unittests/ObjectFile/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(ELF) diff --git a/unittests/ObjectFile/ELF/CMakeLists.txt b/unittests/ObjectFile/ELF/CMakeLists.txt new file mode 100644 index 000000000000..4cae7ab2c0d6 --- /dev/null +++ b/unittests/ObjectFile/ELF/CMakeLists.txt @@ -0,0 +1,7 @@ +add_lldb_unittest(ObjectFileELFTests + TestELFHeader.cpp + + LINK_LIBS + lldbPluginObjectFileELF + lldbCore + ) diff --git a/unittests/ObjectFile/ELF/TestELFHeader.cpp b/unittests/ObjectFile/ELF/TestELFHeader.cpp new file mode 100644 index 000000000000..979011f66a27 --- /dev/null +++ b/unittests/ObjectFile/ELF/TestELFHeader.cpp @@ -0,0 +1,62 @@ +//===-- TestELFHeader.cpp ---------------------------------------*- C++ -*-===// +// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/ObjectFile/ELF/ELFHeader.h" +#include "lldb/Utility/DataExtractor.h" +#include "gtest/gtest.h" + +using namespace lldb; +using namespace lldb_private; + + +TEST(ELFHeader, ParseHeaderExtension) { + uint8_t data[] = { + // e_ident + 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // e_type, e_machine, e_version, e_entry + 0x03, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x90, 0x48, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // e_phoff, e_shoff + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, + // e_shstrndx + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0xff, 0xff, 0x40, 0x00, + 0x00, 0x00, 0xff, 0xff, + + // sh_name, sh_type, sh_flags + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // sh_addr, sh_offset + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // sh_size, sh_link, sh_info + 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x56, 0x78, 0x00, + 0x12, 0x34, 0x56, 0x00, + + // sh_addralign, sh_entsize + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + DataExtractor extractor(data, sizeof data, eByteOrderLittle, 8); + elf::ELFHeader header; + offset_t offset = 0; + ASSERT_TRUE(header.Parse(extractor, &offset)); + EXPECT_EQ(0x563412u, header.e_phnum); + EXPECT_EQ(0x785634u, header.e_shstrndx); + EXPECT_EQ(0x674523u, header.e_shnum); +} diff --git a/unittests/Platform/CMakeLists.txt b/unittests/Platform/CMakeLists.txt index af1121dac7b6..3362ca08d60c 100644 --- a/unittests/Platform/CMakeLists.txt +++ b/unittests/Platform/CMakeLists.txt @@ -1,3 +1,8 @@ add_lldb_unittest(LLDBPlatformTests PlatformDarwinTest.cpp + + LINK_LIBS + lldbPluginPlatformMacOSX + LINK_COMPONENTS + Support ) diff --git a/unittests/Process/gdb-remote/CMakeLists.txt b/unittests/Process/gdb-remote/CMakeLists.txt index de4cac11b233..694ba182d42f 100644 --- a/unittests/Process/gdb-remote/CMakeLists.txt +++ b/unittests/Process/gdb-remote/CMakeLists.txt @@ -2,4 +2,13 @@ add_lldb_unittest(ProcessGdbRemoteTests GDBRemoteClientBaseTest.cpp GDBRemoteCommunicationClientTest.cpp GDBRemoteTestUtils.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbPluginPlatformMacOSX + lldbPluginProcessUtility + lldbPluginProcessGDBRemote + LINK_COMPONENTS + Support ) diff --git a/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp b/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp index 2cfd52f5767a..5e709815b2d5 100644 --- a/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp @@ -6,13 +6,6 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif #include <future> #include "GDBRemoteTestUtils.h" @@ -20,7 +13,7 @@ #include "Plugins/Process/Utility/LinuxSignals.h" #include "Plugins/Process/gdb-remote/GDBRemoteClientBase.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h" -#include "lldb/Core/StreamGDBRemote.h" +#include "lldb/Utility/StreamGDBRemote.h" #include "llvm/ADT/STLExtras.h" diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 4bac9ebd404f..d1eb3a7e9c9e 100644 --- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -6,21 +6,15 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif #include <future> #include "GDBRemoteTestUtils.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" -#include "lldb/Core/DataBuffer.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/DataBuffer.h" #include "llvm/ADT/ArrayRef.h" @@ -298,6 +292,7 @@ TEST_F(GDBRemoteCommunicationClientTest, TestPacketSpeedJSON) { client.Disconnect(); server_thread.join(); + GTEST_LOG_(INFO) << "Formatted output: " << ss.GetData(); auto object_sp = StructuredData::ParseJSON(ss.GetString()); ASSERT_TRUE(bool(object_sp)); auto dict_sp = object_sp->GetAsDictionary(); @@ -313,3 +308,65 @@ TEST_F(GDBRemoteCommunicationClientTest, TestPacketSpeedJSON) { << ss.GetString(); ASSERT_EQ(10, num_packets); } + +TEST_F(GDBRemoteCommunicationClientTest, SendSignalsToIgnore) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::tid_t tid = 0x47; + const uint32_t reg_num = 4; + std::future<Error> result = std::async(std::launch::async, [&] { + return client.SendSignalsToIgnore({2, 3, 5, 7, 0xB, 0xD, 0x11}); + }); + + HandlePacket(server, "QPassSignals:02;03;05;07;0b;0d;11", "OK"); + EXPECT_TRUE(result.get().Success()); + + result = std::async(std::launch::async, [&] { + return client.SendSignalsToIgnore(std::vector<int32_t>()); + }); + + HandlePacket(server, "QPassSignals:", "OK"); + EXPECT_TRUE(result.get().Success()); +} + +TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::addr_t addr = 0xa000; + MemoryRegionInfo region_info; + std::future<Error> result = std::async(std::launch::async, [&] { + return client.GetMemoryRegionInfo(addr, region_info); + }); + + // name is: /foo/bar.so + HandlePacket(server, + "qMemoryRegionInfo:a000", + "start:a000;size:2000;permissions:rx;name:2f666f6f2f6261722e736f;"); + EXPECT_TRUE(result.get().Success()); + +} + +TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + const lldb::addr_t addr = 0x4000; + MemoryRegionInfo region_info; + std::future<Error> result = std::async(std::launch::async, [&] { + return client.GetMemoryRegionInfo(addr, region_info); + }); + + HandlePacket(server, "qMemoryRegionInfo:4000", "start:4000;size:0000;"); + EXPECT_FALSE(result.get().Success()); +} diff --git a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp index 58cc9f50586a..08501f50f65a 100644 --- a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp @@ -7,13 +7,6 @@ // //===----------------------------------------------------------------------===// -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Workaround for MSVC standard library bug, which fails to include <thread> -// when -// exceptions are disabled. -#include <eh.h> -#endif - #include "GDBRemoteTestUtils.h" #include "lldb/Host/common/TCPSocket.h" diff --git a/unittests/Process/minidump/CMakeLists.txt b/unittests/Process/minidump/CMakeLists.txt index 10cb8c34f352..2b2df6327e9a 100644 --- a/unittests/Process/minidump/CMakeLists.txt +++ b/unittests/Process/minidump/CMakeLists.txt @@ -1,5 +1,14 @@ add_lldb_unittest(LLDBMinidumpTests MinidumpParserTest.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbTarget + lldbPluginProcessUtility + lldbPluginProcessMinidump + LINK_COMPONENTS + Support ) set(test_inputs diff --git a/unittests/Process/minidump/MinidumpParserTest.cpp b/unittests/Process/minidump/MinidumpParserTest.cpp index 83225e88ee03..755095f75918 100644 --- a/unittests/Process/minidump/MinidumpParserTest.cpp +++ b/unittests/Process/minidump/MinidumpParserTest.cpp @@ -19,13 +19,15 @@ #include "gtest/gtest.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" // C includes @@ -46,14 +48,15 @@ public: llvm::sys::path::append(inputs_folder, "Inputs"); } - void SetUpData(const char *minidump_filename, size_t load_size = SIZE_MAX) { + void SetUpData(const char *minidump_filename, + uint64_t load_size = UINT64_MAX) { llvm::SmallString<128> filename = inputs_folder; llvm::sys::path::append(filename, minidump_filename); - FileSpec minidump_file(filename.c_str(), false); - lldb::DataBufferSP data_sp( - minidump_file.MemoryMapFileContents(0, load_size)); + + auto BufferPtr = DataBufferLLVM::CreateSliceFromPath(filename, load_size, 0); + llvm::Optional<MinidumpParser> optional_parser = - MinidumpParser::Create(data_sp); + MinidumpParser::Create(BufferPtr); ASSERT_TRUE(optional_parser.hasValue()); parser.reset(new MinidumpParser(optional_parser.getValue())); ASSERT_GT(parser->GetData().size(), 0UL); @@ -450,4 +453,4 @@ TEST_F(MinidumpParserTest, ConvertMinidumpContext_x86_32_wow64) { REG_VAL32(buf->GetBytes() + reg_info[reg_index].byte_offset)); } } -}
\ No newline at end of file +} diff --git a/unittests/ScriptInterpreter/Python/CMakeLists.txt b/unittests/ScriptInterpreter/Python/CMakeLists.txt index f011200e6475..891ade25b76b 100644 --- a/unittests/ScriptInterpreter/Python/CMakeLists.txt +++ b/unittests/ScriptInterpreter/Python/CMakeLists.txt @@ -2,7 +2,12 @@ add_lldb_unittest(ScriptInterpreterPythonTests PythonDataObjectsTests.cpp PythonExceptionStateTests.cpp PythonTestSuite.cpp - ) - target_link_libraries(ScriptInterpreterPythonTests lldbPluginScriptInterpreterPython ${PYTHON_LIBRARY}) + LINK_LIBS + lldbHost + lldbPluginScriptInterpreterPython + ${PYTHON_LIBRARY} + LINK_COMPONENTS + Support + )
\ No newline at end of file diff --git a/unittests/Signals/CMakeLists.txt b/unittests/Signals/CMakeLists.txt new file mode 100644 index 000000000000..e3f2e884d930 --- /dev/null +++ b/unittests/Signals/CMakeLists.txt @@ -0,0 +1,6 @@ +add_lldb_unittest(SignalsTests + UnixSignalsTest.cpp + + LINK_LIBS + lldbTarget + ) diff --git a/unittests/Signals/UnixSignalsTest.cpp b/unittests/Signals/UnixSignalsTest.cpp new file mode 100644 index 000000000000..9183aed76aef --- /dev/null +++ b/unittests/Signals/UnixSignalsTest.cpp @@ -0,0 +1,140 @@ +//===-- UnixSignalsTest.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <string> + +#include "gtest/gtest.h" + +#include "lldb/Target/UnixSignals.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace lldb; +using namespace lldb_private; +using llvm::None; + +class TestSignals : public UnixSignals { +public: + TestSignals() { + m_signals.clear(); + AddSignal(2, "SIG2", false, true, true, "DESC2"); + AddSignal(4, "SIG4", true, false, true, "DESC4"); + AddSignal(8, "SIG8", true, true, true, "DESC8"); + AddSignal(16, "SIG16", true, false, false, "DESC16"); + } +}; + +void ExpectEqArrays(llvm::ArrayRef<int32_t> expected, + llvm::ArrayRef<int32_t> observed, const char *file, + int line) { + std::string location = llvm::formatv("{0}:{1}", file, line); + ASSERT_EQ(expected.size(), observed.size()) << location; + + for (size_t i = 0; i < observed.size(); ++i) { + ASSERT_EQ(expected[i], observed[i]) + << "array index: " << i << "location:" << location; + } +} + +#define EXPECT_EQ_ARRAYS(expected, observed) \ + ExpectEqArrays((expected), (observed), __FILE__, __LINE__); + +TEST(UnixSignalsTest, Iteration) { + TestSignals signals; + + EXPECT_EQ(4, signals.GetNumSignals()); + EXPECT_EQ(2, signals.GetFirstSignalNumber()); + EXPECT_EQ(4, signals.GetNextSignalNumber(2)); + EXPECT_EQ(8, signals.GetNextSignalNumber(4)); + EXPECT_EQ(16, signals.GetNextSignalNumber(8)); + EXPECT_EQ(LLDB_INVALID_SIGNAL_NUMBER, signals.GetNextSignalNumber(16)); +} + +TEST(UnixSignalsTest, GetInfo) { + TestSignals signals; + + bool should_suppress = false, should_stop = false, should_notify = false; + int32_t signo = 4; + std::string name = + signals.GetSignalInfo(signo, should_suppress, should_stop, should_notify); + EXPECT_EQ("SIG4", name); + EXPECT_EQ(true, should_suppress); + EXPECT_EQ(false, should_stop); + EXPECT_EQ(true, should_notify); + + EXPECT_EQ(true, signals.GetShouldSuppress(signo)); + EXPECT_EQ(false, signals.GetShouldStop(signo)); + EXPECT_EQ(true, signals.GetShouldNotify(signo)); + EXPECT_EQ(name, signals.GetSignalAsCString(signo)); +} + +TEST(UnixSignalsTest, VersionChange) { + TestSignals signals; + + int32_t signo = 8; + uint64_t ver = signals.GetVersion(); + EXPECT_GT(ver, 0ull); + EXPECT_EQ(true, signals.GetShouldSuppress(signo)); + EXPECT_EQ(true, signals.GetShouldStop(signo)); + EXPECT_EQ(true, signals.GetShouldNotify(signo)); + + EXPECT_EQ(signals.GetVersion(), ver); + + signals.SetShouldSuppress(signo, false); + EXPECT_LT(ver, signals.GetVersion()); + ver = signals.GetVersion(); + + signals.SetShouldStop(signo, true); + EXPECT_LT(ver, signals.GetVersion()); + ver = signals.GetVersion(); + + signals.SetShouldNotify(signo, false); + EXPECT_LT(ver, signals.GetVersion()); + ver = signals.GetVersion(); + + EXPECT_EQ(false, signals.GetShouldSuppress(signo)); + EXPECT_EQ(true, signals.GetShouldStop(signo)); + EXPECT_EQ(false, signals.GetShouldNotify(signo)); + + EXPECT_EQ(ver, signals.GetVersion()); +} + +TEST(UnixSignalsTest, GetFilteredSignals) { + TestSignals signals; + + auto all_signals = signals.GetFilteredSignals(None, None, None); + std::vector<int32_t> expected = {2, 4, 8, 16}; + EXPECT_EQ_ARRAYS(expected, all_signals); + + auto supressed = signals.GetFilteredSignals(true, None, None); + expected = {4, 8, 16}; + EXPECT_EQ_ARRAYS(expected, supressed); + + auto not_supressed = signals.GetFilteredSignals(false, None, None); + expected = {2}; + EXPECT_EQ_ARRAYS(expected, not_supressed); + + auto stopped = signals.GetFilteredSignals(None, true, None); + expected = {2, 8}; + EXPECT_EQ_ARRAYS(expected, stopped); + + auto not_stopped = signals.GetFilteredSignals(None, false, None); + expected = {4, 16}; + EXPECT_EQ_ARRAYS(expected, not_stopped); + + auto notified = signals.GetFilteredSignals(None, None, true); + expected = {2, 4, 8}; + EXPECT_EQ_ARRAYS(expected, notified); + + auto not_notified = signals.GetFilteredSignals(None, None, false); + expected = {16}; + EXPECT_EQ_ARRAYS(expected, not_notified); + + auto signal4 = signals.GetFilteredSignals(true, false, true); + expected = {4}; + EXPECT_EQ_ARRAYS(expected, signal4); +} diff --git a/unittests/Symbol/CMakeLists.txt b/unittests/Symbol/CMakeLists.txt index 75cabddba5c4..dca5f17b15de 100644 --- a/unittests/Symbol/CMakeLists.txt +++ b/unittests/Symbol/CMakeLists.txt @@ -1,4 +1,8 @@ add_lldb_unittest(SymbolTests TestClangASTContext.cpp TestType.cpp + + LINK_LIBS + lldbHost + lldbSymbol ) diff --git a/unittests/SymbolFile/DWARF/CMakeLists.txt b/unittests/SymbolFile/DWARF/CMakeLists.txt index c0e4300dadd7..c764bd477fab 100644 --- a/unittests/SymbolFile/DWARF/CMakeLists.txt +++ b/unittests/SymbolFile/DWARF/CMakeLists.txt @@ -1,5 +1,16 @@ add_lldb_unittest(SymbolFileDWARFTests SymbolFileDWARFTests.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbPluginObjectFilePECOFF + lldbPluginSymbolFileDWARF + lldbPluginSymbolFilePDB + LINK_COMPONENTS + Support + DebugInfoPDB ) set(test_inputs diff --git a/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp b/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp index 10465d785ac9..8ef6ad05bd54 100644 --- a/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp +++ b/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp @@ -19,12 +19,12 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Utility/FileSpec.h" #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" diff --git a/unittests/SymbolFile/PDB/CMakeLists.txt b/unittests/SymbolFile/PDB/CMakeLists.txt index 37adf39463d4..d9aff4e2eaca 100644 --- a/unittests/SymbolFile/PDB/CMakeLists.txt +++ b/unittests/SymbolFile/PDB/CMakeLists.txt @@ -1,5 +1,16 @@ add_lldb_unittest(SymbolFilePDBTests SymbolFilePDBTests.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbPluginObjectFilePECOFF + lldbPluginSymbolFileDWARF + lldbPluginSymbolFilePDB + LINK_COMPONENTS + Support + DebugInfoPDB ) set(test_inputs diff --git a/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp index 5aedffecfe90..226057f89369 100644 --- a/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp +++ b/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp @@ -19,12 +19,12 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Utility/FileSpec.h" #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" @@ -120,7 +120,7 @@ protected: return false; } - uint64_t GetGlobalConstantInteger(const llvm::pdb::IPDBSession &session, + uint64_t GetGlobalConstantInteger(llvm::pdb::IPDBSession &session, llvm::StringRef var) const { auto global = session.getGlobalScope(); auto results = @@ -371,7 +371,7 @@ TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) { SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); - const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); + llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); SymbolContext sc; llvm::DenseSet<SymbolFile *> searched_files; TypeMap results; @@ -394,7 +394,7 @@ TEST_F(SymbolFilePDBTests, TestNestedClassTypes) { SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); - const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); + llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); SymbolContext sc; llvm::DenseSet<SymbolFile *> searched_files; TypeMap results; @@ -417,7 +417,7 @@ TEST_F(SymbolFilePDBTests, TestClassInNamespace) { SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); - const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); + llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); SymbolContext sc; llvm::DenseSet<SymbolFile *> searched_files; TypeMap results; @@ -440,7 +440,7 @@ TEST_F(SymbolFilePDBTests, TestEnumTypes) { SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); - const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); + llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); SymbolContext sc; llvm::DenseSet<SymbolFile *> searched_files; const char *EnumsToCheck[] = {"Enum", "ShortEnum"}; @@ -487,7 +487,7 @@ TEST_F(SymbolFilePDBTests, TestTypedefs) { SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); - const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); + llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); SymbolContext sc; llvm::DenseSet<SymbolFile *> searched_files; TypeMap results; diff --git a/unittests/Target/CMakeLists.txt b/unittests/Target/CMakeLists.txt new file mode 100644 index 000000000000..e4f6e52b0634 --- /dev/null +++ b/unittests/Target/CMakeLists.txt @@ -0,0 +1,15 @@ +add_lldb_unittest(TargetTests + MemoryRegionInfoTest.cpp + ModuleCacheTest.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbUtility + lldbPluginObjectFileELF + LINK_COMPONENTS + Support + ) + +add_unittest_inputs(TargetTests TestModule.so) diff --git a/unittests/Utility/Inputs/TestModule.c b/unittests/Target/Inputs/TestModule.c index 6347f7264944..6347f7264944 100644 --- a/unittests/Utility/Inputs/TestModule.c +++ b/unittests/Target/Inputs/TestModule.c diff --git a/unittests/Utility/Inputs/TestModule.so b/unittests/Target/Inputs/TestModule.so Binary files differindex 9e9bf0b6e17e..9e9bf0b6e17e 100644 --- a/unittests/Utility/Inputs/TestModule.so +++ b/unittests/Target/Inputs/TestModule.so diff --git a/unittests/Target/MemoryRegionInfoTest.cpp b/unittests/Target/MemoryRegionInfoTest.cpp new file mode 100644 index 000000000000..704f7f8c48c6 --- /dev/null +++ b/unittests/Target/MemoryRegionInfoTest.cpp @@ -0,0 +1,20 @@ +//===-- MemoryRegionInfoTest.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/MemoryRegionInfo.h" +#include "llvm/Support/FormatVariadic.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +TEST(MemoryRegionInfoTest, Formatv) { + EXPECT_EQ("yes", llvm::formatv("{0}", MemoryRegionInfo::eYes).str()); + EXPECT_EQ("no", llvm::formatv("{0}", MemoryRegionInfo::eNo).str()); + EXPECT_EQ("don't know", llvm::formatv("{0}", MemoryRegionInfo::eDontKnow).str()); +} diff --git a/unittests/Utility/ModuleCacheTest.cpp b/unittests/Target/ModuleCacheTest.cpp index 911c278c1626..09b3edc4148b 100644 --- a/unittests/Utility/ModuleCacheTest.cpp +++ b/unittests/Target/ModuleCacheTest.cpp @@ -5,11 +5,11 @@ #include "llvm/Support/Path.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" -#include "Utility/ModuleCache.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ModuleCache.h" extern const char *TestMainArgv0; diff --git a/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt b/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt index 5e274a229919..7cc0befa386b 100644 --- a/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt +++ b/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt @@ -1,3 +1,15 @@ if ("AArch64" IN_LIST LLVM_TARGETS_TO_BUILD) - add_lldb_unittest(InstEmulationTests TestArm64InstEmulation.cpp) + add_lldb_unittest(InstEmulationTests + TestArm64InstEmulation.cpp + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbPluginUnwindAssemblyInstEmulation + lldbPluginDisassemblerLLVM + lldbPluginInstructionARM64 + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ${LLVM_TARGETS_TO_BUILD}) endif() diff --git a/unittests/UnwindAssembly/x86/CMakeLists.txt b/unittests/UnwindAssembly/x86/CMakeLists.txt index 7112467b3975..2b5b31f79063 100644 --- a/unittests/UnwindAssembly/x86/CMakeLists.txt +++ b/unittests/UnwindAssembly/x86/CMakeLists.txt @@ -1,3 +1,10 @@ add_lldb_unittest(UnwindAssemblyx86Tests Testx86AssemblyInspectionEngine.cpp + LINK_LIBS + lldbCore + lldbSymbol + lldbPluginUnwindAssemblyX86 + LINK_COMPONENTS + Support + ${LLVM_TARGETS_TO_BUILD} ) diff --git a/unittests/Utility/CMakeLists.txt b/unittests/Utility/CMakeLists.txt index 15a29825f1da..60868bcb414c 100644 --- a/unittests/Utility/CMakeLists.txt +++ b/unittests/Utility/CMakeLists.txt @@ -1,9 +1,20 @@ +add_subdirectory(Mocks) + add_lldb_unittest(UtilityTests - ModuleCacheTest.cpp + ConstStringTest.cpp + ErrorTest.cpp + LogTest.cpp + NameMatchesTest.cpp StringExtractorTest.cpp TaskPoolTest.cpp + TildeExpressionResolverTest.cpp TimeoutTest.cpp UriParserTest.cpp - ) + VASprintfTest.cpp -add_unittest_inputs(UtilityTests TestModule.so) + LINK_LIBS + lldbUtility + lldbUtilityMocks + LINK_COMPONENTS + Support + ) diff --git a/unittests/Utility/ConstStringTest.cpp b/unittests/Utility/ConstStringTest.cpp new file mode 100644 index 000000000000..454f656760ca --- /dev/null +++ b/unittests/Utility/ConstStringTest.cpp @@ -0,0 +1,18 @@ +//===-- ConstStringTest.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/ConstString.h" +#include "llvm/Support/FormatVariadic.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +TEST(ConstStringTest, format_provider) { + EXPECT_EQ("foo", llvm::formatv("{0}", ConstString("foo")).str()); +} diff --git a/unittests/Core/ErrorTest.cpp b/unittests/Utility/ErrorTest.cpp index f3727bbd78ae..a114b26ebe54 100644 --- a/unittests/Core/ErrorTest.cpp +++ b/unittests/Utility/ErrorTest.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Utility/Error.h" #include "gtest/gtest.h" -#include "lldb/Core/Error.h" using namespace lldb_private; diff --git a/unittests/Utility/LogTest.cpp b/unittests/Utility/LogTest.cpp new file mode 100644 index 000000000000..61fb6b5e4a5b --- /dev/null +++ b/unittests/Utility/LogTest.cpp @@ -0,0 +1,280 @@ +//===-- LogTest.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Threading.h" +#include <thread> + +using namespace lldb; +using namespace lldb_private; + +enum { FOO = 1, BAR = 2 }; +static constexpr Log::Category test_categories[] = { + {{"foo"}, {"log foo"}, FOO}, {{"bar"}, {"log bar"}, BAR}, +}; +static constexpr uint32_t default_flags = FOO; + +static Log::Channel test_channel(test_categories, default_flags); + +struct LogChannelTest : public ::testing::Test { + void TearDown() override { Log::DisableAllLogChannels(); } + + static void SetUpTestCase() { + Log::Register("chan", test_channel); + } + + static void TearDownTestCase() { + Log::Unregister("chan"); + llvm::llvm_shutdown(); + } +}; + +// Wrap enable, disable and list functions to make them easier to test. +static bool EnableChannel(std::shared_ptr<llvm::raw_ostream> stream_sp, + uint32_t log_options, llvm::StringRef channel, + llvm::ArrayRef<const char *> categories, + std::string &error) { + error.clear(); + llvm::raw_string_ostream error_stream(error); + return Log::EnableLogChannel(stream_sp, log_options, channel, categories, + error_stream); +} + +static bool DisableChannel(llvm::StringRef channel, + llvm::ArrayRef<const char *> categories, + std::string &error) { + error.clear(); + llvm::raw_string_ostream error_stream(error); + return Log::DisableLogChannel(channel, categories, error_stream); +} + +static bool ListCategories(llvm::StringRef channel, std::string &result) { + result.clear(); + llvm::raw_string_ostream result_stream(result); + return Log::ListChannelCategories(channel, result_stream); +} + +TEST(LogTest, LLDB_LOG_nullptr) { + Log *log = nullptr; + LLDB_LOG(log, "{0}", 0); // Shouldn't crash +} + +TEST(LogTest, Register) { + llvm::llvm_shutdown_obj obj; + Log::Register("chan", test_channel); + Log::Unregister("chan"); + Log::Register("chan", test_channel); + Log::Unregister("chan"); +} + +TEST(LogTest, Unregister) { + llvm::llvm_shutdown_obj obj; + Log::Register("chan", test_channel); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {"foo"}, llvm::nulls())); + EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO)); + Log::Unregister("chan"); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); +} + +TEST_F(LogChannelTest, Enable) { + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string error; + ASSERT_FALSE(EnableChannel(stream_sp, 0, "chanchan", {}, error)); + EXPECT_EQ("Invalid log channel 'chanchan'.\n", error); + + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, error)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"bar"}, error)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"baz"}, error)); + EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'")) + << "error: " << error; + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); +} + +TEST_F(LogChannelTest, EnableOptions) { + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string error; + EXPECT_TRUE( + EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan", {}, error)); + + Log *log = test_channel.GetLogIfAll(FOO); + ASSERT_NE(nullptr, log); + EXPECT_TRUE(log->GetVerbose()); +} + +TEST_F(LogChannelTest, Disable) { + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string error; + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"foo", "bar"}, error)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + + EXPECT_TRUE(DisableChannel("chan", {"bar"}, error)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + + EXPECT_TRUE(DisableChannel("chan", {"baz"}, error)); + EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'")) + << "error: " << error; + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + + EXPECT_TRUE(DisableChannel("chan", {}, error)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR)); +} + +TEST_F(LogChannelTest, List) { + std::string list; + EXPECT_TRUE(ListCategories("chan", list)); + std::string expected = + R"(Logging categories for 'chan': + all - all available logging categories + default - default set of logging categories + foo - log foo + bar - log bar +)"; + EXPECT_EQ(expected, list); + + EXPECT_FALSE(ListCategories("chanchan", list)); + EXPECT_EQ("Invalid log channel 'chanchan'.\n", list); +} + +static std::string GetLogString(uint32_t log_options, const char *format, + int arg) { + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string error; + llvm::raw_string_ostream error_stream(error); + EXPECT_TRUE( + Log::EnableLogChannel(stream_sp, log_options, "chan", {}, error_stream)); + + Log *log = test_channel.GetLogIfAll(FOO); + EXPECT_NE(nullptr, log); + + LLDB_LOG(log, format, arg); + EXPECT_TRUE(Log::DisableLogChannel("chan", {}, error_stream)); + + return stream_sp->str(); +} + +TEST_F(LogChannelTest, log_options) { + EXPECT_EQ("Hello World 47\n", GetLogString(0, "Hello World {0}", 47)); + EXPECT_EQ("Hello World 47\n", + GetLogString(LLDB_LOG_OPTION_THREADSAFE, "Hello World {0}", 47)); + + { + std::string msg = + GetLogString(LLDB_LOG_OPTION_PREPEND_SEQUENCE, "Hello World {0}", 47); + int seq_no; + EXPECT_EQ(1, sscanf(msg.c_str(), "%d Hello World 47", &seq_no)); + } + + EXPECT_EQ( + "LogTest.cpp:GetLogString Hello " + "World 47\n", + GetLogString(LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION, "Hello World {0}", 47)); + + EXPECT_EQ(llvm::formatv("[{0,0+4}/{1,0+4}] Hello World 47\n", ::getpid(), + llvm::get_threadid()) + .str(), + GetLogString(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, + "Hello World {0}", 47)); +} + +TEST_F(LogChannelTest, LogThread) { + // Test that we are able to concurrently write to a log channel and disable + // it. + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string err; + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err)); + + Log *log = test_channel.GetLogIfAll(FOO); + + // Start logging on one thread. Concurrently, try disabling the log channel. + std::thread log_thread([log] { LLDB_LOG(log, "Hello World"); }); + EXPECT_TRUE(DisableChannel("chan", {}, err)); + log_thread.join(); + + // The log thread either managed to write to the log in time, or it didn't. In + // either case, we should not trip any undefined behavior (run the test under + // TSAN to verify this). + EXPECT_TRUE(stream_sp->str() == "" || stream_sp->str() == "Hello World\n") + << "str(): " << stream_sp->str(); +} + +TEST_F(LogChannelTest, LogVerboseThread) { + // Test that we are able to concurrently check the verbose flag of a log + // channel and enable it. + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string err; + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err)); + + Log *log = test_channel.GetLogIfAll(FOO); + + // Start logging on one thread. Concurrently, try enabling the log channel + // (with different log options). + std::thread log_thread([log] { LLDB_LOGV(log, "Hello World"); }); + EXPECT_TRUE(EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan", + {}, err)); + log_thread.join(); + EXPECT_TRUE(DisableChannel("chan", {}, err)); + + // The log thread either managed to write to the log, or it didn't. In either + // case, we should not trip any undefined behavior (run the test under TSAN to + // verify this). + EXPECT_TRUE(stream_sp->str() == "" || stream_sp->str() == "Hello World\n") + << "str(): " << stream_sp->str(); +} + +TEST_F(LogChannelTest, LogGetLogThread) { + // Test that we are able to concurrently get mask of a Log object and disable + // it. + std::string message; + std::shared_ptr<llvm::raw_string_ostream> stream_sp( + new llvm::raw_string_ostream(message)); + std::string err; + EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, err)); + Log *log = test_channel.GetLogIfAll(FOO); + + // Try fetching the log on one thread. Concurrently, try disabling the log + // channel. + uint32_t mask; + std::thread log_thread([log, &mask] { mask = log->GetMask().Get(); }); + EXPECT_TRUE(DisableChannel("chan", {}, err)); + log_thread.join(); + + // The mask should be either zero of "FOO". In either case, we should not trip + // any undefined behavior (run the test under TSAN to verify this). + EXPECT_TRUE(mask == 0 || mask == FOO) << "mask: " << mask; +} diff --git a/unittests/Utility/Mocks/CMakeLists.txt b/unittests/Utility/Mocks/CMakeLists.txt new file mode 100644 index 000000000000..57db5bf3b628 --- /dev/null +++ b/unittests/Utility/Mocks/CMakeLists.txt @@ -0,0 +1,9 @@ +add_lldb_library(lldbUtilityMocks + MockTildeExpressionResolver.cpp + + LINK_LIBS + lldbUtility + + LINK_COMPONENTS + Support + ) diff --git a/unittests/Utility/Mocks/MockTildeExpressionResolver.cpp b/unittests/Utility/Mocks/MockTildeExpressionResolver.cpp new file mode 100644 index 000000000000..832836682b50 --- /dev/null +++ b/unittests/Utility/Mocks/MockTildeExpressionResolver.cpp @@ -0,0 +1,80 @@ +//===----------------- MockTildeExpressionResolver.cpp ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MockTildeExpressionResolver.h" +#include "llvm/Support/Path.h" + +using namespace lldb_private; +using namespace llvm; + +MockTildeExpressionResolver::MockTildeExpressionResolver(StringRef CurrentUser, + StringRef HomeDir) + : CurrentUser(CurrentUser) { + UserDirectories.insert(std::make_pair(CurrentUser, HomeDir)); +} + +void MockTildeExpressionResolver::AddKnownUser(StringRef User, + StringRef HomeDir) { + assert(UserDirectories.find(User) == UserDirectories.end()); + UserDirectories.insert(std::make_pair(User, HomeDir)); +} + +void MockTildeExpressionResolver::Clear() { + CurrentUser = StringRef(); + UserDirectories.clear(); +} + +void MockTildeExpressionResolver::SetCurrentUser(StringRef User) { + assert(UserDirectories.find(User) != UserDirectories.end()); + CurrentUser = User; +} + +bool MockTildeExpressionResolver::ResolveExact(StringRef Expr, + SmallVectorImpl<char> &Output) { + Output.clear(); + + assert(!llvm::any_of( + Expr, [](char c) { return llvm::sys::path::is_separator(c); })); + assert(Expr.empty() || Expr[0] == '~'); + Expr = Expr.drop_front(); + if (Expr.empty()) { + auto Dir = UserDirectories[CurrentUser]; + Output.append(Dir.begin(), Dir.end()); + return true; + } + + for (const auto &User : UserDirectories) { + if (User.getKey() != Expr) + continue; + Output.append(User.getValue().begin(), User.getValue().end()); + return true; + } + return false; +} + +bool MockTildeExpressionResolver::ResolvePartial(StringRef Expr, + StringSet<> &Output) { + Output.clear(); + + assert(!llvm::any_of( + Expr, [](char c) { return llvm::sys::path::is_separator(c); })); + assert(Expr.empty() || Expr[0] == '~'); + Expr = Expr.drop_front(); + + SmallString<16> QualifiedName("~"); + for (const auto &User : UserDirectories) { + if (!User.getKey().startswith(Expr)) + continue; + QualifiedName.resize(1); + QualifiedName.append(User.getKey().begin(), User.getKey().end()); + Output.insert(QualifiedName); + } + + return !Output.empty(); +} diff --git a/unittests/Utility/Mocks/MockTildeExpressionResolver.h b/unittests/Utility/Mocks/MockTildeExpressionResolver.h new file mode 100644 index 000000000000..7ae5623f839a --- /dev/null +++ b/unittests/Utility/Mocks/MockTildeExpressionResolver.h @@ -0,0 +1,37 @@ +//===--------------------- TildeExpressionResolver.h ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UNITTESTS_UTILITY_MOCKS_MOCK_TILDE_EXPRESSION_RESOLVER_H +#define LLDB_UNITTESTS_UTILITY_MOCKS_MOCK_TILDE_EXPRESSION_RESOLVER_H + +#include "lldb/Utility/TildeExpressionResolver.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" + +namespace lldb_private { +class MockTildeExpressionResolver : public TildeExpressionResolver { + llvm::StringRef CurrentUser; + llvm::StringMap<llvm::StringRef> UserDirectories; + +public: + MockTildeExpressionResolver(llvm::StringRef CurrentUser, + llvm::StringRef HomeDir); + + void AddKnownUser(llvm::StringRef User, llvm::StringRef HomeDir); + void Clear(); + void SetCurrentUser(llvm::StringRef User); + + bool ResolveExact(llvm::StringRef Expr, + llvm::SmallVectorImpl<char> &Output) override; + bool ResolvePartial(llvm::StringRef Expr, llvm::StringSet<> &Output) override; +}; +} + +#endif diff --git a/unittests/Utility/NameMatchesTest.cpp b/unittests/Utility/NameMatchesTest.cpp new file mode 100644 index 000000000000..28ae16c7ddd5 --- /dev/null +++ b/unittests/Utility/NameMatchesTest.cpp @@ -0,0 +1,58 @@ +//===-- NameMatchesTest.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/NameMatches.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +TEST(NameMatchesTest, Ignore) { + EXPECT_TRUE(NameMatches("foo", NameMatch::Ignore, "bar")); +} + +TEST(NameMatchesTest, Equals) { + EXPECT_TRUE(NameMatches("foo", NameMatch::Equals, "foo")); + EXPECT_FALSE(NameMatches("foo", NameMatch::Equals, "bar")); +} + +TEST(NameMatchesTest, Contains) { + EXPECT_TRUE(NameMatches("foobar", NameMatch::Contains, "foo")); + EXPECT_TRUE(NameMatches("foobar", NameMatch::Contains, "oob")); + EXPECT_TRUE(NameMatches("foobar", NameMatch::Contains, "bar")); + EXPECT_TRUE(NameMatches("foobar", NameMatch::Contains, "foobar")); + EXPECT_TRUE(NameMatches("", NameMatch::Contains, "")); + EXPECT_FALSE(NameMatches("", NameMatch::Contains, "foo")); + EXPECT_FALSE(NameMatches("foobar", NameMatch::Contains, "baz")); +} + +TEST(NameMatchesTest, StartsWith) { + EXPECT_TRUE(NameMatches("foo", NameMatch::StartsWith, "f")); + EXPECT_TRUE(NameMatches("foo", NameMatch::StartsWith, "")); + EXPECT_TRUE(NameMatches("", NameMatch::StartsWith, "")); + EXPECT_FALSE(NameMatches("foo", NameMatch::StartsWith, "b")); + EXPECT_FALSE(NameMatches("", NameMatch::StartsWith, "b")); +} + +TEST(NameMatchesTest, EndsWith) { + EXPECT_TRUE(NameMatches("foo", NameMatch::EndsWith, "o")); + EXPECT_TRUE(NameMatches("foo", NameMatch::EndsWith, "")); + EXPECT_TRUE(NameMatches("", NameMatch::EndsWith, "")); + EXPECT_FALSE(NameMatches("foo", NameMatch::EndsWith, "b")); + EXPECT_FALSE(NameMatches("", NameMatch::EndsWith, "b")); +} + +TEST(NameMatchesTest, RegularExpression) { + EXPECT_TRUE(NameMatches("foobar", NameMatch::RegularExpression, "foo")); + EXPECT_TRUE(NameMatches("foobar", NameMatch::RegularExpression, "f[oa]o")); + EXPECT_TRUE(NameMatches("foo", NameMatch::RegularExpression, "")); + EXPECT_TRUE(NameMatches("", NameMatch::RegularExpression, "")); + EXPECT_FALSE(NameMatches("foo", NameMatch::RegularExpression, "b")); + EXPECT_FALSE(NameMatches("", NameMatch::RegularExpression, "b")); + EXPECT_FALSE(NameMatches("^a", NameMatch::RegularExpression, "^a")); +} diff --git a/unittests/Utility/TildeExpressionResolverTest.cpp b/unittests/Utility/TildeExpressionResolverTest.cpp new file mode 100644 index 000000000000..fd953390ed5d --- /dev/null +++ b/unittests/Utility/TildeExpressionResolverTest.cpp @@ -0,0 +1,36 @@ +#include "gtest/gtest.h" + +#include "Mocks/MockTildeExpressionResolver.h" +#include "lldb/Utility/TildeExpressionResolver.h" + +#include "llvm/ADT/SmallString.h" + +using namespace llvm; +using namespace lldb_private; + +TEST(TildeExpressionResolver, ResolveFullPath) { + MockTildeExpressionResolver Resolver("James", "/james"); + Resolver.AddKnownUser("Kirk", "/kirk"); + Resolver.AddKnownUser("Lars", "/lars"); + Resolver.AddKnownUser("Jason", "/jason"); + Resolver.AddKnownUser("Larry", "/larry"); + + SmallString<32> Result; + ASSERT_TRUE(Resolver.ResolveFullPath("~", Result)); + EXPECT_EQ("/james", Result); + ASSERT_TRUE(Resolver.ResolveFullPath("~/", Result)); + EXPECT_EQ("/james/", Result); + + ASSERT_TRUE(Resolver.ResolveFullPath("~James/bar/baz", Result)); + EXPECT_EQ("/james/bar/baz", Result); + + ASSERT_TRUE(Resolver.ResolveFullPath("~Jason/", Result)); + EXPECT_EQ("/jason/", Result); + + ASSERT_TRUE(Resolver.ResolveFullPath("~Lars", Result)); + EXPECT_EQ("/lars", Result); + + ASSERT_FALSE(Resolver.ResolveFullPath("~Jaso", Result)); + ASSERT_FALSE(Resolver.ResolveFullPath("", Result)); + ASSERT_FALSE(Resolver.ResolveFullPath("Jason", Result)); +} diff --git a/unittests/Utility/TimeoutTest.cpp b/unittests/Utility/TimeoutTest.cpp index a30c616d411b..d1002fb840da 100644 --- a/unittests/Utility/TimeoutTest.cpp +++ b/unittests/Utility/TimeoutTest.cpp @@ -8,15 +8,23 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/Timeout.h" +#include "llvm/Support/FormatVariadic.h" #include "gtest/gtest.h" using namespace lldb_private; using namespace std::chrono; TEST(TimeoutTest, Construction) { - ASSERT_FALSE(Timeout<std::micro>(llvm::None)); - ASSERT_TRUE(bool(Timeout<std::micro>(seconds(0)))); - ASSERT_EQ(seconds(0), *Timeout<std::micro>(seconds(0))); - ASSERT_EQ(seconds(3), *Timeout<std::micro>(seconds(3))); - ASSERT_TRUE(bool(Timeout<std::micro>(Timeout<std::milli>(seconds(0))))); + EXPECT_FALSE(Timeout<std::micro>(llvm::None)); + EXPECT_TRUE(bool(Timeout<std::micro>(seconds(0)))); + EXPECT_EQ(seconds(0), *Timeout<std::micro>(seconds(0))); + EXPECT_EQ(seconds(3), *Timeout<std::micro>(seconds(3))); + EXPECT_TRUE(bool(Timeout<std::micro>(Timeout<std::milli>(seconds(0))))); +} + +TEST(TimeoutTest, Format) { + EXPECT_EQ("<infinite>", + llvm::formatv("{0}", Timeout<std::milli>(llvm::None)).str()); + EXPECT_EQ("1000 ms", + llvm::formatv("{0}", Timeout<std::milli>(seconds(1))).str()); } diff --git a/unittests/Utility/UriParserTest.cpp b/unittests/Utility/UriParserTest.cpp index 8b08e63eb8c7..c07d59a55e01 100644 --- a/unittests/Utility/UriParserTest.cpp +++ b/unittests/Utility/UriParserTest.cpp @@ -1,9 +1,7 @@ -#include "Utility/UriParser.h" +#include "lldb/Utility/UriParser.h" #include "gtest/gtest.h" -namespace { -class UriParserTest : public ::testing::Test {}; -} +using namespace lldb_private; // result strings (scheme/hostname/port/path) passed into UriParser::Parse // are initialized to kAsdf so we can verify that they are unmodified if the @@ -41,12 +39,12 @@ public: EXPECT_EQ(testCase.m_port, port); \ EXPECT_STREQ(testCase.m_path, path.str().c_str()); -TEST_F(UriParserTest, Minimal) { +TEST(UriParserTest, Minimal) { const UriTestCase testCase("x://y", "x", "y", -1, "/"); VALIDATE } -TEST_F(UriParserTest, MinimalPort) { +TEST(UriParserTest, MinimalPort) { const UriTestCase testCase("x://y:1", "x", "y", 1, "/"); llvm::StringRef scheme(kAsdf); llvm::StringRef hostname(kAsdf); @@ -61,28 +59,28 @@ TEST_F(UriParserTest, MinimalPort) { EXPECT_STREQ(testCase.m_path, path.str().c_str()); } -TEST_F(UriParserTest, MinimalPath) { +TEST(UriParserTest, MinimalPath) { const UriTestCase testCase("x://y/", "x", "y", -1, "/"); VALIDATE } -TEST_F(UriParserTest, MinimalPortPath) { +TEST(UriParserTest, MinimalPortPath) { const UriTestCase testCase("x://y:1/", "x", "y", 1, "/"); VALIDATE } -TEST_F(UriParserTest, LongPath) { +TEST(UriParserTest, LongPath) { const UriTestCase testCase("x://y/abc/def/xyz", "x", "y", -1, "/abc/def/xyz"); VALIDATE } -TEST_F(UriParserTest, TypicalPortPath) { +TEST(UriParserTest, TypicalPortPath) { const UriTestCase testCase("connect://192.168.100.132:5432/", "connect", "192.168.100.132", 5432, "/"); VALIDATE; } -TEST_F(UriParserTest, BracketedHostnamePort) { +TEST(UriParserTest, BracketedHostnamePort) { const UriTestCase testCase("connect://[192.168.100.132]:5432/", "connect", "192.168.100.132", 5432, "/"); llvm::StringRef scheme(kAsdf); @@ -98,54 +96,54 @@ TEST_F(UriParserTest, BracketedHostnamePort) { EXPECT_STREQ(testCase.m_path, path.str().c_str()); } -TEST_F(UriParserTest, BracketedHostname) { +TEST(UriParserTest, BracketedHostname) { const UriTestCase testCase("connect://[192.168.100.132]", "connect", "192.168.100.132", -1, "/"); VALIDATE } -TEST_F(UriParserTest, BracketedHostnameWithColon) { +TEST(UriParserTest, BracketedHostnameWithColon) { const UriTestCase testCase("connect://[192.168.100.132:5555]:1234", "connect", "192.168.100.132:5555", 1234, "/"); VALIDATE } -TEST_F(UriParserTest, SchemeHostSeparator) { +TEST(UriParserTest, SchemeHostSeparator) { const UriTestCase testCase("x:/y"); VALIDATE } -TEST_F(UriParserTest, SchemeHostSeparator2) { +TEST(UriParserTest, SchemeHostSeparator2) { const UriTestCase testCase("x:y"); VALIDATE } -TEST_F(UriParserTest, SchemeHostSeparator3) { +TEST(UriParserTest, SchemeHostSeparator3) { const UriTestCase testCase("x//y"); VALIDATE } -TEST_F(UriParserTest, SchemeHostSeparator4) { +TEST(UriParserTest, SchemeHostSeparator4) { const UriTestCase testCase("x/y"); VALIDATE } -TEST_F(UriParserTest, BadPort) { +TEST(UriParserTest, BadPort) { const UriTestCase testCase("x://y:a/"); VALIDATE } -TEST_F(UriParserTest, BadPort2) { +TEST(UriParserTest, BadPort2) { const UriTestCase testCase("x://y:5432a/"); VALIDATE } -TEST_F(UriParserTest, Empty) { +TEST(UriParserTest, Empty) { const UriTestCase testCase(""); VALIDATE } -TEST_F(UriParserTest, PortOverflow) { +TEST(UriParserTest, PortOverflow) { const UriTestCase testCase("x://" "y:" "0123456789012345678901234567890123456789012345678" diff --git a/unittests/Utility/VASprintfTest.cpp b/unittests/Utility/VASprintfTest.cpp new file mode 100644 index 000000000000..0b440942eb5a --- /dev/null +++ b/unittests/Utility/VASprintfTest.cpp @@ -0,0 +1,59 @@ +//===-- VASprintfTest.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/VASPrintf.h" +#include "llvm/ADT/SmallString.h" + +#include "gtest/gtest.h" + +#include <locale.h> + +using namespace lldb_private; +using namespace llvm; + +static bool Sprintf(llvm::SmallVectorImpl<char> &Buffer, const char *Fmt, ...) { + va_list args; + va_start(args, Fmt); + bool Result = VASprintf(Buffer, Fmt, args); + va_end(args); + return Result; +} + +TEST(VASprintfTest, NoBufferResize) { + std::string TestStr("small"); + + llvm::SmallString<32> BigBuffer; + ASSERT_TRUE(Sprintf(BigBuffer, "%s", TestStr.c_str())); + EXPECT_STREQ(TestStr.c_str(), BigBuffer.c_str()); + EXPECT_EQ(TestStr.size(), BigBuffer.size()); +} + +TEST(VASprintfTest, BufferResize) { + std::string TestStr("bigger"); + llvm::SmallString<4> SmallBuffer; + ASSERT_TRUE(Sprintf(SmallBuffer, "%s", TestStr.c_str())); + EXPECT_STREQ(TestStr.c_str(), SmallBuffer.c_str()); + EXPECT_EQ(TestStr.size(), SmallBuffer.size()); +} + +TEST(VASprintfTest, EncodingError) { + // Save the current locale first. + std::string Current(::setlocale(LC_ALL, nullptr)); + + setlocale(LC_ALL, ".932"); + + wchar_t Invalid[2]; + Invalid[0] = 0x100; + Invalid[1] = 0; + llvm::SmallString<32> Buffer; + EXPECT_FALSE(Sprintf(Buffer, "%ls", Invalid)); + EXPECT_EQ("<Encoding error>", Buffer); + + setlocale(LC_ALL, Current.c_str()); +} diff --git a/unittests/debugserver/CMakeLists.txt b/unittests/debugserver/CMakeLists.txt new file mode 100644 index 000000000000..cfb520a0dc76 --- /dev/null +++ b/unittests/debugserver/CMakeLists.txt @@ -0,0 +1,19 @@ +# Note: debugserver is a Darwin-only implementation of a remote debugging +# server. It is not intended to be used on other platforms. The tests are here +# because using the LLDB Host API is convienent and allows testing of both parts +# of the debugserver communication path. If you are looking for a non-darwin +# remote debugging server, please use lldb-server. + +include_directories(${LLDB_SOURCE_DIR}/tools/debugserver/source + ${LLDB_SOURCE_DIR}/tools/debugserver/source/MacOSX) + +add_lldb_unittest(debugserverTests + RNBSocketTest.cpp + debugserver_LogCallback.cpp + + LINK_LIBS + lldbDebugserverCommon + lldbHost + LINK_COMPONENTS + Support + ) diff --git a/unittests/debugserver/RNBSocketTest.cpp b/unittests/debugserver/RNBSocketTest.cpp new file mode 100644 index 000000000000..997041f6154b --- /dev/null +++ b/unittests/debugserver/RNBSocketTest.cpp @@ -0,0 +1,133 @@ +//===-- RNBSocketTest.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include <arpa/inet.h> +#include <sys/sysctl.h> +#include <unistd.h> + +#include "RNBDefs.h" +#include "RNBSocket.h" +#include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" +#include "lldb/Host/common/TCPSocket.h" + +using namespace lldb_private; + +std::string hello = "Hello, world!"; +std::string goodbye = "Goodbye!"; + +static void ServerCallbackv4(const void *baton, in_port_t port) { + auto child_pid = fork(); + if (child_pid == 0) { + Socket *client_socket; + char addr_buffer[256]; + sprintf(addr_buffer, "%s:%d", baton, port); + Error err = Socket::TcpConnect(addr_buffer, false, client_socket); + if (err.Fail()) + abort(); + char buffer[32]; + size_t read_size = 32; + err = client_socket->Read((void *)&buffer[0], read_size); + if (err.Fail()) + abort(); + std::string Recv(&buffer[0], read_size); + if (Recv != hello) + abort(); + size_t write_size = goodbye.length(); + err = client_socket->Write(goodbye.c_str(), write_size); + if (err.Fail()) + abort(); + if (write_size != goodbye.length()) + abort(); + delete client_socket; + exit(0); + } +} + +void TestSocketListen(const char *addr) { + RNBSocket server_socket; + auto result = + server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr); + ASSERT_TRUE(result == rnb_success); + result = server_socket.Write(hello.c_str(), hello.length()); + ASSERT_TRUE(result == rnb_success); + std::string bye; + result = server_socket.Read(bye); + ASSERT_TRUE(result == rnb_success); + ASSERT_EQ(bye, goodbye); + + int exit_status; + wait(&exit_status); + ASSERT_EQ(exit_status, 0); +} + +TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); } + +void TestSocketConnect(const char *addr) { + char addr_wrap[256]; + sprintf(addr_wrap, "%s:0", addr); + + Socket *server_socket; + Predicate<uint16_t> port_predicate; + port_predicate.SetValue(0, eBroadcastNever); + Error err = + Socket::TcpListen(addr_wrap, false, server_socket, &port_predicate); + ASSERT_FALSE(err.Fail()); + + auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber(); + auto child_pid = fork(); + if (child_pid != 0) { + RNBSocket client_socket; + auto result = client_socket.Connect(addr, port); + ASSERT_TRUE(result == rnb_success); + result = client_socket.Write(hello.c_str(), hello.length()); + ASSERT_TRUE(result == rnb_success); + std::string bye; + result = client_socket.Read(bye); + ASSERT_TRUE(result == rnb_success); + ASSERT_EQ(bye, goodbye); + } else { + Socket *connected_socket; + err = server_socket->Accept(addr_wrap, false, connected_socket); + if (err.Fail()) { + llvm::errs() << err.AsCString(); + abort(); + } + char buffer[32]; + size_t read_size = 32; + err = connected_socket->Read((void *)&buffer[0], read_size); + if (err.Fail()) { + llvm::errs() << err.AsCString(); + abort(); + } + std::string Recv(&buffer[0], read_size); + if (Recv != hello) { + llvm::errs() << err.AsCString(); + abort(); + } + size_t write_size = goodbye.length(); + err = connected_socket->Write(goodbye.c_str(), write_size); + if (err.Fail()) { + llvm::errs() << err.AsCString(); + abort(); + } + if (write_size != goodbye.length()) { + llvm::errs() << err.AsCString(); + abort(); + } + exit(0); + } + int exit_status; + wait(&exit_status); + ASSERT_EQ(exit_status, 0); +} + +TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); } diff --git a/unittests/debugserver/debugserver_LogCallback.cpp b/unittests/debugserver/debugserver_LogCallback.cpp new file mode 100644 index 000000000000..7a724b419775 --- /dev/null +++ b/unittests/debugserver/debugserver_LogCallback.cpp @@ -0,0 +1,20 @@ +//===-- debugserver_LogCallback.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//------------------------------------------------------------------------------ +// this function is defined in debugserver.cpp, but is needed to link the +// debugserver Common library. It is for logging only, so it is left +// unimplemented here. +//------------------------------------------------------------------------------ + +#include <stdint.h> +#include <stdarg.h> + +void FileLogCallback(void *baton, uint32_t flags, const char *format, + va_list args) {} diff --git a/unittests/gtest_common.h b/unittests/gtest_common.h index c8fe92575941..f61ba9d0c371 100644 --- a/unittests/gtest_common.h +++ b/unittests/gtest_common.h @@ -15,12 +15,3 @@ // This header file is force included by all of LLDB's unittest compilation // units. Be very leary about putting anything in this file. - -#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) -// Due to a bug in <thread>, when _HAS_EXCEPTIONS == 0 the header will try to -// call -// uncaught_exception() without having a declaration for it. The fix for this -// is -// to manually #include <eh.h>, which contains this declaration. -#include <eh.h> -#endif |