Rework the gtest directory structure.
authorZachary Turner <zturner@google.com>
Fri, 13 Mar 2015 20:54:57 +0000 (20:54 +0000)
committerZachary Turner <zturner@google.com>
Fri, 13 Mar 2015 20:54:57 +0000 (20:54 +0000)
This makes the directory structure mirror the canonical LLVM
directory structure for a gtest suite.

Additionally, this patch deletes the xcode project.  Nobody
is currently depending on this, and it would be better to have
gtest unit tests be hand-maintained in the Xcode workspace
rather than using this python test runner.  Patches to that
effect will be submitted as followups.

llvm-svn: 232211

37 files changed:
lldb/CMakeLists.txt
lldb/gtest/CMakeLists.txt [deleted file]
lldb/gtest/do-gtest.py [deleted file]
lldb/gtest/gtest.xcodeproj/project.pbxproj [deleted file]
lldb/gtest/include/gtest_common.h [deleted file]
lldb/gtest/make/Makefile.rules [deleted file]
lldb/gtest/unittest/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Host/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Host/Makefile [deleted file]
lldb/gtest/unittest/Host/SocketAddressTest.cpp [deleted file]
lldb/gtest/unittest/Host/SocketTest.cpp [deleted file]
lldb/gtest/unittest/Host/SocketTestMock.cpp [deleted file]
lldb/gtest/unittest/Plugins/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Plugins/Process/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Plugins/Process/Linux/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Plugins/Process/Linux/Makefile [deleted file]
lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp [deleted file]
lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp [deleted file]
lldb/gtest/unittest/Utility/CMakeLists.txt [deleted file]
lldb/gtest/unittest/Utility/Makefile [deleted file]
lldb/gtest/unittest/Utility/StringExtractorTest.cpp [deleted file]
lldb/gtest/unittest/Utility/UriParserTest.cpp [deleted file]
lldb/unittests/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Host/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Host/SocketAddressTest.cpp [new file with mode: 0644]
lldb/unittests/Host/SocketTest.cpp [new file with mode: 0644]
lldb/unittests/Host/SocketTestMock.cpp [new file with mode: 0644]
lldb/unittests/Plugins/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Plugins/Process/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Plugins/Process/Linux/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Plugins/Process/Linux/Makefile [new file with mode: 0644]
lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp [new file with mode: 0644]
lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp [new file with mode: 0644]
lldb/unittests/Utility/CMakeLists.txt [new file with mode: 0644]
lldb/unittests/Utility/StringExtractorTest.cpp [new file with mode: 0644]
lldb/unittests/Utility/UriParserTest.cpp [new file with mode: 0644]
lldb/unittests/gtest_common.h [new file with mode: 0644]

index 4629f40f08198e131361b847a826fd55a107903c..5f8c1884ca71dadfa7a466a8f22c6a49010aa25a 100644 (file)
@@ -10,7 +10,7 @@ endif ()
 add_subdirectory(source)
 add_subdirectory(test)
 add_subdirectory(tools)
-add_subdirectory(gtest)
+add_subdirectory(unittests)
 
 
 if ( LLDB_ENABLE_PYTHON_SCRIPTS_SWIG_API_GENERATION AND NOT LLDB_DISABLE_PYTHON )
