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 )
+++ /dev/null
-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
+++ /dev/null
-#!/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)
+++ /dev/null
-// !$*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 */;
-}
+++ /dev/null
-//===-- 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
+++ /dev/null
-# 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
+++ /dev/null
-add_subdirectory(Host)\r
-add_subdirectory(Plugins)\r
-add_subdirectory(Utility)\r
+++ /dev/null
-add_lldb_unittest(HostTests\r
- SocketAddressTest.cpp\r
- SocketTest.cpp\r
- SocketTestMock.cpp\r
- )\r
+++ /dev/null
-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
+++ /dev/null
-//===-- 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
-
-
+++ /dev/null
-//===-- 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 ());
-}
-
-
-
+++ /dev/null
-//===-- 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
-
+++ /dev/null
-add_subdirectory(Process)\r
+++ /dev/null
-if (CMAKE_SYSTEM_NAME MATCHES "Linux")\r
- add_subdirectory(Linux)\r
-endif()\r
+++ /dev/null
-add_lldb_unittest(ProcessLinuxTests\r
- ThreadStateCoordinatorTest.cpp\r
- ThreadStatecoordinatorMock.cpp\r
- )\r
+++ /dev/null
-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
+++ /dev/null
-#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 ());
-}
+++ /dev/null
-//===-- 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;
-}
+++ /dev/null
-add_lldb_unittest(UtilityTests\r
- StringExtractorTest.cpp\r
- UriParserTest.cpp\r
- )\r
+++ /dev/null
-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
+++ /dev/null
-#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());
-}
-
-
+++ /dev/null
-#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
-}
-
--- /dev/null
+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
--- /dev/null
+add_lldb_unittest(HostTests\r
+ SocketAddressTest.cpp\r
+ SocketTest.cpp\r
+ SocketTestMock.cpp\r
+ )\r
--- /dev/null
+//===-- 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
+
+
--- /dev/null
+//===-- 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 ());
+}
+
+
+
--- /dev/null
+//===-- 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
+
--- /dev/null
+add_subdirectory(Process)\r
--- /dev/null
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")\r
+ add_subdirectory(Linux)\r
+endif()\r
--- /dev/null
+add_lldb_unittest(ProcessLinuxTests\r
+ ThreadStateCoordinatorTest.cpp\r
+ ThreadStatecoordinatorMock.cpp\r
+ )\r
--- /dev/null
+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
--- /dev/null
+#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 ());
+}
--- /dev/null
+//===-- 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;
+}
--- /dev/null
+add_lldb_unittest(UtilityTests\r
+ StringExtractorTest.cpp\r
+ UriParserTest.cpp\r
+ )\r
--- /dev/null
+#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());
+}
+
+
--- /dev/null
+#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
+}
+
--- /dev/null
+//===-- 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