diff --git a/lldb/gtest/CMakeLists.txt b/lldb/gtest/CMakeLists.txt
deleted file mode 100644 (file)
index 467dd12..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-add_custom_target(LLDBUnitTests)\r
-set_target_properties(LLDBUnitTests PROPERTIES FOLDER "LLDB tests")\r
-\r
-include_directories(${LLDB_SOURCE_ROOT})\r
-\r
-set(LLDB_GTEST_COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include/gtest_common.h)\r
-if (MSVC)\r
-  list(APPEND LLVM_COMPILE_FLAGS /FI ${LLDB_GTEST_COMMON_INCLUDE})\r
-else ()\r
-  list(APPEND LLVM_COMPILE_FLAGS -include ${LLDB_GTEST_COMMON_INCLUDE})\r
-endif ()\r
-\r
-# add_lldb_unittest(test_dirname file1.cpp file2.cpp)\r
-#\r
-# Will compile the list of files together and link against the liblldb\r
-function(add_lldb_unittest test_name)\r
-  add_unittest(LLDBUnitTests ${test_name} ${ARGN})\r
-  target_link_libraries(${test_name} liblldb)\r
-endfunction()\r
-\r
-add_subdirectory(unittest)\r
diff --git a/lldb/gtest/do-gtest.py b/lldb/gtest/do-gtest.py
deleted file mode 100755 (executable)
index d2d4357..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-import os
-import re
-import select
-import subprocess
-import sys
-
-# Wrapping this rather than os.devnull since os.devnull does not seem to implement 'write'.
-class NullWriter(object):
-    def write (self, *args):
-        pass
-    def writelines (self, *args):
-        pass
-    def close (self, *args):
-        pass
-
-# Find all "Makefile"-s in the current directory.
-def find_makefile_dirs():
-    makefile_dirs = []
-    for root, dirs, files in os.walk("."):
-        for file in files:
-            if file == "Makefile":
-                makefile_dirs.append(root)
-    return makefile_dirs
-
-# Test if line starts with <file name>:<line number> pattern
-_TESTDIR_RELATIVE_REGEX = re.compile(r"^([^/:]+:\d+:)")
-
-# Test if the line starts with the string "[ FAILED ]" (whitespace
-# independent) what displayed on the end of a failed test case
-_COMBINER_TERMINATION_REGEX = re.compile(r"^\[ *FAILED *\]")
-
-# Prepends directory before each file name in line matching the regular
-# expression "_TESTDIR_RELATIVE_REGEX" and returns the new value of line and the
-# number of file names modified as a tuple.
-def expand_file_name(directory, line):
-    return _TESTDIR_RELATIVE_REGEX.subn(directory + r"/\1", line)
-
-# Combine the failure report information from the output of gtest into a
-# single line for better displaying inside IDEs
-def line_combine_printer(file, previous_data, new_line_subn_result):
-    (incoming_line, sub_match_count) = new_line_subn_result
-
-    if sub_match_count > 0:
-        # New line was a match for a file name. It means is the first line of
-        # a failure report. Don't print yet, start an accumulation for more
-        # info about the failure.
-        if len(previous_data) > 0:
-            # Flush anything previously accumulated (most likely part of the
-            # previous failure report).
-            print(previous_data, file=file)
-        return incoming_line + ": "
-    else:
-        # If we're combining and incoming is a "[ FAILED ]" line then we have
-        # to stop combining now.
-        if (len(previous_data) > 0) and _COMBINER_TERMINATION_REGEX.match(incoming_line):
-            # Stop the combine and print out its data and the FAIL line also.
-            print(previous_data, file=file)
-            print(incoming_line, file=file)
-            return ""
-
-        if len(previous_data) > 0:
-            # Previous data is available what means we are currently
-            # accumulating a failure report. Append this line to it.
-            if len(previous_data) >= 2 and previous_data[-2:] != ": ":
-                return previous_data + ", " + incoming_line
-            else:
-                return previous_data + incoming_line
-        else:
-            # No previous data and don't have to start new accumulation. Just
-            # print the incoming line if it is not empty.
-            if len(incoming_line) > 0:
-                print(incoming_line, file=file)
-            return ""
-
-def call_make(makefile_dir, extra_args=None, stdout=sys.stdout, stderr=sys.stderr):
-    command = ["make", "-C", makefile_dir]
-    if extra_args:
-        command.extend(extra_args)
-
-    # Execute make as a new subprocess
-    proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
-    stdout_data, stderr_data = "", ""
-
-    while True:
-        reads = [proc.stdout.fileno(), proc.stderr.fileno()]
-        select_result = select.select(reads, [], [])
-
-        # Copy the currently available output from make to the standard output
-        # streams (stdout or stderr)
-        for fd in select_result[0]:
-            if fd == proc.stdout.fileno():
-                line = proc.stdout.readline()
-                stdout_data = line_combine_printer(stdout, stdout_data, expand_file_name(makefile_dir, line.rstrip()))
-            elif fd == proc.stderr.fileno():
-                line = proc.stderr.readline()
-                stderr_data = line_combine_printer(stderr, stderr_data, expand_file_name(makefile_dir, line.rstrip()))
-
-        proc_retval = proc.poll()
-        if proc_retval != None:
-            # Process stopped. Drain output before finishing up.
-
-            # Drain stdout.
-            while True:
-                line = proc.stdout.readline()
-                if line and len(line) > 0:
-                    stdout_data = line_combine_printer(stdout, stdout_data, expand_file_name(makefile_dir, line.rstrip()))
-                else:
-                    break
-
-            # Drain stderr.
-            while True:
-                line = proc.stderr.readline()
-                if line and len(line) > 0:
-                    stderr_data = line_combine_printer(stderr, stderr_data, expand_file_name(makefile_dir, line.rstrip()))
-                else:
-                    break
-
-            return proc_retval
-
-
-global_retval = 0
-
-do_clean_only = ('clean' in sys.argv)
-
-for makefile_dir in find_makefile_dirs():
-    # If we're not only cleaning, we do the normal build.
-    if not do_clean_only:
-        print("making: {}".format(makefile_dir))
-        retval = call_make(makefile_dir)
-        # Remember any errors that happen here.
-        if retval != 0:
-            print()
-            print("-" * 80)
-            print("Tests failed for Makefile in directory: %s" % makefile_dir)
-            print("-" * 80)
-            print()
-            global_retval = retval
-
-    # Now clean
-    call_make(makefile_dir, ['clean'], stdout=NullWriter(), stderr=NullWriter())
-
-if global_retval == 0:
-    print()
-    print("========================")
-    print("| All tests are PASSED |")
-    print("========================")
-else:
-    print()
-    print("=========================================================")
-    print("| Some of the test cases are FAILED with return code: %d |" % global_retval)
-    print("=========================================================")
-sys.exit(global_retval)
diff --git a/lldb/gtest/gtest.xcodeproj/project.pbxproj b/lldb/gtest/gtest.xcodeproj/project.pbxproj
deleted file mode 100644 (file)
index e6c4362..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-// !$*UTF8*$!
-{
-       archiveVersion = 1;
-       classes = {
-       };
-       objectVersion = 46;
-       objects = {
-
-/* Begin PBXFileReference section */
-               236ED33319D49076008CA7D7 /* ThreadStateCoordinatorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadStateCoordinatorTest.cpp; sourceTree = "<group>"; };
-               236ED33419D49081008CA7D7 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
-               236ED33619D490B0008CA7D7 /* Makefile.rules */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.rules; sourceTree = "<group>"; };
-               33064C981A5C7A1A0033D415 /* UriParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParserTest.cpp; path = Utility/UriParserTest.cpp; sourceTree = "<group>"; };
-               33064C9D1A5C7AC90033D415 /* do-gtest.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "do-gtest.py"; sourceTree = "<group>"; };
-               330E475C1A609CF600FD2884 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Host/Makefile; sourceTree = "<group>"; };
-               330E475D1A609CF600FD2884 /* SocketTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTest.cpp; path = Host/SocketTest.cpp; sourceTree = "<group>"; };
-               330E475E1A60B31F00FD2884 /* SocketTestMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTestMock.cpp; path = Host/SocketTestMock.cpp; sourceTree = "<group>"; };
-               330E47621A62451800FD2884 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddressTest.cpp; path = Host/SocketAddressTest.cpp; sourceTree = "<group>"; };
-               338C47F41A1E67B900B46077 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Utility/Makefile; sourceTree = "<group>"; };
-               338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorTest.cpp; path = Utility/StringExtractorTest.cpp; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXGroup section */
-               236ED32F19D4901D008CA7D7 /* unittest */ = {
-                       isa = PBXGroup;
-                       children = (
-                               330E475B1A609CDF00FD2884 /* Host */,
-                               338C47F31A1E677900B46077 /* Utility */,
-                               236ED33019D4903E008CA7D7 /* Plugins */,
-                       );
-                       path = unittest;
-                       sourceTree = "<group>";
-               };
-               236ED33019D4903E008CA7D7 /* Plugins */ = {
-                       isa = PBXGroup;
-                       children = (
-                               236ED33119D4904B008CA7D7 /* Process */,
-                       );
-                       path = Plugins;
-                       sourceTree = "<group>";
-               };
-               236ED33119D4904B008CA7D7 /* Process */ = {
-                       isa = PBXGroup;
-                       children = (
-                               236ED33219D4905B008CA7D7 /* Linux */,
-                       );
-                       path = Process;
-                       sourceTree = "<group>";
-               };
-               236ED33219D4905B008CA7D7 /* Linux */ = {
-                       isa = PBXGroup;
-                       children = (
-                               236ED33419D49081008CA7D7 /* Makefile */,
-                               236ED33319D49076008CA7D7 /* ThreadStateCoordinatorTest.cpp */,
-                       );
-                       path = Linux;
-                       sourceTree = "<group>";
-               };
-               236ED33519D49098008CA7D7 /* make */ = {
-                       isa = PBXGroup;
-                       children = (
-                               236ED33619D490B0008CA7D7 /* Makefile.rules */,
-                       );
-                       path = make;
-                       sourceTree = "<group>";
-               };
-               23CDD8EE19D4790700461DDC = {
-                       isa = PBXGroup;
-                       children = (
-                               33064C9D1A5C7AC90033D415 /* do-gtest.py */,
-                               236ED33519D49098008CA7D7 /* make */,
-                               236ED32F19D4901D008CA7D7 /* unittest */,
-                       );
-                       sourceTree = "<group>";
-               };
-               330E475B1A609CDF00FD2884 /* Host */ = {
-                       isa = PBXGroup;
-                       children = (
-                               330E475E1A60B31F00FD2884 /* SocketTestMock.cpp */,
-                               330E475C1A609CF600FD2884 /* Makefile */,
-                               330E475D1A609CF600FD2884 /* SocketTest.cpp */,
-                               330E47621A62451800FD2884 /* SocketAddressTest.cpp */,
-                       );
-                       name = Host;
-                       sourceTree = "<group>";
-               };
-               338C47F31A1E677900B46077 /* Utility */ = {
-                       isa = PBXGroup;
-                       children = (
-                               33064C981A5C7A1A0033D415 /* UriParserTest.cpp */,
-                               338C47F41A1E67B900B46077 /* Makefile */,
-                               338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */,
-                       );
-                       name = Utility;
-                       sourceTree = "<group>";
-               };
-/* End PBXGroup section */
-
-/* Begin PBXLegacyTarget section */
-               23CDD8F319D4790700461DDC /* gtest */ = {
-                       isa = PBXLegacyTarget;
-                       buildArgumentsString = "do-gtest.py $(ACTION)";
-                       buildConfigurationList = 23CDD8F619D4790700461DDC /* Build configuration list for PBXLegacyTarget "gtest" */;
-                       buildPhases = (
-                       );
-                       buildToolPath = /usr/bin/python;
-                       buildWorkingDirectory = .;
-                       dependencies = (
-                       );
-                       name = gtest;
-                       passBuildSettingsInEnvironment = 1;
-                       productName = gtest;
-               };
-/* End PBXLegacyTarget section */
-
-/* Begin PBXProject section */
-               23CDD8EF19D4790700461DDC /* Project object */ = {
-                       isa = PBXProject;
-                       attributes = {
-                               LastUpgradeCheck = 0600;
-                               ORGANIZATIONNAME = LLVM;
-                               TargetAttributes = {
-                                       23CDD8F319D4790700461DDC = {
-                                               CreatedOnToolsVersion = 6.1;
-                                       };
-                               };
-                       };
-                       buildConfigurationList = 23CDD8F219D4790700461DDC /* Build configuration list for PBXProject "gtest" */;
-                       compatibilityVersion = "Xcode 3.2";
-                       developmentRegion = English;
-                       hasScannedForEncodings = 0;
-                       knownRegions = (
-                               en,
-                       );
-                       mainGroup = 23CDD8EE19D4790700461DDC;
-                       projectDirPath = "";
-                       projectRoot = "";
-                       targets = (
-                               23CDD8F319D4790700461DDC /* gtest */,
-                       );
-               };
-/* End PBXProject section */
-
-/* Begin XCBuildConfiguration section */
-               23CDD8F419D4790700461DDC /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_CONSTANT_CONVERSION = YES;
-                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COPY_PHASE_STRIP = NO;
-                               ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_OPTIMIZATION_LEVEL = 0;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "DEBUG=1",
-                                       "$(inherited)",
-                               );
-                               GCC_SYMBOLS_PRIVATE_EXTERN = NO;
-                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-                               GCC_WARN_UNDECLARED_SELECTOR = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.10;
-                               MTL_ENABLE_DEBUG_INFO = YES;
-                               ONLY_ACTIVE_ARCH = YES;
-                               SDKROOT = macosx;
-                       };
-                       name = Debug;
-               };
-               23CDD8F519D4790700461DDC /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_CONSTANT_CONVERSION = YES;
-                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COPY_PHASE_STRIP = YES;
-                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-                               ENABLE_NS_ASSERTIONS = NO;
-                               ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-                               GCC_WARN_UNDECLARED_SELECTOR = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.10;
-                               MTL_ENABLE_DEBUG_INFO = NO;
-                               SDKROOT = macosx;
-                       };
-                       name = Release;
-               };
-               23CDD8F719D4790700461DDC /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               DEBUGGING_SYMBOLS = YES;
-                               GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-                               GCC_OPTIMIZATION_LEVEL = 0;
-                               OTHER_CFLAGS = "";
-                               OTHER_LDFLAGS = "";
-                               PRODUCT_NAME = "$(TARGET_NAME)";
-                       };
-                       name = Debug;
-               };
-               23CDD8F819D4790700461DDC /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               OTHER_CFLAGS = "";
-                               OTHER_LDFLAGS = "";
-                               PRODUCT_NAME = "$(TARGET_NAME)";
-                       };
-                       name = Release;
-               };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-               23CDD8F219D4790700461DDC /* Build configuration list for PBXProject "gtest" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               23CDD8F419D4790700461DDC /* Debug */,
-                               23CDD8F519D4790700461DDC /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               23CDD8F619D4790700461DDC /* Build configuration list for PBXLegacyTarget "gtest" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               23CDD8F719D4790700461DDC /* Debug */,
-                               23CDD8F819D4790700461DDC /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-/* End XCConfigurationList section */
-       };
-       rootObject = 23CDD8EF19D4790700461DDC /* Project object */;
-}
diff --git a/lldb/gtest/include/gtest_common.h b/lldb/gtest/include/gtest_common.h
deleted file mode 100644 (file)
index 228dfb0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- gtest_common.h ------------------------------------------*- C++ -*-===//\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#if defined(LLDB_GTEST_COMMON_H)\r
-#error "gtest_common.h should not be included manually."\r
-#else\r
-#define LLDB_GTEST_COMMON_H\r
-#endif\r
-\r
-// This header file is force included by all of LLDB's unittest compilation\r
-// units.  Be very leary about putting anything in this file.\r
-\r
-#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)\r
-// MSVC's STL implementation tries to work well with /EHs-c- and\r
-// _HAS_EXCEPTIONS=0.  But <thread> in particular doesn't work with it, because\r
-// it relies on <concrt.h> which tries to throw an exception without checking\r
-// for _HAS_EXCEPTIONS=0.  This causes the linker to require a definition of\r
-// __uncaught_exception(), but the STL doesn't define this function when\r
-// _HAS_EXCEPTIONS=0.  The workaround here is to just provide a stub\r
-// implementation to get it to link.\r
-inline bool\r
-__uncaught_exception()\r
-{\r
-    return true;\r
-}\r
-#endif\r
diff --git a/lldb/gtest/make/Makefile.rules b/lldb/gtest/make/Makefile.rules
deleted file mode 100644 (file)
index 913be0c..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-# Retrieve this Makefile's location.
-THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
-
-# Set default target to be test
-.DEFAULT_GOAL := test
-
-# Set up GTEST for canonical Linux and MacOSX source trees.
-ifneq ($(wildcard $(THIS_FILE_DIR)../../llvm/utils/unittest/googletest),)
-    # Assume lldb/llvm (MacOSX Xcode) directory form.
-    LLVM_BASE_DIR := $(realpath $(THIS_FILE_DIR)../../llvm)
-else
-    ifneq ($(wildcard $(THIS_FILE_DIR)../../../llvm/utils/unittest/googletest),)
-        # Assume lldb/llvm side-by-side configuration (with symbolic links)
-        LLVM_BASE_DIR := $(realpath $(THIS_FILE_DIR)../../../llvm)
-    else
-        # Assume llvm/tools/lldb (Non-MacOSX) directory form.
-        LLVM_BASE_DIR := $(realpath $(THIS_FILE_DIR)../../../..)
-    endif
-endif
-
-ifeq ($(GTEST_DIR),)
-    GTEST_DIR := $(LLVM_BASE_DIR)/utils/unittest/googletest
-endif
-GTEST_INCLUDE_DIR := $(GTEST_DIR)/include
-
-ifeq ($(LLVM_BUILD_DIR),)
-    ifneq ($(wildcard $(THIS_FILE_DIR)../../llvm-build/Release+Asserts/x86_64/Release+Asserts),)
-        LLVM_BUILD_DIR := $(realpath $(THIS_FILE_DIR)../../llvm-build/Release+Asserts/x86_64/Release+Asserts)
-    else ifneq ($(wildcard $(THIS_FILE_DIR)../../../../../build-debug/lib),)
-        LLVM_BUILD_DIR := $(realpath $(THIS_FILE_DIR)../../../../../build-debug)
-    endif
-endif
-
-ifeq ($(LLVM_BUILD_DIR),)
-    $(error Could not find LLVM build output dir, please set it with LLVM_BUILD_DIR)
-endif
-GTEST_STATIC_LIB_DIR := $(LLVM_BUILD_DIR)/lib
-
-ifeq ($(LLVM_BUILD_INCLUDE_DIR),)
-    ifneq ($(wildcard $(LLVM_BUILD_DIR)/../include),)
-        LLVM_BUILD_INCLUDE_DIR := $(realpath $(LLVM_BUILD_DIR)/../include)
-    else ifneq ($(wildcard $(LLVM_BUILD_DIR)/include),)
-        LLVM_BUILD_INCLUDE_DIR := $(realpath $(LLVM_BUILD_DIR)/include)
-    endif
-endif
-
-ifeq ($(LLVM_BUILD_INCLUDE_DIR),)
-    $(error Could not find LLVM build directory include dir, please set it with LLVM_BUILD_INCLUDE_DIR)
-endif
-
-# $(info LLVM_BASE_DIR = $(LLVM_BASE_DIR))
-# $(info LLVM_BUILD_DIR = $(LLVM_BUILD_DIR))
-# $(info GTEST_DIR = $(GTEST_DIR))
-# $(info GTEST_INCLUDE_DIR = $(GTEST_INCLUDE_DIR))
-# $(info GTEST_STATIC_LIB_DIR = $(GTEST_STATIC_LIB_DIR))
-
-# Note lldb/include is already added for us by test/make/Makefile.rules
-LLDB_HEADER_DIRS += \
-       -I $(realpath $(THIS_FILE_DIR)../../source/)
-#      -I $(realpath $(THIS_FILE_DIR)../../include)
-
-CFLAGS_EXTRAS += -I $(GTEST_INCLUDE_DIR) -I $(LLVM_BASE_DIR)/include -I $(LLVM_BUILD_INCLUDE_DIR) $(LLDB_HEADER_DIRS)
-LD_EXTRAS += $(GTEST_STATIC_LIB_DIR)/libgtest.a $(GTEST_STATIC_LIB_DIR)/libgtest_main.a $(GTEST_STATIC_LIB_DIR)/libLLVMSupport.a
-
-.PHONY: clean test
-
-# Handle subdirs
-ifneq ($(SUBDIRS),)
-
-.PHONY: subdirs $(SUBDIRS)
-
-subdirs: $(SUBDIRS)
-
-test:: subdirs
-
-clean:: subdirs
-
-$(SUBDIRS):
-       $(MAKE) -C $@ $(MAKECMDGOALS)
-
-endif
-
-
-# Skip pulling in build rules when we don't have an CXX_SOURCES defined.
-# If this is the case, then we're just recursing directories.
-# Consider doing directory handling/makefile running via a python script
-# like test/dotest.py.
-
-ifneq ($(CXX_SOURCES),)
-
-include $(realpath $(THIS_FILE_DIR)../../test/make/Makefile.rules)
-
-test:: $(EXE)
-       $(realpath $(EXE))
-
-endif
diff --git a/lldb/gtest/unittest/CMakeLists.txt b/lldb/gtest/unittest/CMakeLists.txt
deleted file mode 100644 (file)
index fd57dd9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-add_subdirectory(Host)\r
-add_subdirectory(Plugins)\r
-add_subdirectory(Utility)\r
diff --git a/lldb/gtest/unittest/Host/CMakeLists.txt b/lldb/gtest/unittest/Host/CMakeLists.txt
deleted file mode 100644 (file)
index 227e48c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-add_lldb_unittest(HostTests\r
-  SocketAddressTest.cpp\r
-  SocketTest.cpp\r
-  SocketTestMock.cpp\r
-  )\r
diff --git a/lldb/gtest/unittest/Host/Makefile b/lldb/gtest/unittest/Host/Makefile
deleted file mode 100644 (file)
index f541dd7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
-
-LEVEL := $(realpath $(THIS_FILE_DIR)../../make)
-
-CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-ENABLE_THREADS := YES
-# the fact that we need all of these source files to compile Socket.cpp
-# is a good indication that we need some refactoring
-CXX_SOURCES := $(wildcard *.cpp) \
-    $(realpath $(LEVEL)/../../source/Core/Error.cpp) \
-    $(realpath $(LEVEL)/../../source/Core/RegularExpression.cpp) \
-    $(realpath $(LEVEL)/../../source/Core/Stream.cpp) \
-    $(realpath $(LEVEL)/../../source/Core/StreamString.cpp) \
-    $(realpath $(LEVEL)/../../source/Host/common/Socket.cpp) \
-    $(realpath $(LEVEL)/../../source/Host/common/SocketAddress.cpp) \
-    $(realpath $(LEVEL)/../../source/Host/common/StringConvert.cpp) \
-    $(realpath $(LEVEL)/../../source/Host/common/TimeValue.cpp)
-
-OS := $(shell uname -s)
-ifeq ($(OS),Windows)
-CXX_SOURCES := $(CXX_SOURCES) \
-    $(LEVEL)/../../source/Host/windows/Condition.cpp \
-    $(LEVEL)/../../source/Host/windows/Mutex.cpp
-else
-CXX_SOURCES := $(CXX_SOURCES) \
-    $(LEVEL)/../../source/Host/common/Condition.cpp \
-    $(LEVEL)/../../source/Host/common/Mutex.cpp
-endif
-
-ifeq ($(OS),Linux)
-    LD_EXTRAS := -lncurses -ldl
-endif
-
-MAKE_DSYM := NO
-
-include $(LEVEL)/Makefile.rules
diff --git a/lldb/gtest/unittest/Host/SocketAddressTest.cpp b/lldb/gtest/unittest/Host/SocketAddressTest.cpp
deleted file mode 100644 (file)
index bd6bda1..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-//===-- SocketAddressTest.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/Host/SocketAddress.h"
-
-namespace
-{
-    class SocketAddressTest: public ::testing::Test
-    {
-    };
-}
-
-using namespace lldb_private;
-
-TEST_F (SocketAddressTest, Set)
-{
-    SocketAddress sa;
-    ASSERT_TRUE (sa.SetToLocalhost (AF_INET, 1138));
-    ASSERT_STREQ ("127.0.0.1", sa.GetIPAddress ().c_str ());
-    ASSERT_EQ (1138, sa.GetPort ());
-
-    ASSERT_TRUE (sa.SetToAnyAddress (AF_INET, 0));
-    ASSERT_STREQ ("0.0.0.0", sa.GetIPAddress ().c_str ());
-    ASSERT_EQ (0, sa.GetPort ());
-
-    ASSERT_TRUE (sa.SetToLocalhost (AF_INET6, 1139));
-#ifdef _WIN32
-    ASSERT_STREQ ("0:0:0:0:0:0:0:1", sa.GetIPAddress ().c_str ());
-#else
-    ASSERT_STREQ ("::1", sa.GetIPAddress ().c_str ());
-#endif
-    ASSERT_EQ (1139, sa.GetPort ());
-}
-
-#ifdef _WIN32
-
-// we need to test our inet_ntop implementation for Windows XP
-const char* inet_ntop (int af, const void * src,
-                        char * dst, socklen_t size);
-
-TEST_F (SocketAddressTest, inet_ntop)
-{
-    const uint8_t address4[4] = {255, 0, 1, 100};
-    const uint8_t address6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 255, 0};
-   
-    char buffer[INET6_ADDRSTRLEN];
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, sizeof (buffer)));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, 31));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 0));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 30));
-    
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, sizeof (buffer)));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, 12));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 0));
-    memset (buffer, 'x', sizeof (buffer));
-    EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 11));
-}
-
-#endif
-
-
diff --git a/lldb/gtest/unittest/Host/SocketTest.cpp b/lldb/gtest/unittest/Host/SocketTest.cpp
deleted file mode 100644 (file)
index deed222..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <thread>
-
-#include "gtest/gtest.h"
-
-#include "lldb/Host/Socket.h"
-
-class SocketTest: public ::testing::Test
-{
-};
-
-using namespace lldb_private;
-
-void AcceptThread (Socket* listen_socket,
-                  const char* listen_remote_address,
-                  bool child_processes_inherit,
-                  Socket** accept_socket,
-                  Error* error)
-{
-    *error = listen_socket->BlockingAccept (listen_remote_address, child_processes_inherit, *accept_socket);
-}
-
-void CreateConnectedSockets (std::unique_ptr<Socket>* a_up, std::unique_ptr<Socket>* b_up)
-{
-    Predicate<uint16_t> port_predicate;
-    // Used when binding to port zero to wait for the thread
-    // that creates the socket, binds and listens to resolve
-    // the port number.
-    
-    port_predicate.SetValue (0, eBroadcastNever);
-    
-    bool child_processes_inherit = false;
-    Socket *socket = nullptr;
-    const char* listen_remote_address = "localhost:0";
-    Error error = Socket::TcpListen (listen_remote_address, child_processes_inherit, socket, &port_predicate);
-    std::unique_ptr<Socket> listen_socket_up (socket);
-    socket = nullptr;
-    EXPECT_FALSE (error.Fail ());
-    EXPECT_NE (nullptr, listen_socket_up.get ());
-    EXPECT_TRUE (listen_socket_up->IsValid ());
-
-    Error accept_error;
-    Socket* accept_socket;
-    std::thread accept_thread (AcceptThread,
-                               listen_socket_up.get (),
-                               listen_remote_address,
-                               child_processes_inherit,
-                               &accept_socket,
-                               &accept_error);
-    
-    char connect_remote_address[64];
-    snprintf (connect_remote_address, sizeof (connect_remote_address), "localhost:%u", port_predicate.GetValue ());
-    error = Socket::TcpConnect (connect_remote_address, child_processes_inherit, socket);
-    a_up->reset (socket);
-    socket = nullptr;
-    EXPECT_TRUE (error.Success ());
-    EXPECT_NE (nullptr, a_up->get ());
-    EXPECT_TRUE ((*a_up)->IsValid ());
-    
-    accept_thread.join ();
-    b_up->reset (accept_socket);
-    EXPECT_TRUE (accept_error.Success ());
-    EXPECT_NE (nullptr, b_up->get ());
-    EXPECT_TRUE ((*b_up)->IsValid ());
-    
-    listen_socket_up.reset ();
-}
-
-TEST_F (SocketTest, DecodeHostAndPort)
-{
-    std::string host_str;
-    std::string port_str;
-    int32_t port;
-    Error error;
-    EXPECT_TRUE (Socket::DecodeHostAndPort ("localhost:1138", host_str, port_str, port, &error));
-    EXPECT_STREQ ("localhost", host_str.c_str ());
-    EXPECT_STREQ ("1138", port_str.c_str ());
-    EXPECT_EQ (1138, port);
-    EXPECT_TRUE (error.Success ());
-    
-    EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:65536", host_str, port_str, port, &error));
-    EXPECT_TRUE (error.Fail ());
-    EXPECT_STREQ ("invalid host:port specification: 'google.com:65536'", error.AsCString ());
-    
-    EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:-1138", host_str, port_str, port, &error));
-    EXPECT_TRUE (error.Fail ());
-    EXPECT_STREQ ("invalid host:port specification: 'google.com:-1138'", error.AsCString ());
-    
-    EXPECT_TRUE (Socket::DecodeHostAndPort ("12345", host_str, port_str, port, &error));
-    EXPECT_STREQ ("", host_str.c_str ());
-    EXPECT_STREQ ("12345", port_str.c_str ());
-    EXPECT_EQ (12345, port);
-    EXPECT_TRUE (error.Success ());
-    
-    EXPECT_TRUE (Socket::DecodeHostAndPort ("*:0", host_str, port_str, port, &error));
-    EXPECT_STREQ ("*", host_str.c_str ());
-    EXPECT_STREQ ("0", port_str.c_str ());
-    EXPECT_EQ (0, port);
-    EXPECT_TRUE (error.Success ());
-    
-}
-
-TEST_F (SocketTest, Listen0ConnectAccept)
-{
-    std::unique_ptr<Socket> socket_a_up;
-    std::unique_ptr<Socket> socket_b_up;
-    CreateConnectedSockets (&socket_a_up, &socket_b_up);
-}
-
-TEST_F (SocketTest, GetAddress)
-{
-    std::unique_ptr<Socket> socket_a_up;
-    std::unique_ptr<Socket> socket_b_up;
-    CreateConnectedSockets (&socket_a_up, &socket_b_up);
-    
-    EXPECT_EQ (socket_a_up->GetLocalPortNumber (), socket_b_up->GetRemotePortNumber ());
-    EXPECT_EQ (socket_b_up->GetLocalPortNumber (), socket_a_up->GetRemotePortNumber ());
-    EXPECT_NE (socket_a_up->GetLocalPortNumber (), socket_b_up->GetLocalPortNumber ());
-    EXPECT_STREQ ("127.0.0.1", socket_a_up->GetRemoteIPAddress ().c_str ());
-    EXPECT_STREQ ("127.0.0.1", socket_b_up->GetRemoteIPAddress ().c_str ());
-}
-
-
-
diff --git a/lldb/gtest/unittest/Host/SocketTestMock.cpp b/lldb/gtest/unittest/Host/SocketTestMock.cpp
deleted file mode 100644 (file)
index d457c51..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-//===-- SocketTestMock.cpp --------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// This file provides a few necessary functions to link SocketTest.cpp
-// Bringing in the real implementations results in a cascade of dependencies
-// that pull in all of lldb.
-
-#include "lldb/Core/Log.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-using namespace lldb_private;
-
-void
-lldb_private::Log::Error (char const*, ...)
-{
-}
-
-void
-lldb_private::Log::Printf (char const*, ...)
-{
-}
-
-Log*
-lldb_private::GetLogIfAnyCategoriesSet (unsigned int)
-{
-    return nullptr;
-}
-
-#include "lldb/Host/FileSystem.h"
-
-#ifdef _WIN32
-
-Error
-FileSystem::Unlink(const char *path)
-{
-    Error error;
-    BOOL result = ::DeleteFile(path);
-    if (!result)
-        error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
-    return error;
-}
-
-#else
-
-Error
-FileSystem::Unlink (const char *path)
-{
-    Error error;
-    if (::unlink (path) == -1)
-        error.SetErrorToErrno ();
-    return error;
-}
-
-#endif
-
diff --git a/lldb/gtest/unittest/Plugins/CMakeLists.txt b/lldb/gtest/unittest/Plugins/CMakeLists.txt
deleted file mode 100644 (file)
index 422f203..0000000
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(Process)\r
diff --git a/lldb/gtest/unittest/Plugins/Process/CMakeLists.txt b/lldb/gtest/unittest/Plugins/Process/CMakeLists.txt
deleted file mode 100644 (file)
index bf3426c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-if (CMAKE_SYSTEM_NAME MATCHES "Linux")\r
-  add_subdirectory(Linux)\r
-endif()\r
diff --git a/lldb/gtest/unittest/Plugins/Process/Linux/CMakeLists.txt b/lldb/gtest/unittest/Plugins/Process/Linux/CMakeLists.txt
deleted file mode 100644 (file)
index 3d71f9a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-add_lldb_unittest(ProcessLinuxTests\r
-  ThreadStateCoordinatorTest.cpp\r
-  ThreadStatecoordinatorMock.cpp\r
-  )\r
diff --git a/lldb/gtest/unittest/Plugins/Process/Linux/Makefile b/lldb/gtest/unittest/Plugins/Process/Linux/Makefile
deleted file mode 100644 (file)
index 6817352..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
-
-LEVEL := $(realpath $(THIS_FILE_DIR)../../../../make)
-
-CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-ENABLE_THREADS := YES
-CXX_SOURCES := $(wildcard *.cpp) \
-       $(realpath $(LEVEL)/../../source/Plugins/Process/Linux/ThreadStateCoordinator.cpp) \
-       $(realpath $(LEVEL)/../../source/Core/Error.cpp)
-MAKE_DSYM := NO
-
-OS := $(shell uname -s)
-
-# $(info OS $(OS))
-ifeq ($(OS),Linux)
-    LD_EXTRAS := -lncurses -ldl
-endif
-
-include $(LEVEL)/Makefile.rules
diff --git a/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp b/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
deleted file mode 100644 (file)
index 9e7cc8e..0000000
+++ /dev/null
@@ -1,821 +0,0 @@
-#include <limits.h>
-#include "gtest/gtest.h"
-
-#include "lldb/Core/Error.h"
-#include "Plugins/Process/Linux/ThreadStateCoordinator.h"
-
-using namespace lldb_private;
-
-namespace
-{
-    const ThreadStateCoordinator::ThreadIDSet EMPTY_THREAD_ID_SET;
-
-    void
-    NOPLogger (const char *format, va_list args)
-    {
-        // Do nothing.
-    }
-
-    void
-    StdoutLogger (const char *format, va_list args)
-    {
-        // Print to stdout.
-        vprintf (format, args);
-        printf ("\n");
-    }
-
-    // These are single-line macros so that IDE integration of gtest results puts
-    // the error markers on the correct failure point within the gtest.
-
-#define ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \
-if (HasError ()) { printf ("unexpected error in processing of event, error: %s\n", m_error_string.c_str ()); } \
-ASSERT_EQ (false, HasError ());
-
-#define ASSERT_PROCESS_NEXT_EVENT_FAILS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \
-ASSERT_EQ (true, HasError ());
-
-    class ThreadStateCoordinatorTest: public ::testing::Test
-    {
-    protected:
-        // Constants.
-        const lldb::tid_t TRIGGERING_TID      = 4105;
-        const lldb::tid_t PENDING_STOP_TID    = 3;
-        const lldb::tid_t PENDING_STOP_TID_02 = 29016;
-        const lldb::tid_t NEW_THREAD_TID      = 1234;
-
-        // Member variables.
-        bool m_error_called = false;
-        std::string m_error_string;
-
-        ThreadStateCoordinator m_coordinator;
-
-        bool m_deferred_notification_called;
-        lldb::tid_t m_deferred_notification_tid;
-
-        ThreadStateCoordinator::ThreadIDSet m_requested_stop_tids;
-
-        // Constructors.
-        ThreadStateCoordinatorTest () :
-        m_error_called (false),
-        m_error_string (),
-        m_coordinator (StdoutLogger),
-        m_deferred_notification_called (false),
-        m_deferred_notification_tid (0),
-        m_requested_stop_tids ()
-        {
-        }
-
-        // Member functions.
-
-        // Error handling.
-        ThreadStateCoordinator::ErrorFunction
-        GetErrorFunction ()
-        {
-            return [this] (const std::string &error_string)
-            {
-                m_error_called = true;
-                m_error_string = error_string;
-                printf ("received error: %s (test might be expecting)\n", error_string.c_str ());
-            };
-        }
-
-        bool
-        HasError () const
-        {
-            return m_error_called;
-        }
-
-        // Deferred notification reception.
-        ThreadStateCoordinator::ThreadIDFunction
-        GetDeferredStopNotificationFunction ()
-        {
-            return [this] (lldb::tid_t triggered_tid)
-            {
-                m_deferred_notification_called = true;
-                m_deferred_notification_tid = triggered_tid;
-            };
-        }
-
-        bool
-        DidFireDeferredNotification () const
-        {
-            return m_deferred_notification_called;
-        }
-
-        lldb::tid_t
-        GetDeferredNotificationTID () const
-        {
-            return m_deferred_notification_tid;
-        }
-
-        // Stop request call reception.
-        ThreadStateCoordinator::StopThreadFunction
-        GetStopRequestFunction ()
-        {
-            return [this] (lldb::tid_t stop_tid)
-            {
-                m_requested_stop_tids.insert (stop_tid);
-                return Error();
-            };
-        }
-
-        ThreadStateCoordinator::ThreadIDSet::size_type
-        GetRequestedStopCount () const
-        {
-            return m_requested_stop_tids.size();
-        }
-
-        ThreadStateCoordinator::ResumeThreadFunction
-        GetResumeThreadFunction (lldb::tid_t& resumed_tid, int& resume_call_count)
-        {
-            return [this, &resumed_tid, &resume_call_count] (lldb::tid_t tid, bool)
-            {
-                resumed_tid = tid;
-                ++resume_call_count;
-                return Error();
-            };
-        }
-
-        bool
-        DidRequestStopForTid (lldb::tid_t tid)
-        {
-            return m_requested_stop_tids.find (tid) != m_requested_stop_tids.end ();
-        }
-
-        // Test state initialization helpers.
-        void
-        SetupKnownRunningThread (lldb::tid_t tid)
-        {
-            NotifyThreadCreate (tid, false);
-            ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-        }
-
-        void
-        SetupKnownStoppedThread (lldb::tid_t tid)
-        {
-            NotifyThreadCreate (tid, true);
-            ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-        }
-
-        // Convenience wrappers for ThreadStateCoordinator, using defaults for expected arguments
-        // that plug into the test case handlers.
-        void
-        CallAfterThreadsStop (lldb::tid_t deferred_tid,
-                              const ThreadStateCoordinator::ThreadIDSet &pending_stop_wait_tids)
-        {
-            m_coordinator.CallAfterThreadsStop (deferred_tid,
-                                                pending_stop_wait_tids,
-                                                GetStopRequestFunction (),
-                                                GetDeferredStopNotificationFunction (),
-                                                GetErrorFunction ());
-        }
-
-        void
-        CallAfterRunningThreadsStop (lldb::tid_t deferred_tid)
-        {
-            m_coordinator.CallAfterRunningThreadsStop (deferred_tid,
-                                                       GetStopRequestFunction (),
-                                                       GetDeferredStopNotificationFunction (),
-                                                       GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadCreate (lldb::tid_t stopped_tid, bool thread_is_stopped)
-        {
-            m_coordinator.NotifyThreadCreate (stopped_tid, thread_is_stopped, GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadStop (lldb::tid_t stopped_tid)
-        {
-            m_coordinator.NotifyThreadStop (stopped_tid, false, GetErrorFunction ());
-        }
-
-        void
-        NotifyThreadDeath (lldb::tid_t tid)
-        {
-            m_coordinator.NotifyThreadDeath (tid, GetErrorFunction ());
-        }
-    };
-}
-
-TEST_F (ThreadStateCoordinatorTest, StopCoordinatorWorksNoPriorEvents)
-{
-    m_coordinator.StopCoordinator ();
-    ASSERT_EQ (ThreadStateCoordinator::eventLoopResultStop, m_coordinator.ProcessNextEvent ());
-    ASSERT_EQ (false, HasError ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadCreateSignalsErrorOnAlreadyKnownThread)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify the thread was created - again.
-    NotifyThreadCreate (TRIGGERING_TID, true);
-
-    // This should error out.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-}
-
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadDeathSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 678;
-
-    // Notify an unknown thread has died.
-    NotifyThreadDeath (UNKNOWN_TID);
-
-    // This should error out.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-}
-
-TEST_F (ThreadStateCoordinatorTest, NotifyThreadStopSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 678;
-
-    // Notify an unknown thread has stopped.
-    NotifyThreadStop (UNKNOWN_TID);
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownDeferredThread)
-{
-    const lldb::tid_t UNKNOWN_TRIGGER_TID = 678;
-
-    // Defer notify for an unknown thread.
-    CallAfterThreadsStop (UNKNOWN_TRIGGER_TID,
-                          EMPTY_THREAD_ID_SET);
-
-    // Shouldn't have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Event should fail because trigger tid is unknown.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-
-    // Shouldn't have fired due to error.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownPendingStopThread)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Defer notify for an unknown thread.
-    const lldb::tid_t UNKNOWN_PENDING_STOP_TID = 7890;
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { UNKNOWN_PENDING_STOP_TID };
-
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Shouldn't have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Event should fail because trigger tid is unknown.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-
-    // Shouldn't have triggered deferred notification due to error.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Shouldn't have triggered stop request due to unknown tid.
-    ASSERT_EQ (0, GetRequestedStopCount ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenNoPendingStops)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          EMPTY_THREAD_ID_SET);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingStop)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Let the coordinator know about a currently-running thread we'll wait on.
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now report the that the pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID);
-
-    // Shouldn't take effect until after next processing step.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingStops)
-{
-    // Setup threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (0, GetRequestedStopCount ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the request thread stops should have been called for the pending stop tids.
-    ASSERT_EQ (2, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-
-    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report the that the first pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Shouldn't take effect until after both pending threads are notified.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report the that the first pending stop occurred.
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenPendingAlreadyStopped)
-{
-    // Setup threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Tell m_coordinator the pending stop tid is already stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // The pending stop should *not* fire because the m_coordinator knows it has already stopped.
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // The deferred signal notification should have fired since all requirements were met.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingOneAlreadyStopped)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
-
-    // Tell coordinator the pending stop tid is already stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (0, GetRequestedStopCount ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // The pending stop should only fire for one of the threads, the one that wasn't already stopped.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // The deferred signal notification should not yet have fired since all pending thread stops have not yet occurred.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Notify final thread has stopped.
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // The deferred signal notification should have fired since all requirements were met.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingThreadDies)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (0, GetRequestedStopCount ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the death to be reported.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now report the that the thread with pending stop dies.
-    NotifyThreadDeath (PENDING_STOP_TID);
-
-    // Shouldn't take effect until after next processing step.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, ExistingPendingNotificationRequiresStopFromNewThread)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (0, GetRequestedStopCount ());
-
-    // Process next event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the request thread stop should have been called for the pending stop.
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But we still shouldn't have the deferred signal call go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Indicate a new thread has just been created.
-    SetupKnownRunningThread (NEW_THREAD_TID);
-
-    // We should have just received a stop request for the new thread id.
-    ASSERT_EQ (2, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (NEW_THREAD_TID));
-
-    // Now report the original pending tid stopped.  This should no longer
-    // trigger the pending notification because we should now require the
-    // new thread to stop too.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the new thread stopped.
-    NotifyThreadStop (NEW_THREAD_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Deferred signal notification should have fired now.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, DeferredNotificationRemovedByResetForExec)
-{
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          EMPTY_THREAD_ID_SET);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now indicate an exec occurred, which will invalidate all state about the process and threads.
-    m_coordinator.ResetForExec ();
-
-    // Verify the deferred stop notification does *not* fire with the next
-    // process.  It will handle the reset and not the deferred signaling, which
-    // should now be removed.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnUnknownThread)
-{
-    const lldb::tid_t UNKNOWN_TID = 411;
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (UNKNOWN_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  This should fail since the coordinator doesn't know about the thread.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-    ASSERT_EQ (0, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeCallsCallbackWhenThreadIsStopped)
-{
-    // Initialize thread to be in stopped state.
-    SetupKnownStoppedThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  After that, the resume request call should have fired.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSkipsCallbackOnSecondResumeAttempt)
-{
-    // Initialize thread to be in stopped state.
-    SetupKnownStoppedThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  After that, the resume request call should have fired.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
-
-    // Make a second resume request.
-    const int initial_resume_call_count = resume_call_count;
-    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-
-    // Process next event.  This should fail since the thread should already be running.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-
-    // And the resume count should not have increased.
-    ASSERT_EQ (initial_resume_call_count, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnAlreadyRunningThread)
-{
-    const lldb::tid_t TEST_TID = 1234;
-    SetupKnownRunningThread (NEW_THREAD_TID);
-
-    // Request a resume.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-
-    m_coordinator.RequestThreadResume (TEST_TID,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-
-    // Shouldn't be called yet.
-    ASSERT_EQ (0, resume_call_count);
-
-    // Process next event.  Should be an error.
-    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
-
-    // The resume request should not have gone off because we think it is already running.
-    ASSERT_EQ (0, resume_call_count);
-}
-
-TEST_F (ThreadStateCoordinatorTest, ResumedThreadAlreadyMarkedDoesNotHoldUpPendingStopNotification)
-{
-    // We're going to test this scenario:
-    //   * Deferred notification waiting on two threads, A and B.  A and B currently running.
-    //   * Thread A stops.
-    //   * Thread A resumes.
-    //   * Thread B stops.
-    //
-    //   Here we could have forced A to stop again (after the Thread A resumes) because we had a pending stop nofication awaiting
-    //   all those threads to stop.  However, we are going to explicitly not try to restop A - somehow
-    //   that seems wrong and possibly buggy since for that to happen, we would have intentionally called
-    //   a resume after the stop.  Instead, we'll just log and indicate this looks suspicous.  We can revisit
-    //   that decision after we see if/when that happens.
-    const lldb::tid_t PENDING_TID_A = 2;
-    const lldb::tid_t PENDING_TID_B = 89;
-
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_TID_A);
-    SetupKnownRunningThread (PENDING_TID_B);
-
-    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_TID_A, PENDING_TID_B };
-
-    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
-    CallAfterThreadsStop (TRIGGERING_TID,
-                          pending_stop_tids);
-
-    // Neither trigger should have gone off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_EQ (0, GetRequestedStopCount ());
-
-    // Execute CallAfterThreadsStop.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Both TID A and TID B should have had stop requests made.
-    ASSERT_EQ (2, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_A));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_B));
-
-    // But we still shouldn't have the deferred signal call go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Report thread A stopped.
-    NotifyThreadStop (PENDING_TID_A);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now report thread A is resuming.  Ensure the resume is called.
-    lldb::tid_t resumed_tid = 0;
-    int resume_call_count = 0;
-    m_coordinator.RequestThreadResume (PENDING_TID_A,
-                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
-                                       GetErrorFunction ());
-    ASSERT_EQ (0, resume_call_count);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (1, resume_call_count);
-    ASSERT_EQ (PENDING_TID_A, resumed_tid);
-
-    // Report thread B stopped.
-    NotifyThreadStop (PENDING_TID_B);
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // After notifying thread b stopped, we now have thread a resumed but thread b stopped.
-    // However, since thread a had stopped, we now have had both requirements stopped at some point.
-    // For now we'll expect this will fire the pending deferred stop notification.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopFiresWhenNoRunningThreads)
-{
-    // Let the coordinator know about our thread.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-
-    // And no stop requests should have been made.
-    ASSERT_EQ (0, GetRequestedStopCount ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsTwoPendingStops)
-{
-    // Let the coordinator know about our threads.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID_02);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // We should have two stop requests for the two threads currently running.
-    ASSERT_EQ (2, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
-
-    // But the deferred stop notification should not have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the two threads stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    NotifyThreadStop (PENDING_STOP_TID_02);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
-
-TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsStopTwoOtherThreadsOneRunning)
-{
-    // Let the coordinator know about our threads.  PENDING_STOP_TID_02 will already be stopped.
-    SetupKnownStoppedThread (TRIGGERING_TID);
-    SetupKnownRunningThread (PENDING_STOP_TID);
-    SetupKnownStoppedThread (PENDING_STOP_TID_02);
-
-    // Notify we have a trigger that needs to be fired when all running threads have stopped.
-    CallAfterRunningThreadsStop (TRIGGERING_TID);
-
-    // Notification trigger shouldn't go off yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Process next event.  This will pick up the call after threads stop event.
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // We should have two stop requests for the two threads currently running.
-    ASSERT_EQ (1, GetRequestedStopCount ());
-    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
-
-    // But the deferred stop notification should not have fired yet.
-    ASSERT_EQ (false, DidFireDeferredNotification ());
-
-    // Now notify the two threads stopped.
-    NotifyThreadStop (PENDING_STOP_TID);
-    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
-
-    // Now the trigger should have fired, since there were no threads that needed to first stop.
-    ASSERT_EQ (true, DidFireDeferredNotification ());
-    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
-}
diff --git a/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp b/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp
deleted file mode 100644 (file)
index 7369360..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- ThreadStateCoordinatorTestMock.cpp ----------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// This file provides a few necessary functions to link
-// ThreadStateCoordinatorTest.cpp Bringing in the real implementations results
-// in a cascade of dependencies that pull in all of lldb.
-
-#include "lldb/Core/Log.h"
-
-using namespace lldb_private;
-
-void
-lldb_private::Log::Error (char const*, ...)
-{
-}
-
-void
-lldb_private::Log::Printf (char const*, ...)
-{
-}
-
-Log*
-lldb_private::GetLogIfAnyCategoriesSet (unsigned int)
-{
-    return nullptr;
-}
diff --git a/lldb/gtest/unittest/Utility/CMakeLists.txt b/lldb/gtest/unittest/Utility/CMakeLists.txt
deleted file mode 100644 (file)
index fea0f53..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-add_lldb_unittest(UtilityTests\r
-  StringExtractorTest.cpp\r
-  UriParserTest.cpp\r
-  )\r
diff --git a/lldb/gtest/unittest/Utility/Makefile b/lldb/gtest/unittest/Utility/Makefile
deleted file mode 100644 (file)
index 6b444f5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
-
-LEVEL := $(realpath $(THIS_FILE_DIR)../../make)
-
-CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-ENABLE_THREADS := YES
-CXX_SOURCES := $(wildcard *.cpp) \
-       $(realpath $(LEVEL)/../../source/Host/common/StringConvert.cpp) \
-       $(realpath $(LEVEL)/../../source/Utility/StringExtractor.cpp) \
-       $(realpath $(LEVEL)/../../source/Utility/UriParser.cpp)
-MAKE_DSYM := NO
-
-OS := $(shell uname -s)
-# $(info OS $(OS))
-ifeq ($(OS),Linux)
-    LD_EXTRAS := -lncurses -ldl
-endif
-
-include $(LEVEL)/Makefile.rules
diff --git a/lldb/gtest/unittest/Utility/StringExtractorTest.cpp b/lldb/gtest/unittest/Utility/StringExtractorTest.cpp
deleted file mode 100644 (file)
index cbb3816..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-#include <limits.h>
-#include "gtest/gtest.h"
-
-#include "Utility/StringExtractor.h"
-
-namespace
-{
-    class StringExtractorTest: public ::testing::Test
-    {
-    };
-}
-
-TEST_F (StringExtractorTest, InitEmpty)
-{
-    const char kEmptyString[] = "";
-    StringExtractor ex (kEmptyString);
-
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_STREQ (kEmptyString, ex.GetStringRef().c_str());
-    ASSERT_EQ (true, ex.Empty());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, InitMisc)
-{
-    const char kInitMiscString[] = "Hello, StringExtractor!";
-    StringExtractor ex (kInitMiscString);
-
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_STREQ (kInitMiscString, ex.GetStringRef().c_str());
-    ASSERT_EQ (false, ex.Empty());
-    ASSERT_EQ (sizeof(kInitMiscString)-1, ex.GetBytesLeft());
-    ASSERT_EQ (kInitMiscString[0], *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_Underflow)
-{
-    const char kEmptyString[] = "";
-    StringExtractor ex (kEmptyString);
-
-    ASSERT_EQ (-1, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (true, ex.Empty());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_Underflow2)
-{
-    const char kEmptyString[] = "1";
-    StringExtractor ex (kEmptyString);
-
-    ASSERT_EQ (-1, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (1, ex.GetBytesLeft());
-    ASSERT_EQ ('1', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex)
-{
-    const char kInvalidHex[] = "xa";
-    StringExtractor ex (kInvalidHex);
-
-    ASSERT_EQ (-1, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('x', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex2)
-{
-    const char kInvalidHex[] = "ax";
-    StringExtractor ex (kInvalidHex);
-
-    ASSERT_EQ (-1, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('a', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_Exact)
-{
-    const char kValidHexPair[] = "12";
-    StringExtractor ex (kValidHexPair);
-
-    ASSERT_EQ (0x12, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, DecodeHexU8_Extra)
-{
-    const char kValidHexPair[] = "1234";
-    StringExtractor ex (kValidHexPair);
-
-    ASSERT_EQ (0x12, ex.DecodeHexU8());
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('3', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Underflow)
-{
-    const char kEmptyString[] = "";
-    StringExtractor ex (kEmptyString);
-
-    ASSERT_EQ (0xab, ex.GetHexU8(0xab));
-    ASSERT_EQ (false, ex.IsGood());
-    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
-    ASSERT_EQ (true, ex.Empty());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Underflow2)
-{
-    const char kOneNibble[] = "1";
-    StringExtractor ex (kOneNibble);
-
-    ASSERT_EQ (0xbc, ex.GetHexU8(0xbc));
-    ASSERT_EQ (false, ex.IsGood());
-    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_InvalidHex)
-{
-    const char kInvalidHex[] = "xx";
-    StringExtractor ex (kInvalidHex);
-
-    ASSERT_EQ (0xcd, ex.GetHexU8(0xcd));
-    ASSERT_EQ (false, ex.IsGood());
-    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Exact)
-{
-    const char kValidHexPair[] = "12";
-    StringExtractor ex (kValidHexPair);
-
-    ASSERT_EQ (0x12, ex.GetHexU8(0x12));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Extra)
-{
-    const char kValidHexPair[] = "1234";
-    StringExtractor ex (kValidHexPair);
-
-    ASSERT_EQ (0x12, ex.GetHexU8(0x12));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('3', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Underflow_NoEof)
-{
-    const char kEmptyString[] = "";
-    StringExtractor ex (kEmptyString);
-    const bool kSetEofOnFail = false;
-
-    ASSERT_EQ (0xab, ex.GetHexU8(0xab, kSetEofOnFail));
-    ASSERT_EQ (false, ex.IsGood()); // this result seems inconsistent with kSetEofOnFail == false
-    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
-    ASSERT_EQ (true, ex.Empty());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Underflow2_NoEof)
-{
-    const char kOneNibble[] = "1";
-    StringExtractor ex (kOneNibble);
-    const bool kSetEofOnFail = false;
-
-    ASSERT_EQ (0xbc, ex.GetHexU8(0xbc, kSetEofOnFail));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (1, ex.GetBytesLeft());
-    ASSERT_EQ ('1', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_InvalidHex_NoEof)
-{
-    const char kInvalidHex[] = "xx";
-    StringExtractor ex (kInvalidHex);
-    const bool kSetEofOnFail = false;
-
-    ASSERT_EQ (0xcd, ex.GetHexU8(0xcd, kSetEofOnFail));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (0, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('x', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Exact_NoEof)
-{
-    const char kValidHexPair[] = "12";
-    StringExtractor ex (kValidHexPair);
-    const bool kSetEofOnFail = false;
-
-    ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (0, ex.GetBytesLeft());
-    ASSERT_EQ (nullptr, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexU8_Extra_NoEof)
-{
-    const char kValidHexPair[] = "1234";
-    StringExtractor ex (kValidHexPair);
-    const bool kSetEofOnFail = false;
-
-    ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
-    ASSERT_EQ (true, ex.IsGood());
-    ASSERT_EQ (2, ex.GetFilePos());
-    ASSERT_EQ (2, ex.GetBytesLeft());
-    ASSERT_EQ ('3', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytes)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kValidHexPairs = 8;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[kValidHexPairs];
-    ASSERT_EQ(kValidHexPairs, ex.GetHexBytes (dst, kValidHexPairs, 0xde));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    EXPECT_EQ(0x23,dst[4]);
-    EXPECT_EQ(0x45,dst[5]);
-    EXPECT_EQ(0x67,dst[6]);
-    EXPECT_EQ(0x89,dst[7]);
-
-    ASSERT_EQ(true, ex.IsGood());
-    ASSERT_EQ(2*kValidHexPairs, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(4, ex.GetBytesLeft());
-    ASSERT_EQ('x', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytes_Underflow)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kValidHexPairs = 8;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[12];
-    ASSERT_EQ(kValidHexPairs, ex.GetHexBytes (dst, sizeof(dst), 0xde));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    EXPECT_EQ(0x23,dst[4]);
-    EXPECT_EQ(0x45,dst[5]);
-    EXPECT_EQ(0x67,dst[6]);
-    EXPECT_EQ(0x89,dst[7]);
-    // these bytes should be filled with fail_fill_value 0xde
-    EXPECT_EQ(0xde,dst[8]);
-    EXPECT_EQ(0xde,dst[9]);
-    EXPECT_EQ(0xde,dst[10]);
-    EXPECT_EQ(0xde,dst[11]);
-
-    ASSERT_EQ(false, ex.IsGood());
-    ASSERT_EQ(UINT64_MAX, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(0, ex.GetBytesLeft());
-    ASSERT_EQ(0, ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytes_Partial)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kReadBytes = 4;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[12];
-    memset(dst, 0xab, sizeof(dst));
-    ASSERT_EQ(kReadBytes, ex.GetHexBytes (dst, kReadBytes, 0xde));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    // these bytes should be unchanged
-    EXPECT_EQ(0xab,dst[4]);
-    EXPECT_EQ(0xab,dst[5]);
-    EXPECT_EQ(0xab,dst[6]);
-    EXPECT_EQ(0xab,dst[7]);
-    EXPECT_EQ(0xab,dst[8]);
-    EXPECT_EQ(0xab,dst[9]);
-    EXPECT_EQ(0xab,dst[10]);
-    EXPECT_EQ(0xab,dst[11]);
-
-    ASSERT_EQ(true, ex.IsGood());
-    ASSERT_EQ(kReadBytes*2, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(12, ex.GetBytesLeft());
-    ASSERT_EQ('2', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytesAvail)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kValidHexPairs = 8;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[kValidHexPairs];
-    ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, kValidHexPairs));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    EXPECT_EQ(0x23,dst[4]);
-    EXPECT_EQ(0x45,dst[5]);
-    EXPECT_EQ(0x67,dst[6]);
-    EXPECT_EQ(0x89,dst[7]);
-
-    ASSERT_EQ(true, ex.IsGood());
-    ASSERT_EQ(2*kValidHexPairs, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(4, ex.GetBytesLeft());
-    ASSERT_EQ('x', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytesAvail_Underflow)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kValidHexPairs = 8;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[12];
-    memset(dst, 0xef, sizeof(dst));
-    ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, sizeof(dst)));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    EXPECT_EQ(0x23,dst[4]);
-    EXPECT_EQ(0x45,dst[5]);
-    EXPECT_EQ(0x67,dst[6]);
-    EXPECT_EQ(0x89,dst[7]);
-    // these bytes should be unchanged
-    EXPECT_EQ(0xef,dst[8]);
-    EXPECT_EQ(0xef,dst[9]);
-    EXPECT_EQ(0xef,dst[10]);
-    EXPECT_EQ(0xef,dst[11]);
-
-    ASSERT_EQ(true, ex.IsGood());
-    ASSERT_EQ(kValidHexPairs*2, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(4, ex.GetBytesLeft());
-    ASSERT_EQ('x', *ex.Peek());
-}
-
-TEST_F (StringExtractorTest, GetHexBytesAvail_Partial)
-{
-    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
-    const size_t kReadBytes = 4;
-    StringExtractor ex(kHexEncodedBytes);
-
-    uint8_t dst[12];
-    memset(dst, 0xab, sizeof(dst));
-    ASSERT_EQ(kReadBytes, ex.GetHexBytesAvail (dst, kReadBytes));
-    EXPECT_EQ(0xab,dst[0]);
-    EXPECT_EQ(0xcd,dst[1]);
-    EXPECT_EQ(0xef,dst[2]);
-    EXPECT_EQ(0x01,dst[3]);
-    // these bytes should be unchanged
-    EXPECT_EQ(0xab,dst[4]);
-    EXPECT_EQ(0xab,dst[5]);
-    EXPECT_EQ(0xab,dst[6]);
-    EXPECT_EQ(0xab,dst[7]);
-    EXPECT_EQ(0xab,dst[8]);
-    EXPECT_EQ(0xab,dst[9]);
-    EXPECT_EQ(0xab,dst[10]);
-    EXPECT_EQ(0xab,dst[11]);
-
-    ASSERT_EQ(true, ex.IsGood());
-    ASSERT_EQ(kReadBytes*2, ex.GetFilePos());
-    ASSERT_EQ(false, ex.Empty());
-    ASSERT_EQ(12, ex.GetBytesLeft());
-    ASSERT_EQ('2', *ex.Peek());
-}
-
-
diff --git a/lldb/gtest/unittest/Utility/UriParserTest.cpp b/lldb/gtest/unittest/Utility/UriParserTest.cpp
deleted file mode 100644 (file)
index a11dd8e..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "gtest/gtest.h"
-#include "Utility/UriParser.h"
-
-namespace
-{
-    class UriParserTest: public ::testing::Test
-    {
-    };
-}
-
-// result strings (scheme/hostname/port/path) passed into UriParser::Parse
-// are initialized to kAsdf so we can verify that they are unmodified if the 
-// URI is invalid
-static const char* kAsdf = "asdf";
-
-class UriTestCase
-{
-public:
-    UriTestCase(const char* uri, const char* scheme, const char* hostname, int port, const char* path) :
-      m_uri(uri),
-      m_result(true),
-      m_scheme(scheme),
-      m_hostname(hostname),
-      m_port(port),
-      m_path(path)
-    {
-    }
-
-    UriTestCase(const char* uri) :
-      m_uri(uri),
-      m_result(false),
-      m_scheme(kAsdf),
-      m_hostname(kAsdf),
-      m_port(1138),
-      m_path(kAsdf)
-    {
-    }
-
-    const char* m_uri;
-    bool        m_result;
-    const char* m_scheme;
-    const char* m_hostname;
-    int         m_port;
-    const char* m_path;
-};
-
-#define VALIDATE \
-    std::string scheme(kAsdf); \
-    std::string hostname(kAsdf); \
-    int port(1138); \
-    std::string path(kAsdf); \
-    EXPECT_EQ (testCase.m_result, UriParser::Parse(testCase.m_uri, scheme, hostname, port, path)); \
-    EXPECT_STREQ (testCase.m_scheme, scheme.c_str()); \
-    EXPECT_STREQ (testCase.m_hostname, hostname.c_str()); \
-    EXPECT_EQ (testCase.m_port, port); \
-    EXPECT_STREQ (testCase.m_path, path.c_str());
-
-TEST_F (UriParserTest, Minimal)
-{
-    const UriTestCase testCase("x://y", "x", "y", -1, "/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, MinimalPort)
-{
-    const UriTestCase testCase("x://y:1", "x", "y", 1, "/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, MinimalPath)
-{
-    const UriTestCase testCase("x://y/", "x", "y", -1, "/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, MinimalPortPath)
-{
-    const UriTestCase testCase("x://y:1/", "x", "y", 1, "/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, TypicalPortPath)
-{
-    const UriTestCase testCase("connect://192.168.100.132:5432/", "connect", "192.168.100.132", 5432, "/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, SchemeHostSeparator)
-{
-    const UriTestCase testCase("x:/y");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, SchemeHostSeparator2)
-{
-    const UriTestCase testCase("x:y");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, SchemeHostSeparator3)
-{
-    const UriTestCase testCase("x//y");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, SchemeHostSeparator4)
-{
-    const UriTestCase testCase("x/y");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, BadPort)
-{
-    const UriTestCase testCase("x://y:a/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, BadPort2)
-{
-    const UriTestCase testCase("x://y:5432a/");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, Empty)
-{
-    const UriTestCase testCase("");
-    VALIDATE
-}
-
-TEST_F (UriParserTest, PortOverflow)
-{
-    const UriTestCase testCase("x://y:0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/");
-    VALIDATE
-}
-
diff --git a/lldb/unittests/CMakeLists.txt b/lldb/unittests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e9b3770
--- /dev/null
@@ -0,0 +1,23 @@
+add_custom_target(LLDBUnitTests)\r
+set_target_properties(LLDBUnitTests PROPERTIES FOLDER "LLDB tests")\r
+\r
+include_directories(${LLDB_SOURCE_ROOT})\r
+\r
+set(LLDB_GTEST_COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/gtest_common.h)\r
+if (MSVC)\r
+  list(APPEND LLVM_COMPILE_FLAGS /FI ${LLDB_GTEST_COMMON_INCLUDE})\r
+else ()\r
+  list(APPEND LLVM_COMPILE_FLAGS -include ${LLDB_GTEST_COMMON_INCLUDE})\r
+endif ()\r
+\r
+# add_lldb_unittest(test_dirname file1.cpp file2.cpp)\r
+#\r
+# Will compile the list of files together and link against the liblldb\r
+function(add_lldb_unittest test_name)\r
+  add_unittest(LLDBUnitTests ${test_name} ${ARGN})\r
+  target_link_libraries(${test_name} liblldb)\r
+endfunction()\r
+\r
+add_subdirectory(Host)\r
+add_subdirectory(Plugins)\r
+add_subdirectory(Utility)\r
diff --git a/lldb/unittests/Host/CMakeLists.txt b/lldb/unittests/Host/CMakeLists.txt
new file mode 100644 (file)
index 0000000..227e48c
--- /dev/null
@@ -0,0 +1,5 @@
+add_lldb_unittest(HostTests\r
+  SocketAddressTest.cpp\r
+  SocketTest.cpp\r
+  SocketTestMock.cpp\r
+  )\r
diff --git a/lldb/unittests/Host/SocketAddressTest.cpp b/lldb/unittests/Host/SocketAddressTest.cpp
new file mode 100644 (file)
index 0000000..bd6bda1
--- /dev/null
@@ -0,0 +1,77 @@
+//===-- SocketAddressTest.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/Host/SocketAddress.h"
+
+namespace
+{
+    class SocketAddressTest: public ::testing::Test
+    {
+    };
+}
+
+using namespace lldb_private;
+
+TEST_F (SocketAddressTest, Set)
+{
+    SocketAddress sa;
+    ASSERT_TRUE (sa.SetToLocalhost (AF_INET, 1138));
+    ASSERT_STREQ ("127.0.0.1", sa.GetIPAddress ().c_str ());
+    ASSERT_EQ (1138, sa.GetPort ());
+
+    ASSERT_TRUE (sa.SetToAnyAddress (AF_INET, 0));
+    ASSERT_STREQ ("0.0.0.0", sa.GetIPAddress ().c_str ());
+    ASSERT_EQ (0, sa.GetPort ());
+
+    ASSERT_TRUE (sa.SetToLocalhost (AF_INET6, 1139));
+#ifdef _WIN32
+    ASSERT_STREQ ("0:0:0:0:0:0:0:1", sa.GetIPAddress ().c_str ());
+#else
+    ASSERT_STREQ ("::1", sa.GetIPAddress ().c_str ());
+#endif
+    ASSERT_EQ (1139, sa.GetPort ());
+}
+
+#ifdef _WIN32
+
+// we need to test our inet_ntop implementation for Windows XP
+const char* inet_ntop (int af, const void * src,
+                        char * dst, socklen_t size);
+
+TEST_F (SocketAddressTest, inet_ntop)
+{
+    const uint8_t address4[4] = {255, 0, 1, 100};
+    const uint8_t address6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 255, 0};
+   
+    char buffer[INET6_ADDRSTRLEN];
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, sizeof (buffer)));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, 31));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 0));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 30));
+    
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, sizeof (buffer)));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, 12));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 0));
+    memset (buffer, 'x', sizeof (buffer));
+    EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 11));
+}
+
+#endif
+
+
diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
new file mode 100644 (file)
index 0000000..deed222
--- /dev/null
@@ -0,0 +1,132 @@
+//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "lldb/Host/Socket.h"
+
+class SocketTest: public ::testing::Test
+{
+};
+
+using namespace lldb_private;
+
+void AcceptThread (Socket* listen_socket,
+                  const char* listen_remote_address,
+                  bool child_processes_inherit,
+                  Socket** accept_socket,
+                  Error* error)
+{
+    *error = listen_socket->BlockingAccept (listen_remote_address, child_processes_inherit, *accept_socket);
+}
+
+void CreateConnectedSockets (std::unique_ptr<Socket>* a_up, std::unique_ptr<Socket>* b_up)
+{
+    Predicate<uint16_t> port_predicate;
+    // Used when binding to port zero to wait for the thread
+    // that creates the socket, binds and listens to resolve
+    // the port number.
+    
+    port_predicate.SetValue (0, eBroadcastNever);
+    
+    bool child_processes_inherit = false;
+    Socket *socket = nullptr;
+    const char* listen_remote_address = "localhost:0";
+    Error error = Socket::TcpListen (listen_remote_address, child_processes_inherit, socket, &port_predicate);
+    std::unique_ptr<Socket> listen_socket_up (socket);
+    socket = nullptr;
+    EXPECT_FALSE (error.Fail ());
+    EXPECT_NE (nullptr, listen_socket_up.get ());
+    EXPECT_TRUE (listen_socket_up->IsValid ());
+
+    Error accept_error;
+    Socket* accept_socket;
+    std::thread accept_thread (AcceptThread,
+                               listen_socket_up.get (),
+                               listen_remote_address,
+                               child_processes_inherit,
+                               &accept_socket,
+                               &accept_error);
+    
+    char connect_remote_address[64];
+    snprintf (connect_remote_address, sizeof (connect_remote_address), "localhost:%u", port_predicate.GetValue ());
+    error = Socket::TcpConnect (connect_remote_address, child_processes_inherit, socket);
+    a_up->reset (socket);
+    socket = nullptr;
+    EXPECT_TRUE (error.Success ());
+    EXPECT_NE (nullptr, a_up->get ());
+    EXPECT_TRUE ((*a_up)->IsValid ());
+    
+    accept_thread.join ();
+    b_up->reset (accept_socket);
+    EXPECT_TRUE (accept_error.Success ());
+    EXPECT_NE (nullptr, b_up->get ());
+    EXPECT_TRUE ((*b_up)->IsValid ());
+    
+    listen_socket_up.reset ();
+}
+
+TEST_F (SocketTest, DecodeHostAndPort)
+{
+    std::string host_str;
+    std::string port_str;
+    int32_t port;
+    Error error;
+    EXPECT_TRUE (Socket::DecodeHostAndPort ("localhost:1138", host_str, port_str, port, &error));
+    EXPECT_STREQ ("localhost", host_str.c_str ());
+    EXPECT_STREQ ("1138", port_str.c_str ());
+    EXPECT_EQ (1138, port);
+    EXPECT_TRUE (error.Success ());
+    
+    EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:65536", host_str, port_str, port, &error));
+    EXPECT_TRUE (error.Fail ());
+    EXPECT_STREQ ("invalid host:port specification: 'google.com:65536'", error.AsCString ());
+    
+    EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:-1138", host_str, port_str, port, &error));
+    EXPECT_TRUE (error.Fail ());
+    EXPECT_STREQ ("invalid host:port specification: 'google.com:-1138'", error.AsCString ());
+    
+    EXPECT_TRUE (Socket::DecodeHostAndPort ("12345", host_str, port_str, port, &error));
+    EXPECT_STREQ ("", host_str.c_str ());
+    EXPECT_STREQ ("12345", port_str.c_str ());
+    EXPECT_EQ (12345, port);
+    EXPECT_TRUE (error.Success ());
+    
+    EXPECT_TRUE (Socket::DecodeHostAndPort ("*:0", host_str, port_str, port, &error));
+    EXPECT_STREQ ("*", host_str.c_str ());
+    EXPECT_STREQ ("0", port_str.c_str ());
+    EXPECT_EQ (0, port);
+    EXPECT_TRUE (error.Success ());
+    
+}
+
+TEST_F (SocketTest, Listen0ConnectAccept)
+{
+    std::unique_ptr<Socket> socket_a_up;
+    std::unique_ptr<Socket> socket_b_up;
+    CreateConnectedSockets (&socket_a_up, &socket_b_up);
+}
+
+TEST_F (SocketTest, GetAddress)
+{
+    std::unique_ptr<Socket> socket_a_up;
+    std::unique_ptr<Socket> socket_b_up;
+    CreateConnectedSockets (&socket_a_up, &socket_b_up);
+    
+    EXPECT_EQ (socket_a_up->GetLocalPortNumber (), socket_b_up->GetRemotePortNumber ());
+    EXPECT_EQ (socket_b_up->GetLocalPortNumber (), socket_a_up->GetRemotePortNumber ());
+    EXPECT_NE (socket_a_up->GetLocalPortNumber (), socket_b_up->GetLocalPortNumber ());
+    EXPECT_STREQ ("127.0.0.1", socket_a_up->GetRemoteIPAddress ().c_str ());
+    EXPECT_STREQ ("127.0.0.1", socket_b_up->GetRemoteIPAddress ().c_str ());
+}
+
+
+
diff --git a/lldb/unittests/Host/SocketTestMock.cpp b/lldb/unittests/Host/SocketTestMock.cpp
new file mode 100644 (file)
index 0000000..d457c51
--- /dev/null
@@ -0,0 +1,64 @@
+//===-- SocketTestMock.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file provides a few necessary functions to link SocketTest.cpp
+// Bringing in the real implementations results in a cascade of dependencies
+// that pull in all of lldb.
+
+#include "lldb/Core/Log.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+using namespace lldb_private;
+
+void
+lldb_private::Log::Error (char const*, ...)
+{
+}
+
+void
+lldb_private::Log::Printf (char const*, ...)
+{
+}
+
+Log*
+lldb_private::GetLogIfAnyCategoriesSet (unsigned int)
+{
+    return nullptr;
+}
+
+#include "lldb/Host/FileSystem.h"
+
+#ifdef _WIN32
+
+Error
+FileSystem::Unlink(const char *path)
+{
+    Error error;
+    BOOL result = ::DeleteFile(path);
+    if (!result)
+        error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+    return error;
+}
+
+#else
+
+Error
+FileSystem::Unlink (const char *path)
+{
+    Error error;
+    if (::unlink (path) == -1)
+        error.SetErrorToErrno ();
+    return error;
+}
+
+#endif
+
diff --git a/lldb/unittests/Plugins/CMakeLists.txt b/lldb/unittests/Plugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..422f203
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(Process)\r
diff --git a/lldb/unittests/Plugins/Process/CMakeLists.txt b/lldb/unittests/Plugins/Process/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bf3426c
--- /dev/null
@@ -0,0 +1,3 @@
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")\r
+  add_subdirectory(Linux)\r
+endif()\r
diff --git a/lldb/unittests/Plugins/Process/Linux/CMakeLists.txt b/lldb/unittests/Plugins/Process/Linux/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3d71f9a
--- /dev/null
@@ -0,0 +1,4 @@
+add_lldb_unittest(ProcessLinuxTests\r
+  ThreadStateCoordinatorTest.cpp\r
+  ThreadStatecoordinatorMock.cpp\r
+  )\r
diff --git a/lldb/unittests/Plugins/Process/Linux/Makefile b/lldb/unittests/Plugins/Process/Linux/Makefile
new file mode 100644 (file)
index 0000000..6817352
--- /dev/null
@@ -0,0 +1,19 @@
+THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/
+
+LEVEL := $(realpath $(THIS_FILE_DIR)../../../../make)
+
+CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
+ENABLE_THREADS := YES
+CXX_SOURCES := $(wildcard *.cpp) \
+       $(realpath $(LEVEL)/../../source/Plugins/Process/Linux/ThreadStateCoordinator.cpp) \
+       $(realpath $(LEVEL)/../../source/Core/Error.cpp)
+MAKE_DSYM := NO
+
+OS := $(shell uname -s)
+
+# $(info OS $(OS))
+ifeq ($(OS),Linux)
+    LD_EXTRAS := -lncurses -ldl
+endif
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp b/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
new file mode 100644 (file)
index 0000000..9e7cc8e
--- /dev/null
@@ -0,0 +1,821 @@
+#include <limits.h>
+#include "gtest/gtest.h"
+
+#include "lldb/Core/Error.h"
+#include "Plugins/Process/Linux/ThreadStateCoordinator.h"
+
+using namespace lldb_private;
+
+namespace
+{
+    const ThreadStateCoordinator::ThreadIDSet EMPTY_THREAD_ID_SET;
+
+    void
+    NOPLogger (const char *format, va_list args)
+    {
+        // Do nothing.
+    }
+
+    void
+    StdoutLogger (const char *format, va_list args)
+    {
+        // Print to stdout.
+        vprintf (format, args);
+        printf ("\n");
+    }
+
+    // These are single-line macros so that IDE integration of gtest results puts
+    // the error markers on the correct failure point within the gtest.
+
+#define ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \
+if (HasError ()) { printf ("unexpected error in processing of event, error: %s\n", m_error_string.c_str ()); } \
+ASSERT_EQ (false, HasError ());
+
+#define ASSERT_PROCESS_NEXT_EVENT_FAILS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \
+ASSERT_EQ (true, HasError ());
+
+    class ThreadStateCoordinatorTest: public ::testing::Test
+    {
+    protected:
+        // Constants.
+        const lldb::tid_t TRIGGERING_TID      = 4105;
+        const lldb::tid_t PENDING_STOP_TID    = 3;
+        const lldb::tid_t PENDING_STOP_TID_02 = 29016;
+        const lldb::tid_t NEW_THREAD_TID      = 1234;
+
+        // Member variables.
+        bool m_error_called = false;
+        std::string m_error_string;
+
+        ThreadStateCoordinator m_coordinator;
+
+        bool m_deferred_notification_called;
+        lldb::tid_t m_deferred_notification_tid;
+
+        ThreadStateCoordinator::ThreadIDSet m_requested_stop_tids;
+
+        // Constructors.
+        ThreadStateCoordinatorTest () :
+        m_error_called (false),
+        m_error_string (),
+        m_coordinator (StdoutLogger),
+        m_deferred_notification_called (false),
+        m_deferred_notification_tid (0),
+        m_requested_stop_tids ()
+        {
+        }
+
+        // Member functions.
+
+        // Error handling.
+        ThreadStateCoordinator::ErrorFunction
+        GetErrorFunction ()
+        {
+            return [this] (const std::string &error_string)
+            {
+                m_error_called = true;
+                m_error_string = error_string;
+                printf ("received error: %s (test might be expecting)\n", error_string.c_str ());
+            };
+        }
+
+        bool
+        HasError () const
+        {
+            return m_error_called;
+        }
+
+        // Deferred notification reception.
+        ThreadStateCoordinator::ThreadIDFunction
+        GetDeferredStopNotificationFunction ()
+        {
+            return [this] (lldb::tid_t triggered_tid)
+            {
+                m_deferred_notification_called = true;
+                m_deferred_notification_tid = triggered_tid;
+            };
+        }
+
+        bool
+        DidFireDeferredNotification () const
+        {
+            return m_deferred_notification_called;
+        }
+
+        lldb::tid_t
+        GetDeferredNotificationTID () const
+        {
+            return m_deferred_notification_tid;
+        }
+
+        // Stop request call reception.
+        ThreadStateCoordinator::StopThreadFunction
+        GetStopRequestFunction ()
+        {
+            return [this] (lldb::tid_t stop_tid)
+            {
+                m_requested_stop_tids.insert (stop_tid);
+                return Error();
+            };
+        }
+
+        ThreadStateCoordinator::ThreadIDSet::size_type
+        GetRequestedStopCount () const
+        {
+            return m_requested_stop_tids.size();
+        }
+
+        ThreadStateCoordinator::ResumeThreadFunction
+        GetResumeThreadFunction (lldb::tid_t& resumed_tid, int& resume_call_count)
+        {
+            return [this, &resumed_tid, &resume_call_count] (lldb::tid_t tid, bool)
+            {
+                resumed_tid = tid;
+                ++resume_call_count;
+                return Error();
+            };
+        }
+
+        bool
+        DidRequestStopForTid (lldb::tid_t tid)
+        {
+            return m_requested_stop_tids.find (tid) != m_requested_stop_tids.end ();
+        }
+
+        // Test state initialization helpers.
+        void
+        SetupKnownRunningThread (lldb::tid_t tid)
+        {
+            NotifyThreadCreate (tid, false);
+            ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+        }
+
+        void
+        SetupKnownStoppedThread (lldb::tid_t tid)
+        {
+            NotifyThreadCreate (tid, true);
+            ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+        }
+
+        // Convenience wrappers for ThreadStateCoordinator, using defaults for expected arguments
+        // that plug into the test case handlers.
+        void
+        CallAfterThreadsStop (lldb::tid_t deferred_tid,
+                              const ThreadStateCoordinator::ThreadIDSet &pending_stop_wait_tids)
+        {
+            m_coordinator.CallAfterThreadsStop (deferred_tid,
+                                                pending_stop_wait_tids,
+                                                GetStopRequestFunction (),
+                                                GetDeferredStopNotificationFunction (),
+                                                GetErrorFunction ());
+        }
+
+        void
+        CallAfterRunningThreadsStop (lldb::tid_t deferred_tid)
+        {
+            m_coordinator.CallAfterRunningThreadsStop (deferred_tid,
+                                                       GetStopRequestFunction (),
+                                                       GetDeferredStopNotificationFunction (),
+                                                       GetErrorFunction ());
+        }
+
+        void
+        NotifyThreadCreate (lldb::tid_t stopped_tid, bool thread_is_stopped)
+        {
+            m_coordinator.NotifyThreadCreate (stopped_tid, thread_is_stopped, GetErrorFunction ());
+        }
+
+        void
+        NotifyThreadStop (lldb::tid_t stopped_tid)
+        {
+            m_coordinator.NotifyThreadStop (stopped_tid, false, GetErrorFunction ());
+        }
+
+        void
+        NotifyThreadDeath (lldb::tid_t tid)
+        {
+            m_coordinator.NotifyThreadDeath (tid, GetErrorFunction ());
+        }
+    };
+}
+
+TEST_F (ThreadStateCoordinatorTest, StopCoordinatorWorksNoPriorEvents)
+{
+    m_coordinator.StopCoordinator ();
+    ASSERT_EQ (ThreadStateCoordinator::eventLoopResultStop, m_coordinator.ProcessNextEvent ());
+    ASSERT_EQ (false, HasError ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, NotifyThreadCreateSignalsErrorOnAlreadyKnownThread)
+{
+    // Let the coordinator know about our thread.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Notify the thread was created - again.
+    NotifyThreadCreate (TRIGGERING_TID, true);
+
+    // This should error out.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+}
+
+
+TEST_F (ThreadStateCoordinatorTest, NotifyThreadDeathSignalsErrorOnUnknownThread)
+{
+    const lldb::tid_t UNKNOWN_TID = 678;
+
+    // Notify an unknown thread has died.
+    NotifyThreadDeath (UNKNOWN_TID);
+
+    // This should error out.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+}
+
+TEST_F (ThreadStateCoordinatorTest, NotifyThreadStopSignalsErrorOnUnknownThread)
+{
+    const lldb::tid_t UNKNOWN_TID = 678;
+
+    // Notify an unknown thread has stopped.
+    NotifyThreadStop (UNKNOWN_TID);
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownDeferredThread)
+{
+    const lldb::tid_t UNKNOWN_TRIGGER_TID = 678;
+
+    // Defer notify for an unknown thread.
+    CallAfterThreadsStop (UNKNOWN_TRIGGER_TID,
+                          EMPTY_THREAD_ID_SET);
+
+    // Shouldn't have fired yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Event should fail because trigger tid is unknown.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+
+    // Shouldn't have fired due to error.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownPendingStopThread)
+{
+    // Let the coordinator know about our thread.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Defer notify for an unknown thread.
+    const lldb::tid_t UNKNOWN_PENDING_STOP_TID = 7890;
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { UNKNOWN_PENDING_STOP_TID };
+
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Shouldn't have fired yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Event should fail because trigger tid is unknown.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+
+    // Shouldn't have triggered deferred notification due to error.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Shouldn't have triggered stop request due to unknown tid.
+    ASSERT_EQ (0, GetRequestedStopCount ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenNoPendingStops)
+{
+    // Let the coordinator know about our thread.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          EMPTY_THREAD_ID_SET);
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.  This will pick up the call after threads stop event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the trigger should have fired, since there were no threads that needed to first stop.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingStop)
+{
+    // Let the coordinator know about our thread.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Let the coordinator know about a currently-running thread we'll wait on.
+    SetupKnownRunningThread (PENDING_STOP_TID);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the request thread stop should have been called for the pending stop.
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now report the that the pending stop occurred.
+    NotifyThreadStop (PENDING_STOP_TID);
+
+    // Shouldn't take effect until after next processing step.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Deferred signal notification should have fired now.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingStops)
+{
+    // Setup threads.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID_02);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (0, GetRequestedStopCount ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the request thread stops should have been called for the pending stop tids.
+    ASSERT_EQ (2, GetRequestedStopCount ());
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
+
+    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the stop to be reported.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Report the that the first pending stop occurred.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Shouldn't take effect until after both pending threads are notified.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Report the that the first pending stop occurred.
+    NotifyThreadStop (PENDING_STOP_TID_02);
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Deferred signal notification should have fired now.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenPendingAlreadyStopped)
+{
+    // Setup threads.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
+
+    // Tell m_coordinator the pending stop tid is already stopped.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // The pending stop should *not* fire because the m_coordinator knows it has already stopped.
+    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // The deferred signal notification should have fired since all requirements were met.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenTwoPendingOneAlreadyStopped)
+{
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID_02);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID, PENDING_STOP_TID_02 };
+
+    // Tell coordinator the pending stop tid is already stopped.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (0, GetRequestedStopCount ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // The pending stop should only fire for one of the threads, the one that wasn't already stopped.
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
+    ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // The deferred signal notification should not yet have fired since all pending thread stops have not yet occurred.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Notify final thread has stopped.
+    NotifyThreadStop (PENDING_STOP_TID_02);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // The deferred signal notification should have fired since all requirements were met.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterThreadsStopFiresWhenOnePendingThreadDies)
+{
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (0, GetRequestedStopCount ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the request thread stop should have been called for the pending stop.
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // But we still shouldn't have the deferred signal call go off yet.  Need to wait for the death to be reported.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now report the that the thread with pending stop dies.
+    NotifyThreadDeath (PENDING_STOP_TID);
+
+    // Shouldn't take effect until after next processing step.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Deferred signal notification should have fired now.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, ExistingPendingNotificationRequiresStopFromNewThread)
+{
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_STOP_TID };
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (0, GetRequestedStopCount ());
+
+    // Process next event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the request thread stop should have been called for the pending stop.
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // But we still shouldn't have the deferred signal call go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Indicate a new thread has just been created.
+    SetupKnownRunningThread (NEW_THREAD_TID);
+
+    // We should have just received a stop request for the new thread id.
+    ASSERT_EQ (2, GetRequestedStopCount ());
+    ASSERT_EQ (true, DidRequestStopForTid (NEW_THREAD_TID));
+
+    // Now report the original pending tid stopped.  This should no longer
+    // trigger the pending notification because we should now require the
+    // new thread to stop too.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now notify the new thread stopped.
+    NotifyThreadStop (NEW_THREAD_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Deferred signal notification should have fired now.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, DeferredNotificationRemovedByResetForExec)
+{
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          EMPTY_THREAD_ID_SET);
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now indicate an exec occurred, which will invalidate all state about the process and threads.
+    m_coordinator.ResetForExec ();
+
+    // Verify the deferred stop notification does *not* fire with the next
+    // process.  It will handle the reset and not the deferred signaling, which
+    // should now be removed.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnUnknownThread)
+{
+    const lldb::tid_t UNKNOWN_TID = 411;
+
+    // Request a resume.
+    lldb::tid_t resumed_tid = 0;
+    int resume_call_count = 0;
+
+    m_coordinator.RequestThreadResume (UNKNOWN_TID,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+    // Shouldn't be called yet.
+    ASSERT_EQ (0, resume_call_count);
+
+    // Process next event.  This should fail since the coordinator doesn't know about the thread.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+    ASSERT_EQ (0, resume_call_count);
+}
+
+TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeCallsCallbackWhenThreadIsStopped)
+{
+    // Initialize thread to be in stopped state.
+    SetupKnownStoppedThread (NEW_THREAD_TID);
+
+    // Request a resume.
+    lldb::tid_t resumed_tid = 0;
+    int resume_call_count = 0;
+
+    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+    // Shouldn't be called yet.
+    ASSERT_EQ (0, resume_call_count);
+
+    // Process next event.  After that, the resume request call should have fired.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (1, resume_call_count);
+    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
+}
+
+TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSkipsCallbackOnSecondResumeAttempt)
+{
+    // Initialize thread to be in stopped state.
+    SetupKnownStoppedThread (NEW_THREAD_TID);
+
+    // Request a resume.
+    lldb::tid_t resumed_tid = 0;
+    int resume_call_count = 0;
+
+    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+    // Shouldn't be called yet.
+    ASSERT_EQ (0, resume_call_count);
+
+    // Process next event.  After that, the resume request call should have fired.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (1, resume_call_count);
+    ASSERT_EQ (NEW_THREAD_TID, resumed_tid);
+
+    // Make a second resume request.
+    const int initial_resume_call_count = resume_call_count;
+    m_coordinator.RequestThreadResume (NEW_THREAD_TID,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+
+    // Process next event.  This should fail since the thread should already be running.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+
+    // And the resume count should not have increased.
+    ASSERT_EQ (initial_resume_call_count, resume_call_count);
+}
+
+TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnAlreadyRunningThread)
+{
+    const lldb::tid_t TEST_TID = 1234;
+    SetupKnownRunningThread (NEW_THREAD_TID);
+
+    // Request a resume.
+    lldb::tid_t resumed_tid = 0;
+    int resume_call_count = 0;
+
+    m_coordinator.RequestThreadResume (TEST_TID,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+
+    // Shouldn't be called yet.
+    ASSERT_EQ (0, resume_call_count);
+
+    // Process next event.  Should be an error.
+    ASSERT_PROCESS_NEXT_EVENT_FAILS ();
+
+    // The resume request should not have gone off because we think it is already running.
+    ASSERT_EQ (0, resume_call_count);
+}
+
+TEST_F (ThreadStateCoordinatorTest, ResumedThreadAlreadyMarkedDoesNotHoldUpPendingStopNotification)
+{
+    // We're going to test this scenario:
+    //   * Deferred notification waiting on two threads, A and B.  A and B currently running.
+    //   * Thread A stops.
+    //   * Thread A resumes.
+    //   * Thread B stops.
+    //
+    //   Here we could have forced A to stop again (after the Thread A resumes) because we had a pending stop nofication awaiting
+    //   all those threads to stop.  However, we are going to explicitly not try to restop A - somehow
+    //   that seems wrong and possibly buggy since for that to happen, we would have intentionally called
+    //   a resume after the stop.  Instead, we'll just log and indicate this looks suspicous.  We can revisit
+    //   that decision after we see if/when that happens.
+    const lldb::tid_t PENDING_TID_A = 2;
+    const lldb::tid_t PENDING_TID_B = 89;
+
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_TID_A);
+    SetupKnownRunningThread (PENDING_TID_B);
+
+    ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_TID_A, PENDING_TID_B };
+
+    // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+    CallAfterThreadsStop (TRIGGERING_TID,
+                          pending_stop_tids);
+
+    // Neither trigger should have gone off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_EQ (0, GetRequestedStopCount ());
+
+    // Execute CallAfterThreadsStop.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Both TID A and TID B should have had stop requests made.
+    ASSERT_EQ (2, GetRequestedStopCount ());
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_A));
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_TID_B));
+
+    // But we still shouldn't have the deferred signal call go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Report thread A stopped.
+    NotifyThreadStop (PENDING_TID_A);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now report thread A is resuming.  Ensure the resume is called.
+    lldb::tid_t resumed_tid = 0;
+    int resume_call_count = 0;
+    m_coordinator.RequestThreadResume (PENDING_TID_A,
+                                       GetResumeThreadFunction(resumed_tid, resume_call_count),
+                                       GetErrorFunction ());
+    ASSERT_EQ (0, resume_call_count);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (1, resume_call_count);
+    ASSERT_EQ (PENDING_TID_A, resumed_tid);
+
+    // Report thread B stopped.
+    NotifyThreadStop (PENDING_TID_B);
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // After notifying thread b stopped, we now have thread a resumed but thread b stopped.
+    // However, since thread a had stopped, we now have had both requirements stopped at some point.
+    // For now we'll expect this will fire the pending deferred stop notification.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopFiresWhenNoRunningThreads)
+{
+    // Let the coordinator know about our thread.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+
+    // Notify we have a trigger that needs to be fired when all running threads have stopped.
+    CallAfterRunningThreadsStop (TRIGGERING_TID);
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.  This will pick up the call after threads stop event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the trigger should have fired, since there were no threads that needed to first stop.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+
+    // And no stop requests should have been made.
+    ASSERT_EQ (0, GetRequestedStopCount ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsTwoPendingStops)
+{
+    // Let the coordinator know about our threads.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID_02);
+
+    // Notify we have a trigger that needs to be fired when all running threads have stopped.
+    CallAfterRunningThreadsStop (TRIGGERING_TID);
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.  This will pick up the call after threads stop event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // We should have two stop requests for the two threads currently running.
+    ASSERT_EQ (2, GetRequestedStopCount ());
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02));
+
+    // But the deferred stop notification should not have fired yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now notify the two threads stopped.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    NotifyThreadStop (PENDING_STOP_TID_02);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the trigger should have fired, since there were no threads that needed to first stop.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
+
+TEST_F (ThreadStateCoordinatorTest, CallAfterRunningThreadsStopRequestsStopTwoOtherThreadsOneRunning)
+{
+    // Let the coordinator know about our threads.  PENDING_STOP_TID_02 will already be stopped.
+    SetupKnownStoppedThread (TRIGGERING_TID);
+    SetupKnownRunningThread (PENDING_STOP_TID);
+    SetupKnownStoppedThread (PENDING_STOP_TID_02);
+
+    // Notify we have a trigger that needs to be fired when all running threads have stopped.
+    CallAfterRunningThreadsStop (TRIGGERING_TID);
+
+    // Notification trigger shouldn't go off yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Process next event.  This will pick up the call after threads stop event.
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // We should have two stop requests for the two threads currently running.
+    ASSERT_EQ (1, GetRequestedStopCount ());
+    ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID));
+
+    // But the deferred stop notification should not have fired yet.
+    ASSERT_EQ (false, DidFireDeferredNotification ());
+
+    // Now notify the two threads stopped.
+    NotifyThreadStop (PENDING_STOP_TID);
+    ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS ();
+
+    // Now the trigger should have fired, since there were no threads that needed to first stop.
+    ASSERT_EQ (true, DidFireDeferredNotification ());
+    ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ());
+}
diff --git a/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp b/lldb/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTestMock.cpp
new file mode 100644 (file)
index 0000000..7369360
--- /dev/null
@@ -0,0 +1,32 @@
+//===-- ThreadStateCoordinatorTestMock.cpp ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This file provides a few necessary functions to link
+// ThreadStateCoordinatorTest.cpp Bringing in the real implementations results
+// in a cascade of dependencies that pull in all of lldb.
+
+#include "lldb/Core/Log.h"
+
+using namespace lldb_private;
+
+void
+lldb_private::Log::Error (char const*, ...)
+{
+}
+
+void
+lldb_private::Log::Printf (char const*, ...)
+{
+}
+
+Log*
+lldb_private::GetLogIfAnyCategoriesSet (unsigned int)
+{
+    return nullptr;
+}
diff --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fea0f53
--- /dev/null
@@ -0,0 +1,4 @@
+add_lldb_unittest(UtilityTests\r
+  StringExtractorTest.cpp\r
+  UriParserTest.cpp\r
+  )\r
diff --git a/lldb/unittests/Utility/StringExtractorTest.cpp b/lldb/unittests/Utility/StringExtractorTest.cpp
new file mode 100644 (file)
index 0000000..cbb3816
--- /dev/null
@@ -0,0 +1,406 @@
+#include <limits.h>
+#include "gtest/gtest.h"
+
+#include "Utility/StringExtractor.h"
+
+namespace
+{
+    class StringExtractorTest: public ::testing::Test
+    {
+    };
+}
+
+TEST_F (StringExtractorTest, InitEmpty)
+{
+    const char kEmptyString[] = "";
+    StringExtractor ex (kEmptyString);
+
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_STREQ (kEmptyString, ex.GetStringRef().c_str());
+    ASSERT_EQ (true, ex.Empty());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, InitMisc)
+{
+    const char kInitMiscString[] = "Hello, StringExtractor!";
+    StringExtractor ex (kInitMiscString);
+
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_STREQ (kInitMiscString, ex.GetStringRef().c_str());
+    ASSERT_EQ (false, ex.Empty());
+    ASSERT_EQ (sizeof(kInitMiscString)-1, ex.GetBytesLeft());
+    ASSERT_EQ (kInitMiscString[0], *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_Underflow)
+{
+    const char kEmptyString[] = "";
+    StringExtractor ex (kEmptyString);
+
+    ASSERT_EQ (-1, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (true, ex.Empty());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_Underflow2)
+{
+    const char kEmptyString[] = "1";
+    StringExtractor ex (kEmptyString);
+
+    ASSERT_EQ (-1, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (1, ex.GetBytesLeft());
+    ASSERT_EQ ('1', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex)
+{
+    const char kInvalidHex[] = "xa";
+    StringExtractor ex (kInvalidHex);
+
+    ASSERT_EQ (-1, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('x', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex2)
+{
+    const char kInvalidHex[] = "ax";
+    StringExtractor ex (kInvalidHex);
+
+    ASSERT_EQ (-1, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('a', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_Exact)
+{
+    const char kValidHexPair[] = "12";
+    StringExtractor ex (kValidHexPair);
+
+    ASSERT_EQ (0x12, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, DecodeHexU8_Extra)
+{
+    const char kValidHexPair[] = "1234";
+    StringExtractor ex (kValidHexPair);
+
+    ASSERT_EQ (0x12, ex.DecodeHexU8());
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('3', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Underflow)
+{
+    const char kEmptyString[] = "";
+    StringExtractor ex (kEmptyString);
+
+    ASSERT_EQ (0xab, ex.GetHexU8(0xab));
+    ASSERT_EQ (false, ex.IsGood());
+    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
+    ASSERT_EQ (true, ex.Empty());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Underflow2)
+{
+    const char kOneNibble[] = "1";
+    StringExtractor ex (kOneNibble);
+
+    ASSERT_EQ (0xbc, ex.GetHexU8(0xbc));
+    ASSERT_EQ (false, ex.IsGood());
+    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_InvalidHex)
+{
+    const char kInvalidHex[] = "xx";
+    StringExtractor ex (kInvalidHex);
+
+    ASSERT_EQ (0xcd, ex.GetHexU8(0xcd));
+    ASSERT_EQ (false, ex.IsGood());
+    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Exact)
+{
+    const char kValidHexPair[] = "12";
+    StringExtractor ex (kValidHexPair);
+
+    ASSERT_EQ (0x12, ex.GetHexU8(0x12));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Extra)
+{
+    const char kValidHexPair[] = "1234";
+    StringExtractor ex (kValidHexPair);
+
+    ASSERT_EQ (0x12, ex.GetHexU8(0x12));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('3', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Underflow_NoEof)
+{
+    const char kEmptyString[] = "";
+    StringExtractor ex (kEmptyString);
+    const bool kSetEofOnFail = false;
+
+    ASSERT_EQ (0xab, ex.GetHexU8(0xab, kSetEofOnFail));
+    ASSERT_EQ (false, ex.IsGood()); // this result seems inconsistent with kSetEofOnFail == false
+    ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
+    ASSERT_EQ (true, ex.Empty());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Underflow2_NoEof)
+{
+    const char kOneNibble[] = "1";
+    StringExtractor ex (kOneNibble);
+    const bool kSetEofOnFail = false;
+
+    ASSERT_EQ (0xbc, ex.GetHexU8(0xbc, kSetEofOnFail));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (1, ex.GetBytesLeft());
+    ASSERT_EQ ('1', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_InvalidHex_NoEof)
+{
+    const char kInvalidHex[] = "xx";
+    StringExtractor ex (kInvalidHex);
+    const bool kSetEofOnFail = false;
+
+    ASSERT_EQ (0xcd, ex.GetHexU8(0xcd, kSetEofOnFail));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (0, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('x', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Exact_NoEof)
+{
+    const char kValidHexPair[] = "12";
+    StringExtractor ex (kValidHexPair);
+    const bool kSetEofOnFail = false;
+
+    ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (0, ex.GetBytesLeft());
+    ASSERT_EQ (nullptr, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexU8_Extra_NoEof)
+{
+    const char kValidHexPair[] = "1234";
+    StringExtractor ex (kValidHexPair);
+    const bool kSetEofOnFail = false;
+
+    ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
+    ASSERT_EQ (true, ex.IsGood());
+    ASSERT_EQ (2, ex.GetFilePos());
+    ASSERT_EQ (2, ex.GetBytesLeft());
+    ASSERT_EQ ('3', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytes)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kValidHexPairs = 8;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[kValidHexPairs];
+    ASSERT_EQ(kValidHexPairs, ex.GetHexBytes (dst, kValidHexPairs, 0xde));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    EXPECT_EQ(0x23,dst[4]);
+    EXPECT_EQ(0x45,dst[5]);
+    EXPECT_EQ(0x67,dst[6]);
+    EXPECT_EQ(0x89,dst[7]);
+
+    ASSERT_EQ(true, ex.IsGood());
+    ASSERT_EQ(2*kValidHexPairs, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(4, ex.GetBytesLeft());
+    ASSERT_EQ('x', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytes_Underflow)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kValidHexPairs = 8;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[12];
+    ASSERT_EQ(kValidHexPairs, ex.GetHexBytes (dst, sizeof(dst), 0xde));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    EXPECT_EQ(0x23,dst[4]);
+    EXPECT_EQ(0x45,dst[5]);
+    EXPECT_EQ(0x67,dst[6]);
+    EXPECT_EQ(0x89,dst[7]);
+    // these bytes should be filled with fail_fill_value 0xde
+    EXPECT_EQ(0xde,dst[8]);
+    EXPECT_EQ(0xde,dst[9]);
+    EXPECT_EQ(0xde,dst[10]);
+    EXPECT_EQ(0xde,dst[11]);
+
+    ASSERT_EQ(false, ex.IsGood());
+    ASSERT_EQ(UINT64_MAX, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(0, ex.GetBytesLeft());
+    ASSERT_EQ(0, ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytes_Partial)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kReadBytes = 4;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[12];
+    memset(dst, 0xab, sizeof(dst));
+    ASSERT_EQ(kReadBytes, ex.GetHexBytes (dst, kReadBytes, 0xde));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    // these bytes should be unchanged
+    EXPECT_EQ(0xab,dst[4]);
+    EXPECT_EQ(0xab,dst[5]);
+    EXPECT_EQ(0xab,dst[6]);
+    EXPECT_EQ(0xab,dst[7]);
+    EXPECT_EQ(0xab,dst[8]);
+    EXPECT_EQ(0xab,dst[9]);
+    EXPECT_EQ(0xab,dst[10]);
+    EXPECT_EQ(0xab,dst[11]);
+
+    ASSERT_EQ(true, ex.IsGood());
+    ASSERT_EQ(kReadBytes*2, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(12, ex.GetBytesLeft());
+    ASSERT_EQ('2', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytesAvail)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kValidHexPairs = 8;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[kValidHexPairs];
+    ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, kValidHexPairs));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    EXPECT_EQ(0x23,dst[4]);
+    EXPECT_EQ(0x45,dst[5]);
+    EXPECT_EQ(0x67,dst[6]);
+    EXPECT_EQ(0x89,dst[7]);
+
+    ASSERT_EQ(true, ex.IsGood());
+    ASSERT_EQ(2*kValidHexPairs, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(4, ex.GetBytesLeft());
+    ASSERT_EQ('x', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytesAvail_Underflow)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kValidHexPairs = 8;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[12];
+    memset(dst, 0xef, sizeof(dst));
+    ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, sizeof(dst)));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    EXPECT_EQ(0x23,dst[4]);
+    EXPECT_EQ(0x45,dst[5]);
+    EXPECT_EQ(0x67,dst[6]);
+    EXPECT_EQ(0x89,dst[7]);
+    // these bytes should be unchanged
+    EXPECT_EQ(0xef,dst[8]);
+    EXPECT_EQ(0xef,dst[9]);
+    EXPECT_EQ(0xef,dst[10]);
+    EXPECT_EQ(0xef,dst[11]);
+
+    ASSERT_EQ(true, ex.IsGood());
+    ASSERT_EQ(kValidHexPairs*2, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(4, ex.GetBytesLeft());
+    ASSERT_EQ('x', *ex.Peek());
+}
+
+TEST_F (StringExtractorTest, GetHexBytesAvail_Partial)
+{
+    const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
+    const size_t kReadBytes = 4;
+    StringExtractor ex(kHexEncodedBytes);
+
+    uint8_t dst[12];
+    memset(dst, 0xab, sizeof(dst));
+    ASSERT_EQ(kReadBytes, ex.GetHexBytesAvail (dst, kReadBytes));
+    EXPECT_EQ(0xab,dst[0]);
+    EXPECT_EQ(0xcd,dst[1]);
+    EXPECT_EQ(0xef,dst[2]);
+    EXPECT_EQ(0x01,dst[3]);
+    // these bytes should be unchanged
+    EXPECT_EQ(0xab,dst[4]);
+    EXPECT_EQ(0xab,dst[5]);
+    EXPECT_EQ(0xab,dst[6]);
+    EXPECT_EQ(0xab,dst[7]);
+    EXPECT_EQ(0xab,dst[8]);
+    EXPECT_EQ(0xab,dst[9]);
+    EXPECT_EQ(0xab,dst[10]);
+    EXPECT_EQ(0xab,dst[11]);
+
+    ASSERT_EQ(true, ex.IsGood());
+    ASSERT_EQ(kReadBytes*2, ex.GetFilePos());
+    ASSERT_EQ(false, ex.Empty());
+    ASSERT_EQ(12, ex.GetBytesLeft());
+    ASSERT_EQ('2', *ex.Peek());
+}
+
+
diff --git a/lldb/unittests/Utility/UriParserTest.cpp b/lldb/unittests/Utility/UriParserTest.cpp
new file mode 100644 (file)
index 0000000..a11dd8e
--- /dev/null
@@ -0,0 +1,135 @@
+#include "gtest/gtest.h"
+#include "Utility/UriParser.h"
+
+namespace
+{
+    class UriParserTest: public ::testing::Test
+    {
+    };
+}
+
+// result strings (scheme/hostname/port/path) passed into UriParser::Parse
+// are initialized to kAsdf so we can verify that they are unmodified if the 
+// URI is invalid
+static const char* kAsdf = "asdf";
+
+class UriTestCase
+{
+public:
+    UriTestCase(const char* uri, const char* scheme, const char* hostname, int port, const char* path) :
+      m_uri(uri),
+      m_result(true),
+      m_scheme(scheme),
+      m_hostname(hostname),
+      m_port(port),
+      m_path(path)
+    {
+    }
+
+    UriTestCase(const char* uri) :
+      m_uri(uri),
+      m_result(false),
+      m_scheme(kAsdf),
+      m_hostname(kAsdf),
+      m_port(1138),
+      m_path(kAsdf)
+    {
+    }
+
+    const char* m_uri;
+    bool        m_result;
+    const char* m_scheme;
+    const char* m_hostname;
+    int         m_port;
+    const char* m_path;
+};
+
+#define VALIDATE \
+    std::string scheme(kAsdf); \
+    std::string hostname(kAsdf); \
+    int port(1138); \
+    std::string path(kAsdf); \
+    EXPECT_EQ (testCase.m_result, UriParser::Parse(testCase.m_uri, scheme, hostname, port, path)); \
+    EXPECT_STREQ (testCase.m_scheme, scheme.c_str()); \
+    EXPECT_STREQ (testCase.m_hostname, hostname.c_str()); \
+    EXPECT_EQ (testCase.m_port, port); \
+    EXPECT_STREQ (testCase.m_path, path.c_str());
+
+TEST_F (UriParserTest, Minimal)
+{
+    const UriTestCase testCase("x://y", "x", "y", -1, "/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, MinimalPort)
+{
+    const UriTestCase testCase("x://y:1", "x", "y", 1, "/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, MinimalPath)
+{
+    const UriTestCase testCase("x://y/", "x", "y", -1, "/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, MinimalPortPath)
+{
+    const UriTestCase testCase("x://y:1/", "x", "y", 1, "/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, TypicalPortPath)
+{
+    const UriTestCase testCase("connect://192.168.100.132:5432/", "connect", "192.168.100.132", 5432, "/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, SchemeHostSeparator)
+{
+    const UriTestCase testCase("x:/y");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, SchemeHostSeparator2)
+{
+    const UriTestCase testCase("x:y");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, SchemeHostSeparator3)
+{
+    const UriTestCase testCase("x//y");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, SchemeHostSeparator4)
+{
+    const UriTestCase testCase("x/y");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, BadPort)
+{
+    const UriTestCase testCase("x://y:a/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, BadPort2)
+{
+    const UriTestCase testCase("x://y:5432a/");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, Empty)
+{
+    const UriTestCase testCase("");
+    VALIDATE
+}
+
+TEST_F (UriParserTest, PortOverflow)
+{
+    const UriTestCase testCase("x://y:0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/");
+    VALIDATE
+}
+
diff --git a/lldb/unittests/gtest_common.h b/lldb/unittests/gtest_common.h
new file mode 100644 (file)
index 0000000..228dfb0
--- /dev/null
@@ -0,0 +1,32 @@
+//===-- gtest_common.h ------------------------------------------*- C++ -*-===//\r
+//\r
+//                     The LLVM Compiler Infrastructure\r
+//\r
+// This file is distributed under the University of Illinois Open Source\r
+// License. See LICENSE.TXT for details.\r
+//\r
+//===----------------------------------------------------------------------===//\r
+\r
+#if defined(LLDB_GTEST_COMMON_H)\r
+#error "gtest_common.h should not be included manually."\r
+#else\r
+#define LLDB_GTEST_COMMON_H\r
+#endif\r
+\r
+// This header file is force included by all of LLDB's unittest compilation\r
+// units.  Be very leary about putting anything in this file.\r
+\r
+#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)\r
+// MSVC's STL implementation tries to work well with /EHs-c- and\r
+// _HAS_EXCEPTIONS=0.  But <thread> in particular doesn't work with it, because\r
+// it relies on <concrt.h> which tries to throw an exception without checking\r
+// for _HAS_EXCEPTIONS=0.  This causes the linker to require a definition of\r
+// __uncaught_exception(), but the STL doesn't define this function when\r
+// _HAS_EXCEPTIONS=0.  The workaround here is to just provide a stub\r
+// implementation to get it to link.\r
+inline bool\r
+__uncaught_exception()\r
+{\r
+    return true;\r
+}\r
+#endif\r