From 9bb2e1889abc8d24216079856e6a8e443194b566 Mon Sep 17 00:00:00 2001 From: Santtu Date: Thu, 22 Aug 2024 10:44:06 +0300 Subject: [PATCH 01/67] Streamr iOS xcframework creation script added --- create-streamr-xcframework.pl | 49 +++++++++++++++++++++++++++++++++++ install.sh | 4 +++ 2 files changed, 53 insertions(+) create mode 100755 create-streamr-xcframework.pl diff --git a/create-streamr-xcframework.pl b/create-streamr-xcframework.pl new file mode 100755 index 00000000..c4c816bc --- /dev/null +++ b/create-streamr-xcframework.pl @@ -0,0 +1,49 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use File::Find; +use File::Path qw(make_path); +use File::Copy::Recursive qw(dircopy); +use Cwd; + +my $abs_path = getcwd; +my $root_build = "build/ios"; +my $build_include = "$abs_path/$root_build/include"; +my $build_lib = "$abs_path/$root_build/lib"; +my $dist_path = "$abs_path/dist/ios"; + +print "Please wait, building xcframework.\n"; + +`rm -rf $build_include`; +`rm -rf $build_lib`; +`rm -rf $dist_path`; + +make_path($build_include); +make_path($build_lib); + +# Copy streamr headers +dircopy("$abs_path/packages/streamr-proto-rpc/include", $build_include); +dircopy("$abs_path/packages/streamr-logger/include", $build_include); +dircopy("$abs_path/packages/streamr-logger/include", $build_include); +dircopy("$abs_path/packages/streamr-logger/include", $build_include); + +# Find all include and lib directories and process them +find(\&process_dir, "./vcpkg/packages"); + +`libtool -static -o $build_lib/streamr.a $build_lib/*.a`; +`xcodebuild -create-xcframework -library $build_lib/streamr.a -headers $build_include -output $dist_path/streamr.xcframework`; +print "\nstreamr.xcframework was created in the directory: dist/ios.\n"; + +# Subroutine to process each directory +sub process_dir { + my $dir = $File::Find::name; + if ($dir =~ m|^\./vcpkg/packages/[^/]+/include$|) { + # Copy includes from vcpkg-packages (vcpkg/packages//include) + dircopy("$abs_path/$dir", $build_include); + } elsif ($dir =~ m|^\./vcpkg/packages/[^/]+/lib$|) { + # Copy libs from vcpkg-packages (vcpkg/packages//lib) + dircopy("$abs_path/$dir", $build_lib); + } +} + diff --git a/install.sh b/install.sh index b0d21f86..1df39871 100755 --- a/install.sh +++ b/install.sh @@ -25,6 +25,7 @@ while [[ "$#" -gt 0 ]]; do --prod) PROD_BUILD=true ;; --ios) TARGET_TRIPLET="arm64-ios"; CHAINLOAD_TOOLCHAIN_FILE="$(pwd)/overlaytriplets/arm64-ios.cmake"; PLATFORM="OS64" ;; --android) TARGET_TRIPLET="arm64-android"; CHAINLOAD_TOOLCHAIN_FILE="$(pwd)/overlaytriplets/arm64-android.cmake"; PLATFORM="android" ;; + --xcframework) CREATE_XCFRAMEWORK=true ;; *) echo "Unknown parameter passed: $1. Usage: ./install.sh [--prod] [--ios] [--android]"; exit 1 ;; esac shift @@ -72,3 +73,6 @@ else cd build && cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. && cmake --build . && cd .. fi +if [ "$CREATE_XCFRAMEWORK" = true ]; then + create-streamr-xcframework.pl +fi From 21c138a04b1afc6a923107e0f3664a98215e4690 Mon Sep 17 00:00:00 2001 From: Santtu Date: Thu, 22 Aug 2024 10:52:47 +0300 Subject: [PATCH 02/67] Calling create-streamr-xcframework.pl fixed --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 1df39871..84d0bdfb 100755 --- a/install.sh +++ b/install.sh @@ -74,5 +74,5 @@ else fi if [ "$CREATE_XCFRAMEWORK" = true ]; then - create-streamr-xcframework.pl + ./create-streamr-xcframework.pl fi From 1457079983d085d7c15899d9559a2383d4e0ca65 Mon Sep 17 00:00:00 2001 From: Santtu Date: Thu, 22 Aug 2024 11:47:40 +0300 Subject: [PATCH 03/67] iOS app example StreamrProtoRpcExampleApp added --- .../project.pbxproj | 413 ++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 103594 bytes .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../ContentView.swift | 20 + .../StreamrProtoRpcExampleApp/Hello.cpp | 75 ++ .../StreamrProtoRpcExampleApp/Hello.hpp | 15 + .../HelloRpc.client.pb.h | 26 + .../StreamrProtoRpcExampleApp/HelloRpc.pb.cc | 270 ++++ .../StreamrProtoRpcExampleApp/HelloRpc.pb.h | 525 ++++++++ .../HelloRpc.server.pb.h | 19 + .../Preview Assets.xcassets/Contents.json | 6 + .../StreamrProtoRpcExampleApp/ProtoRpc.pb.cc | 430 +++++++ .../StreamrProtoRpcExampleApp/ProtoRpc.pb.h | 1126 +++++++++++++++++ ...treamrProtoRpcExampleApp-Bridging-Header.h | 5 + .../StreamrProtoRpcExampleAppApp.swift | 17 + .../StreamrProtoRpcExampleApp/Wrapper.h | 12 + .../StreamrProtoRpcExampleApp/Wrapper.mm | 17 + 22 files changed, 3035 insertions(+) create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.pbxproj create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/Contents.json create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.cpp create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.hpp create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.client.pb.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.cc create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.server.pb.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.cc create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleAppApp.swift create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.h create mode 100644 packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.mm diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.pbxproj b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.pbxproj new file mode 100644 index 00000000..6dc8c29b --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.pbxproj @@ -0,0 +1,413 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 417762BC2C7609FD000CA1B3 /* StreamrProtoRpcExampleAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 417762BB2C7609FD000CA1B3 /* StreamrProtoRpcExampleAppApp.swift */; }; + 417762BE2C7609FD000CA1B3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 417762BD2C7609FD000CA1B3 /* ContentView.swift */; }; + 417762C02C7609FF000CA1B3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 417762BF2C7609FF000CA1B3 /* Assets.xcassets */; }; + 417762C32C7609FF000CA1B3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 417762C22C7609FF000CA1B3 /* Preview Assets.xcassets */; }; + 417762CD2C7610EC000CA1B3 /* Wrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 417762CC2C7610EC000CA1B3 /* Wrapper.mm */; }; + 417762D92C76182A000CA1B3 /* Hello.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417762D72C76182A000CA1B3 /* Hello.cpp */; }; + 417762F32C764712000CA1B3 /* HelloRpc.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 417762F22C764711000CA1B3 /* HelloRpc.pb.cc */; }; + 417762F52C7648D7000CA1B3 /* ProtoRpc.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 417762F42C7648D7000CA1B3 /* ProtoRpc.pb.cc */; }; + 417762F72C765648000CA1B3 /* streamr.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 417762F62C765648000CA1B3 /* streamr.xcframework */; }; + 417762FA2C767117000CA1B3 /* libc++abi.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 417762F92C767117000CA1B3 /* libc++abi.tbd */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 417762B82C7609FD000CA1B3 /* StreamrProtoRpcExampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StreamrProtoRpcExampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 417762BB2C7609FD000CA1B3 /* StreamrProtoRpcExampleAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamrProtoRpcExampleAppApp.swift; sourceTree = ""; }; + 417762BD2C7609FD000CA1B3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 417762BF2C7609FF000CA1B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 417762C22C7609FF000CA1B3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 417762CB2C7610EB000CA1B3 /* StreamrProtoRpcExampleApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StreamrProtoRpcExampleApp-Bridging-Header.h"; sourceTree = ""; }; + 417762CC2C7610EC000CA1B3 /* Wrapper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Wrapper.mm; sourceTree = ""; }; + 417762CE2C761123000CA1B3 /* Wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Wrapper.h; sourceTree = ""; }; + 417762D72C76182A000CA1B3 /* Hello.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Hello.cpp; sourceTree = ""; }; + 417762D82C76182A000CA1B3 /* Hello.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Hello.hpp; sourceTree = ""; }; + 417762EC2C763CC9000CA1B3 /* HelloRpc.client.pb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HelloRpc.client.pb.h; sourceTree = ""; }; + 417762ED2C763D7B000CA1B3 /* HelloRpc.pb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HelloRpc.pb.h; sourceTree = ""; }; + 417762F02C764569000CA1B3 /* ProtoRpc.pb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProtoRpc.pb.h; sourceTree = ""; }; + 417762F12C7645A0000CA1B3 /* HelloRpc.server.pb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HelloRpc.server.pb.h; sourceTree = ""; }; + 417762F22C764711000CA1B3 /* HelloRpc.pb.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HelloRpc.pb.cc; sourceTree = ""; }; + 417762F42C7648D7000CA1B3 /* ProtoRpc.pb.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProtoRpc.pb.cc; sourceTree = ""; }; + 417762F62C765648000CA1B3 /* streamr.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = streamr.xcframework; path = "../../../../../../dist/ios/streamr.xcframework"; sourceTree = ""; }; + 417762F92C767117000CA1B3 /* libc++abi.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++abi.tbd"; path = "usr/lib/libc++abi.tbd"; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 417762B52C7609FD000CA1B3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 417762FA2C767117000CA1B3 /* libc++abi.tbd in Frameworks */, + 417762F72C765648000CA1B3 /* streamr.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 417762AF2C7609FD000CA1B3 = { + isa = PBXGroup; + children = ( + 417762BA2C7609FD000CA1B3 /* StreamrProtoRpcExampleApp */, + 417762B92C7609FD000CA1B3 /* Products */, + 417762F82C767117000CA1B3 /* Frameworks */, + ); + sourceTree = ""; + }; + 417762B92C7609FD000CA1B3 /* Products */ = { + isa = PBXGroup; + children = ( + 417762B82C7609FD000CA1B3 /* StreamrProtoRpcExampleApp.app */, + ); + name = Products; + sourceTree = ""; + }; + 417762BA2C7609FD000CA1B3 /* StreamrProtoRpcExampleApp */ = { + isa = PBXGroup; + children = ( + 417762F62C765648000CA1B3 /* streamr.xcframework */, + 417762F22C764711000CA1B3 /* HelloRpc.pb.cc */, + 417762F42C7648D7000CA1B3 /* ProtoRpc.pb.cc */, + 417762F02C764569000CA1B3 /* ProtoRpc.pb.h */, + 417762EC2C763CC9000CA1B3 /* HelloRpc.client.pb.h */, + 417762F12C7645A0000CA1B3 /* HelloRpc.server.pb.h */, + 417762ED2C763D7B000CA1B3 /* HelloRpc.pb.h */, + 417762BB2C7609FD000CA1B3 /* StreamrProtoRpcExampleAppApp.swift */, + 417762BD2C7609FD000CA1B3 /* ContentView.swift */, + 417762BF2C7609FF000CA1B3 /* Assets.xcassets */, + 417762C12C7609FF000CA1B3 /* Preview Content */, + 417762CC2C7610EC000CA1B3 /* Wrapper.mm */, + 417762CB2C7610EB000CA1B3 /* StreamrProtoRpcExampleApp-Bridging-Header.h */, + 417762CE2C761123000CA1B3 /* Wrapper.h */, + 417762D72C76182A000CA1B3 /* Hello.cpp */, + 417762D82C76182A000CA1B3 /* Hello.hpp */, + ); + path = StreamrProtoRpcExampleApp; + sourceTree = ""; + }; + 417762C12C7609FF000CA1B3 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 417762C22C7609FF000CA1B3 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 417762F82C767117000CA1B3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 417762F92C767117000CA1B3 /* libc++abi.tbd */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 417762B72C7609FD000CA1B3 /* StreamrProtoRpcExampleApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 417762C62C7609FF000CA1B3 /* Build configuration list for PBXNativeTarget "StreamrProtoRpcExampleApp" */; + buildPhases = ( + 417762B42C7609FD000CA1B3 /* Sources */, + 417762B52C7609FD000CA1B3 /* Frameworks */, + 417762B62C7609FD000CA1B3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = StreamrProtoRpcExampleApp; + productName = StreamrProtoRpcExampleApp; + productReference = 417762B82C7609FD000CA1B3 /* StreamrProtoRpcExampleApp.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 417762B02C7609FD000CA1B3 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 417762B72C7609FD000CA1B3 = { + CreatedOnToolsVersion = 15.4; + LastSwiftMigration = 1540; + }; + }; + }; + buildConfigurationList = 417762B32C7609FD000CA1B3 /* Build configuration list for PBXProject "StreamrProtoRpcExampleApp" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 417762AF2C7609FD000CA1B3; + productRefGroup = 417762B92C7609FD000CA1B3 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 417762B72C7609FD000CA1B3 /* StreamrProtoRpcExampleApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 417762B62C7609FD000CA1B3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 417762C32C7609FF000CA1B3 /* Preview Assets.xcassets in Resources */, + 417762C02C7609FF000CA1B3 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 417762B42C7609FD000CA1B3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 417762BE2C7609FD000CA1B3 /* ContentView.swift in Sources */, + 417762BC2C7609FD000CA1B3 /* StreamrProtoRpcExampleAppApp.swift in Sources */, + 417762F32C764712000CA1B3 /* HelloRpc.pb.cc in Sources */, + 417762F52C7648D7000CA1B3 /* ProtoRpc.pb.cc in Sources */, + 417762D92C76182A000CA1B3 /* Hello.cpp in Sources */, + 417762CD2C7610EC000CA1B3 /* Wrapper.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 417762C42C7609FF000CA1B3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "\"-L c++abi\""; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OBJC_INTEROP_MODE = objcxx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 417762C52C7609FF000CA1B3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + 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; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = "\"-L c++abi\""; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_INTEROP_MODE = objcxx; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 417762C72C7609FF000CA1B3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"StreamrProtoRpcExampleApp/Preview Content\""; + DEVELOPMENT_TEAM = S933S46DZS; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.StreamrProtoRpcExampleApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 417762C82C7609FF000CA1B3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"StreamrProtoRpcExampleApp/Preview Content\""; + DEVELOPMENT_TEAM = S933S46DZS; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.StreamrProtoRpcExampleApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 417762B32C7609FD000CA1B3 /* Build configuration list for PBXProject "StreamrProtoRpcExampleApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 417762C42C7609FF000CA1B3 /* Debug */, + 417762C52C7609FF000CA1B3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 417762C62C7609FF000CA1B3 /* Build configuration list for PBXNativeTarget "StreamrProtoRpcExampleApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 417762C72C7609FF000CA1B3 /* Debug */, + 417762C82C7609FF000CA1B3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 417762B02C7609FD000CA1B3 /* Project object */; +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..3dc953113850a3b3226feecea74c5c67cedb7820 GIT binary patch literal 103594 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:m;v@);50 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 + + + + SchemeUserState + + StreamrProtoRpcExampleApp.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AccentColor.colorset/Contents.json b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/Contents.json b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift new file mode 100644 index 00000000..405e7125 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift @@ -0,0 +1,20 @@ +// +// ContentView.swift +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("\(Wrapper().greetingWrapper())") + } + .padding() + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.cpp b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.cpp new file mode 100644 index 00000000..44a18993 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.cpp @@ -0,0 +1,75 @@ +// +// Hello.cpp +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// +#define GLOG_USE_GLOG_EXPORT + +#include "Hello.hpp" +#include +#include +#include "HelloRpc.client.pb.h" +#include "HelloRpc.pb.h" +#include "HelloRpc.server.pb.h" +#include "streamr-proto-rpc/ProtoCallContext.hpp" +#include "streamr-proto-rpc/RpcCommunicator.hpp" + +using streamr::protorpc::HelloRpcService; +using streamr::protorpc::HelloRpcServiceClient; +using streamr::protorpc::ProtoCallContext; +using streamr::protorpc::RpcCommunicator; +using streamr::protorpc::RpcMessage; + +class HelloService : public HelloRpcService { +public: + HelloResponse sayHello( + const HelloRequest& request, + const ProtoCallContext& /* callContext */) override { + HelloResponse response; + response.set_greeting("Hello, " + request.myname()); + return response; + } +}; + +std::string sayHello() { + RpcCommunicator communicator1; + HelloService helloService; + + communicator1.registerRpcMethod( + "sayHello", + std::bind( // NOLINT(modernize-avoid-bind) + &HelloService::sayHello, + &helloService, + std::placeholders::_1, + std::placeholders::_2)); + + // Setup client + RpcCommunicator communicator2; + HelloRpcServiceClient helloClient(communicator2); + + // Simulate a network connection between the client and server + communicator1.setOutgoingMessageCallback( + [&communicator2]( + const RpcMessage& message, + const std::string& /* requestId */, + const ProtoCallContext& /* context */) -> void { + communicator2.handleIncomingMessage(message, ProtoCallContext()); + }); + + communicator2.setOutgoingMessageCallback( + [&communicator1]( + const RpcMessage& message, + const std::string& /* requestId */, + const ProtoCallContext& /* context */) -> void { + communicator1.handleIncomingMessage(message, ProtoCallContext()); + }); + + // Make the RPC call + + HelloRequest request; + request.set_myname("Alice"); + auto response = folly::coro::blockingWait( + helloClient.sayHello(request, ProtoCallContext())); + return response.greeting(); +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.hpp b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.hpp new file mode 100644 index 00000000..98cf27c4 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Hello.hpp @@ -0,0 +1,15 @@ +// +// Hello.hpp +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// + +#ifndef Hello_hpp +#define Hello_hpp + +#include + +std::string sayHello(); + +#endif /* Hello_hpp */ diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.client.pb.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.client.pb.h new file mode 100644 index 00000000..222d435e --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.client.pb.h @@ -0,0 +1,26 @@ +// generated by the protocol buffer streamr pluging. DO NOT EDIT! +// generated from protobuf file "HelloRpc.proto" + +#ifndef STREAMR_PROTORPC_HELLORPC_CLIENT_PB_H +#define STREAMR_PROTORPC_HELLORPC_CLIENT_PB_H + +#include +#include "HelloRpc.pb.h" // NOLINT +#include "streamr-proto-rpc/ProtoCallContext.hpp" +#include "streamr-proto-rpc/RpcCommunicator.hpp" + + +namespace streamr::protorpc { +class HelloRpcServiceClient { +private: +RpcCommunicator& communicator; +public: + HelloRpcServiceClient(RpcCommunicator& communicator) : communicator(communicator) {} + folly::coro::Task sayHello(const HelloRequest& request, const ProtoCallContext& callContext) { + return communicator.request("sayHello", request, callContext); + } +}; // class HelloRpcServiceClient +}; // namespace streamr::protorpc + +#endif // STREAMR_PROTORPC_HELLORPC_CLIENT_PB_H + diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.cc b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.cc new file mode 100644 index 00000000..13ea014c --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.cc @@ -0,0 +1,270 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: HelloRpc.proto + +#include "HelloRpc.pb.h" + +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; + +inline constexpr HelloResponse::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : greeting_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR HelloResponse::HelloResponse(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct HelloResponseDefaultTypeInternal { + PROTOBUF_CONSTEXPR HelloResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~HelloResponseDefaultTypeInternal() {} + union { + HelloResponse _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 HelloResponseDefaultTypeInternal _HelloResponse_default_instance_; + +inline constexpr HelloRequest::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : myname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR HelloRequest::HelloRequest(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct HelloRequestDefaultTypeInternal { + PROTOBUF_CONSTEXPR HelloRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~HelloRequestDefaultTypeInternal() {} + union { + HelloRequest _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 HelloRequestDefaultTypeInternal _HelloRequest_default_instance_; +static ::_pb::Metadata file_level_metadata_HelloRpc_2eproto[2]; +static constexpr const ::_pb::EnumDescriptor** + file_level_enum_descriptors_HelloRpc_2eproto = nullptr; +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_HelloRpc_2eproto = nullptr; +const ::uint32_t TableStruct_HelloRpc_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::HelloRequest, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::HelloRequest, _impl_.myname_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::HelloResponse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::HelloResponse, _impl_.greeting_), +}; + +static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + {0, -1, -1, sizeof(::HelloRequest)}, + {9, -1, -1, sizeof(::HelloResponse)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::_HelloRequest_default_instance_._instance, + &::_HelloResponse_default_instance_._instance, +}; +const char descriptor_table_protodef_HelloRpc_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + "\n\016HelloRpc.proto\"\036\n\014HelloRequest\022\016\n\006myNa" + "me\030\001 \001(\t\"!\n\rHelloResponse\022\020\n\010greeting\030\001 " + "\001(\t2<\n\017HelloRpcService\022)\n\010sayHello\022\r.Hel" + "loRequest\032\016.HelloResponseB\002H\002b\006proto3" +}; +static ::absl::once_flag descriptor_table_HelloRpc_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_HelloRpc_2eproto = { + false, + false, + 157, + descriptor_table_protodef_HelloRpc_2eproto, + "HelloRpc.proto", + &descriptor_table_HelloRpc_2eproto_once, + nullptr, + 0, + 2, + schemas, + file_default_instances, + TableStruct_HelloRpc_2eproto::offsets, + file_level_metadata_HelloRpc_2eproto, + file_level_enum_descriptors_HelloRpc_2eproto, + file_level_service_descriptors_HelloRpc_2eproto, +}; + +// This function exists to be marked as weak. +// It can significantly speed up compilation by breaking up LLVM's SCC +// in the .pb.cc translation units. Large translation units see a +// reduction of more than 35% of walltime for optimized builds. Without +// the weak attribute all the messages in the file, including all the +// vtables and everything they use become part of the same SCC through +// a cycle like: +// GetMetadata -> descriptor table -> default instances -> +// vtables -> GetMetadata +// By adding a weak function here we break the connection from the +// individual vtables back into the descriptor table. +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_HelloRpc_2eproto_getter() { + return &descriptor_table_HelloRpc_2eproto; +} +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_HelloRpc_2eproto(&descriptor_table_HelloRpc_2eproto); +// =================================================================== + +class HelloRequest::_Internal { + public: +}; + +HelloRequest::HelloRequest(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:HelloRequest) +} +inline PROTOBUF_NDEBUG_INLINE HelloRequest::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : myname_(arena, from.myname_), + _cached_size_{0} {} + +HelloRequest::HelloRequest( + ::google::protobuf::Arena* arena, + const HelloRequest& from) + : ::google::protobuf::Message(arena) { + HelloRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + + // @@protoc_insertion_point(copy_constructor:HelloRequest) +} +inline PROTOBUF_NDEBUG_INLINE HelloRequest::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : myname_(arena), + _cached_size_{0} {} + +inline void HelloRequest::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +HelloRequest::~HelloRequest() { + // @@protoc_insertion_point(destructor:HelloRequest) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void HelloRequest::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.myname_.Destroy(); + _impl_.~Impl_(); +} + +::_pbi::CachedSize* HelloRequest::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void HelloRequest::InternalSwap(HelloRequest* PROTOBUF_RESTRICT other) { + using std::swap; + GetReflection()->Swap(this, other);} + +::google::protobuf::Metadata HelloRequest::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_HelloRpc_2eproto_getter, &descriptor_table_HelloRpc_2eproto_once, + file_level_metadata_HelloRpc_2eproto[0]); +} +// =================================================================== + +class HelloResponse::_Internal { + public: +}; + +HelloResponse::HelloResponse(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:HelloResponse) +} +inline PROTOBUF_NDEBUG_INLINE HelloResponse::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : greeting_(arena, from.greeting_), + _cached_size_{0} {} + +HelloResponse::HelloResponse( + ::google::protobuf::Arena* arena, + const HelloResponse& from) + : ::google::protobuf::Message(arena) { + HelloResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + + // @@protoc_insertion_point(copy_constructor:HelloResponse) +} +inline PROTOBUF_NDEBUG_INLINE HelloResponse::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : greeting_(arena), + _cached_size_{0} {} + +inline void HelloResponse::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +HelloResponse::~HelloResponse() { + // @@protoc_insertion_point(destructor:HelloResponse) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void HelloResponse::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.greeting_.Destroy(); + _impl_.~Impl_(); +} + +::_pbi::CachedSize* HelloResponse::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void HelloResponse::InternalSwap(HelloResponse* PROTOBUF_RESTRICT other) { + using std::swap; + GetReflection()->Swap(this, other);} + +::google::protobuf::Metadata HelloResponse::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_HelloRpc_2eproto_getter, &descriptor_table_HelloRpc_2eproto_once, + file_level_metadata_HelloRpc_2eproto[1]); +} +// @@protoc_insertion_point(namespace_scope) +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +#include "google/protobuf/port_undef.inc" diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.h new file mode 100644 index 00000000..894d25a3 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.pb.h @@ -0,0 +1,525 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: HelloRpc.proto +// Protobuf C++ Version: 4.25.1 + +#ifndef GOOGLE_PROTOBUF_INCLUDED_HelloRpc_2eproto_2epb_2eh +#define GOOGLE_PROTOBUF_INCLUDED_HelloRpc_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/port_def.inc" +#if PROTOBUF_VERSION < 4025000 +#error "This file was generated by a newer version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please update" +#error "your headers." +#endif // PROTOBUF_VERSION + +#if 4025001 < PROTOBUF_MIN_PROTOC_VERSION +#error "This file was generated by an older version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please" +#error "regenerate this file with a newer version of protoc." +#endif // PROTOBUF_MIN_PROTOC_VERSION +#include "google/protobuf/port_undef.inc" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/unknown_field_set.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_HelloRpc_2eproto + +namespace google { +namespace protobuf { +namespace internal { +class AnyMetadata; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_HelloRpc_2eproto { + static const ::uint32_t offsets[]; +}; +extern const ::google::protobuf::internal::DescriptorTable + descriptor_table_HelloRpc_2eproto; +class HelloRequest; +struct HelloRequestDefaultTypeInternal; +extern HelloRequestDefaultTypeInternal _HelloRequest_default_instance_; +class HelloResponse; +struct HelloResponseDefaultTypeInternal; +extern HelloResponseDefaultTypeInternal _HelloResponse_default_instance_; +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + + +// =================================================================== + + +// ------------------------------------------------------------------- + +class HelloResponse final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:HelloResponse) */ { + public: + inline HelloResponse() : HelloResponse(nullptr) {} + ~HelloResponse() override; + template + explicit PROTOBUF_CONSTEXPR HelloResponse(::google::protobuf::internal::ConstantInitialized); + + inline HelloResponse(const HelloResponse& from) + : HelloResponse(nullptr, from) {} + HelloResponse(HelloResponse&& from) noexcept + : HelloResponse() { + *this = ::std::move(from); + } + + inline HelloResponse& operator=(const HelloResponse& from) { + CopyFrom(from); + return *this; + } + inline HelloResponse& operator=(HelloResponse&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const HelloResponse& default_instance() { + return *internal_default_instance(); + } + static inline const HelloResponse* internal_default_instance() { + return reinterpret_cast( + &_HelloResponse_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(HelloResponse& a, HelloResponse& b) { + a.Swap(&b); + } + inline void Swap(HelloResponse* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(HelloResponse* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + HelloResponse* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(HelloResponse* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "HelloResponse"; + } + protected: + explicit HelloResponse(::google::protobuf::Arena* arena); + HelloResponse(::google::protobuf::Arena* arena, const HelloResponse& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kGreetingFieldNumber = 1, + }; + // string greeting = 1; + void clear_greeting() ; + const std::string& greeting() const; + template + void set_greeting(Arg_&& arg, Args_... args); + std::string* mutable_greeting(); + PROTOBUF_NODISCARD std::string* release_greeting(); + void set_allocated_greeting(std::string* value); + + private: + const std::string& _internal_greeting() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_greeting( + const std::string& value); + std::string* _internal_mutable_greeting(); + + public: + // @@protoc_insertion_point(class_scope:HelloResponse) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr greeting_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_HelloRpc_2eproto; +};// ------------------------------------------------------------------- + +class HelloRequest final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:HelloRequest) */ { + public: + inline HelloRequest() : HelloRequest(nullptr) {} + ~HelloRequest() override; + template + explicit PROTOBUF_CONSTEXPR HelloRequest(::google::protobuf::internal::ConstantInitialized); + + inline HelloRequest(const HelloRequest& from) + : HelloRequest(nullptr, from) {} + HelloRequest(HelloRequest&& from) noexcept + : HelloRequest() { + *this = ::std::move(from); + } + + inline HelloRequest& operator=(const HelloRequest& from) { + CopyFrom(from); + return *this; + } + inline HelloRequest& operator=(HelloRequest&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const HelloRequest& default_instance() { + return *internal_default_instance(); + } + static inline const HelloRequest* internal_default_instance() { + return reinterpret_cast( + &_HelloRequest_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(HelloRequest& a, HelloRequest& b) { + a.Swap(&b); + } + inline void Swap(HelloRequest* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(HelloRequest* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + HelloRequest* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(HelloRequest* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "HelloRequest"; + } + protected: + explicit HelloRequest(::google::protobuf::Arena* arena); + HelloRequest(::google::protobuf::Arena* arena, const HelloRequest& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kMyNameFieldNumber = 1, + }; + // string myName = 1; + void clear_myname() ; + const std::string& myname() const; + template + void set_myname(Arg_&& arg, Args_... args); + std::string* mutable_myname(); + PROTOBUF_NODISCARD std::string* release_myname(); + void set_allocated_myname(std::string* value); + + private: + const std::string& _internal_myname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_myname( + const std::string& value); + std::string* _internal_mutable_myname(); + + public: + // @@protoc_insertion_point(class_scope:HelloRequest) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr myname_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_HelloRpc_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// HelloRequest + +// string myName = 1; +inline void HelloRequest::clear_myname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.myname_.ClearToEmpty(); +} +inline const std::string& HelloRequest::myname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:HelloRequest.myName) + return _internal_myname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void HelloRequest::set_myname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.myname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:HelloRequest.myName) +} +inline std::string* HelloRequest::mutable_myname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_myname(); + // @@protoc_insertion_point(field_mutable:HelloRequest.myName) + return _s; +} +inline const std::string& HelloRequest::_internal_myname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.myname_.Get(); +} +inline void HelloRequest::_internal_set_myname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.myname_.Set(value, GetArena()); +} +inline std::string* HelloRequest::_internal_mutable_myname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.myname_.Mutable( GetArena()); +} +inline std::string* HelloRequest::release_myname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:HelloRequest.myName) + return _impl_.myname_.Release(); +} +inline void HelloRequest::set_allocated_myname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.myname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.myname_.IsDefault()) { + _impl_.myname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:HelloRequest.myName) +} + +// ------------------------------------------------------------------- + +// HelloResponse + +// string greeting = 1; +inline void HelloResponse::clear_greeting() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.greeting_.ClearToEmpty(); +} +inline const std::string& HelloResponse::greeting() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:HelloResponse.greeting) + return _internal_greeting(); +} +template +inline PROTOBUF_ALWAYS_INLINE void HelloResponse::set_greeting(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.greeting_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:HelloResponse.greeting) +} +inline std::string* HelloResponse::mutable_greeting() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_greeting(); + // @@protoc_insertion_point(field_mutable:HelloResponse.greeting) + return _s; +} +inline const std::string& HelloResponse::_internal_greeting() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.greeting_.Get(); +} +inline void HelloResponse::_internal_set_greeting(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.greeting_.Set(value, GetArena()); +} +inline std::string* HelloResponse::_internal_mutable_greeting() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.greeting_.Mutable( GetArena()); +} +inline std::string* HelloResponse::release_greeting() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:HelloResponse.greeting) + return _impl_.greeting_.Release(); +} +inline void HelloResponse::set_allocated_greeting(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.greeting_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.greeting_.IsDefault()) { + _impl_.greeting_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:HelloResponse.greeting) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_INCLUDED_HelloRpc_2eproto_2epb_2eh diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.server.pb.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.server.pb.h new file mode 100644 index 00000000..be6e45e0 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/HelloRpc.server.pb.h @@ -0,0 +1,19 @@ +// Generated by the protocol buffer streamr pluging. DO NOT EDIT! +// Generated from protobuf file "HelloRpc.proto" + +#ifndef STREAMR_PROTORPC_HELLORPC_SERVER_PB_H +#define STREAMR_PROTORPC_HELLORPC_SERVER_PB_H + +#include "HelloRpc.pb.h" // NOLINT +#include + +namespace streamr::protorpc { +class HelloRpcService { +public: + virtual ~HelloRpcService() = default; + virtual HelloResponse sayHello(const HelloRequest& request, const ProtoCallContext& callContext) = 0; +}; // class HelloRpcService +}; // namespace streamr::protorpc + +#endif // STREAMR_PROTORPC_HELLORPC_SERVER_PB_H + diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Preview Content/Preview Assets.xcassets/Contents.json b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.cc b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.cc new file mode 100644 index 00000000..ce6fc9ca --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.cc @@ -0,0 +1,430 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: ProtoRpc.proto + +#include "ProtoRpc.pb.h" + +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace protorpc { + template +PROTOBUF_CONSTEXPR RpcMessage_HeaderEntry_DoNotUse::RpcMessage_HeaderEntry_DoNotUse(::_pbi::ConstantInitialized) {} +struct RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal { + PROTOBUF_CONSTEXPR RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal() {} + union { + RpcMessage_HeaderEntry_DoNotUse _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal _RpcMessage_HeaderEntry_DoNotUse_default_instance_; + +inline constexpr RpcMessage::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + header_{}, + requestid_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + errorclassname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + errorcode_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + errormessage_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + body_{nullptr}, + errortype_{static_cast< ::protorpc::RpcErrorType >(0)} {} + +template +PROTOBUF_CONSTEXPR RpcMessage::RpcMessage(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct RpcMessageDefaultTypeInternal { + PROTOBUF_CONSTEXPR RpcMessageDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~RpcMessageDefaultTypeInternal() {} + union { + RpcMessage _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RpcMessageDefaultTypeInternal _RpcMessage_default_instance_; + +inline constexpr Mnfo2uhnf92hvqi2nviouq2hv9puhq::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + empty_{nullptr} {} + +template +PROTOBUF_CONSTEXPR Mnfo2uhnf92hvqi2nviouq2hv9puhq::Mnfo2uhnf92hvqi2nviouq2hv9puhq(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal { + PROTOBUF_CONSTEXPR Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal() {} + union { + Mnfo2uhnf92hvqi2nviouq2hv9puhq _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal _Mnfo2uhnf92hvqi2nviouq2hv9puhq_default_instance_; +} // namespace protorpc +static ::_pb::Metadata file_level_metadata_ProtoRpc_2eproto[3]; +static const ::_pb::EnumDescriptor* file_level_enum_descriptors_ProtoRpc_2eproto[1]; +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_ProtoRpc_2eproto = nullptr; +const ::uint32_t TableStruct_ProtoRpc_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage_HeaderEntry_DoNotUse, _has_bits_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage_HeaderEntry_DoNotUse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage_HeaderEntry_DoNotUse, key_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage_HeaderEntry_DoNotUse, value_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.header_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.body_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.requestid_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.errortype_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.errorclassname_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.errorcode_), + PROTOBUF_FIELD_OFFSET(::protorpc::RpcMessage, _impl_.errormessage_), + ~0u, + 3, + ~0u, + 4, + 0, + 1, + 2, + PROTOBUF_FIELD_OFFSET(::protorpc::Mnfo2uhnf92hvqi2nviouq2hv9puhq, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::protorpc::Mnfo2uhnf92hvqi2nviouq2hv9puhq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::protorpc::Mnfo2uhnf92hvqi2nviouq2hv9puhq, _impl_.empty_), + 0, +}; + +static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + {0, 10, -1, sizeof(::protorpc::RpcMessage_HeaderEntry_DoNotUse)}, + {12, 27, -1, sizeof(::protorpc::RpcMessage)}, + {34, 43, -1, sizeof(::protorpc::Mnfo2uhnf92hvqi2nviouq2hv9puhq)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::protorpc::_RpcMessage_HeaderEntry_DoNotUse_default_instance_._instance, + &::protorpc::_RpcMessage_default_instance_._instance, + &::protorpc::_Mnfo2uhnf92hvqi2nviouq2hv9puhq_default_instance_._instance, +}; +const char descriptor_table_protodef_ProtoRpc_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + "\n\016ProtoRpc.proto\022\010protorpc\032\033google/proto" + "buf/empty.proto\032\031google/protobuf/any.pro" + "to\"\344\002\n\nRpcMessage\0220\n\006header\030\001 \003(\0132 .prot" + "orpc.RpcMessage.HeaderEntry\022\"\n\004body\030\002 \001(" + "\0132\024.google.protobuf.Any\022\021\n\trequestId\030\003 \001" + "(\t\022.\n\terrorType\030\004 \001(\0162\026.protorpc.RpcErro" + "rTypeH\000\210\001\001\022\033\n\016errorClassName\030\005 \001(\tH\001\210\001\001\022" + "\026\n\terrorCode\030\006 \001(\tH\002\210\001\001\022\031\n\014errorMessage\030" + "\007 \001(\tH\003\210\001\001\032-\n\013HeaderEntry\022\013\n\003key\030\001 \001(\t\022\r" + "\n\005value\030\002 \001(\t:\0028\001B\014\n\n_errorTypeB\021\n\017_erro" + "rClassNameB\014\n\n_errorCodeB\017\n\r_errorMessag" + "e\"G\n\036Mnfo2uhnf92hvqi2nviouq2hv9puhq\022%\n\005e" + "mpty\030\001 \001(\0132\026.google.protobuf.Empty*r\n\014Rp" + "cErrorType\022\022\n\016SERVER_TIMEOUT\020\000\022\022\n\016CLIENT" + "_TIMEOUT\020\001\022\026\n\022UNKNOWN_RPC_METHOD\020\002\022\020\n\014CL" + "IENT_ERROR\020\003\022\020\n\014SERVER_ERROR\020\004B\002H\002b\006prot" + "o3" +}; +static const ::_pbi::DescriptorTable* const descriptor_table_ProtoRpc_2eproto_deps[2] = + { + &::descriptor_table_google_2fprotobuf_2fany_2eproto, + &::descriptor_table_google_2fprotobuf_2fempty_2eproto, +}; +static ::absl::once_flag descriptor_table_ProtoRpc_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_ProtoRpc_2eproto = { + false, + false, + 642, + descriptor_table_protodef_ProtoRpc_2eproto, + "ProtoRpc.proto", + &descriptor_table_ProtoRpc_2eproto_once, + descriptor_table_ProtoRpc_2eproto_deps, + 2, + 3, + schemas, + file_default_instances, + TableStruct_ProtoRpc_2eproto::offsets, + file_level_metadata_ProtoRpc_2eproto, + file_level_enum_descriptors_ProtoRpc_2eproto, + file_level_service_descriptors_ProtoRpc_2eproto, +}; + +// This function exists to be marked as weak. +// It can significantly speed up compilation by breaking up LLVM's SCC +// in the .pb.cc translation units. Large translation units see a +// reduction of more than 35% of walltime for optimized builds. Without +// the weak attribute all the messages in the file, including all the +// vtables and everything they use become part of the same SCC through +// a cycle like: +// GetMetadata -> descriptor table -> default instances -> +// vtables -> GetMetadata +// By adding a weak function here we break the connection from the +// individual vtables back into the descriptor table. +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_ProtoRpc_2eproto_getter() { + return &descriptor_table_ProtoRpc_2eproto; +} +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_ProtoRpc_2eproto(&descriptor_table_ProtoRpc_2eproto); +namespace protorpc { +const ::google::protobuf::EnumDescriptor* RpcErrorType_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_ProtoRpc_2eproto); + return file_level_enum_descriptors_ProtoRpc_2eproto[0]; +} +PROTOBUF_CONSTINIT const uint32_t RpcErrorType_internal_data_[] = { + 327680u, 0u, }; +bool RpcErrorType_IsValid(int value) { + return 0 <= value && value <= 4; +} +// =================================================================== + +RpcMessage_HeaderEntry_DoNotUse::RpcMessage_HeaderEntry_DoNotUse() {} +RpcMessage_HeaderEntry_DoNotUse::RpcMessage_HeaderEntry_DoNotUse(::google::protobuf::Arena* arena) + : SuperType(arena) {} +::google::protobuf::Metadata RpcMessage_HeaderEntry_DoNotUse::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_ProtoRpc_2eproto_getter, &descriptor_table_ProtoRpc_2eproto_once, + file_level_metadata_ProtoRpc_2eproto[0]); +} +// =================================================================== + +class RpcMessage::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(RpcMessage, _impl_._has_bits_); + static const ::google::protobuf::Any& body(const RpcMessage* msg); + static void set_has_body(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_errortype(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_errorclassname(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_errorcode(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_errormessage(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +const ::google::protobuf::Any& RpcMessage::_Internal::body(const RpcMessage* msg) { + return *msg->_impl_.body_; +} +void RpcMessage::clear_body() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (_impl_.body_ != nullptr) _impl_.body_->Clear(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +RpcMessage::RpcMessage(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:protorpc.RpcMessage) +} +inline PROTOBUF_NDEBUG_INLINE RpcMessage::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + header_{visibility, arena, from.header_}, + requestid_(arena, from.requestid_), + errorclassname_(arena, from.errorclassname_), + errorcode_(arena, from.errorcode_), + errormessage_(arena, from.errormessage_) {} + +RpcMessage::RpcMessage( + ::google::protobuf::Arena* arena, + const RpcMessage& from) + : ::google::protobuf::Message(arena) { + RpcMessage* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.body_ = (cached_has_bits & 0x00000008u) + ? CreateMaybeMessage<::google::protobuf::Any>(arena, *from._impl_.body_) + : nullptr; + _impl_.errortype_ = from._impl_.errortype_; + + // @@protoc_insertion_point(copy_constructor:protorpc.RpcMessage) +} +inline PROTOBUF_NDEBUG_INLINE RpcMessage::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0}, + header_{visibility, arena}, + requestid_(arena), + errorclassname_(arena), + errorcode_(arena), + errormessage_(arena) {} + +inline void RpcMessage::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, body_), + 0, + offsetof(Impl_, errortype_) - + offsetof(Impl_, body_) + + sizeof(Impl_::errortype_)); +} +RpcMessage::~RpcMessage() { + // @@protoc_insertion_point(destructor:protorpc.RpcMessage) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void RpcMessage::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.requestid_.Destroy(); + _impl_.errorclassname_.Destroy(); + _impl_.errorcode_.Destroy(); + _impl_.errormessage_.Destroy(); + delete _impl_.body_; + _impl_.~Impl_(); +} + +::_pbi::CachedSize* RpcMessage::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void RpcMessage::InternalSwap(RpcMessage* PROTOBUF_RESTRICT other) { + using std::swap; + GetReflection()->Swap(this, other);} + +::google::protobuf::Metadata RpcMessage::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_ProtoRpc_2eproto_getter, &descriptor_table_ProtoRpc_2eproto_once, + file_level_metadata_ProtoRpc_2eproto[1]); +} +// =================================================================== + +class Mnfo2uhnf92hvqi2nviouq2hv9puhq::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Mnfo2uhnf92hvqi2nviouq2hv9puhq, _impl_._has_bits_); + static const ::google::protobuf::Empty& empty(const Mnfo2uhnf92hvqi2nviouq2hv9puhq* msg); + static void set_has_empty(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +const ::google::protobuf::Empty& Mnfo2uhnf92hvqi2nviouq2hv9puhq::_Internal::empty(const Mnfo2uhnf92hvqi2nviouq2hv9puhq* msg) { + return *msg->_impl_.empty_; +} +void Mnfo2uhnf92hvqi2nviouq2hv9puhq::clear_empty() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (_impl_.empty_ != nullptr) _impl_.empty_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +Mnfo2uhnf92hvqi2nviouq2hv9puhq::Mnfo2uhnf92hvqi2nviouq2hv9puhq(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq) +} +inline PROTOBUF_NDEBUG_INLINE Mnfo2uhnf92hvqi2nviouq2hv9puhq::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +Mnfo2uhnf92hvqi2nviouq2hv9puhq::Mnfo2uhnf92hvqi2nviouq2hv9puhq( + ::google::protobuf::Arena* arena, + const Mnfo2uhnf92hvqi2nviouq2hv9puhq& from) + : ::google::protobuf::Message(arena) { + Mnfo2uhnf92hvqi2nviouq2hv9puhq* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.empty_ = (cached_has_bits & 0x00000001u) + ? CreateMaybeMessage<::google::protobuf::Empty>(arena, *from._impl_.empty_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq) +} +inline PROTOBUF_NDEBUG_INLINE Mnfo2uhnf92hvqi2nviouq2hv9puhq::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0} {} + +inline void Mnfo2uhnf92hvqi2nviouq2hv9puhq::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.empty_ = {}; +} +Mnfo2uhnf92hvqi2nviouq2hv9puhq::~Mnfo2uhnf92hvqi2nviouq2hv9puhq() { + // @@protoc_insertion_point(destructor:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void Mnfo2uhnf92hvqi2nviouq2hv9puhq::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + delete _impl_.empty_; + _impl_.~Impl_(); +} + +::_pbi::CachedSize* Mnfo2uhnf92hvqi2nviouq2hv9puhq::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void Mnfo2uhnf92hvqi2nviouq2hv9puhq::InternalSwap(Mnfo2uhnf92hvqi2nviouq2hv9puhq* PROTOBUF_RESTRICT other) { + using std::swap; + GetReflection()->Swap(this, other);} + +::google::protobuf::Metadata Mnfo2uhnf92hvqi2nviouq2hv9puhq::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_ProtoRpc_2eproto_getter, &descriptor_table_ProtoRpc_2eproto_once, + file_level_metadata_ProtoRpc_2eproto[2]); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace protorpc +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +#include "google/protobuf/port_undef.inc" diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.h new file mode 100644 index 00000000..29b981ba --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ProtoRpc.pb.h @@ -0,0 +1,1126 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: ProtoRpc.proto +// Protobuf C++ Version: 4.25.1 + +#ifndef GOOGLE_PROTOBUF_INCLUDED_ProtoRpc_2eproto_2epb_2eh +#define GOOGLE_PROTOBUF_INCLUDED_ProtoRpc_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/port_def.inc" +#if PROTOBUF_VERSION < 4025000 +#error "This file was generated by a newer version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please update" +#error "your headers." +#endif // PROTOBUF_VERSION + +#if 4025001 < PROTOBUF_MIN_PROTOC_VERSION +#error "This file was generated by an older version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please" +#error "regenerate this file with a newer version of protoc." +#endif // PROTOBUF_MIN_PROTOC_VERSION +#include "google/protobuf/port_undef.inc" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/map.h" // IWYU pragma: export +#include "google/protobuf/map_entry.h" +#include "google/protobuf/map_field_inl.h" +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +#include "google/protobuf/empty.pb.h" +#include "google/protobuf/any.pb.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_ProtoRpc_2eproto + +namespace google { +namespace protobuf { +namespace internal { +class AnyMetadata; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_ProtoRpc_2eproto { + static const ::uint32_t offsets[]; +}; +extern const ::google::protobuf::internal::DescriptorTable + descriptor_table_ProtoRpc_2eproto; +namespace protorpc { +class Mnfo2uhnf92hvqi2nviouq2hv9puhq; +struct Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal; +extern Mnfo2uhnf92hvqi2nviouq2hv9puhqDefaultTypeInternal _Mnfo2uhnf92hvqi2nviouq2hv9puhq_default_instance_; +class RpcMessage; +struct RpcMessageDefaultTypeInternal; +extern RpcMessageDefaultTypeInternal _RpcMessage_default_instance_; +class RpcMessage_HeaderEntry_DoNotUse; +struct RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal; +extern RpcMessage_HeaderEntry_DoNotUseDefaultTypeInternal _RpcMessage_HeaderEntry_DoNotUse_default_instance_; +} // namespace protorpc +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + +namespace protorpc { +enum RpcErrorType : int { + SERVER_TIMEOUT = 0, + CLIENT_TIMEOUT = 1, + UNKNOWN_RPC_METHOD = 2, + CLIENT_ERROR = 3, + SERVER_ERROR = 4, + RpcErrorType_INT_MIN_SENTINEL_DO_NOT_USE_ = + std::numeric_limits<::int32_t>::min(), + RpcErrorType_INT_MAX_SENTINEL_DO_NOT_USE_ = + std::numeric_limits<::int32_t>::max(), +}; + +bool RpcErrorType_IsValid(int value); +extern const uint32_t RpcErrorType_internal_data_[]; +constexpr RpcErrorType RpcErrorType_MIN = static_cast(0); +constexpr RpcErrorType RpcErrorType_MAX = static_cast(4); +constexpr int RpcErrorType_ARRAYSIZE = 4 + 1; +const ::google::protobuf::EnumDescriptor* +RpcErrorType_descriptor(); +template +const std::string& RpcErrorType_Name(T value) { + static_assert(std::is_same::value || + std::is_integral::value, + "Incorrect type passed to RpcErrorType_Name()."); + return RpcErrorType_Name(static_cast(value)); +} +template <> +inline const std::string& RpcErrorType_Name(RpcErrorType value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool RpcErrorType_Parse(absl::string_view name, RpcErrorType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RpcErrorType_descriptor(), name, value); +} + +// =================================================================== + + +// ------------------------------------------------------------------- + +class RpcMessage_HeaderEntry_DoNotUse final + : public ::google::protobuf::internal::MapEntry< + RpcMessage_HeaderEntry_DoNotUse, std::string, std::string, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING> { + public: + using SuperType = ::google::protobuf::internal::MapEntry< + RpcMessage_HeaderEntry_DoNotUse, std::string, std::string, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING>; + RpcMessage_HeaderEntry_DoNotUse(); + template + explicit PROTOBUF_CONSTEXPR RpcMessage_HeaderEntry_DoNotUse( + ::google::protobuf::internal::ConstantInitialized); + explicit RpcMessage_HeaderEntry_DoNotUse(::google::protobuf::Arena* arena); + static const RpcMessage_HeaderEntry_DoNotUse* internal_default_instance() { + return reinterpret_cast( + &_RpcMessage_HeaderEntry_DoNotUse_default_instance_); + } + static bool ValidateKey(std::string* s) { + return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "protorpc.RpcMessage.HeaderEntry.key"); + } + static bool ValidateValue(std::string* s) { + return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "protorpc.RpcMessage.HeaderEntry.value"); + } + ::google::protobuf::Metadata GetMetadata() const final; + friend struct ::TableStruct_ProtoRpc_2eproto; +}; +// ------------------------------------------------------------------- + +class RpcMessage final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:protorpc.RpcMessage) */ { + public: + inline RpcMessage() : RpcMessage(nullptr) {} + ~RpcMessage() override; + template + explicit PROTOBUF_CONSTEXPR RpcMessage(::google::protobuf::internal::ConstantInitialized); + + inline RpcMessage(const RpcMessage& from) + : RpcMessage(nullptr, from) {} + RpcMessage(RpcMessage&& from) noexcept + : RpcMessage() { + *this = ::std::move(from); + } + + inline RpcMessage& operator=(const RpcMessage& from) { + CopyFrom(from); + return *this; + } + inline RpcMessage& operator=(RpcMessage&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const RpcMessage& default_instance() { + return *internal_default_instance(); + } + static inline const RpcMessage* internal_default_instance() { + return reinterpret_cast( + &_RpcMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(RpcMessage& a, RpcMessage& b) { + a.Swap(&b); + } + inline void Swap(RpcMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RpcMessage* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + RpcMessage* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(RpcMessage* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "protorpc.RpcMessage"; + } + protected: + explicit RpcMessage(::google::protobuf::Arena* arena); + RpcMessage(::google::protobuf::Arena* arena, const RpcMessage& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + + // accessors ------------------------------------------------------- + + enum : int { + kHeaderFieldNumber = 1, + kRequestIdFieldNumber = 3, + kErrorClassNameFieldNumber = 5, + kErrorCodeFieldNumber = 6, + kErrorMessageFieldNumber = 7, + kBodyFieldNumber = 2, + kErrorTypeFieldNumber = 4, + }; + // map header = 1; + int header_size() const; + private: + int _internal_header_size() const; + + public: + void clear_header() ; + const ::google::protobuf::Map& header() const; + ::google::protobuf::Map* mutable_header(); + + private: + const ::google::protobuf::Map& _internal_header() const; + ::google::protobuf::Map* _internal_mutable_header(); + + public: + // string requestId = 3; + void clear_requestid() ; + const std::string& requestid() const; + template + void set_requestid(Arg_&& arg, Args_... args); + std::string* mutable_requestid(); + PROTOBUF_NODISCARD std::string* release_requestid(); + void set_allocated_requestid(std::string* value); + + private: + const std::string& _internal_requestid() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_requestid( + const std::string& value); + std::string* _internal_mutable_requestid(); + + public: + // optional string errorClassName = 5; + bool has_errorclassname() const; + void clear_errorclassname() ; + const std::string& errorclassname() const; + template + void set_errorclassname(Arg_&& arg, Args_... args); + std::string* mutable_errorclassname(); + PROTOBUF_NODISCARD std::string* release_errorclassname(); + void set_allocated_errorclassname(std::string* value); + + private: + const std::string& _internal_errorclassname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_errorclassname( + const std::string& value); + std::string* _internal_mutable_errorclassname(); + + public: + // optional string errorCode = 6; + bool has_errorcode() const; + void clear_errorcode() ; + const std::string& errorcode() const; + template + void set_errorcode(Arg_&& arg, Args_... args); + std::string* mutable_errorcode(); + PROTOBUF_NODISCARD std::string* release_errorcode(); + void set_allocated_errorcode(std::string* value); + + private: + const std::string& _internal_errorcode() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_errorcode( + const std::string& value); + std::string* _internal_mutable_errorcode(); + + public: + // optional string errorMessage = 7; + bool has_errormessage() const; + void clear_errormessage() ; + const std::string& errormessage() const; + template + void set_errormessage(Arg_&& arg, Args_... args); + std::string* mutable_errormessage(); + PROTOBUF_NODISCARD std::string* release_errormessage(); + void set_allocated_errormessage(std::string* value); + + private: + const std::string& _internal_errormessage() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_errormessage( + const std::string& value); + std::string* _internal_mutable_errormessage(); + + public: + // .google.protobuf.Any body = 2; + bool has_body() const; + void clear_body() ; + const ::google::protobuf::Any& body() const; + PROTOBUF_NODISCARD ::google::protobuf::Any* release_body(); + ::google::protobuf::Any* mutable_body(); + void set_allocated_body(::google::protobuf::Any* value); + void unsafe_arena_set_allocated_body(::google::protobuf::Any* value); + ::google::protobuf::Any* unsafe_arena_release_body(); + + private: + const ::google::protobuf::Any& _internal_body() const; + ::google::protobuf::Any* _internal_mutable_body(); + + public: + // optional .protorpc.RpcErrorType errorType = 4; + bool has_errortype() const; + void clear_errortype() ; + ::protorpc::RpcErrorType errortype() const; + void set_errortype(::protorpc::RpcErrorType value); + + private: + ::protorpc::RpcErrorType _internal_errortype() const; + void _internal_set_errortype(::protorpc::RpcErrorType value); + + public: + // @@protoc_insertion_point(class_scope:protorpc.RpcMessage) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::HasBits<1> _has_bits_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::MapField + header_; + ::google::protobuf::internal::ArenaStringPtr requestid_; + ::google::protobuf::internal::ArenaStringPtr errorclassname_; + ::google::protobuf::internal::ArenaStringPtr errorcode_; + ::google::protobuf::internal::ArenaStringPtr errormessage_; + ::google::protobuf::Any* body_; + int errortype_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_ProtoRpc_2eproto; +};// ------------------------------------------------------------------- + +class Mnfo2uhnf92hvqi2nviouq2hv9puhq final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq) */ { + public: + inline Mnfo2uhnf92hvqi2nviouq2hv9puhq() : Mnfo2uhnf92hvqi2nviouq2hv9puhq(nullptr) {} + ~Mnfo2uhnf92hvqi2nviouq2hv9puhq() override; + template + explicit PROTOBUF_CONSTEXPR Mnfo2uhnf92hvqi2nviouq2hv9puhq(::google::protobuf::internal::ConstantInitialized); + + inline Mnfo2uhnf92hvqi2nviouq2hv9puhq(const Mnfo2uhnf92hvqi2nviouq2hv9puhq& from) + : Mnfo2uhnf92hvqi2nviouq2hv9puhq(nullptr, from) {} + Mnfo2uhnf92hvqi2nviouq2hv9puhq(Mnfo2uhnf92hvqi2nviouq2hv9puhq&& from) noexcept + : Mnfo2uhnf92hvqi2nviouq2hv9puhq() { + *this = ::std::move(from); + } + + inline Mnfo2uhnf92hvqi2nviouq2hv9puhq& operator=(const Mnfo2uhnf92hvqi2nviouq2hv9puhq& from) { + CopyFrom(from); + return *this; + } + inline Mnfo2uhnf92hvqi2nviouq2hv9puhq& operator=(Mnfo2uhnf92hvqi2nviouq2hv9puhq&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Mnfo2uhnf92hvqi2nviouq2hv9puhq& default_instance() { + return *internal_default_instance(); + } + static inline const Mnfo2uhnf92hvqi2nviouq2hv9puhq* internal_default_instance() { + return reinterpret_cast( + &_Mnfo2uhnf92hvqi2nviouq2hv9puhq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Mnfo2uhnf92hvqi2nviouq2hv9puhq& a, Mnfo2uhnf92hvqi2nviouq2hv9puhq& b) { + a.Swap(&b); + } + inline void Swap(Mnfo2uhnf92hvqi2nviouq2hv9puhq* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Mnfo2uhnf92hvqi2nviouq2hv9puhq* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Mnfo2uhnf92hvqi2nviouq2hv9puhq* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(Mnfo2uhnf92hvqi2nviouq2hv9puhq* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq"; + } + protected: + explicit Mnfo2uhnf92hvqi2nviouq2hv9puhq(::google::protobuf::Arena* arena); + Mnfo2uhnf92hvqi2nviouq2hv9puhq(::google::protobuf::Arena* arena, const Mnfo2uhnf92hvqi2nviouq2hv9puhq& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kEmptyFieldNumber = 1, + }; + // .google.protobuf.Empty empty = 1; + bool has_empty() const; + void clear_empty() ; + const ::google::protobuf::Empty& empty() const; + PROTOBUF_NODISCARD ::google::protobuf::Empty* release_empty(); + ::google::protobuf::Empty* mutable_empty(); + void set_allocated_empty(::google::protobuf::Empty* value); + void unsafe_arena_set_allocated_empty(::google::protobuf::Empty* value); + ::google::protobuf::Empty* unsafe_arena_release_empty(); + + private: + const ::google::protobuf::Empty& _internal_empty() const; + ::google::protobuf::Empty* _internal_mutable_empty(); + + public: + // @@protoc_insertion_point(class_scope:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::HasBits<1> _has_bits_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::Empty* empty_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_ProtoRpc_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// RpcMessage + +// map header = 1; +inline int RpcMessage::_internal_header_size() const { + return _internal_header().size(); +} +inline int RpcMessage::header_size() const { + return _internal_header_size(); +} +inline void RpcMessage::clear_header() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.header_.Clear(); +} +inline const ::google::protobuf::Map& RpcMessage::_internal_header() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.header_.GetMap(); +} +inline const ::google::protobuf::Map& RpcMessage::header() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_map:protorpc.RpcMessage.header) + return _internal_header(); +} +inline ::google::protobuf::Map* RpcMessage::_internal_mutable_header() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + return _impl_.header_.MutableMap(); +} +inline ::google::protobuf::Map* RpcMessage::mutable_header() ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_map:protorpc.RpcMessage.header) + return _internal_mutable_header(); +} + +// .google.protobuf.Any body = 2; +inline bool RpcMessage::has_body() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || _impl_.body_ != nullptr); + return value; +} +inline const ::google::protobuf::Any& RpcMessage::_internal_body() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + const ::google::protobuf::Any* p = _impl_.body_; + return p != nullptr ? *p : reinterpret_cast(::google::protobuf::_Any_default_instance_); +} +inline const ::google::protobuf::Any& RpcMessage::body() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.body) + return _internal_body(); +} +inline void RpcMessage::unsafe_arena_set_allocated_body(::google::protobuf::Any* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.body_); + } + _impl_.body_ = reinterpret_cast<::google::protobuf::Any*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:protorpc.RpcMessage.body) +} +inline ::google::protobuf::Any* RpcMessage::release_body() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + + _impl_._has_bits_[0] &= ~0x00000008u; + ::google::protobuf::Any* released = _impl_.body_; + _impl_.body_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::google::protobuf::Any* RpcMessage::unsafe_arena_release_body() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.RpcMessage.body) + + _impl_._has_bits_[0] &= ~0x00000008u; + ::google::protobuf::Any* temp = _impl_.body_; + _impl_.body_ = nullptr; + return temp; +} +inline ::google::protobuf::Any* RpcMessage::_internal_mutable_body() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000008u; + if (_impl_.body_ == nullptr) { + auto* p = CreateMaybeMessage<::google::protobuf::Any>(GetArena()); + _impl_.body_ = reinterpret_cast<::google::protobuf::Any*>(p); + } + return _impl_.body_; +} +inline ::google::protobuf::Any* RpcMessage::mutable_body() ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::Any* _msg = _internal_mutable_body(); + // @@protoc_insertion_point(field_mutable:protorpc.RpcMessage.body) + return _msg; +} +inline void RpcMessage::set_allocated_body(::google::protobuf::Any* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.body_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::MessageLite*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + + _impl_.body_ = reinterpret_cast<::google::protobuf::Any*>(value); + // @@protoc_insertion_point(field_set_allocated:protorpc.RpcMessage.body) +} + +// string requestId = 3; +inline void RpcMessage::clear_requestid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.requestid_.ClearToEmpty(); +} +inline const std::string& RpcMessage::requestid() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.requestId) + return _internal_requestid(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RpcMessage::set_requestid(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.requestid_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:protorpc.RpcMessage.requestId) +} +inline std::string* RpcMessage::mutable_requestid() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_requestid(); + // @@protoc_insertion_point(field_mutable:protorpc.RpcMessage.requestId) + return _s; +} +inline const std::string& RpcMessage::_internal_requestid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.requestid_.Get(); +} +inline void RpcMessage::_internal_set_requestid(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.requestid_.Set(value, GetArena()); +} +inline std::string* RpcMessage::_internal_mutable_requestid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.requestid_.Mutable( GetArena()); +} +inline std::string* RpcMessage::release_requestid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.RpcMessage.requestId) + return _impl_.requestid_.Release(); +} +inline void RpcMessage::set_allocated_requestid(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.requestid_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.requestid_.IsDefault()) { + _impl_.requestid_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:protorpc.RpcMessage.requestId) +} + +// optional .protorpc.RpcErrorType errorType = 4; +inline bool RpcMessage::has_errortype() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline void RpcMessage::clear_errortype() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.errortype_ = 0; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline ::protorpc::RpcErrorType RpcMessage::errortype() const { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.errorType) + return _internal_errortype(); +} +inline void RpcMessage::set_errortype(::protorpc::RpcErrorType value) { + _internal_set_errortype(value); + // @@protoc_insertion_point(field_set:protorpc.RpcMessage.errorType) +} +inline ::protorpc::RpcErrorType RpcMessage::_internal_errortype() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return static_cast<::protorpc::RpcErrorType>(_impl_.errortype_); +} +inline void RpcMessage::_internal_set_errortype(::protorpc::RpcErrorType value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.errortype_ = value; +} + +// optional string errorClassName = 5; +inline bool RpcMessage::has_errorclassname() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline void RpcMessage::clear_errorclassname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.errorclassname_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& RpcMessage::errorclassname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.errorClassName) + return _internal_errorclassname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RpcMessage::set_errorclassname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.errorclassname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:protorpc.RpcMessage.errorClassName) +} +inline std::string* RpcMessage::mutable_errorclassname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_errorclassname(); + // @@protoc_insertion_point(field_mutable:protorpc.RpcMessage.errorClassName) + return _s; +} +inline const std::string& RpcMessage::_internal_errorclassname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.errorclassname_.Get(); +} +inline void RpcMessage::_internal_set_errorclassname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.errorclassname_.Set(value, GetArena()); +} +inline std::string* RpcMessage::_internal_mutable_errorclassname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.errorclassname_.Mutable( GetArena()); +} +inline std::string* RpcMessage::release_errorclassname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.RpcMessage.errorClassName) + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.errorclassname_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.errorclassname_.Set("", GetArena()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void RpcMessage::set_allocated_errorclassname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.errorclassname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.errorclassname_.IsDefault()) { + _impl_.errorclassname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:protorpc.RpcMessage.errorClassName) +} + +// optional string errorCode = 6; +inline bool RpcMessage::has_errorcode() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline void RpcMessage::clear_errorcode() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.errorcode_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& RpcMessage::errorcode() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.errorCode) + return _internal_errorcode(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RpcMessage::set_errorcode(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.errorcode_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:protorpc.RpcMessage.errorCode) +} +inline std::string* RpcMessage::mutable_errorcode() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_errorcode(); + // @@protoc_insertion_point(field_mutable:protorpc.RpcMessage.errorCode) + return _s; +} +inline const std::string& RpcMessage::_internal_errorcode() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.errorcode_.Get(); +} +inline void RpcMessage::_internal_set_errorcode(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.errorcode_.Set(value, GetArena()); +} +inline std::string* RpcMessage::_internal_mutable_errorcode() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.errorcode_.Mutable( GetArena()); +} +inline std::string* RpcMessage::release_errorcode() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.RpcMessage.errorCode) + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* released = _impl_.errorcode_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.errorcode_.Set("", GetArena()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void RpcMessage::set_allocated_errorcode(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.errorcode_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.errorcode_.IsDefault()) { + _impl_.errorcode_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:protorpc.RpcMessage.errorCode) +} + +// optional string errorMessage = 7; +inline bool RpcMessage::has_errormessage() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline void RpcMessage::clear_errormessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.errormessage_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& RpcMessage::errormessage() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.RpcMessage.errorMessage) + return _internal_errormessage(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RpcMessage::set_errormessage(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.errormessage_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:protorpc.RpcMessage.errorMessage) +} +inline std::string* RpcMessage::mutable_errormessage() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_errormessage(); + // @@protoc_insertion_point(field_mutable:protorpc.RpcMessage.errorMessage) + return _s; +} +inline const std::string& RpcMessage::_internal_errormessage() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.errormessage_.Get(); +} +inline void RpcMessage::_internal_set_errormessage(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.errormessage_.Set(value, GetArena()); +} +inline std::string* RpcMessage::_internal_mutable_errormessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.errormessage_.Mutable( GetArena()); +} +inline std::string* RpcMessage::release_errormessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.RpcMessage.errorMessage) + if ((_impl_._has_bits_[0] & 0x00000004u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* released = _impl_.errormessage_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.errormessage_.Set("", GetArena()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void RpcMessage::set_allocated_errormessage(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.errormessage_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.errormessage_.IsDefault()) { + _impl_.errormessage_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:protorpc.RpcMessage.errorMessage) +} + +// ------------------------------------------------------------------- + +// Mnfo2uhnf92hvqi2nviouq2hv9puhq + +// .google.protobuf.Empty empty = 1; +inline bool Mnfo2uhnf92hvqi2nviouq2hv9puhq::has_empty() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || _impl_.empty_ != nullptr); + return value; +} +inline const ::google::protobuf::Empty& Mnfo2uhnf92hvqi2nviouq2hv9puhq::_internal_empty() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + const ::google::protobuf::Empty* p = _impl_.empty_; + return p != nullptr ? *p : reinterpret_cast(::google::protobuf::_Empty_default_instance_); +} +inline const ::google::protobuf::Empty& Mnfo2uhnf92hvqi2nviouq2hv9puhq::empty() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq.empty) + return _internal_empty(); +} +inline void Mnfo2uhnf92hvqi2nviouq2hv9puhq::unsafe_arena_set_allocated_empty(::google::protobuf::Empty* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.empty_); + } + _impl_.empty_ = reinterpret_cast<::google::protobuf::Empty*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq.empty) +} +inline ::google::protobuf::Empty* Mnfo2uhnf92hvqi2nviouq2hv9puhq::release_empty() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + + _impl_._has_bits_[0] &= ~0x00000001u; + ::google::protobuf::Empty* released = _impl_.empty_; + _impl_.empty_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::google::protobuf::Empty* Mnfo2uhnf92hvqi2nviouq2hv9puhq::unsafe_arena_release_empty() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq.empty) + + _impl_._has_bits_[0] &= ~0x00000001u; + ::google::protobuf::Empty* temp = _impl_.empty_; + _impl_.empty_ = nullptr; + return temp; +} +inline ::google::protobuf::Empty* Mnfo2uhnf92hvqi2nviouq2hv9puhq::_internal_mutable_empty() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + if (_impl_.empty_ == nullptr) { + auto* p = CreateMaybeMessage<::google::protobuf::Empty>(GetArena()); + _impl_.empty_ = reinterpret_cast<::google::protobuf::Empty*>(p); + } + return _impl_.empty_; +} +inline ::google::protobuf::Empty* Mnfo2uhnf92hvqi2nviouq2hv9puhq::mutable_empty() ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::Empty* _msg = _internal_mutable_empty(); + // @@protoc_insertion_point(field_mutable:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq.empty) + return _msg; +} +inline void Mnfo2uhnf92hvqi2nviouq2hv9puhq::set_allocated_empty(::google::protobuf::Empty* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.empty_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::MessageLite*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + + _impl_.empty_ = reinterpret_cast<::google::protobuf::Empty*>(value); + // @@protoc_insertion_point(field_set_allocated:protorpc.Mnfo2uhnf92hvqi2nviouq2hv9puhq.empty) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace protorpc + + +namespace google { +namespace protobuf { + +template <> +struct is_proto_enum<::protorpc::RpcErrorType> : std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor<::protorpc::RpcErrorType>() { + return ::protorpc::RpcErrorType_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_INCLUDED_ProtoRpc_2eproto_2epb_2eh diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h new file mode 100644 index 00000000..c3dc66b1 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleApp-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#include "Wrapper.h" diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleAppApp.swift b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleAppApp.swift new file mode 100644 index 00000000..971dc8c3 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/StreamrProtoRpcExampleAppApp.swift @@ -0,0 +1,17 @@ +// +// StreamrProtoRpcExampleAppApp.swift +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// + +import SwiftUI + +@main +struct StreamrProtoRpcExampleAppApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.h b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.h new file mode 100644 index 00000000..b246b573 --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.h @@ -0,0 +1,12 @@ +// +// Wrapper.h +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// + +#import + +@interface Wrapper : NSObject +-(NSString*) greetingWrapper; +@end diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.mm b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.mm new file mode 100644 index 00000000..7ffb91db --- /dev/null +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/Wrapper.mm @@ -0,0 +1,17 @@ +// +// Wrapper.m +// StreamrProtoRpcExampleApp +// +// Created by Santtu Rantanen on 21.8.2024. +// +#include "Wrapper.h" +#include "folly/Format.h" +#include "Hello.hpp" + +@implementation Wrapper + +- (NSString *)greetingWrapper { + return [NSString stringWithUTF8String:sayHello().c_str()]; +} + +@end From 8626d0968ae19c99e07bb7351c8ca2c8de1c4b7a Mon Sep 17 00:00:00 2001 From: Santtu Date: Thu, 22 Aug 2024 13:10:21 +0300 Subject: [PATCH 04/67] Small improvement --- .../StreamrProtoRpcExampleApp/ContentView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift index 405e7125..8eb49d1e 100644 --- a/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift +++ b/packages/streamr-proto-rpc/examples/ios/xcframeworkexampleapp/StreamrProtoRpcExampleApp/ContentView.swift @@ -13,7 +13,7 @@ struct ContentView: View { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) - Text("\(Wrapper().greetingWrapper())") + Text(Wrapper().greetingWrapper()) } .padding() } From afa638a5c842bf82becc90ceaf9f7931036efe2b Mon Sep 17 00:00:00 2001 From: Santtu Date: Sun, 25 Aug 2024 20:54:18 +0300 Subject: [PATCH 05/67] LocationShare example iOS app --- .../LocationShare.xcodeproj/project.pbxproj | 635 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 61402 bytes .../xcschemes/LocationShare.xcscheme | 104 +++ .../xcdebugger/Breakpoints_v2.xcbkptlist | 200 ++++++ .../xcschemes/xcschememanagement.plist | 32 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../LocationShare/LocationShare/Info.plist | 5 + .../LocationShare/LocationManager.swift | 31 + .../LocationShare-Bridging-Header.h | 5 + .../LocationShare/LocationShareApp.swift | 17 + .../LocationShare/LocationShareView.swift | 61 ++ .../LocationShareViewModel.swift | 98 +++ .../LocationShare/PeerDescriptor.hpp | 18 + .../LocationShare/PeerDescriptor.swift | 13 + .../Preview Assets.xcassets/Contents.json | 6 + .../LocationShare/ProxyClient.cpp | 33 + .../LocationShare/ProxyClient.hpp | 23 + .../LocationShare/LocationShare/Result.hpp | 18 + .../LocationShare/StreamrProxyClient.swift | 85 +++ .../LocationShareTests.swift | 36 + .../LocationShareUITests.swift | 41 ++ .../LocationShareUITestsLaunchTests.swift | 32 + 26 files changed, 1538 insertions(+) create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.pbxproj create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcshareddata/xcschemes/LocationShare.xcscheme create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/Contents.json create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Info.plist create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationManager.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShare-Bridging-Header.h create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareApp.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.hpp create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareTests/LocationShareTests.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITests.swift create mode 100644 packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITestsLaunchTests.swift diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.pbxproj b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.pbxproj new file mode 100644 index 00000000..25c37576 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.pbxproj @@ -0,0 +1,635 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 413E46C32C7867670030132D /* LocationShareApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46C22C7867670030132D /* LocationShareApp.swift */; }; + 413E46C52C7867670030132D /* LocationShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46C42C7867670030132D /* LocationShareView.swift */; }; + 413E46C72C78676A0030132D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 413E46C62C78676A0030132D /* Assets.xcassets */; }; + 413E46CA2C78676A0030132D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 413E46C92C78676A0030132D /* Preview Assets.xcassets */; }; + 413E46D42C78676A0030132D /* LocationShareTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46D32C78676A0030132D /* LocationShareTests.swift */; }; + 413E46DE2C78676A0030132D /* LocationShareUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46DD2C78676A0030132D /* LocationShareUITests.swift */; }; + 413E46E02C78676A0030132D /* LocationShareUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46DF2C78676A0030132D /* LocationShareUITestsLaunchTests.swift */; }; + 413E46ED2C7875CE0030132D /* LocationShareViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46EC2C7875CD0030132D /* LocationShareViewModel.swift */; }; + 413E46EF2C78773C0030132D /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46EE2C78773C0030132D /* LocationManager.swift */; }; + 413E46F22C7895900030132D /* StreamrProxyClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46F12C7895900030132D /* StreamrProxyClient.swift */; }; + 413E46F62C7898D40030132D /* PeerDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413E46F52C7898D40030132D /* PeerDescriptor.swift */; }; + 4176FEC02C7B9078004F8A48 /* ProxyClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4176FEBE2C7B9078004F8A48 /* ProxyClient.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 413E46D02C78676A0030132D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 413E46B72C7867670030132D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 413E46BE2C7867670030132D; + remoteInfo = LocationShare; + }; + 413E46DA2C78676A0030132D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 413E46B72C7867670030132D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 413E46BE2C7867670030132D; + remoteInfo = LocationShare; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 413E46BF2C7867670030132D /* LocationShare.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LocationShare.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 413E46C22C7867670030132D /* LocationShareApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareApp.swift; sourceTree = ""; }; + 413E46C42C7867670030132D /* LocationShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareView.swift; sourceTree = ""; }; + 413E46C62C78676A0030132D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 413E46C92C78676A0030132D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 413E46CF2C78676A0030132D /* LocationShareTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LocationShareTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 413E46D32C78676A0030132D /* LocationShareTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareTests.swift; sourceTree = ""; }; + 413E46D92C78676A0030132D /* LocationShareUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LocationShareUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 413E46DD2C78676A0030132D /* LocationShareUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareUITests.swift; sourceTree = ""; }; + 413E46DF2C78676A0030132D /* LocationShareUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareUITestsLaunchTests.swift; sourceTree = ""; }; + 413E46EC2C7875CD0030132D /* LocationShareViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareViewModel.swift; sourceTree = ""; }; + 413E46EE2C78773C0030132D /* LocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = ""; }; + 413E46F02C787E820030132D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 413E46F12C7895900030132D /* StreamrProxyClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamrProxyClient.swift; sourceTree = ""; }; + 413E46F52C7898D40030132D /* PeerDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerDescriptor.swift; sourceTree = ""; }; + 4176FEBD2C7B9077004F8A48 /* LocationShare-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LocationShare-Bridging-Header.h"; sourceTree = ""; }; + 4176FEBE2C7B9078004F8A48 /* ProxyClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyClient.cpp; sourceTree = ""; }; + 4176FEBF2C7B9078004F8A48 /* ProxyClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ProxyClient.hpp; sourceTree = ""; }; + 4176FEC12C7B9204004F8A48 /* Result.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Result.hpp; sourceTree = ""; }; + 4176FEC22C7B92DA004F8A48 /* PeerDescriptor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PeerDescriptor.hpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 413E46BC2C7867670030132D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46CC2C78676A0030132D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46D62C78676A0030132D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 413E46B62C7867670030132D = { + isa = PBXGroup; + children = ( + 413E46C12C7867670030132D /* LocationShare */, + 413E46D22C78676A0030132D /* LocationShareTests */, + 413E46DC2C78676A0030132D /* LocationShareUITests */, + 413E46C02C7867670030132D /* Products */, + ); + sourceTree = ""; + }; + 413E46C02C7867670030132D /* Products */ = { + isa = PBXGroup; + children = ( + 413E46BF2C7867670030132D /* LocationShare.app */, + 413E46CF2C78676A0030132D /* LocationShareTests.xctest */, + 413E46D92C78676A0030132D /* LocationShareUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 413E46C12C7867670030132D /* LocationShare */ = { + isa = PBXGroup; + children = ( + 413E46F02C787E820030132D /* Info.plist */, + 413E46C22C7867670030132D /* LocationShareApp.swift */, + 413E46C42C7867670030132D /* LocationShareView.swift */, + 413E46C62C78676A0030132D /* Assets.xcassets */, + 413E46C82C78676A0030132D /* Preview Content */, + 413E46EC2C7875CD0030132D /* LocationShareViewModel.swift */, + 413E46EE2C78773C0030132D /* LocationManager.swift */, + 413E46F12C7895900030132D /* StreamrProxyClient.swift */, + 413E46F52C7898D40030132D /* PeerDescriptor.swift */, + 4176FEBE2C7B9078004F8A48 /* ProxyClient.cpp */, + 4176FEBF2C7B9078004F8A48 /* ProxyClient.hpp */, + 4176FEBD2C7B9077004F8A48 /* LocationShare-Bridging-Header.h */, + 4176FEC12C7B9204004F8A48 /* Result.hpp */, + 4176FEC22C7B92DA004F8A48 /* PeerDescriptor.hpp */, + ); + path = LocationShare; + sourceTree = ""; + }; + 413E46C82C78676A0030132D /* Preview Content */ = { + isa = PBXGroup; + children = ( + 413E46C92C78676A0030132D /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 413E46D22C78676A0030132D /* LocationShareTests */ = { + isa = PBXGroup; + children = ( + 413E46D32C78676A0030132D /* LocationShareTests.swift */, + ); + path = LocationShareTests; + sourceTree = ""; + }; + 413E46DC2C78676A0030132D /* LocationShareUITests */ = { + isa = PBXGroup; + children = ( + 413E46DD2C78676A0030132D /* LocationShareUITests.swift */, + 413E46DF2C78676A0030132D /* LocationShareUITestsLaunchTests.swift */, + ); + path = LocationShareUITests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 413E46BE2C7867670030132D /* LocationShare */ = { + isa = PBXNativeTarget; + buildConfigurationList = 413E46E32C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShare" */; + buildPhases = ( + 413E46BB2C7867670030132D /* Sources */, + 413E46BC2C7867670030132D /* Frameworks */, + 413E46BD2C7867670030132D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LocationShare; + productName = LocationShare; + productReference = 413E46BF2C7867670030132D /* LocationShare.app */; + productType = "com.apple.product-type.application"; + }; + 413E46CE2C78676A0030132D /* LocationShareTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 413E46E62C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShareTests" */; + buildPhases = ( + 413E46CB2C78676A0030132D /* Sources */, + 413E46CC2C78676A0030132D /* Frameworks */, + 413E46CD2C78676A0030132D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 413E46D12C78676A0030132D /* PBXTargetDependency */, + ); + name = LocationShareTests; + productName = LocationShareTests; + productReference = 413E46CF2C78676A0030132D /* LocationShareTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 413E46D82C78676A0030132D /* LocationShareUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 413E46E92C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShareUITests" */; + buildPhases = ( + 413E46D52C78676A0030132D /* Sources */, + 413E46D62C78676A0030132D /* Frameworks */, + 413E46D72C78676A0030132D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 413E46DB2C78676A0030132D /* PBXTargetDependency */, + ); + name = LocationShareUITests; + productName = LocationShareUITests; + productReference = 413E46D92C78676A0030132D /* LocationShareUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 413E46B72C7867670030132D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 413E46BE2C7867670030132D = { + CreatedOnToolsVersion = 15.4; + LastSwiftMigration = 1540; + }; + 413E46CE2C78676A0030132D = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 413E46BE2C7867670030132D; + }; + 413E46D82C78676A0030132D = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 413E46BE2C7867670030132D; + }; + }; + }; + buildConfigurationList = 413E46BA2C7867670030132D /* Build configuration list for PBXProject "LocationShare" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 413E46B62C7867670030132D; + productRefGroup = 413E46C02C7867670030132D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 413E46BE2C7867670030132D /* LocationShare */, + 413E46CE2C78676A0030132D /* LocationShareTests */, + 413E46D82C78676A0030132D /* LocationShareUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 413E46BD2C7867670030132D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 413E46CA2C78676A0030132D /* Preview Assets.xcassets in Resources */, + 413E46C72C78676A0030132D /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46CD2C78676A0030132D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46D72C78676A0030132D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 413E46BB2C7867670030132D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 413E46F62C7898D40030132D /* PeerDescriptor.swift in Sources */, + 413E46EF2C78773C0030132D /* LocationManager.swift in Sources */, + 413E46C52C7867670030132D /* LocationShareView.swift in Sources */, + 413E46F22C7895900030132D /* StreamrProxyClient.swift in Sources */, + 413E46ED2C7875CE0030132D /* LocationShareViewModel.swift in Sources */, + 4176FEC02C7B9078004F8A48 /* ProxyClient.cpp in Sources */, + 413E46C32C7867670030132D /* LocationShareApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46CB2C78676A0030132D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 413E46D42C78676A0030132D /* LocationShareTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 413E46D52C78676A0030132D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 413E46DE2C78676A0030132D /* LocationShareUITests.swift in Sources */, + 413E46E02C78676A0030132D /* LocationShareUITestsLaunchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 413E46D12C78676A0030132D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 413E46BE2C7867670030132D /* LocationShare */; + targetProxy = 413E46D02C78676A0030132D /* PBXContainerItemProxy */; + }; + 413E46DB2C78676A0030132D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 413E46BE2C7867670030132D /* LocationShare */; + targetProxy = 413E46DA2C78676A0030132D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 413E46E12C78676A0030132D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OBJC_INTEROP_MODE = objcxx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 413E46E22C78676A0030132D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + 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; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_INTEROP_MODE = objcxx; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 413E46E42C78676A0030132D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"LocationShare/Preview Content\""; + DEVELOPMENT_TEAM = S933S46DZS; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = LocationShare/Info.plist; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The app needs access to your location to provide location-based services."; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShare; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "LocationShare/LocationShare-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 413E46E52C78676A0030132D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"LocationShare/Preview Content\""; + DEVELOPMENT_TEAM = S933S46DZS; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = LocationShare/Info.plist; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The app needs access to your location to provide location-based services."; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShare; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "LocationShare/LocationShare-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 413E46E72C78676A0030132D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S933S46DZS; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShareTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LocationShare.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/LocationShare"; + }; + name = Debug; + }; + 413E46E82C78676A0030132D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S933S46DZS; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShareTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LocationShare.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/LocationShare"; + }; + name = Release; + }; + 413E46EA2C78676A0030132D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S933S46DZS; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShareUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = LocationShare; + }; + name = Debug; + }; + 413E46EB2C78676A0030132D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S933S46DZS; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = testing.LocationShareUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = LocationShare; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 413E46BA2C7867670030132D /* Build configuration list for PBXProject "LocationShare" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 413E46E12C78676A0030132D /* Debug */, + 413E46E22C78676A0030132D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 413E46E32C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShare" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 413E46E42C78676A0030132D /* Debug */, + 413E46E52C78676A0030132D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 413E46E62C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShareTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 413E46E72C78676A0030132D /* Debug */, + 413E46E82C78676A0030132D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 413E46E92C78676A0030132D /* Build configuration list for PBXNativeTarget "LocationShareUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 413E46EA2C78676A0030132D /* Debug */, + 413E46EB2C78676A0030132D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 413E46B72C7867670030132D /* Project object */; +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..8a1a40f1b163a8f73029e6414ae0ea58fe73a388 GIT binary patch literal 61402 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�VySDD~U9yd3bT@p7xPy~PkNzU~(kTNhXtzcZL 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 OKaoWLgi!%b5C1<1FpBvA literal 0 HcmV?d00001 diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcshareddata/xcschemes/LocationShare.xcscheme b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcshareddata/xcschemes/LocationShare.xcscheme new file mode 100644 index 00000000..6cd4e489 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcshareddata/xcschemes/LocationShare.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 00000000..201feeda --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..29fff48f --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,32 @@ + + + + + SchemeUserState + + LocationShare.xcscheme_^#shared#^_ + + orderHint + 0 + + + SuppressBuildableAutocreation + + 413E46BE2C7867670030132D + + primary + + + 413E46CE2C78676A0030132D + + primary + + + 413E46D82C78676A0030132D + + primary + + + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AccentColor.colorset/Contents.json b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/Contents.json b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Info.plist b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Info.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Info.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationManager.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationManager.swift new file mode 100644 index 00000000..6b8594c7 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationManager.swift @@ -0,0 +1,31 @@ +// +// LocationManager.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import SwiftUI +import CoreLocation + +@Observable +class LocationManager { + + @MainActor var location: (latitude: Double, longitude: Double)? = nil + private let locationManager = CLLocationManager() + + func requestUserAuthorization() async throws { + locationManager.requestWhenInUseAuthorization() + } + + func startCurrentLocationUpdates() async throws { + for try await locationUpdate in CLLocationUpdate.liveUpdates() { + if let coodinate = locationUpdate.location?.coordinate { + await MainActor.run() { + print("Thread: startCurrentLocationUpdates: \(Thread.current)") + self.location = (coodinate.latitude, coodinate.longitude) + } + } + } + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShare-Bridging-Header.h b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShare-Bridging-Header.h new file mode 100644 index 00000000..12a3284b --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShare-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#include "ProxyClient.hpp" diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareApp.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareApp.swift new file mode 100644 index 00000000..73e9a89b --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareApp.swift @@ -0,0 +1,17 @@ +// +// LocationShareApp.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import SwiftUI + +@main +struct LocationShareApp: App { + var body: some Scene { + WindowGroup { + LocationShareView() + } + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift new file mode 100644 index 00000000..00aba9ce --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift @@ -0,0 +1,61 @@ +// +// ContentView.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import SwiftUI + +struct LocationShareView: View { + @State var viewModel = LocationShareViewModel() + + var body: some View { + ZStack { + List { + Section(header: Text("Proxy Information")) { + TextField( + "Enter proxy address", + text: $viewModel.proxyAddress + ) + TextField( + "Enter proxy ID", + text: $viewModel.proxyId + ) + TextField( + "Enter sending interval in seconds", + text: $viewModel.publishingIntervalInSeconds + ) + + } + Section(header: Text("GPS Location")) { + Text("\(viewModel.latitude), \(viewModel.longitude)") + } + } + VStack { + Spacer() + Button { + viewModel.buttonClicked() + } label: { + Text(viewModel.buttonText) + .frame(maxWidth: .infinity) + }.buttonStyle(.borderedProminent) + .controlSize(.large) + .padding([.leading, .trailing, .top, .bottom]) + .disabled(viewModel.proxyAddress == "" || + viewModel.proxyId == "" || + viewModel.publishingIntervalInSeconds == "") + } + + } + .task { + await viewModel.initialize() + } + } +} + +/* +#Preview { + ContentView() +} +*/ diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift new file mode 100644 index 00000000..fd741f27 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift @@ -0,0 +1,98 @@ +// +// LocationShareViewModel.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import Foundation + +struct LocationShareViewModel { + private var locationManager: LocationManager + private var streamrProxyClient: StreamrProxyClient + + init() { + self.locationManager = LocationManager() + self.streamrProxyClient = StreamrProxyClient(locationManager: locationManager) + } + + @MainActor + var buttonText: String { + streamrProxyClient.status == .stopped ? "Start Sharing" : "Stop Sharing" + } + + @MainActor + var proxyAddress: String { + get { + streamrProxyClient.proxyInfo.peerAddress + } + set(newProxyAddress) { + streamrProxyClient.proxyInfo.peerAddress = newProxyAddress + } + } + + @MainActor + var proxyId: String { + get { + streamrProxyClient.proxyInfo.peerId + } + set(newProxyId) { + streamrProxyClient.proxyInfo.peerId = newProxyId + } + } + + @MainActor + var publishingIntervalInSeconds: String { + get { + print("Thread: publishingIntervalInSeconds: \(Thread.current)") + + return String(streamrProxyClient.publishingIntervalInSeconds) + } + set(newProxyId) { + streamrProxyClient.publishingIntervalInSeconds = + TimeInterval(newProxyId) ?? StreamrProxyClient.defaultPublishingIntervalInSeconds + } + } + + @MainActor + private var locationCoordinates: (latitude: String, longitude: String) { + guard let location = locationManager.location else { + return (latitude: "Unknown", longitude: "Unknown") + } + return (latitude: String(location.latitude), longitude: String(location.longitude)) + } + + @MainActor + var latitude: String { + locationCoordinates.latitude + } + + @MainActor + var longitude: String { + locationCoordinates.longitude + } + + @MainActor + func buttonClicked() { + switch(streamrProxyClient.status) { + case .stopped: + streamrProxyClient.startPublishing() + case .proxySet: + streamrProxyClient.startPublishing() + case .publishing: + streamrProxyClient.stopPublishing() + } + } + + func initialize() async { + try? await locationManager.requestUserAuthorization() + try? await locationManager.startCurrentLocationUpdates() + } + + func setProxyAndStartPublishing() { + streamrProxyClient.startPublishing() + } + + +} + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.hpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.hpp new file mode 100644 index 00000000..c1d7c0ca --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.hpp @@ -0,0 +1,18 @@ +// +// PeerDescriptor.h +// LocationShare +// +// Created by Santtu Rantanen on 25.8.2024. +// + +#ifndef PeerDescriptor_hpp +#define PeerDescriptor_hpp + +#include + +struct PeerDescriptor { + std::string peerId; + std::string peerAddress; +}; + +#endif /* PeerDescriptor_hpp */ diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.swift new file mode 100644 index 00000000..3b6b4472 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/PeerDescriptor.swift @@ -0,0 +1,13 @@ +// +// PeerDescriptor.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import Foundation + +struct PeerDesc { + var peerId: String + var peerAddress: String +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Preview Content/Preview Assets.xcassets/Contents.json b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp new file mode 100644 index 00000000..adce46a3 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp @@ -0,0 +1,33 @@ +// +// ProxyClient.cpp +// LocationShare +// +// Created by Santtu Rantanen on 25.8.2024. +// + +#include "ProxyClient.hpp" +#include "PeerDescriptor.hpp" +#include +#include +#include + +using namespace std::chrono_literals; + +int ProxyClient::newClient() const { + return 1; +} + +Result ProxyClient::deleteClient(int proxyClientHandle) const { + return Result{0, ""}; +} + +Result ProxyClient::publish(int proxyClientHandle, std::string data) const { + std::this_thread::sleep_for(1s); + return Result{0, ""}; +} + +Result ProxyClient::setProxy(int proxyClientHandle, PeerDescriptor proxy) const { + std::this_thread::sleep_for(10s); + return Result{0, ""}; +} + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp new file mode 100644 index 00000000..f46ff9b7 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp @@ -0,0 +1,23 @@ +// +// ProxyClient.hpp +// LocationShare +// +// Created by Santtu Rantanen on 25.8.2024. +// + +#ifndef ProxyClient_hpp +#define ProxyClient_hpp + +#include +#include "Result.hpp" +#include "PeerDescriptor.hpp" + +class ProxyClient { +public: + ProxyClient() { } + int newClient() const; + Result deleteClient(int proxyClientHandle) const; + Result publish(int proxyClientHandle, std::string data) const; + Result setProxy(int proxyClientHandle, PeerDescriptor proxy) const; +}; +#endif /* ProxyClient_hpp */ diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp new file mode 100644 index 00000000..10a42d10 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp @@ -0,0 +1,18 @@ +// +// Result.h +// LocationShare +// +// Created by Santtu Rantanen on 25.8.2024. +// + +#ifndef Result_hpp +#define Result_hpp + +#include + +struct Result { + int code; + std::string message; +}; + +#endif /* Result_h */ diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift new file mode 100644 index 00000000..b180ed6c --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift @@ -0,0 +1,85 @@ +// +// StreamrProxyClient.swift +// LocationShare +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import Foundation +import Combine + +@Observable +class StreamrProxyClient { + @MainActor var proxyInfo: PeerDesc = PeerDesc(peerId: "", peerAddress: "") + @MainActor var publishingIntervalInSeconds: TimeInterval = defaultPublishingIntervalInSeconds + @MainActor private(set) var status: Status = .stopped + private var cancellable: AnyCancellable? + private var locationManager: LocationManager + private var proxyClient = ProxyClient() + static var defaultPublishingIntervalInSeconds: TimeInterval = 5 + private var proxyClientHandle: Int32 = 0 + + enum Status { + case stopped + case proxySet + case publishing + } + + init(locationManager: LocationManager) { + self.locationManager = locationManager + proxyClientHandle = self.proxyClient.newClient() + } + + @MainActor + private func setProxy() async -> Result { + print("Set Proxy start") + let peerDescriptor = PeerDescriptor(peerId: "9f8wunfaiwuhfwe9a8", peerAddress: "ws://127.0.0.1:8080") + let result = await Task.detached { + self.proxyClient.setProxy(self.proxyClientHandle, peerDescriptor) + }.value + print("Set Proxy end") + return result + } + + private func publish() { + print("Set Proxy start") + Task { @MainActor in + print("Thread: publish: \(Thread.current)") + let latitude = locationManager.location?.latitude ?? 0 + let longitude = locationManager.location?.longitude ?? 0 + print("Publish: \(latitude), \(longitude)") + self.status = .publishing + } + } + + func startPublishing() { + Task { @MainActor in + print("Thread: startPublishing: \(Thread.current)") + print("startPublishing with interval: \(publishingIntervalInSeconds)") + let result = await setProxy() + if result.code == 1 { + return + } + status = .proxySet + let task = Timer.publish(every: publishingIntervalInSeconds, on: .main, in: .default).values + cancellable = Timer.publish(every: publishingIntervalInSeconds, on: .main, in: .default) + .autoconnect() + .sink { [self] _ in + publish() + } + } + } + + func stopPublishing() { + print("stopPublishing") + cancellable?.cancel() + cancellable = nil + Task { @MainActor in + status = .stopped + } + } + + +} + + diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareTests/LocationShareTests.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareTests/LocationShareTests.swift new file mode 100644 index 00000000..b3d78ced --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareTests/LocationShareTests.swift @@ -0,0 +1,36 @@ +// +// LocationShareTests.swift +// LocationShareTests +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import XCTest +@testable import LocationShare + +final class LocationShareTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITests.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITests.swift new file mode 100644 index 00000000..adef20a5 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITests.swift @@ -0,0 +1,41 @@ +// +// LocationShareUITests.swift +// LocationShareUITests +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import XCTest + +final class LocationShareUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITestsLaunchTests.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITestsLaunchTests.swift new file mode 100644 index 00000000..64991924 --- /dev/null +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShareUITests/LocationShareUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// LocationShareUITestsLaunchTests.swift +// LocationShareUITests +// +// Created by Santtu Rantanen on 23.8.2024. +// + +import XCTest + +final class LocationShareUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} From 6d024729a3dcff61b3324aeba420722375539dae Mon Sep 17 00:00:00 2001 From: Santtu Date: Mon, 26 Aug 2024 07:27:23 +0300 Subject: [PATCH 06/67] Small change for LocationShare example iOS app --- .../ios/LocationShare/LocationShare/LocationShareView.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift index 00aba9ce..a479e35c 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift @@ -22,11 +22,12 @@ struct LocationShareView: View { "Enter proxy ID", text: $viewModel.proxyId ) + } + Section(header: Text("Publishing Interval")) { TextField( - "Enter sending interval in seconds", + "Enter interval in seconds", text: $viewModel.publishingIntervalInSeconds ) - } Section(header: Text("GPS Location")) { Text("\(viewModel.latitude), \(viewModel.longitude)") From 7df38fe3631bd76c973ea0891932d409841eb50f Mon Sep 17 00:00:00 2001 From: Santtu Date: Mon, 26 Aug 2024 08:35:20 +0300 Subject: [PATCH 07/67] Some changes --- .../UserInterfaceState.xcuserstate | Bin 61402 -> 95939 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 16 ----- .../LocationShare/ProxyClient.cpp | 8 +-- .../LocationShare/ProxyClient.hpp | 10 +-- .../LocationShare/StreamrProxyClient.swift | 65 ++++++++++-------- 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate index 8a1a40f1b163a8f73029e6414ae0ea58fe73a388..49daff593f452e5a172ee8021d6d5dbc198697ea 100644 GIT binary patch literal 95939 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 J_Y?L^`!_Q8_Im&T literal 61402 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�VySDD~U9yd3bT@p7xPy~PkNzU~(kTNhXtzcZL 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 OKaoWLgi!%b5C1<1FpBvA diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 201feeda..29d2c24a 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -36,22 +36,6 @@ landmarkType = "7"> - - - - ? + @ObservationIgnored private var timerSequence = Timer + .publish(every: 1, on: .main, in: .default) + .autoconnect() + .values + enum Status { case stopped case proxySet @@ -33,7 +37,7 @@ class StreamrProxyClient { @MainActor private func setProxy() async -> Result { print("Set Proxy start") - let peerDescriptor = PeerDescriptor(peerId: "9f8wunfaiwuhfwe9a8", peerAddress: "ws://127.0.0.1:8080") + let peerDescriptor = PeerDescriptor(peerId: std.string(proxyInfo.peerId), peerAddress: std.string(proxyInfo.peerAddress)) let result = await Task.detached { self.proxyClient.setProxy(self.proxyClientHandle, peerDescriptor) }.value @@ -41,42 +45,49 @@ class StreamrProxyClient { return result } - private func publish() { - print("Set Proxy start") - Task { @MainActor in - print("Thread: publish: \(Thread.current)") - let latitude = locationManager.location?.latitude ?? 0 - let longitude = locationManager.location?.longitude ?? 0 - print("Publish: \(latitude), \(longitude)") - self.status = .publishing - } + @MainActor + private func publish() async -> Result { + print("Publish start") + let latitude = locationManager.location?.latitude ?? 0 + let longitude = locationManager.location?.longitude ?? 0 + self.status = .publishing + let result = await Task.detached { + self.proxyClient.publish(self.proxyClientHandle, std.string("\(latitude) \(longitude)")) + }.value + print("Publish end with result: \(result)") + return result } func startPublishing() { + print("startPublishing start") Task { @MainActor in - print("Thread: startPublishing: \(Thread.current)") - print("startPublishing with interval: \(publishingIntervalInSeconds)") + status = .proxySet let result = await setProxy() if result.code == 1 { + status = .stopped return } - status = .proxySet - let task = Timer.publish(every: publishingIntervalInSeconds, on: .main, in: .default).values - cancellable = Timer.publish(every: publishingIntervalInSeconds, on: .main, in: .default) - .autoconnect() - .sink { [self] _ in - publish() + timerSequence = Timer + .publish(every: publishingIntervalInSeconds, on: .main, in: .default) + .autoconnect() + .values + task = Task { + for await _ in timerSequence { + await publish() } + } } + print("startPublishing end") } func stopPublishing() { - print("stopPublishing") - cancellable?.cancel() - cancellable = nil + print("stopPublishing start") + task?.cancel() + task = nil Task { @MainActor in status = .stopped } + print("stopPublishing stop") } From 30efb8cd4dd15698e66802d3ac857d240a2d87c1 Mon Sep 17 00:00:00 2001 From: Santtu Date: Mon, 26 Aug 2024 09:41:11 +0300 Subject: [PATCH 08/67] Status added to the main view --- .../LocationShare/LocationShareView.swift | 1 + .../LocationShare/LocationShareViewModel.swift | 7 ++++++- .../ios/LocationShare/LocationShare/ProxyClient.cpp | 10 +++++----- .../ios/LocationShare/LocationShare/ProxyClient.hpp | 2 +- .../ios/LocationShare/LocationShare/Result.hpp | 3 ++- .../LocationShare/StreamrProxyClient.swift | 9 +++++---- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift index a479e35c..4759b046 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareView.swift @@ -22,6 +22,7 @@ struct LocationShareView: View { "Enter proxy ID", text: $viewModel.proxyId ) + Text(viewModel.status) } Section(header: Text("Publishing Interval")) { TextField( diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift index fd741f27..dc9197ce 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/LocationShareViewModel.swift @@ -9,12 +9,17 @@ import Foundation struct LocationShareViewModel { private var locationManager: LocationManager - private var streamrProxyClient: StreamrProxyClient + var streamrProxyClient: StreamrProxyClient init() { self.locationManager = LocationManager() self.streamrProxyClient = StreamrProxyClient(locationManager: locationManager) } + + @MainActor + var status: String { + "Status: \(streamrProxyClient.status)" + } @MainActor var buttonText: String { diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp index 3ceab227..deb21ca8 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.cpp @@ -18,16 +18,16 @@ ProxyClientHandle ProxyClient::newClient() const { } Result ProxyClient::deleteClient(ProxyClientHandle proxyClientHandle) const { - return Result{0, ""}; + return Result{Result::ResultCode::Ok, ""}; } Result ProxyClient::publish(ProxyClientHandle proxyClientHandle, std::string data) const { std::this_thread::sleep_for(1s); - return Result{0, ""}; + return Result{Result::ResultCode::Ok, ""}; } -Result ProxyClient::setProxy(ProxyClientHandle proxyClientHandle, PeerDescriptor proxy) const { - std::this_thread::sleep_for(10s); - return Result{0, ""}; +Result ProxyClient::setProxies(ProxyClientHandle proxyClientHandle, std::vector proxy) const { + std::this_thread::sleep_for(1s); + return Result{Result::ResultCode::Ok, ""}; } diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp index 91b687c2..40e30865 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/ProxyClient.hpp @@ -20,6 +20,6 @@ class ProxyClient { ProxyClientHandle newClient() const; Result deleteClient(ProxyClientHandle proxyClientHandle) const; Result publish(ProxyClientHandle proxyClientHandle, std::string data) const; - Result setProxy(ProxyClientHandle proxyClientHandle, PeerDescriptor proxy) const; + Result setProxies(ProxyClientHandle proxyClientHandle, std::vector proxy) const; }; #endif /* ProxyClient_hpp */ diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp index 10a42d10..3291a4f4 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/Result.hpp @@ -11,7 +11,8 @@ #include struct Result { - int code; + enum class ResultCode{ Ok, Error }; + ResultCode code; std::string message; }; diff --git a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift index a5b00032..630063c6 100644 --- a/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift +++ b/packages/streamr-libstreamrproxyclient/examples/ios/LocationShare/LocationShare/StreamrProxyClient.swift @@ -12,7 +12,7 @@ import Combine class StreamrProxyClient { @MainActor var proxyInfo: PeerDesc = PeerDesc(peerId: "", peerAddress: "") @MainActor var publishingIntervalInSeconds: TimeInterval = defaultPublishingIntervalInSeconds - @MainActor private(set) var status: Status = .stopped + var status: Status = .stopped private let locationManager: LocationManager private let proxyClient = ProxyClient() static let defaultPublishingIntervalInSeconds: TimeInterval = 5 @@ -39,7 +39,7 @@ class StreamrProxyClient { print("Set Proxy start") let peerDescriptor = PeerDescriptor(peerId: std.string(proxyInfo.peerId), peerAddress: std.string(proxyInfo.peerAddress)) let result = await Task.detached { - self.proxyClient.setProxy(self.proxyClientHandle, peerDescriptor) + self.proxyClient.setProxies(self.proxyClientHandle, [peerDescriptor]) }.value print("Set Proxy end") return result @@ -54,7 +54,7 @@ class StreamrProxyClient { let result = await Task.detached { self.proxyClient.publish(self.proxyClientHandle, std.string("\(latitude) \(longitude)")) }.value - print("Publish end with result: \(result)") + print("Publish end") return result } @@ -63,7 +63,7 @@ class StreamrProxyClient { Task { @MainActor in status = .proxySet let result = await setProxy() - if result.code == 1 { + if result.code == Result.ResultCode.Error { status = .stopped return } @@ -74,6 +74,7 @@ class StreamrProxyClient { task = Task { for await _ in timerSequence { await publish() + if Task.isCancelled { return } } } } From c8c05be1b9875a6b417c3de887e22e69daf7e59d Mon Sep 17 00:00:00 2001 From: Santtu Date: Fri, 30 Aug 2024 19:52:59 +0300 Subject: [PATCH 09/67] Gtest unit tests can be run in iOS device using testing app --- packages/streamr-eventemitter/test/unit/EventEmitterTest.cpp | 2 ++ packages/streamr-logger/test/unit/LoggerTest.cpp | 2 ++ packages/streamr-logger/test/unit/StreamrLogFormatterTest.cpp | 2 ++ packages/streamr-proto-rpc/test/unit/RpcCommunicatorTest.cpp | 2 ++ packages/streamr-proto-rpc/test/unit/ServerRegistryTest.cpp | 4 +++- test/ios/iOSUnitTesting | 1 + 6 files changed, 12 insertions(+), 1 deletion(-) create mode 160000 test/ios/iOSUnitTesting diff --git a/packages/streamr-eventemitter/test/unit/EventEmitterTest.cpp b/packages/streamr-eventemitter/test/unit/EventEmitterTest.cpp index 2d40ba6e..36d3d028 100644 --- a/packages/streamr-eventemitter/test/unit/EventEmitterTest.cpp +++ b/packages/streamr-eventemitter/test/unit/EventEmitterTest.cpp @@ -1,3 +1,5 @@ +#define GLOG_USE_GLOG_EXPORT + #include #include #include diff --git a/packages/streamr-logger/test/unit/LoggerTest.cpp b/packages/streamr-logger/test/unit/LoggerTest.cpp index bacc77c3..987d87b4 100644 --- a/packages/streamr-logger/test/unit/LoggerTest.cpp +++ b/packages/streamr-logger/test/unit/LoggerTest.cpp @@ -1,3 +1,5 @@ +#define GLOG_USE_GLOG_EXPORT + #include "streamr-logger/Logger.hpp" #include #include diff --git a/packages/streamr-logger/test/unit/StreamrLogFormatterTest.cpp b/packages/streamr-logger/test/unit/StreamrLogFormatterTest.cpp index a3b724a2..41abcbd2 100644 --- a/packages/streamr-logger/test/unit/StreamrLogFormatterTest.cpp +++ b/packages/streamr-logger/test/unit/StreamrLogFormatterTest.cpp @@ -1,3 +1,5 @@ +#define GLOG_USE_GLOG_EXPORT + #include #include #include diff --git a/packages/streamr-proto-rpc/test/unit/RpcCommunicatorTest.cpp b/packages/streamr-proto-rpc/test/unit/RpcCommunicatorTest.cpp index 04a7ff32..07875d4a 100644 --- a/packages/streamr-proto-rpc/test/unit/RpcCommunicatorTest.cpp +++ b/packages/streamr-proto-rpc/test/unit/RpcCommunicatorTest.cpp @@ -1,3 +1,5 @@ +#define GLOG_USE_GLOG_EXPORT + #include #include #include diff --git a/packages/streamr-proto-rpc/test/unit/ServerRegistryTest.cpp b/packages/streamr-proto-rpc/test/unit/ServerRegistryTest.cpp index b381a9fc..99f65837 100644 --- a/packages/streamr-proto-rpc/test/unit/ServerRegistryTest.cpp +++ b/packages/streamr-proto-rpc/test/unit/ServerRegistryTest.cpp @@ -1,3 +1,5 @@ +#define GLOG_USE_GLOG_EXPORT + #include #include @@ -88,4 +90,4 @@ TEST_F(ServerRegistryTest, HandleNotificationWithMissingMethodHeader) { } // namespace streamr::protorpc -// ENDNOLINT \ No newline at end of file +// ENDNOLINT diff --git a/test/ios/iOSUnitTesting b/test/ios/iOSUnitTesting new file mode 160000 index 00000000..01de1a2c --- /dev/null +++ b/test/ios/iOSUnitTesting @@ -0,0 +1 @@ +Subproject commit 01de1a2ca43d626767512d7dc6d5574c281015b0 From ee054f1480eeac3163b1b1a23fe9e21533e298dc Mon Sep 17 00:00:00 2001 From: Santtu Date: Fri, 30 Aug 2024 20:02:03 +0300 Subject: [PATCH 10/67] Gtest unit tests can be run in iOS device using testing app --- test/ios/iOSUnitTesting | 1 - .../extern/googletest/.clang-format | 4 + .../extern/googletest/BUILD.bazel | 236 + .../extern/googletest/CMakeLists.txt | 36 + .../extern/googletest/CONTRIBUTING.md | 141 + .../extern/googletest/CONTRIBUTORS | 66 + .../iOSUnitTesting/extern/googletest/LICENSE | 28 + .../extern/googletest/MODULE.bazel | 67 + .../extern/googletest/README.md | 142 + .../extern/googletest/WORKSPACE | 62 + .../extern/googletest/WORKSPACE.bzlmod | 35 + .../extern/googletest/ci/linux-presubmit.sh | 139 + .../extern/googletest/ci/macos-presubmit.sh | 77 + .../googletest/ci/windows-presubmit.bat | 63 + .../extern/googletest/docs/_config.yml | 1 + .../googletest/docs/_data/navigation.yml | 43 + .../googletest/docs/_layouts/default.html | 58 + .../extern/googletest/docs/_sass/main.scss | 200 + .../extern/googletest/docs/advanced.md | 2446 ++++++ .../googletest/docs/assets/css/style.scss | 5 + .../docs/community_created_documentation.md | 7 + .../extern/googletest/docs/faq.md | 671 ++ .../googletest/docs/gmock_cheat_sheet.md | 241 + .../extern/googletest/docs/gmock_cook_book.md | 4379 ++++++++++ .../extern/googletest/docs/gmock_faq.md | 390 + .../googletest/docs/gmock_for_dummies.md | 702 ++ .../extern/googletest/docs/index.md | 22 + .../extern/googletest/docs/pkgconfig.md | 144 + .../extern/googletest/docs/platforms.md | 8 + .../extern/googletest/docs/primer.md | 482 + .../googletest/docs/quickstart-bazel.md | 146 + .../googletest/docs/quickstart-cmake.md | 157 + .../googletest/docs/reference/actions.md | 115 + .../googletest/docs/reference/assertions.md | 633 ++ .../googletest/docs/reference/matchers.md | 302 + .../googletest/docs/reference/mocking.md | 588 ++ .../googletest/docs/reference/testing.md | 1453 +++ .../extern/googletest/docs/samples.md | 22 + .../extern/googletest/fake_fuchsia_sdk.bzl | 33 + .../googletest/googlemock/CMakeLists.txt | 210 + .../extern/googletest/googlemock/README.md | 40 + .../googletest/googlemock/cmake/gmock.pc.in | 10 + .../googlemock/cmake/gmock_main.pc.in | 10 + .../googletest/googlemock/docs/README.md | 4 + .../googlemock/include/gmock/gmock-actions.h | 2360 +++++ .../include/gmock/gmock-cardinalities.h | 159 + .../include/gmock/gmock-function-mocker.h | 519 ++ .../googlemock/include/gmock/gmock-matchers.h | 5638 ++++++++++++ .../include/gmock/gmock-more-actions.h | 660 ++ .../include/gmock/gmock-more-matchers.h | 120 + .../include/gmock/gmock-nice-strict.h | 277 + .../include/gmock/gmock-spec-builders.h | 2146 +++++ .../googlemock/include/gmock/gmock.h | 97 + .../include/gmock/internal/custom/README.md | 18 + .../internal/custom/gmock-generated-actions.h | 7 + .../gmock/internal/custom/gmock-matchers.h | 37 + .../gmock/internal/custom/gmock-port.h | 40 + .../gmock/internal/gmock-internal-utils.h | 489 ++ .../include/gmock/internal/gmock-port.h | 140 + .../include/gmock/internal/gmock-pp.h | 279 + .../googletest/googlemock/src/gmock-all.cc | 46 + .../googlemock/src/gmock-cardinalities.cc | 155 + .../googlemock/src/gmock-internal-utils.cc | 258 + .../googlemock/src/gmock-matchers.cc | 478 + .../googlemock/src/gmock-spec-builders.cc | 792 ++ .../extern/googletest/googlemock/src/gmock.cc | 225 + .../googletest/googlemock/src/gmock_main.cc | 73 + .../googletest/googlemock/test/BUILD.bazel | 118 + .../googlemock/test/gmock-actions_test.cc | 2217 +++++ .../test/gmock-cardinalities_test.cc | 424 + .../test/gmock-function-mocker_test.cc | 998 +++ .../test/gmock-internal-utils_test.cc | 766 ++ .../test/gmock-matchers-arithmetic_test.cc | 1518 ++++ .../test/gmock-matchers-comparisons_test.cc | 2373 +++++ .../test/gmock-matchers-containers_test.cc | 3148 +++++++ .../test/gmock-matchers-misc_test.cc | 1823 ++++ .../googlemock/test/gmock-matchers_test.h | 192 + .../test/gmock-more-actions_test.cc | 1588 ++++ .../googlemock/test/gmock-nice-strict_test.cc | 541 ++ .../googlemock/test/gmock-port_test.cc | 42 + .../googlemock/test/gmock-pp-string_test.cc | 205 + .../googlemock/test/gmock-pp_test.cc | 83 + .../test/gmock-spec-builders_test.cc | 2600 ++++++ .../googlemock/test/gmock_all_test.cc | 49 + .../googlemock/test/gmock_ex_test.cc | 80 + .../googlemock/test/gmock_leak_test.py | 113 + .../googlemock/test/gmock_leak_test_.cc | 99 + .../googlemock/test/gmock_link2_test.cc | 38 + .../googlemock/test/gmock_link_test.cc | 38 + .../googlemock/test/gmock_link_test.h | 693 ++ .../googlemock/test/gmock_output_test.py | 190 + .../googlemock/test/gmock_output_test_.cc | 286 + .../test/gmock_output_test_golden.txt | 335 + .../googlemock/test/gmock_stress_test.cc | 227 + .../googletest/googlemock/test/gmock_test.cc | 179 + .../googlemock/test/gmock_test_utils.py | 91 + .../googletest/googletest/CMakeLists.txt | 330 + .../extern/googletest/googletest/README.md | 231 + .../googletest/cmake/Config.cmake.in | 13 + .../googletest/googletest/cmake/gtest.pc.in | 9 + .../googletest/cmake/gtest_main.pc.in | 10 + .../googletest/cmake/internal_utils.cmake | 334 + .../googletest/cmake/libgtest.la.in | 21 + .../googletest/googletest/docs/README.md | 4 + .../include/gtest/gtest-assertion-result.h | 237 + .../include/gtest/gtest-death-test.h | 345 + .../googletest/include/gtest/gtest-matchers.h | 923 ++ .../googletest/include/gtest/gtest-message.h | 251 + .../include/gtest/gtest-param-test.h | 546 ++ .../googletest/include/gtest/gtest-printers.h | 1197 +++ .../googletest/include/gtest/gtest-spi.h | 250 + .../include/gtest/gtest-test-part.h | 192 + .../include/gtest/gtest-typed-test.h | 335 + .../googletest/include/gtest/gtest.h | 2338 +++++ .../include/gtest/gtest_pred_impl.h | 279 + .../googletest/include/gtest/gtest_prod.h | 60 + .../include/gtest/internal/custom/README.md | 44 + .../gtest/internal/custom/gtest-port.h | 37 + .../gtest/internal/custom/gtest-printers.h | 42 + .../include/gtest/internal/custom/gtest.h | 37 + .../internal/gtest-death-test-internal.h | 306 + .../include/gtest/internal/gtest-filepath.h | 233 + .../include/gtest/internal/gtest-internal.h | 1521 ++++ .../include/gtest/internal/gtest-param-util.h | 1030 +++ .../include/gtest/internal/gtest-port-arch.h | 124 + .../include/gtest/internal/gtest-port.h | 2536 ++++++ .../include/gtest/internal/gtest-string.h | 178 + .../include/gtest/internal/gtest-type-util.h | 220 + .../googletest/samples/prime_tables.h | 125 + .../googletest/googletest/samples/sample1.cc | 66 + .../googletest/googletest/samples/sample1.h | 41 + .../googletest/samples/sample10_unittest.cc | 138 + .../googletest/samples/sample1_unittest.cc | 148 + .../googletest/googletest/samples/sample2.cc | 54 + .../googletest/googletest/samples/sample2.h | 79 + .../googletest/samples/sample2_unittest.cc | 107 + .../googletest/samples/sample3-inl.h | 171 + .../googletest/samples/sample3_unittest.cc | 146 + .../googletest/googletest/samples/sample4.cc | 50 + .../googletest/googletest/samples/sample4.h | 53 + .../googletest/samples/sample4_unittest.cc | 53 + .../googletest/samples/sample5_unittest.cc | 189 + .../googletest/samples/sample6_unittest.cc | 214 + .../googletest/samples/sample7_unittest.cc | 113 + .../googletest/samples/sample8_unittest.cc | 154 + .../googletest/samples/sample9_unittest.cc | 148 + .../googletest/googletest/src/gtest-all.cc | 49 + .../googletest/src/gtest-assertion-result.cc | 77 + .../googletest/src/gtest-death-test.cc | 1587 ++++ .../googletest/src/gtest-filepath.cc | 414 + .../googletest/src/gtest-internal-inl.h | 1230 +++ .../googletest/src/gtest-matchers.cc | 98 + .../googletest/googletest/src/gtest-port.cc | 1434 +++ .../googletest/src/gtest-printers.cc | 555 ++ .../googletest/src/gtest-test-part.cc | 106 + .../googletest/src/gtest-typed-test.cc | 108 + .../extern/googletest/googletest/src/gtest.cc | 6960 +++++++++++++++ .../googletest/googletest/src/gtest_main.cc | 66 + .../googletest/googletest/test/BUILD.bazel | 595 ++ .../googletest-break-on-failure-unittest.py | 195 + .../googletest-break-on-failure-unittest_.cc | 83 + .../test/googletest-catch-exceptions-test.py | 315 + .../test/googletest-catch-exceptions-test_.cc | 289 + .../googletest/test/googletest-color-test.py | 130 + .../googletest/test/googletest-color-test_.cc | 60 + .../test/googletest-death-test-test.cc | 1512 ++++ .../test/googletest-death-test_ex_test.cc | 91 + .../test/googletest-env-var-test.py | 120 + .../test/googletest-env-var-test_.cc | 130 + .../test/googletest-failfast-unittest.py | 461 + .../test/googletest-failfast-unittest_.cc | 166 + .../test/googletest-filepath-test.cc | 671 ++ .../test/googletest-filter-unittest.py | 746 ++ .../test/googletest-filter-unittest_.cc | 106 + .../googletest-global-environment-unittest.py | 141 + ...googletest-global-environment-unittest_.cc | 58 + .../test/googletest-json-outfiles-test.py | 180 + .../test/googletest-json-output-unittest.py | 835 ++ .../test/googletest-list-tests-unittest.py | 225 + .../test/googletest-list-tests-unittest_.cc | 143 + .../test/googletest-listener-test.cc | 509 ++ .../test/googletest-message-test.cc | 184 + .../test/googletest-options-test.cc | 225 + .../googletest-output-test-golden-lin.txt | 1201 +++ .../googletest/test/googletest-output-test.py | 385 + .../test/googletest-output-test_.cc | 1058 +++ ...oogletest-param-test-invalid-name1-test.py | 63 + ...ogletest-param-test-invalid-name1-test_.cc | 46 + ...oogletest-param-test-invalid-name2-test.py | 63 + ...ogletest-param-test-invalid-name2-test_.cc | 52 + .../test/googletest-param-test-test.cc | 1173 +++ .../test/googletest-param-test-test.h | 49 + .../test/googletest-param-test2-test.cc | 58 + .../googletest/test/googletest-port-test.cc | 1301 +++ .../test/googletest-printers-test.cc | 2034 +++++ .../test/googletest-setuptestsuite-test.py | 58 + .../test/googletest-setuptestsuite-test_.cc | 44 + .../test/googletest-shuffle-test.py | 378 + .../test/googletest-shuffle-test_.cc | 99 + .../test/googletest-test-part-test.cc | 220 + .../test/googletest-throw-on-failure-test.py | 166 + .../test/googletest-throw-on-failure-test_.cc | 71 + .../test/googletest-uninitialized-test.py | 70 + .../test/googletest-uninitialized-test_.cc | 39 + .../googletest/test/gtest-typed-test2_test.cc | 39 + .../googletest/test/gtest-typed-test_test.cc | 423 + .../googletest/test/gtest-typed-test_test.h | 57 + .../test/gtest-unittest-api_test.cc | 328 + .../googletest/test/gtest_all_test.cc | 46 + .../test/gtest_assert_by_exception_test.cc | 112 + .../googletest/test/gtest_dirs_test.cc | 101 + .../googletest/test/gtest_environment_test.cc | 187 + .../googletest/test/gtest_help_test.py | 183 + .../googletest/test/gtest_help_test_.cc | 44 + .../googletest/test/gtest_json_test_utils.py | 67 + .../test/gtest_list_output_unittest.py | 289 + .../test/gtest_list_output_unittest_.cc | 77 + .../googletest/test/gtest_main_unittest.cc | 42 + .../googletest/test/gtest_no_test_unittest.cc | 54 + .../test/gtest_pred_impl_unittest.cc | 2070 +++++ .../test/gtest_premature_exit_test.cc | 128 + .../googletest/test/gtest_prod_test.cc | 56 + .../googletest/test/gtest_repeat_test.cc | 220 + .../test/gtest_skip_check_output_test.py | 60 + ...test_skip_environment_check_output_test.py | 55 + .../gtest_skip_in_environment_setup_test.cc | 50 + .../googletest/test/gtest_skip_test.cc | 51 + .../googletest/test/gtest_sole_header_test.cc | 54 + .../googletest/test/gtest_stress_test.cc | 245 + .../gtest_test_macro_stack_footprint_test.cc | 89 + .../googletest/test/gtest_test_utils.py | 262 + .../googletest/test/gtest_testbridge_test.py | 63 + .../googletest/test/gtest_testbridge_test_.cc | 42 + .../test/gtest_throw_on_failure_ex_test.cc | 90 + .../googletest/test/gtest_unittest.cc | 7775 +++++++++++++++++ .../test/gtest_xml_outfile1_test_.cc | 43 + .../test/gtest_xml_outfile2_test_.cc | 77 + .../test/gtest_xml_outfiles_test.py | 147 + .../test/gtest_xml_output_unittest.py | 472 + .../test/gtest_xml_output_unittest_.cc | 197 + .../googletest/test/gtest_xml_test_utils.py | 242 + .../googletest/googletest/test/production.cc | 35 + .../googletest/googletest/test/production.h | 55 + .../extern/googletest/googletest_deps.bzl | 28 + .../iOSUnitTesting.xcodeproj/project.pbxproj | 602 ++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 141203 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 120 + .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../iOSUnitTesting/ContentView.swift | 25 + .../Preview Assets.xcassets/Contents.json | 6 + .../iOSUnitTesting/iOSUnitTestingApp.swift | 17 + .../iOSUnitTestingTests/GTestWrapper.mm | 59 + .../iOSUnitTestingTests/GoogleTestRunner.cpp | 25 + .../iOSUnitTestingTests/GoogleTestRunner.hpp | 24 + .../iOSUnitTestingTests/gtest-all.cc | 49 + .../iOSUnitTestingTests/gtest_main.cc | 66 + .../iOSUnitTestingTests-Bridging-Header.h | 5 + .../iOSUnitTestingTests.swift | 22 + 263 files changed, 112163 insertions(+), 1 deletion(-) delete mode 160000 test/ios/iOSUnitTesting create mode 100644 test/ios/iOSUnitTesting/extern/googletest/.clang-format create mode 100644 test/ios/iOSUnitTesting/extern/googletest/BUILD.bazel create mode 100644 test/ios/iOSUnitTesting/extern/googletest/CMakeLists.txt create mode 100644 test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTING.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTORS create mode 100644 test/ios/iOSUnitTesting/extern/googletest/LICENSE create mode 100644 test/ios/iOSUnitTesting/extern/googletest/MODULE.bazel create mode 100644 test/ios/iOSUnitTesting/extern/googletest/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/WORKSPACE create mode 100644 test/ios/iOSUnitTesting/extern/googletest/WORKSPACE.bzlmod create mode 100644 test/ios/iOSUnitTesting/extern/googletest/ci/linux-presubmit.sh create mode 100644 test/ios/iOSUnitTesting/extern/googletest/ci/macos-presubmit.sh create mode 100644 test/ios/iOSUnitTesting/extern/googletest/ci/windows-presubmit.bat create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/_config.yml create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/_data/navigation.yml create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/_layouts/default.html create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/_sass/main.scss create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/advanced.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/assets/css/style.scss create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/community_created_documentation.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/faq.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cheat_sheet.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cook_book.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/gmock_faq.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/gmock_for_dummies.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/index.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/pkgconfig.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/platforms.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/primer.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-bazel.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-cmake.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/reference/actions.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/reference/assertions.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/reference/matchers.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/reference/mocking.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/reference/testing.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/docs/samples.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/fake_fuchsia_sdk.bzl create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/CMakeLists.txt create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock.pc.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock_main.pc.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/docs/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-actions.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-cardinalities.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-function-mocker.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-matchers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-more-actions.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-more-matchers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-nice-strict.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-spec-builders.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/custom/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/custom/gmock-port.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/gmock-port.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/internal/gmock-pp.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock-all.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock-cardinalities.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock-internal-utils.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock-matchers.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock-spec-builders.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/src/gmock_main.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/BUILD.bazel create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-actions_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-cardinalities_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-function-mocker_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-internal-utils_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-matchers-comparisons_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-matchers-containers_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-matchers-misc_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-matchers_test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-more-actions_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-nice-strict_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-port_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-pp-string_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-pp_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock-spec-builders_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_all_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_ex_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_leak_test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_leak_test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_link2_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_link_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_link_test.h create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_output_test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_output_test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_output_test_golden.txt create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_stress_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googlemock/test/gmock_test_utils.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/CMakeLists.txt create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/cmake/Config.cmake.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/cmake/gtest.pc.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/cmake/gtest_main.pc.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/cmake/internal_utils.cmake create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/cmake/libgtest.la.in create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/docs/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-assertion-result.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-death-test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-matchers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-message.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-param-test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-printers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-spi.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-test-part.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest-typed-test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest_pred_impl.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/gtest_prod.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/custom/README.md create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/custom/gtest-port.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/custom/gtest-printers.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/custom/gtest.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-filepath.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-internal.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-param-util.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-port-arch.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-port.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-string.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/include/gtest/internal/gtest-type-util.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/prime_tables.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample1.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample1.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample10_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample1_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample2.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample2.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample2_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample3-inl.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample3_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample4.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample4.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample4_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample5_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample6_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample7_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample8_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/samples/sample9_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-all.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-assertion-result.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-death-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-filepath.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-internal-inl.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-matchers.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-port.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-printers.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-test-part.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest-typed-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/src/gtest_main.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/BUILD.bazel create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-break-on-failure-unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-break-on-failure-unittest_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-catch-exceptions-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-catch-exceptions-test_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-color-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-color-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-death-test-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-death-test_ex_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-env-var-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-env-var-test_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-failfast-unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-failfast-unittest_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-filepath-test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-filter-unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-filter-unittest_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-global-environment-unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-global-environment-unittest_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-json-outfiles-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-json-output-unittest.py create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-list-tests-unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-list-tests-unittest_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-listener-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-message-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-options-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-output-test-golden-lin.txt create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-output-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-output-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-invalid-name1-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-invalid-name1-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-invalid-name2-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-invalid-name2-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test-test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-param-test2-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-port-test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-printers-test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-setuptestsuite-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-setuptestsuite-test_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-shuffle-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-shuffle-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-test-part-test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-throw-on-failure-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-throw-on-failure-test_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-uninitialized-test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/googletest-uninitialized-test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest-typed-test2_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest-typed-test_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest-typed-test_test.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest-unittest-api_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_all_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_assert_by_exception_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_dirs_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_environment_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_help_test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_help_test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_json_test_utils.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_list_output_unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_list_output_unittest_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_main_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_no_test_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_pred_impl_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_premature_exit_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_prod_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_repeat_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_skip_check_output_test.py create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_skip_environment_check_output_test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_skip_in_environment_setup_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_skip_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_sole_header_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_stress_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_test_macro_stack_footprint_test.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_test_utils.py create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_testbridge_test.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_testbridge_test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_unittest.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_outfile1_test_.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_outfile2_test_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_outfiles_test.py create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_output_unittest.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_output_unittest_.cc create mode 100755 test/ios/iOSUnitTesting/extern/googletest/googletest/test/gtest_xml_test_utils.py create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/production.cc create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest/test/production.h create mode 100644 test/ios/iOSUnitTesting/extern/googletest/googletest_deps.bzl create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/project.pbxproj create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/project.xcworkspace/xcuserdata/santturantanen.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj/xcuserdata/santturantanen.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/Assets.xcassets/Contents.json create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/ContentView.swift create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 test/ios/iOSUnitTesting/iOSUnitTesting/iOSUnitTestingApp.swift create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/GTestWrapper.mm create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/GoogleTestRunner.cpp create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/GoogleTestRunner.hpp create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/gtest-all.cc create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/gtest_main.cc create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/iOSUnitTestingTests-Bridging-Header.h create mode 100644 test/ios/iOSUnitTesting/iOSUnitTestingTests/iOSUnitTestingTests.swift diff --git a/test/ios/iOSUnitTesting b/test/ios/iOSUnitTesting deleted file mode 160000 index 01de1a2c..00000000 --- a/test/ios/iOSUnitTesting +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 01de1a2ca43d626767512d7dc6d5574c281015b0 diff --git a/test/ios/iOSUnitTesting/extern/googletest/.clang-format b/test/ios/iOSUnitTesting/extern/googletest/.clang-format new file mode 100644 index 00000000..5b9bfe6d --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/.clang-format @@ -0,0 +1,4 @@ +# Run manually to reformat a file: +# clang-format -i --style=file +Language: Cpp +BasedOnStyle: Google diff --git a/test/ios/iOSUnitTesting/extern/googletest/BUILD.bazel b/test/ios/iOSUnitTesting/extern/googletest/BUILD.bazel new file mode 100644 index 00000000..0306468e --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/BUILD.bazel @@ -0,0 +1,236 @@ +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Bazel Build for Google C++ Testing Framework(Google Test) + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +exports_files(["LICENSE"]) + +config_setting( + name = "qnx", + constraint_values = ["@platforms//os:qnx"], +) + +config_setting( + name = "windows", + constraint_values = ["@platforms//os:windows"], +) + +config_setting( + name = "freebsd", + constraint_values = ["@platforms//os:freebsd"], +) + +config_setting( + name = "openbsd", + constraint_values = ["@platforms//os:openbsd"], +) + +# NOTE: Fuchsia is not an officially supported platform. +config_setting( + name = "fuchsia", + constraint_values = ["@platforms//os:fuchsia"], +) + +config_setting( + name = "msvc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "msvc-cl", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "has_absl", + values = {"define": "absl=1"}, +) + +# Library that defines the FRIEND_TEST macro. +cc_library( + name = "gtest_prod", + hdrs = ["googletest/include/gtest/gtest_prod.h"], + includes = ["googletest/include"], +) + +# Google Test including Google Mock +cc_library( + name = "gtest", + srcs = glob( + include = [ + "googletest/src/*.cc", + "googletest/src/*.h", + "googletest/include/gtest/**/*.h", + "googlemock/src/*.cc", + "googlemock/include/gmock/**/*.h", + ], + exclude = [ + "googletest/src/gtest-all.cc", + "googletest/src/gtest_main.cc", + "googlemock/src/gmock-all.cc", + "googlemock/src/gmock_main.cc", + ], + ), + hdrs = glob([ + "googletest/include/gtest/*.h", + "googlemock/include/gmock/*.h", + ]), + copts = select({ + ":qnx": [], + ":windows": [], + "//conditions:default": ["-pthread"], + }), + defines = select({ + ":has_absl": ["GTEST_HAS_ABSL=1"], + "//conditions:default": [], + }), + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), + includes = [ + "googlemock", + "googlemock/include", + "googletest", + "googletest/include", + ], + linkopts = select({ + ":qnx": ["-lregex"], + ":windows": [], + ":freebsd": [ + "-lm", + "-pthread", + ], + ":openbsd": [ + "-lm", + "-pthread", + ], + "//conditions:default": ["-pthread"], + }), + deps = select({ + ":has_absl": [ + "@abseil-cpp//absl/container:flat_hash_set", + "@abseil-cpp//absl/debugging:failure_signal_handler", + "@abseil-cpp//absl/debugging:stacktrace", + "@abseil-cpp//absl/debugging:symbolize", + "@abseil-cpp//absl/flags:flag", + "@abseil-cpp//absl/flags:parse", + "@abseil-cpp//absl/flags:reflection", + "@abseil-cpp//absl/flags:usage", + "@abseil-cpp//absl/strings", + "@abseil-cpp//absl/types:any", + "@abseil-cpp//absl/types:optional", + "@abseil-cpp//absl/types:variant", + "@re2//:re2", + ], + "//conditions:default": [], + }) + select({ + # `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process, + # expects it to crash and inspects its logs with the given matcher, + # so that's why these libraries are needed. + # Otherwise, builds targeting Fuchsia would fail to compile. + ":fuchsia": [ + "@fuchsia_sdk//pkg/fdio", + "@fuchsia_sdk//pkg/syslog", + "@fuchsia_sdk//pkg/zx", + ], + "//conditions:default": [], + }), +) + +cc_library( + name = "gtest_main", + srcs = ["googlemock/src/gmock_main.cc"], + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), + deps = [":gtest"], +) + +# The following rules build samples of how to use gTest. +cc_library( + name = "gtest_sample_lib", + srcs = [ + "googletest/samples/sample1.cc", + "googletest/samples/sample2.cc", + "googletest/samples/sample4.cc", + ], + hdrs = [ + "googletest/samples/prime_tables.h", + "googletest/samples/sample1.h", + "googletest/samples/sample2.h", + "googletest/samples/sample3-inl.h", + "googletest/samples/sample4.h", + ], + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), +) + +cc_test( + name = "gtest_samples", + size = "small", + # All Samples except: + # sample9 (main) + # sample10 (main and takes a command line option and needs to be separate) + srcs = [ + "googletest/samples/sample1_unittest.cc", + "googletest/samples/sample2_unittest.cc", + "googletest/samples/sample3_unittest.cc", + "googletest/samples/sample4_unittest.cc", + "googletest/samples/sample5_unittest.cc", + "googletest/samples/sample6_unittest.cc", + "googletest/samples/sample7_unittest.cc", + "googletest/samples/sample8_unittest.cc", + ], + linkstatic = 0, + deps = [ + "gtest_sample_lib", + ":gtest_main", + ], +) + +cc_test( + name = "sample9_unittest", + size = "small", + srcs = ["googletest/samples/sample9_unittest.cc"], + deps = [":gtest"], +) + +cc_test( + name = "sample10_unittest", + size = "small", + srcs = ["googletest/samples/sample10_unittest.cc"], + deps = [":gtest"], +) diff --git a/test/ios/iOSUnitTesting/extern/googletest/CMakeLists.txt b/test/ios/iOSUnitTesting/extern/googletest/CMakeLists.txt new file mode 100644 index 00000000..512e5c3d --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/CMakeLists.txt @@ -0,0 +1,36 @@ +# Note: CMake support is community-based. The maintainers do not use CMake +# internally. + +cmake_minimum_required(VERSION 3.13) + +project(googletest-distribution) +set(GOOGLETEST_VERSION 1.15.2) + +if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX) + set(CMAKE_CXX_EXTENSIONS OFF) +endif() + +enable_testing() + +include(CMakeDependentOption) +include(GNUInstallDirs) + +# Note that googlemock target already builds googletest. +option(BUILD_GMOCK "Builds the googlemock subproject" ON) +option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON) +option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF) + +if(GTEST_HAS_ABSL) + if(NOT TARGET absl::base) + find_package(absl REQUIRED) + endif() + if(NOT TARGET re2::re2) + find_package(re2 REQUIRED) + endif() +endif() + +if(BUILD_GMOCK) + add_subdirectory( googlemock ) +else() + add_subdirectory( googletest ) +endif() diff --git a/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTING.md b/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTING.md new file mode 100644 index 00000000..ab5a47bf --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTING.md @@ -0,0 +1,141 @@ +# How to become a contributor and submit your own code + +## Contributor License Agreements + +We'd love to accept your patches! Before we can take them, we have to jump a +couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + +* If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an + [individual CLA](https://developers.google.com/open-source/cla/individual). +* If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a + [corporate CLA](https://developers.google.com/open-source/cla/corporate). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +## Are you a Googler? + +If you are a Googler, please make an attempt to submit an internal contribution +rather than a GitHub Pull Request. If you are not able to submit internally, a +PR is acceptable as an alternative. + +## Contributing A Patch + +1. Submit an issue describing your proposed change to the + [issue tracker](https://github.com/google/googletest/issues). +2. Please don't mix more than one logical change per submittal, because it + makes the history hard to follow. If you want to make a change that doesn't + have a corresponding issue in the issue tracker, please create one. +3. Also, coordinate with team members that are listed on the issue in question. + This ensures that work isn't being duplicated and communicating your plan + early also generally leads to better patches. +4. If your proposed change is accepted, and you haven't already done so, sign a + Contributor License Agreement + ([see details above](#contributor-license-agreements)). +5. Fork the desired repo, develop and test your code changes. +6. Ensure that your code adheres to the existing style in the sample to which + you are contributing. +7. Ensure that your code has an appropriate set of unit tests which all pass. +8. Submit a pull request. + +## The Google Test and Google Mock Communities + +The Google Test community exists primarily through the +[discussion group](https://groups.google.com/group/googletestframework) and the +GitHub repository. Likewise, the Google Mock community exists primarily through +their own [discussion group](https://groups.google.com/group/googlemock). You +are definitely encouraged to contribute to the discussion and you can also help +us to keep the effectiveness of the group high by following and promoting the +guidelines listed here. + +### Please Be Friendly + +Showing courtesy and respect to others is a vital part of the Google culture, +and we strongly encourage everyone participating in Google Test development to +join us in accepting nothing less. Of course, being courteous is not the same as +failing to constructively disagree with each other, but it does mean that we +should be respectful of each other when enumerating the 42 technical reasons +that a particular proposal may not be the best choice. There's never a reason to +be antagonistic or dismissive toward anyone who is sincerely trying to +contribute to a discussion. + +Sure, C++ testing is serious business and all that, but it's also a lot of fun. +Let's keep it that way. Let's strive to be one of the friendliest communities in +all of open source. + +As always, discuss Google Test in the official GoogleTest discussion group. You +don't have to actually submit code in order to sign up. Your participation +itself is a valuable contribution. + +## Style + +To keep the source consistent, readable, diffable and easy to merge, we use a +fairly rigid coding style, as defined by the +[google-styleguide](https://github.com/google/styleguide) project. All patches +will be expected to conform to the style outlined +[here](https://google.github.io/styleguide/cppguide.html). Use +[.clang-format](https://github.com/google/googletest/blob/main/.clang-format) to +check your formatting. + +## Requirements for Contributors + +If you plan to contribute a patch, you need to build Google Test, Google Mock, +and their own tests from a git checkout, which has further requirements: + +* [Python](https://www.python.org/) v3.6 or newer (for running some of the + tests and re-generating certain source files from templates) +* [CMake](https://cmake.org/) v2.8.12 or newer + +## Developing Google Test and Google Mock + +This section discusses how to make your own changes to the Google Test project. + +### Testing Google Test and Google Mock Themselves + +To make sure your changes work as intended and don't break existing +functionality, you'll want to compile and run Google Test and GoogleMock's own +tests. For that you can use CMake: + +``` +mkdir mybuild +cd mybuild +cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR} +``` + +To choose between building only Google Test or Google Mock, you may modify your +cmake command to be one of each + +``` +cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests +cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests +``` + +Make sure you have Python installed, as some of Google Test's tests are written +in Python. If the cmake command complains about not being able to find Python +(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it +explicitly where your Python executable can be found: + +``` +cmake -DPYTHON_EXECUTABLE=path/to/python ... +``` + +Next, you can build Google Test and / or Google Mock and all desired tests. On +\*nix, this is usually done by + +``` +make +``` + +To run the tests, do + +``` +make test +``` + +All tests should pass. diff --git a/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTORS b/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTORS new file mode 100644 index 00000000..ccea41ea --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/CONTRIBUTORS @@ -0,0 +1,66 @@ +# This file contains a list of people who've made non-trivial +# contribution to the Google C++ Testing Framework project. People +# who commit code to the project are encouraged to add their names +# here. Please keep the list sorted by first names. + +Ajay Joshi +Balázs Dán +Benoit Sigoure +Bharat Mediratta +Bogdan Piloca +Chandler Carruth +Chris Prince +Chris Taylor +Dan Egnor +Dave MacLachlan +David Anderson +Dean Sturtevant +Eric Roman +Gene Volovich +Hady Zalek +Hal Burch +Jeffrey Yasskin +Jim Keller +Joe Walnes +Jon Wray +Jói Sigurðsson +Keir Mierle +Keith Ray +Kenton Varda +Kostya Serebryany +Krystian Kuzniarek +Lev Makhlis +Manuel Klimek +Mario Tanev +Mark Paskin +Markus Heule +Martijn Vels +Matthew Simmons +Mika Raento +Mike Bland +Miklós Fazekas +Neal Norwitz +Nermin Ozkiranartli +Owen Carlsen +Paneendra Ba +Pasi Valminen +Patrick Hanna +Patrick Riley +Paul Menage +Peter Kaminski +Piotr Kaminski +Preston Jackson +Rainer Klaffenboeck +Russ Cox +Russ Rufer +Sean Mcafee +Sigurður Ásgeirsson +Soyeon Kim +Sverre Sundsdal +Szymon Sobik +Takeshi Yoshino +Tracy Bialik +Vadim Berman +Vlad Losev +Wolfgang Klier +Zhanyong Wan diff --git a/test/ios/iOSUnitTesting/extern/googletest/LICENSE b/test/ios/iOSUnitTesting/extern/googletest/LICENSE new file mode 100644 index 00000000..1941a11f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/ios/iOSUnitTesting/extern/googletest/MODULE.bazel b/test/ios/iOSUnitTesting/extern/googletest/MODULE.bazel new file mode 100644 index 00000000..c9a52e05 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/MODULE.bazel @@ -0,0 +1,67 @@ +# Copyright 2024 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# https://bazel.build/external/overview#bzlmod + +module( + name = "googletest", + version = "head", + compatibility_level = 1, +) + +# Only direct dependencies need to be listed below. +# Please keep the versions in sync with the versions in the WORKSPACE file. + +bazel_dep(name = "abseil-cpp", + version = "20240116.2") + +bazel_dep(name = "platforms", + version = "0.0.10") + +bazel_dep(name = "re2", + version = "2024-07-02") + +bazel_dep(name = "rules_python", + version = "0.34.0", + dev_dependency = True) + +# https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage +python = use_extension( + "@rules_python//python/extensions:python.bzl", + "python", + dev_dependency = True +) + +python.toolchain(python_version = "3.12", + is_default = True, + ignore_root_user_error = True) + +fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk") +fake_fuchsia_sdk(name = "fuchsia_sdk") diff --git a/test/ios/iOSUnitTesting/extern/googletest/README.md b/test/ios/iOSUnitTesting/extern/googletest/README.md new file mode 100644 index 00000000..03c70a1e --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/README.md @@ -0,0 +1,142 @@ +# GoogleTest + +### Announcements + +#### Live at Head + +GoogleTest now follows the +[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support). +We recommend +[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it). +We do publish occasional semantic versions, tagged with +`v${major}.${minor}.${patch}` (e.g. `v1.15.2`). + +#### Documentation Updates + +Our documentation is now live on GitHub Pages at +https://google.github.io/googletest/. We recommend browsing the documentation on +GitHub Pages rather than directly in the repository. + +#### Release 1.15.2 + +[Release 1.15.2](https://github.com/google/googletest/releases/tag/v1.15.2) is +now available. + +The 1.15.x branch requires at least C++14. + +#### Continuous Integration + +We use Google's internal systems for continuous integration. + +#### Coming Soon + +* We are planning to take a dependency on + [Abseil](https://github.com/abseil/abseil-cpp). + +## Welcome to **GoogleTest**, Google's C++ test framework! + +This repository is a merger of the formerly separate GoogleTest and GoogleMock +projects. These were so closely related that it makes sense to maintain and +release them together. + +### Getting Started + +See the [GoogleTest User's Guide](https://google.github.io/googletest/) for +documentation. We recommend starting with the +[GoogleTest Primer](https://google.github.io/googletest/primer.html). + +More information about building GoogleTest can be found at +[googletest/README.md](googletest/README.md). + +## Features + +* xUnit test framework: \ + Googletest is based on the [xUnit](https://en.wikipedia.org/wiki/XUnit) + testing framework, a popular architecture for unit testing +* Test discovery: \ + Googletest automatically discovers and runs your tests, eliminating the need + to manually register your tests +* Rich set of assertions: \ + Googletest provides a variety of assertions, such as equality, inequality, + exceptions, and more, making it easy to test your code +* User-defined assertions: \ + You can define your own assertions with Googletest, making it simple to + write tests that are specific to your code +* Death tests: \ + Googletest supports death tests, which verify that your code exits in a + certain way, making it useful for testing error-handling code +* Fatal and non-fatal failures: \ + You can specify whether a test failure should be treated as fatal or + non-fatal with Googletest, allowing tests to continue running even if a + failure occurs +* Value-parameterized tests: \ + Googletest supports value-parameterized tests, which run multiple times with + different input values, making it useful for testing functions that take + different inputs +* Type-parameterized tests: \ + Googletest also supports type-parameterized tests, which run with different + data types, making it useful for testing functions that work with different + data types +* Various options for running tests: \ + Googletest provides many options for running tests including running + individual tests, running tests in a specific order and running tests in + parallel + +## Supported Platforms + +GoogleTest follows Google's +[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support). +See +[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) +for a list of currently supported versions of compilers, platforms, and build +tools. + +## Who Is Using GoogleTest? + +In addition to many internal projects at Google, GoogleTest is also used by the +following notable projects: + +* The [Chromium projects](https://www.chromium.org/) (behind the Chrome + browser and Chrome OS). +* The [LLVM](https://llvm.org/) compiler. +* [Protocol Buffers](https://github.com/google/protobuf), Google's data + interchange format. +* The [OpenCV](https://opencv.org/) computer vision library. + +## Related Open Source Projects + +[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based +automated test-runner and Graphical User Interface with powerful features for +Windows and Linux platforms. + +[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that +runs your test binary, allows you to track its progress via a progress bar, and +displays a list of test failures. Clicking on one shows failure text. GoogleTest +UI is written in C#. + +[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event +listener for GoogleTest that implements the +[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test +result output. If your test runner understands TAP, you may find it useful. + +[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that +runs tests from your binary in parallel to provide significant speed-up. + +[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter) +is a VS Code extension allowing to view GoogleTest in a tree view and run/debug +your tests. + +[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS +Code extension allowing to view GoogleTest in a tree view and run/debug your +tests. + +[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser +that generates stub code for GoogleTest. + +## Contributing Changes + +Please read +[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md) +for details on how to contribute to this project. + +Happy testing! diff --git a/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE b/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE new file mode 100644 index 00000000..63f76813 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE @@ -0,0 +1,62 @@ +# Copyright 2024 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +workspace(name = "googletest") + +load("//:googletest_deps.bzl", "googletest_deps") +googletest_deps() + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_python", + sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580", + strip_prefix = "rules_python-0.29.0", + urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.0.tar.gz"], +) + +# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0 +load("@rules_python//python:repositories.bzl", "py_repositories") +py_repositories() + +http_archive( + name = "bazel_skylib", + sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", + urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"], +) + +http_archive( + name = "platforms", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", + ], + sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee", +) diff --git a/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE.bzlmod b/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE.bzlmod new file mode 100644 index 00000000..381432c5 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/WORKSPACE.bzlmod @@ -0,0 +1,35 @@ +# Copyright 2024 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# https://bazel.build/external/migration#workspace.bzlmod +# +# This file is intentionally empty. When bzlmod is enabled and this +# file exists, the content of WORKSPACE is ignored. This prevents +# bzlmod builds from unintentionally depending on the WORKSPACE file. diff --git a/test/ios/iOSUnitTesting/extern/googletest/ci/linux-presubmit.sh b/test/ios/iOSUnitTesting/extern/googletest/ci/linux-presubmit.sh new file mode 100644 index 00000000..6d2b3fb5 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/ci/linux-presubmit.sh @@ -0,0 +1,139 @@ +#!/bin/bash +# +# Copyright 2020, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -euox pipefail + +readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523" +readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120" + +if [[ -z ${GTEST_ROOT:-} ]]; then + GTEST_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [[ -z ${STD:-} ]]; then + STD="c++14 c++17 c++20" +fi + +# Test the CMake build +for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do + for cmake_off_on in OFF ON; do + time docker run \ + --volume="${GTEST_ROOT}:/src:ro" \ + --tmpfs="/build:exec" \ + --workdir="/build" \ + --rm \ + --env="CC=${cc}" \ + --env=CXXFLAGS="-Werror -Wdeprecated" \ + ${LINUX_LATEST_CONTAINER} \ + /bin/bash -c " + cmake /src \ + -DCMAKE_CXX_STANDARD=14 \ + -Dgtest_build_samples=ON \ + -Dgtest_build_tests=ON \ + -Dgmock_build_tests=ON \ + -Dcxx_no_exception=${cmake_off_on} \ + -Dcxx_no_rtti=${cmake_off_on} && \ + make -j$(nproc) && \ + ctest -j$(nproc) --output-on-failure" + done +done + +# Do one test with an older version of GCC +# TODO(googletest-team): This currently uses Bazel 5. When upgrading to a +# version of Bazel that supports Bzlmod, add --enable_bzlmod=false to keep test +# coverage for the old WORKSPACE dependency management. +time docker run \ + --volume="${GTEST_ROOT}:/src:ro" \ + --workdir="/src" \ + --rm \ + --env="CC=/usr/local/bin/gcc" \ + --env="BAZEL_CXXOPTS=-std=c++14" \ + ${LINUX_GCC_FLOOR_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --copt="-Wall" \ + --copt="-Werror" \ + --copt="-Wuninitialized" \ + --copt="-Wundef" \ + --copt="-Wno-error=pragmas" \ + --features=external_include_paths \ + --keep_going \ + --show_timestamps \ + --test_output=errors + +# Test GCC +for std in ${STD}; do + for absl in 0 1; do + time docker run \ + --volume="${GTEST_ROOT}:/src:ro" \ + --workdir="/src" \ + --rm \ + --env="CC=/usr/local/bin/gcc" \ + --env="BAZEL_CXXOPTS=-std=${std}" \ + ${LINUX_LATEST_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --copt="-Wall" \ + --copt="-Werror" \ + --copt="-Wuninitialized" \ + --copt="-Wundef" \ + --define="absl=${absl}" \ + --enable_bzlmod=true \ + --features=external_include_paths \ + --keep_going \ + --show_timestamps \ + --test_output=errors + done +done + +# Test Clang +for std in ${STD}; do + for absl in 0 1; do + time docker run \ + --volume="${GTEST_ROOT}:/src:ro" \ + --workdir="/src" \ + --rm \ + --env="CC=/opt/llvm/clang/bin/clang" \ + --env="BAZEL_CXXOPTS=-std=${std}" \ + ${LINUX_LATEST_CONTAINER} \ + /usr/local/bin/bazel test ... \ + --copt="--gcc-toolchain=/usr/local" \ + --copt="-Wall" \ + --copt="-Werror" \ + --copt="-Wuninitialized" \ + --copt="-Wundef" \ + --define="absl=${absl}" \ + --enable_bzlmod=true \ + --features=external_include_paths \ + --keep_going \ + --linkopt="--gcc-toolchain=/usr/local" \ + --show_timestamps \ + --test_output=errors + done +done diff --git a/test/ios/iOSUnitTesting/extern/googletest/ci/macos-presubmit.sh b/test/ios/iOSUnitTesting/extern/googletest/ci/macos-presubmit.sh new file mode 100644 index 00000000..70eaa74f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/ci/macos-presubmit.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# +# Copyright 2020, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -euox pipefail + +if [[ -z ${GTEST_ROOT:-} ]]; then + GTEST_ROOT="$(realpath $(dirname ${0})/..)" +fi + +# Test the CMake build +for cmake_off_on in OFF ON; do + BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX) + cd ${BUILD_DIR} + time cmake ${GTEST_ROOT} \ + -DCMAKE_CXX_STANDARD=14 \ + -Dgtest_build_samples=ON \ + -Dgtest_build_tests=ON \ + -Dgmock_build_tests=ON \ + -Dcxx_no_exception=${cmake_off_on} \ + -Dcxx_no_rtti=${cmake_off_on} + time make + time ctest -j$(nproc) --output-on-failure +done + +# Test the Bazel build + +# If we are running on Kokoro, check for a versioned Bazel binary. +KOKORO_GFILE_BAZEL_BIN="bazel-7.0.0-darwin-x86_64" +if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then + BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" + chmod +x ${BAZEL_BIN} +else + BAZEL_BIN="bazel" +fi + +cd ${GTEST_ROOT} +for absl in 0 1; do + ${BAZEL_BIN} test ... \ + --copt="-Wall" \ + --copt="-Werror" \ + --copt="-Wundef" \ + --cxxopt="-std=c++14" \ + --define="absl=${absl}" \ + --enable_bzlmod=true \ + --features=external_include_paths \ + --keep_going \ + --show_timestamps \ + --test_output=errors +done diff --git a/test/ios/iOSUnitTesting/extern/googletest/ci/windows-presubmit.bat b/test/ios/iOSUnitTesting/extern/googletest/ci/windows-presubmit.bat new file mode 100644 index 00000000..1adc1a16 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/ci/windows-presubmit.bat @@ -0,0 +1,63 @@ +SETLOCAL ENABLEDELAYEDEXPANSION + +SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe + +SET PATH=C:\Python34;%PATH% +SET BAZEL_PYTHON=C:\python34\python.exe +SET BAZEL_SH=C:\tools\msys64\usr\bin\bash.exe +SET CMAKE_BIN="cmake.exe" +SET CTEST_BIN="ctest.exe" +SET CTEST_OUTPUT_ON_FAILURE=1 +SET CMAKE_BUILD_PARALLEL_LEVEL=16 +SET CTEST_PARALLEL_LEVEL=16 + +IF EXIST git\googletest ( + CD git\googletest +) ELSE IF EXIST github\googletest ( + CD github\googletest +) + +IF %errorlevel% neq 0 EXIT /B 1 + +:: ---------------------------------------------------------------------------- +:: CMake +MKDIR cmake_msvc2022 +CD cmake_msvc2022 + +%CMAKE_BIN% .. ^ + -G "Visual Studio 17 2022" ^ + -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^ + -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^ + -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^ + -Dgtest_build_samples=ON ^ + -Dgtest_build_tests=ON ^ + -Dgmock_build_tests=ON +IF %errorlevel% neq 0 EXIT /B 1 + +%CMAKE_BIN% --build . --target ALL_BUILD --config Debug -- -maxcpucount +IF %errorlevel% neq 0 EXIT /B 1 + +%CTEST_BIN% -C Debug --timeout 600 +IF %errorlevel% neq 0 EXIT /B 1 + +CD .. +RMDIR /S /Q cmake_msvc2022 + +:: ---------------------------------------------------------------------------- +:: Bazel + +:: The default home directory on Kokoro is a long path which causes errors +:: because of Windows limitations on path length. +:: --output_user_root=C:\tmp causes Bazel to use a shorter path. +SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community +%BAZEL_EXE% ^ + --output_user_root=C:\tmp ^ + test ... ^ + --compilation_mode=dbg ^ + --copt=/std:c++14 ^ + --copt=/WX ^ + --enable_bzlmod=true ^ + --keep_going ^ + --test_output=errors ^ + --test_tag_filters=-no_test_msvc2017 +IF %errorlevel% neq 0 EXIT /B 1 diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/_config.yml b/test/ios/iOSUnitTesting/extern/googletest/docs/_config.yml new file mode 100644 index 00000000..d12867ea --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/_config.yml @@ -0,0 +1 @@ +title: GoogleTest diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/_data/navigation.yml b/test/ios/iOSUnitTesting/extern/googletest/docs/_data/navigation.yml new file mode 100644 index 00000000..9f333270 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/_data/navigation.yml @@ -0,0 +1,43 @@ +nav: +- section: "Get Started" + items: + - title: "Supported Platforms" + url: "/platforms.html" + - title: "Quickstart: Bazel" + url: "/quickstart-bazel.html" + - title: "Quickstart: CMake" + url: "/quickstart-cmake.html" +- section: "Guides" + items: + - title: "GoogleTest Primer" + url: "/primer.html" + - title: "Advanced Topics" + url: "/advanced.html" + - title: "Mocking for Dummies" + url: "/gmock_for_dummies.html" + - title: "Mocking Cookbook" + url: "/gmock_cook_book.html" + - title: "Mocking Cheat Sheet" + url: "/gmock_cheat_sheet.html" +- section: "References" + items: + - title: "Testing Reference" + url: "/reference/testing.html" + - title: "Mocking Reference" + url: "/reference/mocking.html" + - title: "Assertions" + url: "/reference/assertions.html" + - title: "Matchers" + url: "/reference/matchers.html" + - title: "Actions" + url: "/reference/actions.html" + - title: "Testing FAQ" + url: "/faq.html" + - title: "Mocking FAQ" + url: "/gmock_faq.html" + - title: "Code Samples" + url: "/samples.html" + - title: "Using pkg-config" + url: "/pkgconfig.html" + - title: "Community Documentation" + url: "/community_created_documentation.html" diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/_layouts/default.html b/test/ios/iOSUnitTesting/extern/googletest/docs/_layouts/default.html new file mode 100644 index 00000000..c7f331b8 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/_layouts/default.html @@ -0,0 +1,58 @@ + + + + + + + +{% seo %} + + + + + + +
+
+ {{ content }} +
+ +
+ + + + diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/_sass/main.scss b/test/ios/iOSUnitTesting/extern/googletest/docs/_sass/main.scss new file mode 100644 index 00000000..92edc877 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/_sass/main.scss @@ -0,0 +1,200 @@ +// Styles for GoogleTest docs website on GitHub Pages. +// Color variables are defined in +// https://github.com/pages-themes/primer/tree/master/_sass/primer-support/lib/variables + +$sidebar-width: 260px; + +body { + display: flex; + margin: 0; +} + +.sidebar { + background: $black; + color: $text-white; + flex-shrink: 0; + height: 100vh; + overflow: auto; + position: sticky; + top: 0; + width: $sidebar-width; +} + +.sidebar h1 { + font-size: 1.5em; +} + +.sidebar h2 { + color: $gray-light; + font-size: 0.8em; + font-weight: normal; + margin-bottom: 0.8em; + padding-left: 2.5em; + text-transform: uppercase; +} + +.sidebar .header { + background: $black; + padding: 2em; + position: sticky; + top: 0; + width: 100%; +} + +.sidebar .header a { + color: $text-white; + text-decoration: none; +} + +.sidebar .nav-toggle { + display: none; +} + +.sidebar .expander { + cursor: pointer; + display: none; + height: 3em; + position: absolute; + right: 1em; + top: 1.5em; + width: 3em; +} + +.sidebar .expander .arrow { + border: solid $white; + border-width: 0 3px 3px 0; + display: block; + height: 0.7em; + margin: 1em auto; + transform: rotate(45deg); + transition: transform 0.5s; + width: 0.7em; +} + +.sidebar nav { + width: 100%; +} + +.sidebar nav ul { + list-style-type: none; + margin-bottom: 1em; + padding: 0; + + &:last-child { + margin-bottom: 2em; + } + + a { + text-decoration: none; + } + + li { + color: $text-white; + padding-left: 2em; + text-decoration: none; + } + + li.active { + background: $border-gray-darker; + font-weight: bold; + } + + li:hover { + background: $border-gray-darker; + } +} + +.main { + background-color: $bg-gray; + width: calc(100% - #{$sidebar-width}); +} + +.main .main-inner { + background-color: $white; + padding: 2em; +} + +.main .footer { + margin: 0; + padding: 2em; +} + +.main table th { + text-align: left; +} + +.main .callout { + border-left: 0.25em solid $white; + padding: 1em; + + a { + text-decoration: underline; + } + + &.important { + background-color: $bg-yellow-light; + border-color: $bg-yellow; + color: $black; + } + + &.note { + background-color: $bg-blue-light; + border-color: $text-blue; + color: $text-blue; + } + + &.tip { + background-color: $green-000; + border-color: $green-700; + color: $green-700; + } + + &.warning { + background-color: $red-000; + border-color: $text-red; + color: $text-red; + } +} + +.main .good pre { + background-color: $bg-green-light; +} + +.main .bad pre { + background-color: $red-000; +} + +@media all and (max-width: 768px) { + body { + flex-direction: column; + } + + .sidebar { + height: auto; + position: relative; + width: 100%; + } + + .sidebar .expander { + display: block; + } + + .sidebar nav { + height: 0; + overflow: hidden; + } + + .sidebar .nav-toggle:checked { + & ~ nav { + height: auto; + } + + & + .expander .arrow { + transform: rotate(-135deg); + } + } + + .main { + width: 100%; + } +} diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/advanced.md b/test/ios/iOSUnitTesting/extern/googletest/docs/advanced.md new file mode 100644 index 00000000..240588a8 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/advanced.md @@ -0,0 +1,2446 @@ +# Advanced GoogleTest Topics + +## Introduction + +Now that you have read the [GoogleTest Primer](primer.md) and learned how to +write tests using GoogleTest, it's time to learn some new tricks. This document +will show you more assertions as well as how to construct complex failure +messages, propagate fatal failures, reuse and speed up your test fixtures, and +use various flags with your tests. + +## More Assertions + +This section covers some less frequently used, but still significant, +assertions. + +### Explicit Success and Failure + +See [Explicit Success and Failure](reference/assertions.md#success-failure) in +the Assertions Reference. + +### Exception Assertions + +See [Exception Assertions](reference/assertions.md#exceptions) in the Assertions +Reference. + +### Predicate Assertions for Better Error Messages + +Even though GoogleTest has a rich set of assertions, they can never be complete, +as it's impossible (nor a good idea) to anticipate all scenarios a user might +run into. Therefore, sometimes a user has to use `EXPECT_TRUE()` to check a +complex expression, for lack of a better macro. This has the problem of not +showing you the values of the parts of the expression, making it hard to +understand what went wrong. As a workaround, some users choose to construct the +failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this +is awkward especially when the expression has side-effects or is expensive to +evaluate. + +GoogleTest gives you three different options to solve this problem: + +#### Using an Existing Boolean Function + +If you already have a function or functor that returns `bool` (or a type that +can be implicitly converted to `bool`), you can use it in a *predicate +assertion* to get the function arguments printed for free. See +[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the Assertions +Reference for details. + +#### Using a Function That Returns an AssertionResult + +While `EXPECT_PRED*()` and friends are handy for a quick job, the syntax is not +satisfactory: you have to use different macros for different arities, and it +feels more like Lisp than C++. The `::testing::AssertionResult` class solves +this problem. + +An `AssertionResult` object represents the result of an assertion (whether it's +a success or a failure, and an associated message). You can create an +`AssertionResult` using one of these factory functions: + +```c++ +namespace testing { + +// Returns an AssertionResult object to indicate that an assertion has +// succeeded. +AssertionResult AssertionSuccess(); + +// Returns an AssertionResult object to indicate that an assertion has +// failed. +AssertionResult AssertionFailure(); + +} +``` + +You can then use the `<<` operator to stream messages to the `AssertionResult` +object. + +To provide more readable messages in Boolean assertions (e.g. `EXPECT_TRUE()`), +write a predicate function that returns `AssertionResult` instead of `bool`. For +example, if you define `IsEven()` as: + +```c++ +testing::AssertionResult IsEven(int n) { + if ((n % 2) == 0) + return testing::AssertionSuccess(); + else + return testing::AssertionFailure() << n << " is odd"; +} +``` + +instead of: + +```c++ +bool IsEven(int n) { + return (n % 2) == 0; +} +``` + +the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print: + +```none +Value of: IsEven(Fib(4)) + Actual: false (3 is odd) +Expected: true +``` + +instead of a more opaque + +```none +Value of: IsEven(Fib(4)) + Actual: false +Expected: true +``` + +If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE` as well +(one third of Boolean assertions in the Google code base are negative ones), and +are fine with making the predicate slower in the success case, you can supply a +success message: + +```c++ +testing::AssertionResult IsEven(int n) { + if ((n % 2) == 0) + return testing::AssertionSuccess() << n << " is even"; + else + return testing::AssertionFailure() << n << " is odd"; +} +``` + +Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print + +```none + Value of: IsEven(Fib(6)) + Actual: true (8 is even) + Expected: false +``` + +#### Using a Predicate-Formatter + +If you find the default message generated by +[`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) and +[`EXPECT_TRUE`](reference/assertions.md#EXPECT_TRUE) unsatisfactory, or some +arguments to your predicate do not support streaming to `ostream`, you can +instead use *predicate-formatter assertions* to *fully* customize how the +message is formatted. See +[`EXPECT_PRED_FORMAT*`](reference/assertions.md#EXPECT_PRED_FORMAT) in the +Assertions Reference for details. + +### Floating-Point Comparison + +See [Floating-Point Comparison](reference/assertions.md#floating-point) in the +Assertions Reference. + +#### Floating-Point Predicate-Format Functions + +Some floating-point operations are useful, but not that often used. In order to +avoid an explosion of new macros, we provide them as predicate-format functions +that can be used in the predicate assertion macro +[`EXPECT_PRED_FORMAT2`](reference/assertions.md#EXPECT_PRED_FORMAT), for +example: + +```c++ +using ::testing::FloatLE; +using ::testing::DoubleLE; +... +EXPECT_PRED_FORMAT2(FloatLE, val1, val2); +EXPECT_PRED_FORMAT2(DoubleLE, val1, val2); +``` + +The above code verifies that `val1` is less than, or approximately equal to, +`val2`. + +### Asserting Using gMock Matchers + +See [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) in the Assertions +Reference. + +### More String Assertions + +(Please read the [previous](#asserting-using-gmock-matchers) section first if +you haven't.) + +You can use the gMock [string matchers](reference/matchers.md#string-matchers) +with [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) to do more string +comparison tricks (sub-string, prefix, suffix, regular expression, and etc). For +example, + +```c++ +using ::testing::HasSubstr; +using ::testing::MatchesRegex; +... + ASSERT_THAT(foo_string, HasSubstr("needle")); + EXPECT_THAT(bar_string, MatchesRegex("\\w*\\d+")); +``` + +### Windows HRESULT assertions + +See [Windows HRESULT Assertions](reference/assertions.md#HRESULT) in the +Assertions Reference. + +### Type Assertions + +You can call the function + +```c++ +::testing::StaticAssertTypeEq(); +``` + +to assert that types `T1` and `T2` are the same. The function does nothing if +the assertion is satisfied. If the types are different, the function call will +fail to compile, the compiler error message will say that `T1 and T2 are not the +same type` and most likely (depending on the compiler) show you the actual +values of `T1` and `T2`. This is mainly useful inside template code. + +**Caveat**: When used inside a member function of a class template or a function +template, `StaticAssertTypeEq()` is effective only if the function is +instantiated. For example, given: + +```c++ +template class Foo { + public: + void Bar() { testing::StaticAssertTypeEq(); } +}; +``` + +the code: + +```c++ +void Test1() { Foo foo; } +``` + +will not generate a compiler error, as `Foo::Bar()` is never actually +instantiated. Instead, you need: + +```c++ +void Test2() { Foo foo; foo.Bar(); } +``` + +to cause a compiler error. + +### Assertion Placement + +You can use assertions in any C++ function. In particular, it doesn't have to be +a method of the test fixture class. The one constraint is that assertions that +generate a fatal failure (`FAIL*` and `ASSERT_*`) can only be used in +void-returning functions. This is a consequence of Google's not using +exceptions. By placing it in a non-void function you'll get a confusing compile +error like `"error: void value not ignored as it ought to be"` or `"cannot +initialize return object of type 'bool' with an rvalue of type 'void'"` or +`"error: no viable conversion from 'void' to 'string'"`. + +If you need to use fatal assertions in a function that returns non-void, one +option is to make the function return the value in an out parameter instead. For +example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You +need to make sure that `*result` contains some sensible value even when the +function returns prematurely. As the function now returns `void`, you can use +any assertion inside of it. + +If changing the function's type is not an option, you should just use assertions +that generate non-fatal failures, such as `ADD_FAILURE*` and `EXPECT_*`. + +{: .callout .note} +NOTE: Constructors and destructors are not considered void-returning functions, +according to the C++ language specification, and so you may not use fatal +assertions in them; you'll get a compilation error if you try. Instead, either +call `abort` and crash the entire test executable, or put the fatal assertion in +a `SetUp`/`TearDown` function; see +[constructor/destructor vs. `SetUp`/`TearDown`](faq.md#CtorVsSetUp) + +{: .callout .warning} +WARNING: A fatal assertion in a helper function (private void-returning method) +called from a constructor or destructor does not terminate the current test, as +your intuition might suggest: it merely returns from the constructor or +destructor early, possibly leaving your object in a partially-constructed or +partially-destructed state! You almost certainly want to `abort` or use +`SetUp`/`TearDown` instead. + +## Skipping test execution + +Related to the assertions `SUCCEED()` and `FAIL()`, you can prevent further test +execution at runtime with the `GTEST_SKIP()` macro. This is useful when you need +to check for preconditions of the system under test during runtime and skip +tests in a meaningful way. + +`GTEST_SKIP()` can be used in individual test cases or in the `SetUp()` methods +of classes derived from either `::testing::Environment` or `::testing::Test`. +For example: + +```c++ +TEST(SkipTest, DoesSkip) { + GTEST_SKIP() << "Skipping single test"; + EXPECT_EQ(0, 1); // Won't fail; it won't be executed +} + +class SkipFixture : public ::testing::Test { + protected: + void SetUp() override { + GTEST_SKIP() << "Skipping all tests for this fixture"; + } +}; + +// Tests for SkipFixture won't be executed. +TEST_F(SkipFixture, SkipsOneTest) { + EXPECT_EQ(5, 7); // Won't fail +} +``` + +As with assertion macros, you can stream a custom message into `GTEST_SKIP()`. + +## Teaching GoogleTest How to Print Your Values + +When a test assertion such as `EXPECT_EQ` fails, GoogleTest prints the argument +values to help you debug. It does this using a user-extensible value printer. + +This printer knows how to print built-in C++ types, native arrays, STL +containers, and any type that supports the `<<` operator. For other types, it +prints the raw bytes in the value and hopes that you the user can figure it out. + +As mentioned earlier, the printer is *extensible*. That means you can teach it +to do a better job at printing your particular type than to dump the bytes. To +do that, define an `AbslStringify()` overload as a `friend` function template +for your type: + +```cpp +namespace foo { + +class Point { // We want GoogleTest to be able to print instances of this. + ... + // Provide a friend overload. + template + friend void AbslStringify(Sink& sink, const Point& point) { + absl::Format(&sink, "(%d, %d)", point.x, point.y); + } + + int x; + int y; +}; + +// If you can't declare the function in the class it's important that the +// AbslStringify overload is defined in the SAME namespace that defines Point. +// C++'s look-up rules rely on that. +enum class EnumWithStringify { kMany = 0, kChoices = 1 }; + +template +void AbslStringify(Sink& sink, EnumWithStringify e) { + absl::Format(&sink, "%s", e == EnumWithStringify::kMany ? "Many" : "Choices"); +} + +} // namespace foo +``` + +{: .callout .note} +Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its +string. For more information about supported operations on `AbslStringify()`'s +sink, see go/abslstringify. + +`AbslStringify()` can also use `absl::StrFormat`'s catch-all `%v` type specifier +within its own format strings to perform type deduction. `Point` above could be +formatted as `"(%v, %v)"` for example, and deduce the `int` values as `%d`. + +Sometimes, `AbslStringify()` might not be an option: your team may wish to print +types with extra debugging information for testing purposes only. If so, you can +instead define a `PrintTo()` function like this: + +```c++ +#include + +namespace foo { + +class Point { + ... + friend void PrintTo(const Point& point, std::ostream* os) { + *os << "(" << point.x << "," << point.y << ")"; + } + + int x; + int y; +}; + +// If you can't declare the function in the class it's important that PrintTo() +// is defined in the SAME namespace that defines Point. C++'s look-up rules +// rely on that. +void PrintTo(const Point& point, std::ostream* os) { + *os << "(" << point.x << "," << point.y << ")"; +} + +} // namespace foo +``` + +If you have defined both `AbslStringify()` and `PrintTo()`, the latter will be +used by GoogleTest. This allows you to customize how the value appears in +GoogleTest's output without affecting code that relies on the behavior of +`AbslStringify()`. + +If you have an existing `<<` operator and would like to define an +`AbslStringify()`, the latter will be used for GoogleTest printing. + +If you want to print a value `x` using GoogleTest's value printer yourself, just +call `::testing::PrintToString(x)`, which returns an `std::string`: + +```c++ +vector > point_ints = GetPointIntVector(); + +EXPECT_TRUE(IsCorrectPointIntVector(point_ints)) + << "point_ints = " << testing::PrintToString(point_ints); +``` + +For more details regarding `AbslStringify()` and its integration with other +libraries, see go/abslstringify. + +## Death Tests + +In many applications, there are assertions that can cause application failure if +a condition is not met. These consistency checks, which ensure that the program +is in a known good state, are there to fail at the earliest possible time after +some program state is corrupted. If the assertion checks the wrong condition, +then the program may proceed in an erroneous state, which could lead to memory +corruption, security holes, or worse. Hence it is vitally important to test that +such assertion statements work as expected. + +Since these precondition checks cause the processes to die, we call such tests +_death tests_. More generally, any test that checks that a program terminates +(except by throwing an exception) in an expected fashion is also a death test. + +Note that if a piece of code throws an exception, we don't consider it "death" +for the purpose of death tests, as the caller of the code could catch the +exception and avoid the crash. If you want to verify exceptions thrown by your +code, see [Exception Assertions](#ExceptionAssertions). + +If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see +["Catching" Failures](#catching-failures). + +### How to Write a Death Test + +GoogleTest provides assertion macros to support death tests. See +[Death Assertions](reference/assertions.md#death) in the Assertions Reference +for details. + +To write a death test, simply use one of the macros inside your test function. +For example, + +```c++ +TEST(MyDeathTest, Foo) { + // This death test uses a compound statement. + ASSERT_DEATH({ + int n = 5; + Foo(&n); + }, "Error on line .* of Foo()"); +} + +TEST(MyDeathTest, NormalExit) { + EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success"); +} + +TEST(MyDeathTest, KillProcess) { + EXPECT_EXIT(KillProcess(), testing::KilledBySignal(SIGKILL), + "Sending myself unblockable signal"); +} +``` + +verifies that: + +* calling `Foo(5)` causes the process to die with the given error message, +* calling `NormalExit()` causes the process to print `"Success"` to stderr and + exit with exit code 0, and +* calling `KillProcess()` kills the process with signal `SIGKILL`. + +The test function body may contain other assertions and statements as well, if +necessary. + +Note that a death test only cares about three things: + +1. does `statement` abort or exit the process? +2. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status + satisfy `predicate`? Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`) + is the exit status non-zero? And +3. does the stderr output match `matcher`? + +In particular, if `statement` generates an `ASSERT_*` or `EXPECT_*` failure, it +will **not** cause the death test to fail, as GoogleTest assertions don't abort +the process. + +### Death Test Naming + +{: .callout .important} +IMPORTANT: We strongly recommend you to follow the convention of naming your +**test suite** (not test) `*DeathTest` when it contains a death test, as +demonstrated in the above example. The +[Death Tests And Threads](#death-tests-and-threads) section below explains why. + +If a test fixture class is shared by normal tests and death tests, you can use +`using` or `typedef` to introduce an alias for the fixture class and avoid +duplicating its code: + +```c++ +class FooTest : public testing::Test { ... }; + +using FooDeathTest = FooTest; + +TEST_F(FooTest, DoesThis) { + // normal test +} + +TEST_F(FooDeathTest, DoesThat) { + // death test +} +``` + +### Regular Expression Syntax + +When built with Bazel and using Abseil, GoogleTest uses the +[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX +systems (Linux, Cygwin, Mac), GoogleTest uses the +[POSIX extended regular expression](https://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04) +syntax. To learn about POSIX syntax, you may want to read this +[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended). + +On Windows, GoogleTest uses its own simple regular expression implementation. It +lacks many features. For example, we don't support union (`"x|y"`), grouping +(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among +others. Below is what we do support (`A` denotes a literal character, period +(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular +expressions.): + +Expression | Meaning +---------- | -------------------------------------------------------------- +`c` | matches any literal character `c` +`\\d` | matches any decimal digit +`\\D` | matches any character that's not a decimal digit +`\\f` | matches `\f` +`\\n` | matches `\n` +`\\r` | matches `\r` +`\\s` | matches any ASCII whitespace, including `\n` +`\\S` | matches any character that's not a whitespace +`\\t` | matches `\t` +`\\v` | matches `\v` +`\\w` | matches any letter, `_`, or decimal digit +`\\W` | matches any character that `\\w` doesn't match +`\\c` | matches any literal character `c`, which must be a punctuation +`.` | matches any single character except `\n` +`A?` | matches 0 or 1 occurrences of `A` +`A*` | matches 0 or many occurrences of `A` +`A+` | matches 1 or many occurrences of `A` +`^` | matches the beginning of a string (not that of each line) +`$` | matches the end of a string (not that of each line) +`xy` | matches `x` followed by `y` + +To help you determine which capability is available on your system, GoogleTest +defines macros to govern which regular expression it is using. The macros are: +`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death +tests to work in all cases, you can either `#if` on these macros or use the more +limited syntax only. + +### How It Works + +See [Death Assertions](reference/assertions.md#death) in the Assertions +Reference. + +### Death Tests And Threads + +The reason for the two death test styles has to do with thread safety. Due to +well-known problems with forking in the presence of threads, death tests should +be run in a single-threaded context. Sometimes, however, it isn't feasible to +arrange that kind of environment. For example, statically-initialized modules +may start threads before main is ever reached. Once threads have been created, +it may be difficult or impossible to clean them up. + +GoogleTest has three features intended to raise awareness of threading issues. + +1. A warning is emitted if multiple threads are running when a death test is + encountered. +2. Test suites with a name ending in "DeathTest" are run before all other + tests. +3. It uses `clone()` instead of `fork()` to spawn the child process on Linux + (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely + to cause the child to hang when the parent process has multiple threads. + +It's perfectly fine to create threads inside a death test statement; they are +executed in a separate process and cannot affect the parent. + +### Death Test Styles + +The "threadsafe" death test style was introduced in order to help mitigate the +risks of testing in a possibly multithreaded environment. It trades increased +test execution time (potentially dramatically so) for improved thread safety. + +The automated testing framework does not set the style flag. You can choose a +particular style of death tests by setting the flag programmatically: + +```c++ +GTEST_FLAG_SET(death_test_style, "threadsafe"); +``` + +You can do this in `main()` to set the style for all death tests in the binary, +or in individual tests. Recall that flags are saved before running each test and +restored afterwards, so you need not do that yourself. For example: + +```c++ +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + GTEST_FLAG_SET(death_test_style, "fast"); + return RUN_ALL_TESTS(); +} + +TEST(MyDeathTest, TestOne) { + GTEST_FLAG_SET(death_test_style, "threadsafe"); + // This test is run in the "threadsafe" style: + ASSERT_DEATH(ThisShouldDie(), ""); +} + +TEST(MyDeathTest, TestTwo) { + // This test is run in the "fast" style: + ASSERT_DEATH(ThisShouldDie(), ""); +} +``` + +### Caveats + +The `statement` argument of `ASSERT_EXIT()` can be any valid C++ statement. If +it leaves the current function via a `return` statement or by throwing an +exception, the death test is considered to have failed. Some GoogleTest macros +may return from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid +them in `statement`. + +Since `statement` runs in the child process, any in-memory side effect (e.g. +modifying a variable, releasing memory, etc) it causes will *not* be observable +in the parent process. In particular, if you release memory in a death test, +your program will fail the heap check as the parent process will never see the +memory reclaimed. To solve this problem, you can + +1. try not to free memory in a death test; +2. free the memory again in the parent process; or +3. do not use the heap checker in your program. + +Due to an implementation detail, you cannot place multiple death test assertions +on the same line; otherwise, compilation will fail with an unobvious error +message. + +Despite the improved thread safety afforded by the "threadsafe" style of death +test, thread problems such as deadlock are still possible in the presence of +handlers registered with `pthread_atfork(3)`. + +## Using Assertions in Sub-routines + +{: .callout .note} +Note: If you want to put a series of test assertions in a subroutine to check +for a complex condition, consider using +[a custom GMock matcher](gmock_cook_book.md#NewMatchers) instead. This lets you +provide a more readable error message in case of failure and avoid all of the +issues described below. + +### Adding Traces to Assertions + +If a test sub-routine is called from several places, when an assertion inside it +fails, it can be hard to tell which invocation of the sub-routine the failure is +from. You can alleviate this problem using extra logging or custom failure +messages, but that usually clutters up your tests. A better solution is to use +the `SCOPED_TRACE` macro or the `ScopedTrace` utility: + +```c++ +SCOPED_TRACE(message); +``` + +```c++ +ScopedTrace trace("file_path", line_number, message); +``` + +where `message` can be anything streamable to `std::ostream`. `SCOPED_TRACE` +macro will cause the current file name, line number, and the given message to be +added in every failure message. `ScopedTrace` accepts explicit file name and +line number in arguments, which is useful for writing test helpers. The effect +will be undone when the control leaves the current lexical scope. + +For example, + +```c++ +10: void Sub1(int n) { +11: EXPECT_EQ(Bar(n), 1); +12: EXPECT_EQ(Bar(n + 1), 2); +13: } +14: +15: TEST(FooTest, Bar) { +16: { +17: SCOPED_TRACE("A"); // This trace point will be included in +18: // every failure in this scope. +19: Sub1(1); +20: } +21: // Now it won't. +22: Sub1(9); +23: } +``` + +could result in messages like these: + +```none +path/to/foo_test.cc:11: Failure +Value of: Bar(n) +Expected: 1 + Actual: 2 +Google Test trace: +path/to/foo_test.cc:17: A + +path/to/foo_test.cc:12: Failure +Value of: Bar(n + 1) +Expected: 2 + Actual: 3 +``` + +Without the trace, it would've been difficult to know which invocation of +`Sub1()` the two failures come from respectively. (You could add an extra +message to each assertion in `Sub1()` to indicate the value of `n`, but that's +tedious.) + +Some tips on using `SCOPED_TRACE`: + +1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the + beginning of a sub-routine, instead of at each call site. +2. When calling sub-routines inside a loop, make the loop iterator part of the + message in `SCOPED_TRACE` such that you can know which iteration the failure + is from. +3. Sometimes the line number of the trace point is enough for identifying the + particular invocation of a sub-routine. In this case, you don't have to + choose a unique message for `SCOPED_TRACE`. You can simply use `""`. +4. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer + scope. In this case, all active trace points will be included in the failure + messages, in reverse order they are encountered. +5. The trace dump is clickable in Emacs - hit `return` on a line number and + you'll be taken to that line in the source file! + +### Propagating Fatal Failures + +A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that +when they fail they only abort the _current function_, not the entire test. For +example, the following test will segfault: + +```c++ +void Subroutine() { + // Generates a fatal failure and aborts the current function. + ASSERT_EQ(1, 2); + + // The following won't be executed. + ... +} + +TEST(FooTest, Bar) { + Subroutine(); // The intended behavior is for the fatal failure + // in Subroutine() to abort the entire test. + + // The actual behavior: the function goes on after Subroutine() returns. + int* p = nullptr; + *p = 3; // Segfault! +} +``` + +To alleviate this, GoogleTest provides three different solutions. You could use +either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the +`HasFatalFailure()` function. They are described in the following two +subsections. + +#### Asserting on Subroutines with an exception + +The following code can turn ASSERT-failure into an exception: + +```c++ +class ThrowListener : public testing::EmptyTestEventListener { + void OnTestPartResult(const testing::TestPartResult& result) override { + if (result.type() == testing::TestPartResult::kFatalFailure) { + throw testing::AssertionException(result); + } + } +}; +int main(int argc, char** argv) { + ... + testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener); + return RUN_ALL_TESTS(); +} +``` + +This listener should be added after other listeners if you have any, otherwise +they won't see failed `OnTestPartResult`. + +#### Asserting on Subroutines + +As shown above, if your test calls a subroutine that has an `ASSERT_*` failure +in it, the test will continue after the subroutine returns. This may not be what +you want. + +Often people want fatal failures to propagate like exceptions. For that +GoogleTest offers the following macros: + +Fatal assertion | Nonfatal assertion | Verifies +------------------------------------- | ------------------------------------- | -------- +`ASSERT_NO_FATAL_FAILURE(statement);` | `EXPECT_NO_FATAL_FAILURE(statement);` | `statement` doesn't generate any new fatal failures in the current thread. + +Only failures in the thread that executes the assertion are checked to determine +the result of this type of assertions. If `statement` creates new threads, +failures in these threads are ignored. + +Examples: + +```c++ +ASSERT_NO_FATAL_FAILURE(Foo()); + +int i; +EXPECT_NO_FATAL_FAILURE({ + i = Bar(); +}); +``` + +Assertions from multiple threads are currently not supported on Windows. + +#### Checking for Failures in the Current Test + +`HasFatalFailure()` in the `::testing::Test` class returns `true` if an +assertion in the current test has suffered a fatal failure. This allows +functions to catch fatal failures in a sub-routine and return early. + +```c++ +class Test { + public: + ... + static bool HasFatalFailure(); +}; +``` + +The typical usage, which basically simulates the behavior of a thrown exception, +is: + +```c++ +TEST(FooTest, Bar) { + Subroutine(); + // Aborts if Subroutine() had a fatal failure. + if (HasFatalFailure()) return; + + // The following won't be executed. + ... +} +``` + +If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test +fixture, you must add the `::testing::Test::` prefix, as in: + +```c++ +if (testing::Test::HasFatalFailure()) return; +``` + +Similarly, `HasNonfatalFailure()` returns `true` if the current test has at +least one non-fatal failure, and `HasFailure()` returns `true` if the current +test has at least one failure of either kind. + +## Logging Additional Information + +In your test code, you can call `RecordProperty("key", value)` to log additional +information, where `value` can be either a string or an `int`. The *last* value +recorded for a key will be emitted to the +[XML output](#generating-an-xml-report) if you specify one. For example, the +test + +```c++ +TEST_F(WidgetUsageTest, MinAndMaxWidgets) { + RecordProperty("MaximumWidgets", ComputeMaxUsage()); + RecordProperty("MinimumWidgets", ComputeMinUsage()); +} +``` + +will output XML like this: + +```xml + ... + + ... +``` + +{: .callout .note} +> NOTE: +> +> * `RecordProperty()` is a static member of the `Test` class. Therefore it +> needs to be prefixed with `::testing::Test::` if used outside of the +> `TEST` body and the test fixture class. +> * *`key`* must be a valid XML attribute name, and cannot conflict with the +> ones already used by GoogleTest (`name`, `status`, `time`, `classname`, +> `type_param`, and `value_param`). +> * Calling `RecordProperty()` outside of the lifespan of a test is allowed. +> If it's called outside of a test but between a test suite's +> `SetUpTestSuite()` and `TearDownTestSuite()` methods, it will be +> attributed to the XML element for the test suite. If it's called outside +> of all test suites (e.g. in a test environment), it will be attributed to +> the top-level XML element. + +## Sharing Resources Between Tests in the Same Test Suite + +GoogleTest creates a new test fixture object for each test in order to make +tests independent and easier to debug. However, sometimes tests use resources +that are expensive to set up, making the one-copy-per-test model prohibitively +expensive. + +If the tests don't change the resource, there's no harm in their sharing a +single resource copy. So, in addition to per-test set-up/tear-down, GoogleTest +also supports per-test-suite set-up/tear-down. To use it: + +1. In your test fixture class (say `FooTest` ), declare as `static` some member + variables to hold the shared resources. +2. Outside your test fixture class (typically just below it), define those + member variables, optionally giving them initial values. +3. In the same test fixture class, define a public member function `static void + SetUpTestSuite()` (remember not to spell it as **`SetupTestSuite`** with a + small `u`!) to set up the shared resources and a `static void + TearDownTestSuite()` function to tear them down. + +That's it! GoogleTest automatically calls `SetUpTestSuite()` before running the +*first test* in the `FooTest` test suite (i.e. before creating the first +`FooTest` object), and calls `TearDownTestSuite()` after running the *last test* +in it (i.e. after deleting the last `FooTest` object). In between, the tests can +use the shared resources. + +Remember that the test order is undefined, so your code can't depend on a test +preceding or following another. Also, the tests must either not modify the state +of any shared resource, or, if they do modify the state, they must restore the +state to its original value before passing control to the next test. + +Note that `SetUpTestSuite()` may be called multiple times for a test fixture +class that has derived classes, so you should not expect code in the function +body to be run only once. Also, derived classes still have access to shared +resources defined as static members, so careful consideration is needed when +managing shared resources to avoid memory leaks if shared resources are not +properly cleaned up in `TearDownTestSuite()`. + +Here's an example of per-test-suite set-up and tear-down: + +```c++ +class FooTest : public testing::Test { + protected: + // Per-test-suite set-up. + // Called before the first test in this test suite. + // Can be omitted if not needed. + static void SetUpTestSuite() { + shared_resource_ = new ...; + + // If `shared_resource_` is **not deleted** in `TearDownTestSuite()`, + // reallocation should be prevented because `SetUpTestSuite()` may be called + // in subclasses of FooTest and lead to memory leak. + // + // if (shared_resource_ == nullptr) { + // shared_resource_ = new ...; + // } + } + + // Per-test-suite tear-down. + // Called after the last test in this test suite. + // Can be omitted if not needed. + static void TearDownTestSuite() { + delete shared_resource_; + shared_resource_ = nullptr; + } + + // You can define per-test set-up logic as usual. + void SetUp() override { ... } + + // You can define per-test tear-down logic as usual. + void TearDown() override { ... } + + // Some expensive resource shared by all tests. + static T* shared_resource_; +}; + +T* FooTest::shared_resource_ = nullptr; + +TEST_F(FooTest, Test1) { + ... you can refer to shared_resource_ here ... +} + +TEST_F(FooTest, Test2) { + ... you can refer to shared_resource_ here ... +} +``` + +{: .callout .note} +NOTE: Though the above code declares `SetUpTestSuite()` protected, it may +sometimes be necessary to declare it public, such as when using it with +`TEST_P`. + +## Global Set-Up and Tear-Down + +Just as you can do set-up and tear-down at the test level and the test suite +level, you can also do it at the test program level. Here's how. + +First, you subclass the `::testing::Environment` class to define a test +environment, which knows how to set-up and tear-down: + +```c++ +class Environment : public ::testing::Environment { + public: + ~Environment() override {} + + // Override this to define how to set up the environment. + void SetUp() override {} + + // Override this to define how to tear down the environment. + void TearDown() override {} +}; +``` + +Then, you register an instance of your environment class with GoogleTest by +calling the `::testing::AddGlobalTestEnvironment()` function: + +```c++ +Environment* AddGlobalTestEnvironment(Environment* env); +``` + +Now, when `RUN_ALL_TESTS()` is invoked, it first calls the `SetUp()` method. The +tests are then executed, provided that none of the environments have reported +fatal failures and `GTEST_SKIP()` has not been invoked. Finally, `TearDown()` is +called. + +Note that `SetUp()` and `TearDown()` are only invoked if there is at least one +test to be performed. Importantly, `TearDown()` is executed even if the test is +not run due to a fatal failure or `GTEST_SKIP()`. + +Calling `SetUp()` and `TearDown()` for each iteration depends on the flag +`gtest_recreate_environments_when_repeating`. `SetUp()` and `TearDown()` are +called for each environment object when the object is recreated for each +iteration. However, if test environments are not recreated for each iteration, +`SetUp()` is called only on the first iteration, and `TearDown()` is called only +on the last iteration. + +It's OK to register multiple environment objects. In this suite, their `SetUp()` +will be called in the order they are registered, and their `TearDown()` will be +called in the reverse order. + +Note that GoogleTest takes ownership of the registered environment objects. +Therefore **do not delete them** by yourself. + +You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is called, +probably in `main()`. If you use `gtest_main`, you need to call this before +`main()` starts for it to take effect. One way to do this is to define a global +variable like this: + +```c++ +testing::Environment* const foo_env = + testing::AddGlobalTestEnvironment(new FooEnvironment); +``` + +However, we strongly recommend you to write your own `main()` and call +`AddGlobalTestEnvironment()` there, as relying on initialization of global +variables makes the code harder to read and may cause problems when you register +multiple environments from different translation units and the environments have +dependencies among them (remember that the compiler doesn't guarantee the order +in which global variables from different translation units are initialized). + +## Value-Parameterized Tests + +*Value-parameterized tests* allow you to test your code with different +parameters without writing multiple copies of the same test. This is useful in a +number of situations, for example: + +* You have a piece of code whose behavior is affected by one or more + command-line flags. You want to make sure your code performs correctly for + various values of those flags. +* You want to test different implementations of an OO interface. +* You want to test your code over various inputs (a.k.a. data-driven testing). + This feature is easy to abuse, so please exercise your good sense when doing + it! + +### How to Write Value-Parameterized Tests + +To write value-parameterized tests, first you should define a fixture class. It +must be derived from both `testing::Test` and `testing::WithParamInterface` +(the latter is a pure interface), where `T` is the type of your parameter +values. For convenience, you can just derive the fixture class from +`testing::TestWithParam`, which itself is derived from both `testing::Test` +and `testing::WithParamInterface`. `T` can be any copyable type. If it's a +raw pointer, you are responsible for managing the lifespan of the pointed +values. + +{: .callout .note} +NOTE: If your test fixture defines `SetUpTestSuite()` or `TearDownTestSuite()` +they must be declared **public** rather than **protected** in order to use +`TEST_P`. + +```c++ +class FooTest : + public testing::TestWithParam { + // You can implement all the usual fixture class members here. + // To access the test parameter, call GetParam() from class + // TestWithParam. +}; + +// Or, when you want to add parameters to a pre-existing fixture class: +class BaseTest : public testing::Test { + ... +}; +class BarTest : public BaseTest, + public testing::WithParamInterface { + ... +}; +``` + +Then, use the `TEST_P` macro to define as many test patterns using this fixture +as you want. The `_P` suffix is for "parameterized" or "pattern", whichever you +prefer to think. + +```c++ +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} +``` + +Finally, you can use the `INSTANTIATE_TEST_SUITE_P` macro to instantiate the +test suite with any set of parameters you want. GoogleTest defines a number of +functions for generating test parameters—see details at +[`INSTANTIATE_TEST_SUITE_P`](reference/testing.md#INSTANTIATE_TEST_SUITE_P) in +the Testing Reference. + +For example, the following statement will instantiate tests from the `FooTest` +test suite each with parameter values `"meeny"`, `"miny"`, and `"moe"` using the +[`Values`](reference/testing.md#param-generators) parameter generator: + +```c++ +INSTANTIATE_TEST_SUITE_P(MeenyMinyMoe, + FooTest, + testing::Values("meeny", "miny", "moe")); +``` + +{: .callout .note} +NOTE: The code above must be placed at global or namespace scope, not at +function scope. + +The first argument to `INSTANTIATE_TEST_SUITE_P` is a unique name for the +instantiation of the test suite. The next argument is the name of the test +pattern, and the last is the +[parameter generator](reference/testing.md#param-generators). + +The parameter generator expression is not evaluated until GoogleTest is +initialized (via `InitGoogleTest()`). Any prior initialization done in the +`main` function will be accessible from the parameter generator, for example, +the results of flag parsing. + +You can instantiate a test pattern more than once, so to distinguish different +instances of the pattern, the instantiation name is added as a prefix to the +actual test suite name. Remember to pick unique prefixes for different +instantiations. The tests from the instantiation above will have these names: + +* `MeenyMinyMoe/FooTest.DoesBlah/0` for `"meeny"` +* `MeenyMinyMoe/FooTest.DoesBlah/1` for `"miny"` +* `MeenyMinyMoe/FooTest.DoesBlah/2` for `"moe"` +* `MeenyMinyMoe/FooTest.HasBlahBlah/0` for `"meeny"` +* `MeenyMinyMoe/FooTest.HasBlahBlah/1` for `"miny"` +* `MeenyMinyMoe/FooTest.HasBlahBlah/2` for `"moe"` + +You can use these names in [`--gtest_filter`](#running-a-subset-of-the-tests). + +The following statement will instantiate all tests from `FooTest` again, each +with parameter values `"cat"` and `"dog"` using the +[`ValuesIn`](reference/testing.md#param-generators) parameter generator: + +```c++ +constexpr absl::string_view kPets[] = {"cat", "dog"}; +INSTANTIATE_TEST_SUITE_P(Pets, FooTest, testing::ValuesIn(kPets)); +``` + +The tests from the instantiation above will have these names: + +* `Pets/FooTest.DoesBlah/0` for `"cat"` +* `Pets/FooTest.DoesBlah/1` for `"dog"` +* `Pets/FooTest.HasBlahBlah/0` for `"cat"` +* `Pets/FooTest.HasBlahBlah/1` for `"dog"` + +Please note that `INSTANTIATE_TEST_SUITE_P` will instantiate *all* tests in the +given test suite, whether their definitions come before or *after* the +`INSTANTIATE_TEST_SUITE_P` statement. + +Additionally, by default, every `TEST_P` without a corresponding +`INSTANTIATE_TEST_SUITE_P` causes a failing test in test suite +`GoogleTestVerification`. If you have a test suite where that omission is not an +error, for example it is in a library that may be linked in for other reasons or +where the list of test cases is dynamic and may be empty, then this check can be +suppressed by tagging the test suite: + +```c++ +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest); +``` + +You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples. + +[sample7_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample7_unittest.cc "Parameterized Test example" +[sample8_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample8_unittest.cc "Parameterized Test example with multiple parameters" + +### Creating Value-Parameterized Abstract Tests + +In the above, we define and instantiate `FooTest` in the *same* source file. +Sometimes you may want to define value-parameterized tests in a library and let +other people instantiate them later. This pattern is known as *abstract tests*. +As an example of its application, when you are designing an interface you can +write a standard suite of abstract tests (perhaps using a factory function as +the test parameter) that all implementations of the interface are expected to +pass. When someone implements the interface, they can instantiate your suite to +get all the interface-conformance tests for free. + +To define abstract tests, you should organize your code like this: + +1. Put the definition of the parameterized test fixture class (e.g. `FooTest`) + in a header file, say `foo_param_test.h`. Think of this as *declaring* your + abstract tests. +2. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes + `foo_param_test.h`. Think of this as *implementing* your abstract tests. + +Once they are defined, you can instantiate them by including `foo_param_test.h`, +invoking `INSTANTIATE_TEST_SUITE_P()`, and depending on the library target that +contains `foo_param_test.cc`. You can instantiate the same abstract test suite +multiple times, possibly in different source files. + +### Specifying Names for Value-Parameterized Test Parameters + +The optional last argument to `INSTANTIATE_TEST_SUITE_P()` allows the user to +specify a function or functor that generates custom test name suffixes based on +the test parameters. The function should accept one argument of type +`testing::TestParamInfo`, and return `std::string`. + +`testing::PrintToStringParamName` is a builtin test suffix generator that +returns the value of `testing::PrintToString(GetParam())`. It does not work for +`std::string` or C strings. + +{: .callout .note} +NOTE: test names must be non-empty, unique, and may only contain ASCII +alphanumeric characters. In particular, they +[should not contain underscores](faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore) + +```c++ +class MyTestSuite : public testing::TestWithParam {}; + +TEST_P(MyTestSuite, MyTest) +{ + std::cout << "Example Test Param: " << GetParam() << std::endl; +} + +INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::Range(0, 10), + testing::PrintToStringParamName()); +``` + +Providing a custom functor allows for more control over test parameter name +generation, especially for types where the automatic conversion does not +generate helpful parameter names (e.g. strings as demonstrated above). The +following example illustrates this for multiple parameters, an enumeration type +and a string, and also demonstrates how to combine generators. It uses a lambda +for conciseness: + +```c++ +enum class MyType { MY_FOO = 0, MY_BAR = 1 }; + +class MyTestSuite : public testing::TestWithParam> { +}; + +INSTANTIATE_TEST_SUITE_P( + MyGroup, MyTestSuite, + testing::Combine( + testing::Values(MyType::MY_FOO, MyType::MY_BAR), + testing::Values("A", "B")), + [](const testing::TestParamInfo& info) { + std::string name = absl::StrCat( + std::get<0>(info.param) == MyType::MY_FOO ? "Foo" : "Bar", + std::get<1>(info.param)); + absl::c_replace_if(name, [](char c) { return !std::isalnum(c); }, '_'); + return name; + }); +``` + +## Typed Tests + +Suppose you have multiple implementations of the same interface and want to make +sure that all of them satisfy some common requirements. Or, you may have defined +several types that are supposed to conform to the same "concept" and you want to +verify it. In both cases, you want the same test logic repeated for different +types. + +While you can write one `TEST` or `TEST_F` for each type you want to test (and +you may even factor the test logic into a function template that you invoke from +the `TEST`), it's tedious and doesn't scale: if you want `m` tests over `n` +types, you'll end up writing `m*n` `TEST`s. + +*Typed tests* allow you to repeat the same test logic over a list of types. You +only need to write the test logic once, although you must know the type list +when writing typed tests. Here's how you do it: + +First, define a fixture class template. It should be parameterized by a type. +Remember to derive it from `::testing::Test`: + +```c++ +template +class FooTest : public testing::Test { + public: + ... + using List = std::list; + static T shared_; + T value_; +}; +``` + +Next, associate a list of types with the test suite, which will be repeated for +each type in the list: + +```c++ +using MyTypes = ::testing::Types; +TYPED_TEST_SUITE(FooTest, MyTypes); +``` + +The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE` +macro to parse correctly. Otherwise the compiler will think that each comma in +the type list introduces a new macro argument. + +Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test for this +test suite. You can repeat this as many times as you want: + +```c++ +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to the special name TypeParam to get the type + // parameter. Since we are inside a derived class template, C++ requires + // us to visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the 'TestFixture::' + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the 'typename TestFixture::' + // prefix. The 'typename' is required to satisfy the compiler. + typename TestFixture::List values; + + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } +``` + +You can see [sample6_unittest.cc] for a complete example. + +[sample6_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample6_unittest.cc "Typed Test example" + +## Type-Parameterized Tests + +*Type-parameterized tests* are like typed tests, except that they don't require +you to know the list of types ahead of time. Instead, you can define the test +logic first and instantiate it with different type lists later. You can even +instantiate it more than once in the same program. + +If you are designing an interface or concept, you can define a suite of +type-parameterized tests to verify properties that any valid implementation of +the interface/concept should have. Then, the author of each implementation can +just instantiate the test suite with their type to verify that it conforms to +the requirements, without having to write similar tests repeatedly. Here's an +example: + +First, define a fixture class template, as we did with typed tests: + +```c++ +template +class FooTest : public testing::Test { + void DoSomethingInteresting(); + ... +}; +``` + +Next, declare that you will define a type-parameterized test suite: + +```c++ +TYPED_TEST_SUITE_P(FooTest); +``` + +Then, use `TYPED_TEST_P()` to define a type-parameterized test. You can repeat +this as many times as you want: + +```c++ +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + + // You will need to use `this` explicitly to refer to fixture members. + this->DoSomethingInteresting() + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } +``` + +Now the tricky part: you need to register all test patterns using the +`REGISTER_TYPED_TEST_SUITE_P` macro before you can instantiate them. The first +argument of the macro is the test suite name; the rest are the names of the +tests in this test suite: + +```c++ +REGISTER_TYPED_TEST_SUITE_P(FooTest, + DoesBlah, HasPropertyA); +``` + +Finally, you are free to instantiate the pattern with the types you want. If you +put the above code in a header file, you can `#include` it in multiple C++ +source files and instantiate it multiple times. + +```c++ +using MyTypes = ::testing::Types; +INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); +``` + +To distinguish different instances of the pattern, the first argument to the +`INSTANTIATE_TYPED_TEST_SUITE_P` macro is a prefix that will be added to the +actual test suite name. Remember to pick unique prefixes for different +instances. + +In the special case where the type list contains only one type, you can write +that type directly without `::testing::Types<...>`, like this: + +```c++ +INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int); +``` + +You can see [sample6_unittest.cc] for a complete example. + +## Testing Private Code + +If you change your software's internal implementation, your tests should not +break as long as the change is not observable by users. Therefore, **per the +black-box testing principle, most of the time you should test your code through +its public interfaces.** + +**If you still find yourself needing to test internal implementation code, +consider if there's a better design.** The desire to test internal +implementation is often a sign that the class is doing too much. Consider +extracting an implementation class, and testing it. Then use that implementation +class in the original class. + +If you absolutely have to test non-public interface code though, you can. There +are two cases to consider: + +* Static functions ( *not* the same as static member functions!) or unnamed + namespaces, and +* Private or protected class members + +To test them, we use the following special techniques: + +* Both static functions and definitions/declarations in an unnamed namespace + are only visible within the same translation unit. To test them, you can + `#include` the entire `.cc` file being tested in your `*_test.cc` file. + (#including `.cc` files is not a good way to reuse code - you should not do + this in production code!) + + However, a better approach is to move the private code into the + `foo::internal` namespace, where `foo` is the namespace your project + normally uses, and put the private declarations in a `*-internal.h` file. + Your production `.cc` files and your tests are allowed to include this + internal header, but your clients are not. This way, you can fully test your + internal implementation without leaking it to your clients. + +* Private class members are only accessible from within the class or by + friends. To access a class' private members, you can declare your test + fixture as a friend to the class and define accessors in your fixture. Tests + using the fixture can then access the private members of your production + class via the accessors in the fixture. Note that even though your fixture + is a friend to your production class, your tests are not automatically + friends to it, as they are technically defined in sub-classes of the + fixture. + + Another way to test private members is to refactor them into an + implementation class, which is then declared in a `*-internal.h` file. Your + clients aren't allowed to include this header but your tests can. Such is + called the + [Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/) + (Private Implementation) idiom. + + Or, you can declare an individual test as a friend of your class by adding + this line in the class body: + + ```c++ + FRIEND_TEST(TestSuiteName, TestName); + ``` + + For example, + + ```c++ + // foo.h + class Foo { + ... + private: + FRIEND_TEST(FooTest, BarReturnsZeroOnNull); + + int Bar(void* x); + }; + + // foo_test.cc + ... + TEST(FooTest, BarReturnsZeroOnNull) { + Foo foo; + EXPECT_EQ(foo.Bar(NULL), 0); // Uses Foo's private member Bar(). + } + ``` + + Pay special attention when your class is defined in a namespace. If you want + your test fixtures and tests to be friends of your class, then they must be + defined in the exact same namespace (no anonymous or inline namespaces). + + For example, if the code to be tested looks like: + + ```c++ + namespace my_namespace { + + class Foo { + friend class FooTest; + FRIEND_TEST(FooTest, Bar); + FRIEND_TEST(FooTest, Baz); + ... definition of the class Foo ... + }; + + } // namespace my_namespace + ``` + + Your test code should be something like: + + ```c++ + namespace my_namespace { + + class FooTest : public testing::Test { + protected: + ... + }; + + TEST_F(FooTest, Bar) { ... } + TEST_F(FooTest, Baz) { ... } + + } // namespace my_namespace + ``` + +## "Catching" Failures + +If you are building a testing utility on top of GoogleTest, you'll want to test +your utility. What framework would you use to test it? GoogleTest, of course. + +The challenge is to verify that your testing utility reports failures correctly. +In frameworks that report a failure by throwing an exception, you could catch +the exception and assert on it. But GoogleTest doesn't use exceptions, so how do +we test that a piece of code generates an expected failure? + +`"gtest/gtest-spi.h"` contains some constructs to do this. +After #including this header, you can use + +```c++ + EXPECT_FATAL_FAILURE(statement, substring); +``` + +to assert that `statement` generates a fatal (e.g. `ASSERT_*`) failure in the +current thread whose message contains the given `substring`, or use + +```c++ + EXPECT_NONFATAL_FAILURE(statement, substring); +``` + +if you are expecting a non-fatal (e.g. `EXPECT_*`) failure. + +Only failures in the current thread are checked to determine the result of this +type of expectations. If `statement` creates new threads, failures in these +threads are also ignored. If you want to catch failures in other threads as +well, use one of the following macros instead: + +```c++ + EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substring); + EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substring); +``` + +{: .callout .note} +NOTE: Assertions from multiple threads are currently not supported on Windows. + +For technical reasons, there are some caveats: + +1. You cannot stream a failure message to either macro. + +2. `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot reference + local non-static variables or non-static members of `this` object. + +3. `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot return a + value. + +## Registering tests programmatically + +The `TEST` macros handle the vast majority of all use cases, but there are few +where runtime registration logic is required. For those cases, the framework +provides the `::testing::RegisterTest` that allows callers to register arbitrary +tests dynamically. + +This is an advanced API only to be used when the `TEST` macros are insufficient. +The macros should be preferred when possible, as they avoid most of the +complexity of calling this function. + +It provides the following signature: + +```c++ +template +TestInfo* RegisterTest(const char* test_suite_name, const char* test_name, + const char* type_param, const char* value_param, + const char* file, int line, Factory factory); +``` + +The `factory` argument is a factory callable (move-constructible) object or +function pointer that creates a new instance of the Test object. It handles +ownership to the caller. The signature of the callable is `Fixture*()`, where +`Fixture` is the test fixture class for the test. All tests registered with the +same `test_suite_name` must return the same fixture type. This is checked at +runtime. + +The framework will infer the fixture class from the factory and will call the +`SetUpTestSuite` and `TearDownTestSuite` for it. + +Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is +undefined. + +Use case example: + +```c++ +class MyFixture : public testing::Test { + public: + // All of these optional, just like in regular macro usage. + static void SetUpTestSuite() { ... } + static void TearDownTestSuite() { ... } + void SetUp() override { ... } + void TearDown() override { ... } +}; + +class MyTest : public MyFixture { + public: + explicit MyTest(int data) : data_(data) {} + void TestBody() override { ... } + + private: + int data_; +}; + +void RegisterMyTests(const std::vector& values) { + for (int v : values) { + testing::RegisterTest( + "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr, + std::to_string(v).c_str(), + __FILE__, __LINE__, + // Important to use the fixture type as the return type here. + [=]() -> MyFixture* { return new MyTest(v); }); + } +} +... +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + std::vector values_to_test = LoadValuesFromConfig(); + RegisterMyTests(values_to_test); + ... + return RUN_ALL_TESTS(); +} +``` + +## Getting the Current Test's Name + +Sometimes a function may need to know the name of the currently running test. +For example, you may be using the `SetUp()` method of your test fixture to set +the golden file name based on which test is running. The +[`TestInfo`](reference/testing.md#TestInfo) class has this information. + +To obtain a `TestInfo` object for the currently running test, call +`current_test_info()` on the [`UnitTest`](reference/testing.md#UnitTest) +singleton object: + +```c++ + // Gets information about the currently running test. + // Do NOT delete the returned object - it's managed by the UnitTest class. + const testing::TestInfo* const test_info = + testing::UnitTest::GetInstance()->current_test_info(); + + printf("We are in test %s of test suite %s.\n", + test_info->name(), + test_info->test_suite_name()); +``` + +`current_test_info()` returns a null pointer if no test is running. In +particular, you cannot find the test suite name in `SetUpTestSuite()`, +`TearDownTestSuite()` (where you know the test suite name implicitly), or +functions called from them. + +## Extending GoogleTest by Handling Test Events + +GoogleTest provides an **event listener API** to let you receive notifications +about the progress of a test program and test failures. The events you can +listen to include the start and end of the test program, a test suite, or a test +method, among others. You may use this API to augment or replace the standard +console output, replace the XML output, or provide a completely different form +of output, such as a GUI or a database. You can also use test events as +checkpoints to implement a resource leak checker, for example. + +### Defining Event Listeners + +To define a event listener, you subclass either +[`testing::TestEventListener`](reference/testing.md#TestEventListener) or +[`testing::EmptyTestEventListener`](reference/testing.md#EmptyTestEventListener) +The former is an (abstract) interface, where *each pure virtual method can be +overridden to handle a test event* (For example, when a test starts, the +`OnTestStart()` method will be called.). The latter provides an empty +implementation of all methods in the interface, such that a subclass only needs +to override the methods it cares about. + +When an event is fired, its context is passed to the handler function as an +argument. The following argument types are used: + +* UnitTest reflects the state of the entire test program, +* TestSuite has information about a test suite, which can contain one or more + tests, +* TestInfo contains the state of a test, and +* TestPartResult represents the result of a test assertion. + +An event handler function can examine the argument it receives to find out +interesting information about the event and the test program's state. + +Here's an example: + +```c++ + class MinimalistPrinter : public testing::EmptyTestEventListener { + // Called before a test starts. + void OnTestStart(const testing::TestInfo& test_info) override { + printf("*** Test %s.%s starting.\n", + test_info.test_suite_name(), test_info.name()); + } + + // Called after a failed assertion or a SUCCESS(). + void OnTestPartResult(const testing::TestPartResult& test_part_result) override { + printf("%s in %s:%d\n%s\n", + test_part_result.failed() ? "*** Failure" : "Success", + test_part_result.file_name(), + test_part_result.line_number(), + test_part_result.summary()); + } + + // Called after a test ends. + void OnTestEnd(const testing::TestInfo& test_info) override { + printf("*** Test %s.%s ending.\n", + test_info.test_suite_name(), test_info.name()); + } + }; +``` + +### Using Event Listeners + +To use the event listener you have defined, add an instance of it to the +GoogleTest event listener list (represented by class +[`TestEventListeners`](reference/testing.md#TestEventListeners) - note the "s" +at the end of the name) in your `main()` function, before calling +`RUN_ALL_TESTS()`: + +```c++ +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + // Gets hold of the event listener list. + testing::TestEventListeners& listeners = + testing::UnitTest::GetInstance()->listeners(); + // Adds a listener to the end. GoogleTest takes the ownership. + listeners.Append(new MinimalistPrinter); + return RUN_ALL_TESTS(); +} +``` + +There's only one problem: the default test result printer is still in effect, so +its output will mingle with the output from your minimalist printer. To suppress +the default printer, just release it from the event listener list and delete it. +You can do so by adding one line: + +```c++ + ... + delete listeners.Release(listeners.default_result_printer()); + listeners.Append(new MinimalistPrinter); + return RUN_ALL_TESTS(); +``` + +Now, sit back and enjoy a completely different output from your tests. For more +details, see [sample9_unittest.cc]. + +[sample9_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample9_unittest.cc "Event listener example" + +You may append more than one listener to the list. When an `On*Start()` or +`OnTestPartResult()` event is fired, the listeners will receive it in the order +they appear in the list (since new listeners are added to the end of the list, +the default text printer and the default XML generator will receive the event +first). An `On*End()` event will be received by the listeners in the *reverse* +order. This allows output by listeners added later to be framed by output from +listeners added earlier. + +### Generating Failures in Listeners + +You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`, `FAIL()`, etc) +when processing an event. There are some restrictions: + +1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will + cause `OnTestPartResult()` to be called recursively). +2. A listener that handles `OnTestPartResult()` is not allowed to generate any + failure. + +When you add listeners to the listener list, you should put listeners that +handle `OnTestPartResult()` *before* listeners that can generate failures. This +ensures that failures generated by the latter are attributed to the right test +by the former. + +See [sample10_unittest.cc] for an example of a failure-raising listener. + +[sample10_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample10_unittest.cc "Failure-raising listener example" + +## Running Test Programs: Advanced Options + +GoogleTest test programs are ordinary executables. Once built, you can run them +directly and affect their behavior via the following environment variables +and/or command line flags. For the flags to work, your programs must call +`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`. + +To see a list of supported flags and their usage, please run your test program +with the `--help` flag. + +If an option is specified both by an environment variable and by a flag, the +latter takes precedence. + +### Selecting Tests + +#### Listing Test Names + +Sometimes it is necessary to list the available tests in a program before +running them so that a filter may be applied if needed. Including the flag +`--gtest_list_tests` overrides all other flags and lists tests in the following +format: + +```none +TestSuite1. + TestName1 + TestName2 +TestSuite2. + TestName +``` + +None of the tests listed are actually run if the flag is provided. There is no +corresponding environment variable for this flag. + +#### Running a Subset of the Tests + +By default, a GoogleTest program runs all tests the user has defined. Sometimes, +you want to run only a subset of the tests (e.g. for debugging or quickly +verifying a change). If you set the `GTEST_FILTER` environment variable or the +`--gtest_filter` flag to a filter string, GoogleTest will only run the tests +whose full names (in the form of `TestSuiteName.TestName`) match the filter. + +The format of a filter is a '`:`'-separated list of wildcard patterns (called +the *positive patterns*) optionally followed by a '`-`' and another +'`:`'-separated pattern list (called the *negative patterns*). A test matches +the filter if and only if it matches any of the positive patterns but does not +match any of the negative patterns. + +A pattern may contain `'*'` (matches any string) or `'?'` (matches any single +character). For convenience, the filter `'*-NegativePatterns'` can be also +written as `'-NegativePatterns'`. + +For example: + +* `./foo_test` Has no flag, and thus runs all its tests. +* `./foo_test --gtest_filter=*` Also runs everything, due to the single + match-everything `*` value. +* `./foo_test --gtest_filter=FooTest.*` Runs everything in test suite + `FooTest` . +* `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full + name contains either `"Null"` or `"Constructor"` . +* `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests. +* `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test + suite `FooTest` except `FooTest.Bar`. +* `./foo_test --gtest_filter=FooTest.*:BarTest.*-FooTest.Bar:BarTest.Foo` Runs + everything in test suite `FooTest` except `FooTest.Bar` and everything in + test suite `BarTest` except `BarTest.Foo`. + +#### Stop test execution upon first failure + +By default, a GoogleTest program runs all tests the user has defined. In some +cases (e.g. iterative test development & execution) it may be desirable stop +test execution upon first failure (trading improved latency for completeness). +If `GTEST_FAIL_FAST` environment variable or `--gtest_fail_fast` flag is set, +the test runner will stop execution as soon as the first test failure is found. + +#### Temporarily Disabling Tests + +If you have a broken test that you cannot fix right away, you can add the +`DISABLED_` prefix to its name. This will exclude it from execution. This is +better than commenting out the code or using `#if 0`, as disabled tests are +still compiled (and thus won't rot). + +If you need to disable all tests in a test suite, you can either add `DISABLED_` +to the front of the name of each test, or alternatively add it to the front of +the test suite name. + +For example, the following tests won't be run by GoogleTest, even though they +will still be compiled: + +```c++ +// Tests that Foo does Abc. +TEST(FooTest, DISABLED_DoesAbc) { ... } + +class DISABLED_BarTest : public testing::Test { ... }; + +// Tests that Bar does Xyz. +TEST_F(DISABLED_BarTest, DoesXyz) { ... } +``` + +{: .callout .note} +NOTE: This feature should only be used for temporary pain-relief. You still have +to fix the disabled tests at a later date. As a reminder, GoogleTest will print +a banner warning you if a test program contains any disabled tests. + +{: .callout .tip} +TIP: You can easily count the number of disabled tests you have using +`grep`. This number can be used as a metric for +improving your test quality. + +#### Temporarily Enabling Disabled Tests + +To include disabled tests in test execution, just invoke the test program with +the `--gtest_also_run_disabled_tests` flag or set the +`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other than `0`. +You can combine this with the `--gtest_filter` flag to further select which +disabled tests to run. + +### Repeating the Tests + +Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it +will fail only 1% of the time, making it rather hard to reproduce the bug under +a debugger. This can be a major source of frustration. + +The `--gtest_repeat` flag allows you to repeat all (or selected) test methods in +a program many times. Hopefully, a flaky test will eventually fail and give you +a chance to debug. Here's how to use it: + +```none +$ foo_test --gtest_repeat=1000 +Repeat foo_test 1000 times and don't stop at failures. + +$ foo_test --gtest_repeat=-1 +A negative count means repeating forever. + +$ foo_test --gtest_repeat=1000 --gtest_break_on_failure +Repeat foo_test 1000 times, stopping at the first failure. This +is especially useful when running under a debugger: when the test +fails, it will drop into the debugger and you can then inspect +variables and stacks. + +$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar.* +Repeat the tests whose name matches the filter 1000 times. +``` + +If your test program contains +[global set-up/tear-down](#global-set-up-and-tear-down) code, it will be +repeated in each iteration as well, as the flakiness may be in it. To avoid +repeating global set-up/tear-down, specify +`--gtest_recreate_environments_when_repeating=false`{.nowrap}. + +You can also specify the repeat count by setting the `GTEST_REPEAT` environment +variable. + +### Shuffling the Tests + +You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE` +environment variable to `1`) to run the tests in a program in a random order. +This helps to reveal bad dependencies between tests. + +By default, GoogleTest uses a random seed calculated from the current time. +Therefore you'll get a different order every time. The console output includes +the random seed value, such that you can reproduce an order-related test failure +later. To specify the random seed explicitly, use the `--gtest_random_seed=SEED` +flag (or set the `GTEST_RANDOM_SEED` environment variable), where `SEED` is an +integer in the range [0, 99999]. The seed value 0 is special: it tells +GoogleTest to do the default behavior of calculating the seed from the current +time. + +If you combine this with `--gtest_repeat=N`, GoogleTest will pick a different +random seed and re-shuffle the tests in each iteration. + +### Distributing Test Functions to Multiple Machines + +If you have more than one machine you can use to run a test program, you might +want to run the test functions in parallel and get the result faster. We call +this technique *sharding*, where each machine is called a *shard*. + +GoogleTest is compatible with test sharding. To take advantage of this feature, +your test runner (not part of GoogleTest) needs to do the following: + +1. Allocate a number of machines (shards) to run the tests. +1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total + number of shards. It must be the same for all shards. +1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index + of the shard. Different shards must be assigned different indices, which + must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`. +1. Run the same test program on all shards. When GoogleTest sees the above two + environment variables, it will select a subset of the test functions to run. + Across all shards, each test function in the program will be run exactly + once. +1. Wait for all shards to finish, then collect and report the results. + +Your project may have tests that were written without GoogleTest and thus don't +understand this protocol. In order for your test runner to figure out which test +supports sharding, it can set the environment variable `GTEST_SHARD_STATUS_FILE` +to a non-existent file path. If a test program supports sharding, it will create +this file to acknowledge that fact; otherwise it will not create it. The actual +contents of the file are not important at this time, although we may put some +useful information in it in the future. + +Here's an example to make it clear. Suppose you have a test program `foo_test` +that contains the following 5 test functions: + +``` +TEST(A, V) +TEST(A, W) +TEST(B, X) +TEST(B, Y) +TEST(B, Z) +``` + +Suppose you have 3 machines at your disposal. To run the test functions in +parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and set +`GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively. Then you would +run the same `foo_test` on each machine. + +GoogleTest reserves the right to change how the work is distributed across the +shards, but here's one possible scenario: + +* Machine #0 runs `A.V` and `B.X`. +* Machine #1 runs `A.W` and `B.Y`. +* Machine #2 runs `B.Z`. + +### Controlling Test Output + +#### Colored Terminal Output + +GoogleTest can use colors in its terminal output to make it easier to spot the +important information: + +
...
+[----------] 1 test from FooTest
+[ RUN      ] FooTest.DoesAbc
+[       OK ] FooTest.DoesAbc
+[----------] 2 tests from BarTest
+[ RUN      ] BarTest.HasXyzProperty
+[       OK ] BarTest.HasXyzProperty
+[ RUN      ] BarTest.ReturnsTrueOnSuccess
+... some error messages ...
+[   FAILED ] BarTest.ReturnsTrueOnSuccess
+...
+[==========] 30 tests from 14 test suites ran.
+[   PASSED ] 28 tests.
+[   FAILED ] 2 tests, listed below:
+[   FAILED ] BarTest.ReturnsTrueOnSuccess
+[   FAILED ] AnotherTest.DoesXyz
+
+ 2 FAILED TESTS
+
+ +You can set the `GTEST_COLOR` environment variable or the `--gtest_color` +command line flag to `yes`, `no`, or `auto` (the default) to enable colors, +disable colors, or let GoogleTest decide. When the value is `auto`, GoogleTest +will use colors if and only if the output goes to a terminal and (on non-Windows +platforms) the `TERM` environment variable is set to `xterm` or `xterm-color`. + +#### Suppressing test passes + +By default, GoogleTest prints 1 line of output for each test, indicating if it +passed or failed. To show only test failures, run the test program with +`--gtest_brief=1`, or set the GTEST_BRIEF environment variable to `1`. + +#### Suppressing the Elapsed Time + +By default, GoogleTest prints the time it takes to run each test. To disable +that, run the test program with the `--gtest_print_time=0` command line flag, or +set the GTEST_PRINT_TIME environment variable to `0`. + +#### Suppressing UTF-8 Text Output + +In case of assertion failures, GoogleTest prints expected and actual values of +type `string` both as hex-encoded strings as well as in readable UTF-8 text if +they contain valid non-ASCII UTF-8 characters. If you want to suppress the UTF-8 +text because, for example, you don't have an UTF-8 compatible output medium, run +the test program with `--gtest_print_utf8=0` or set the `GTEST_PRINT_UTF8` +environment variable to `0`. + +#### Generating an XML Report + +GoogleTest can emit a detailed XML report to a file in addition to its normal +textual output. The report contains the duration of each test, and thus can help +you identify slow tests. + +To generate the XML report, set the `GTEST_OUTPUT` environment variable or the +`--gtest_output` flag to the string `"xml:path_to_output_file"`, which will +create the file at the given location. You can also just use the string `"xml"`, +in which case the output can be found in the `test_detail.xml` file in the +current directory. + +If you specify a directory (for example, `"xml:output/directory/"` on Linux or +`"xml:output\directory\"` on Windows), GoogleTest will create the XML file in +that directory, named after the test executable (e.g. `foo_test.xml` for test +program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left +over from a previous run), GoogleTest will pick a different name (e.g. +`foo_test_1.xml`) to avoid overwriting it. + +The report is based on the `junitreport` Ant task. Since that format was +originally intended for Java, a little interpretation is required to make it +apply to GoogleTest tests, as shown here: + +```xml + + + + + + + + + +``` + +* The root `` element corresponds to the entire test program. +* `` elements correspond to GoogleTest test suites. +* `` elements correspond to GoogleTest test functions. + +For instance, the following program + +```c++ +TEST(MathTest, Addition) { ... } +TEST(MathTest, Subtraction) { ... } +TEST(LogicTest, NonContradiction) { ... } +``` + +could generate this report: + +```xml + + + + + ... + ... + + + + + + + + + +``` + +Things to note: + +* The `tests` attribute of a `` or `` element tells how + many test functions the GoogleTest program or test suite contains, while the + `failures` attribute tells how many of them failed. + +* The `time` attribute expresses the duration of the test, test suite, or + entire test program in seconds. + +* The `timestamp` attribute records the local date and time of the test + execution. + +* The `file` and `line` attributes record the source file location, where the + test was defined. + +* Each `` element corresponds to a single failed GoogleTest + assertion. + +#### Generating a JSON Report + +GoogleTest can also emit a JSON report as an alternative format to XML. To +generate the JSON report, set the `GTEST_OUTPUT` environment variable or the +`--gtest_output` flag to the string `"json:path_to_output_file"`, which will +create the file at the given location. You can also just use the string +`"json"`, in which case the output can be found in the `test_detail.json` file +in the current directory. + +The report format conforms to the following JSON Schema: + +```json +{ + "$schema": "https://json-schema.org/schema#", + "type": "object", + "definitions": { + "TestCase": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "tests": { "type": "integer" }, + "failures": { "type": "integer" }, + "disabled": { "type": "integer" }, + "time": { "type": "string" }, + "testsuite": { + "type": "array", + "items": { + "$ref": "#/definitions/TestInfo" + } + } + } + }, + "TestInfo": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "status": { + "type": "string", + "enum": ["RUN", "NOTRUN"] + }, + "time": { "type": "string" }, + "classname": { "type": "string" }, + "failures": { + "type": "array", + "items": { + "$ref": "#/definitions/Failure" + } + } + } + }, + "Failure": { + "type": "object", + "properties": { + "failures": { "type": "string" }, + "type": { "type": "string" } + } + } + }, + "properties": { + "tests": { "type": "integer" }, + "failures": { "type": "integer" }, + "disabled": { "type": "integer" }, + "errors": { "type": "integer" }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "time": { "type": "string" }, + "name": { "type": "string" }, + "testsuites": { + "type": "array", + "items": { + "$ref": "#/definitions/TestCase" + } + } + } +} +``` + +The report uses the format that conforms to the following Proto3 using the +[JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json): + +```proto +syntax = "proto3"; + +package googletest; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +message UnitTest { + int32 tests = 1; + int32 failures = 2; + int32 disabled = 3; + int32 errors = 4; + google.protobuf.Timestamp timestamp = 5; + google.protobuf.Duration time = 6; + string name = 7; + repeated TestCase testsuites = 8; +} + +message TestCase { + string name = 1; + int32 tests = 2; + int32 failures = 3; + int32 disabled = 4; + int32 errors = 5; + google.protobuf.Duration time = 6; + repeated TestInfo testsuite = 7; +} + +message TestInfo { + string name = 1; + string file = 6; + int32 line = 7; + enum Status { + RUN = 0; + NOTRUN = 1; + } + Status status = 2; + google.protobuf.Duration time = 3; + string classname = 4; + message Failure { + string failures = 1; + string type = 2; + } + repeated Failure failures = 5; +} +``` + +For instance, the following program + +```c++ +TEST(MathTest, Addition) { ... } +TEST(MathTest, Subtraction) { ... } +TEST(LogicTest, NonContradiction) { ... } +``` + +could generate this report: + +```json +{ + "tests": 3, + "failures": 1, + "errors": 0, + "time": "0.035s", + "timestamp": "2011-10-31T18:52:42Z", + "name": "AllTests", + "testsuites": [ + { + "name": "MathTest", + "tests": 2, + "failures": 1, + "errors": 0, + "time": "0.015s", + "testsuite": [ + { + "name": "Addition", + "file": "test.cpp", + "line": 1, + "status": "RUN", + "time": "0.007s", + "classname": "", + "failures": [ + { + "message": "Value of: add(1, 1)\n Actual: 3\nExpected: 2", + "type": "" + }, + { + "message": "Value of: add(1, -1)\n Actual: 1\nExpected: 0", + "type": "" + } + ] + }, + { + "name": "Subtraction", + "file": "test.cpp", + "line": 2, + "status": "RUN", + "time": "0.005s", + "classname": "" + } + ] + }, + { + "name": "LogicTest", + "tests": 1, + "failures": 0, + "errors": 0, + "time": "0.005s", + "testsuite": [ + { + "name": "NonContradiction", + "file": "test.cpp", + "line": 3, + "status": "RUN", + "time": "0.005s", + "classname": "" + } + ] + } + ] +} +``` + +{: .callout .important} +IMPORTANT: The exact format of the JSON document is subject to change. + +### Controlling How Failures Are Reported + +#### Detecting Test Premature Exit + +Google Test implements the _premature-exit-file_ protocol for test runners to +catch any kind of unexpected exits of test programs. Upon start, Google Test +creates the file which will be automatically deleted after all work has been +finished. Then, the test runner can check if this file exists. In case the file +remains undeleted, the inspected test has exited prematurely. + +This feature is enabled only if the `TEST_PREMATURE_EXIT_FILE` environment +variable has been set. + +#### Turning Assertion Failures into Break-Points + +When running test programs under a debugger, it's very convenient if the +debugger can catch an assertion failure and automatically drop into interactive +mode. GoogleTest's *break-on-failure* mode supports this behavior. + +To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value +other than `0`. Alternatively, you can use the `--gtest_break_on_failure` +command line flag. + +#### Disabling Catching Test-Thrown Exceptions + +GoogleTest can be used either with or without exceptions enabled. If a test +throws a C++ exception or (on Windows) a structured exception (SEH), by default +GoogleTest catches it, reports it as a test failure, and continues with the next +test method. This maximizes the coverage of a test run. Also, on Windows an +uncaught exception will cause a pop-up window, so catching the exceptions allows +you to run the tests automatically. + +When debugging the test failures, however, you may instead want the exceptions +to be handled by the debugger, such that you can examine the call stack when an +exception is thrown. To achieve that, set the `GTEST_CATCH_EXCEPTIONS` +environment variable to `0`, or use the `--gtest_catch_exceptions=0` flag when +running the tests. + +### Sanitizer Integration + +The +[Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html), +[Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer), +and +[Thread Sanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual) +all provide weak functions that you can override to trigger explicit failures +when they detect sanitizer errors, such as creating a reference from `nullptr`. +To override these functions, place definitions for them in a source file that +you compile as part of your main binary: + +``` +extern "C" { +void __ubsan_on_report() { + FAIL() << "Encountered an undefined behavior sanitizer error"; +} +void __asan_on_error() { + FAIL() << "Encountered an address sanitizer error"; +} +void __tsan_on_report() { + FAIL() << "Encountered a thread sanitizer error"; +} +} // extern "C" +``` + +After compiling your project with one of the sanitizers enabled, if a particular +test triggers a sanitizer error, GoogleTest will report that it failed. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/assets/css/style.scss b/test/ios/iOSUnitTesting/extern/googletest/docs/assets/css/style.scss new file mode 100644 index 00000000..bb30f418 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/assets/css/style.scss @@ -0,0 +1,5 @@ +--- +--- + +@import "jekyll-theme-primer"; +@import "main"; diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/community_created_documentation.md b/test/ios/iOSUnitTesting/extern/googletest/docs/community_created_documentation.md new file mode 100644 index 00000000..4569075f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/community_created_documentation.md @@ -0,0 +1,7 @@ +# Community-Created Documentation + +The following is a list, in no particular order, of links to documentation +created by the Googletest community. + +* [Googlemock Insights](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/googletest/insights.md), + by [ElectricRCAircraftGuy](https://github.com/ElectricRCAircraftGuy) diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/faq.md b/test/ios/iOSUnitTesting/extern/googletest/docs/faq.md new file mode 100644 index 00000000..c7d10b50 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/faq.md @@ -0,0 +1,671 @@ +# GoogleTest FAQ + +## Why should test suite names and test names not contain underscore? + +{: .callout .note} +Note: GoogleTest reserves underscore (`_`) for special-purpose keywords, such as +[the `DISABLED_` prefix](advanced.md#temporarily-disabling-tests), in addition +to the following rationale. + +Underscore (`_`) is special, as C++ reserves the following to be used by the +compiler and the standard library: + +1. any identifier that starts with an `_` followed by an upper-case letter, and +2. any identifier that contains two consecutive underscores (i.e. `__`) + *anywhere* in its name. + +User code is *prohibited* from using such identifiers. + +Now let's look at what this means for `TEST` and `TEST_F`. + +Currently `TEST(TestSuiteName, TestName)` generates a class named +`TestSuiteName_TestName_Test`. What happens if `TestSuiteName` or `TestName` +contains `_`? + +1. If `TestSuiteName` starts with an `_` followed by an upper-case letter (say, + `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus + invalid. +2. If `TestSuiteName` ends with an `_` (say, `Foo_`), we get + `Foo__TestName_Test`, which is invalid. +3. If `TestName` starts with an `_` (say, `_Bar`), we get + `TestSuiteName__Bar_Test`, which is invalid. +4. If `TestName` ends with an `_` (say, `Bar_`), we get + `TestSuiteName_Bar__Test`, which is invalid. + +So clearly `TestSuiteName` and `TestName` cannot start or end with `_` +(Actually, `TestSuiteName` can start with `_`—as long as the `_` isn't followed +by an upper-case letter. But that's getting complicated. So for simplicity we +just say that it cannot start with `_`.). + +It may seem fine for `TestSuiteName` and `TestName` to contain `_` in the +middle. However, consider this: + +```c++ +TEST(Time, Flies_Like_An_Arrow) { ... } +TEST(Time_Flies, Like_An_Arrow) { ... } +``` + +Now, the two `TEST`s will both generate the same class +(`Time_Flies_Like_An_Arrow_Test`). That's not good. + +So for simplicity, we just ask the users to avoid `_` in `TestSuiteName` and +`TestName`. The rule is more constraining than necessary, but it's simple and +easy to remember. It also gives GoogleTest some wiggle room in case its +implementation needs to change in the future. + +If you violate the rule, there may not be immediate consequences, but your test +may (just may) break with a new compiler (or a new version of the compiler you +are using) or with a new version of GoogleTest. Therefore it's best to follow +the rule. + +## Why does GoogleTest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`? + +First of all, you can use `nullptr` with each of these macros, e.g. +`EXPECT_EQ(ptr, nullptr)`, `EXPECT_NE(ptr, nullptr)`, `ASSERT_EQ(ptr, nullptr)`, +`ASSERT_NE(ptr, nullptr)`. This is the preferred syntax in the style guide +because `nullptr` does not have the type problems that `NULL` does. + +Due to some peculiarity of C++, it requires some non-trivial template meta +programming tricks to support using `NULL` as an argument of the `EXPECT_XX()` +and `ASSERT_XX()` macros. Therefore we only do it where it's most needed +(otherwise we make the implementation of GoogleTest harder to maintain and more +error-prone than necessary). + +Historically, the `EXPECT_EQ()` macro took the *expected* value as its first +argument and the *actual* value as the second, though this argument order is now +discouraged. It was reasonable that someone wanted +to write `EXPECT_EQ(NULL, some_expression)`, and this indeed was requested +several times. Therefore we implemented it. + +The need for `EXPECT_NE(NULL, ptr)` wasn't nearly as strong. When the assertion +fails, you already know that `ptr` must be `NULL`, so it doesn't add any +information to print `ptr` in this case. That means `EXPECT_TRUE(ptr != NULL)` +works just as well. + +If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'd have to +support `EXPECT_NE(ptr, NULL)` as well. This means using the template meta +programming tricks twice in the implementation, making it even harder to +understand and maintain. We believe the benefit doesn't justify the cost. + +Finally, with the growth of the gMock matcher library, we are encouraging people +to use the unified `EXPECT_THAT(value, matcher)` syntax more often in tests. One +significant advantage of the matcher approach is that matchers can be easily +combined to form new matchers, while the `EXPECT_NE`, etc, macros cannot be +easily combined. Therefore we want to invest more in the matchers than in the +`EXPECT_XX()` macros. + +## I need to test that different implementations of an interface satisfy some common requirements. Should I use typed tests or value-parameterized tests? + +For testing various implementations of the same interface, either typed tests or +value-parameterized tests can get it done. It's really up to you the user to +decide which is more convenient for you, depending on your particular case. Some +rough guidelines: + +* Typed tests can be easier to write if instances of the different + implementations can be created the same way, modulo the type. For example, + if all these implementations have a public default constructor (such that + you can write `new TypeParam`), or if their factory functions have the same + form (e.g. `CreateInstance()`). +* Value-parameterized tests can be easier to write if you need different code + patterns to create different implementations' instances, e.g. `new Foo` vs + `new Bar(5)`. To accommodate for the differences, you can write factory + function wrappers and pass these function pointers to the tests as their + parameters. +* When a typed test fails, the default output includes the name of the type, + which can help you quickly identify which implementation is wrong. + Value-parameterized tests only show the number of the failed iteration by + default. You will need to define a function that returns the iteration name + and pass it as the third parameter to INSTANTIATE_TEST_SUITE_P to have more + useful output. +* When using typed tests, you need to make sure you are testing against the + interface type, not the concrete types (in other words, you want to make + sure `implicit_cast(my_concrete_impl)` works, not just that + `my_concrete_impl` works). It's less likely to make mistakes in this area + when using value-parameterized tests. + +I hope I didn't confuse you more. :-) If you don't mind, I'd suggest you to give +both approaches a try. Practice is a much better way to grasp the subtle +differences between the two tools. Once you have some concrete experience, you +can much more easily decide which one to use the next time. + +## My death test modifies some state, but the change seems lost after the death test finishes. Why? + +Death tests (`EXPECT_DEATH`, etc.) are executed in a sub-process s.t. the +expected crash won't kill the test program (i.e. the parent process). As a +result, any in-memory side effects they incur are observable in their respective +sub-processes, but not in the parent process. You can think of them as running +in a parallel universe, more or less. + +In particular, if you use mocking and the death test statement invokes some mock +methods, the parent process will think the calls have never occurred. Therefore, +you may want to move your `EXPECT_CALL` statements inside the `EXPECT_DEATH` +macro. + +## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a GoogleTest bug? + +Actually, the bug is in `htonl()`. + +According to `'man htonl'`, `htonl()` is a *function*, which means it's valid to +use `htonl` as a function pointer. However, in opt mode `htonl()` is defined as +a *macro*, which breaks this usage. + +Worse, the macro definition of `htonl()` uses a `gcc` extension and is *not* +standard C++. That hacky implementation has some ad hoc limitations. In +particular, it prevents you from writing `Foo()`, where `Foo` +is a template that has an integral argument. + +The implementation of `EXPECT_EQ(a, b)` uses `sizeof(... a ...)` inside a +template argument, and thus doesn't compile in opt mode when `a` contains a call +to `htonl()`. It is difficult to make `EXPECT_EQ` bypass the `htonl()` bug, as +the solution must work with different compilers on various platforms. + +## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong? + +If your class has a static data member: + +```c++ +// foo.h +class Foo { + ... + static const int kBar = 100; +}; +``` + +you also need to define it *outside* of the class body in `foo.cc`: + +```c++ +const int Foo::kBar; // No initializer here. +``` + +Otherwise your code is **invalid C++**, and may break in unexpected ways. In +particular, using it in GoogleTest comparison assertions (`EXPECT_EQ`, etc.) +will generate an "undefined reference" linker error. The fact that "it used to +work" doesn't mean it's valid. It just means that you were lucky. :-) + +If the declaration of the static data member is `constexpr` then it is +implicitly an `inline` definition, and a separate definition in `foo.cc` is not +needed: + +```c++ +// foo.h +class Foo { + ... + static constexpr int kBar = 100; // Defines kBar, no need to do it in foo.cc. +}; +``` + +## Can I derive a test fixture from another? + +Yes. + +Each test fixture has a corresponding and same named test suite. This means only +one test suite can use a particular fixture. Sometimes, however, multiple test +cases may want to use the same or slightly different fixtures. For example, you +may want to make sure that all of a GUI library's test suites don't leak +important system resources like fonts and brushes. + +In GoogleTest, you share a fixture among test suites by putting the shared logic +in a base test fixture, then deriving from that base a separate fixture for each +test suite that wants to use this common logic. You then use `TEST_F()` to write +tests using each derived fixture. + +Typically, your code looks like this: + +```c++ +// Defines a base test fixture. +class BaseTest : public ::testing::Test { + protected: + ... +}; + +// Derives a fixture FooTest from BaseTest. +class FooTest : public BaseTest { + protected: + void SetUp() override { + BaseTest::SetUp(); // Sets up the base fixture first. + ... additional set-up work ... + } + + void TearDown() override { + ... clean-up work for FooTest ... + BaseTest::TearDown(); // Remember to tear down the base fixture + // after cleaning up FooTest! + } + + ... functions and variables for FooTest ... +}; + +// Tests that use the fixture FooTest. +TEST_F(FooTest, Bar) { ... } +TEST_F(FooTest, Baz) { ... } + +... additional fixtures derived from BaseTest ... +``` + +If necessary, you can continue to derive test fixtures from a derived fixture. +GoogleTest has no limit on how deep the hierarchy can be. + +For a complete example using derived test fixtures, see +[sample5_unittest.cc](https://github.com/google/googletest/blob/main/googletest/samples/sample5_unittest.cc). + +## My compiler complains "void value not ignored as it ought to be." What does this mean? + +You're probably using an `ASSERT_*()` in a function that doesn't return `void`. +`ASSERT_*()` can only be used in `void` functions, due to exceptions being +disabled by our build system. Please see more details +[here](advanced.md#assertion-placement). + +## My death test hangs (or seg-faults). How do I fix it? + +In GoogleTest, death tests are run in a child process and the way they work is +delicate. To write death tests you really need to understand how they work—see +the details at [Death Assertions](reference/assertions.md#death) in the +Assertions Reference. + +In particular, death tests don't like having multiple threads in the parent +process. So the first thing you can try is to eliminate creating threads outside +of `EXPECT_DEATH()`. For example, you may want to use mocks or fake objects +instead of real ones in your tests. + +Sometimes this is impossible as some library you must use may be creating +threads before `main()` is even reached. In this case, you can try to minimize +the chance of conflicts by either moving as many activities as possible inside +`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or +leaving as few things as possible in it. Also, you can try to set the death test +style to `"threadsafe"`, which is safer but slower, and see if it helps. + +If you go with thread-safe death tests, remember that they rerun the test +program from the beginning in the child process. Therefore make sure your +program can run side-by-side with itself and is deterministic. + +In the end, this boils down to good concurrent programming. You have to make +sure that there are no race conditions or deadlocks in your program. No silver +bullet - sorry! + +## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp} + +The first thing to remember is that GoogleTest does **not** reuse the same test +fixture object across multiple tests. For each `TEST_F`, GoogleTest will create +a **fresh** test fixture object, immediately call `SetUp()`, run the test body, +call `TearDown()`, and then delete the test fixture object. + +When you need to write per-test set-up and tear-down logic, you have the choice +between using the test fixture constructor/destructor or `SetUp()`/`TearDown()`. +The former is usually preferred, as it has the following benefits: + +* By initializing a member variable in the constructor, we have the option to + make it `const`, which helps prevent accidental changes to its value and + makes the tests more obviously correct. +* In case we need to subclass the test fixture class, the subclass' + constructor is guaranteed to call the base class' constructor *first*, and + the subclass' destructor is guaranteed to call the base class' destructor + *afterward*. With `SetUp()/TearDown()`, a subclass may make the mistake of + forgetting to call the base class' `SetUp()/TearDown()` or call them at the + wrong time. + +You may still want to use `SetUp()/TearDown()` in the following cases: + +* C++ does not allow virtual function calls in constructors and destructors. + You can call a method declared as virtual, but it will not use dynamic + dispatch. It will use the definition from the class the constructor of which + is currently executing. This is because calling a virtual method before the + derived class constructor has a chance to run is very dangerous - the + virtual method might operate on uninitialized data. Therefore, if you need + to call a method that will be overridden in a derived class, you have to use + `SetUp()/TearDown()`. +* In the body of a constructor (or destructor), it's not possible to use the + `ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal + test failure that should prevent the test from running, it's necessary to + use `abort` and abort the whole test + executable, or to use `SetUp()` instead of a constructor. +* If the tear-down operation could throw an exception, you must use + `TearDown()` as opposed to the destructor, as throwing in a destructor leads + to undefined behavior and usually will kill your program right away. Note + that many standard libraries (like STL) may throw when exceptions are + enabled in the compiler. Therefore you should prefer `TearDown()` if you + want to write portable tests that work with or without exceptions. +* The GoogleTest team is considering making the assertion macros throw on + platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux + client-side), which will eliminate the need for the user to propagate + failures from a subroutine to its caller. Therefore, you shouldn't use + GoogleTest assertions in a destructor if your code could run on such a + platform. + +## The compiler complains "no matching function to call" when I use `ASSERT_PRED*`. How do I fix it? + +See details for [`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the +Assertions Reference. + +## My compiler complains about "ignoring return value" when I call RUN_ALL_TESTS(). Why? + +Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is, +instead of + +```c++ + return RUN_ALL_TESTS(); +``` + +they write + +```c++ + RUN_ALL_TESTS(); +``` + +This is **wrong and dangerous**. The testing services needs to see the return +value of `RUN_ALL_TESTS()` in order to determine if a test has passed. If your +`main()` function ignores it, your test will be considered successful even if it +has a GoogleTest assertion failure. Very bad. + +We have decided to fix this (thanks to Michael Chastain for the idea). Now, your +code will no longer be able to ignore `RUN_ALL_TESTS()` when compiled with +`gcc`. If you do so, you'll get a compiler error. + +If you see the compiler complaining about you ignoring the return value of +`RUN_ALL_TESTS()`, the fix is simple: just make sure its value is used as the +return value of `main()`. + +But how could we introduce a change that breaks existing tests? Well, in this +case, the code was already broken in the first place, so we didn't break it. :-) + +## My compiler complains that a constructor (or destructor) cannot return a value. What's going on? + +Due to a peculiarity of C++, in order to support the syntax for streaming +messages to an `ASSERT_*`, e.g. + +```c++ + ASSERT_EQ(1, Foo()) << "blah blah" << foo; +``` + +we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and +`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the +content of your constructor/destructor to a private void member function, or +switch to `EXPECT_*()` if that works. This +[section](advanced.md#assertion-placement) in the user's guide explains it. + +## My SetUp() function is not called. Why? + +C++ is case-sensitive. Did you spell it as `Setup()`? + +Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and +wonder why it's never called. + +## I have several test suites which share the same test fixture logic; do I have to define a new test fixture class for each of them? This seems pretty tedious. + +You don't have to. Instead of + +```c++ +class FooTest : public BaseTest {}; + +TEST_F(FooTest, Abc) { ... } +TEST_F(FooTest, Def) { ... } + +class BarTest : public BaseTest {}; + +TEST_F(BarTest, Abc) { ... } +TEST_F(BarTest, Def) { ... } +``` + +you can simply `typedef` the test fixtures: + +```c++ +typedef BaseTest FooTest; + +TEST_F(FooTest, Abc) { ... } +TEST_F(FooTest, Def) { ... } + +typedef BaseTest BarTest; + +TEST_F(BarTest, Abc) { ... } +TEST_F(BarTest, Def) { ... } +``` + +## GoogleTest output is buried in a whole bunch of LOG messages. What do I do? + +The GoogleTest output is meant to be a concise and human-friendly report. If +your test generates textual output itself, it will mix with the GoogleTest +output, making it hard to read. However, there is an easy solution to this +problem. + +Since `LOG` messages go to stderr, we decided to let GoogleTest output go to +stdout. This way, you can easily separate the two using redirection. For +example: + +```shell +$ ./my_test > gtest_output.txt +``` + +## Why should I prefer test fixtures over global variables? + +There are several good reasons: + +1. It's likely your test needs to change the states of its global variables. + This makes it difficult to keep side effects from escaping one test and + contaminating others, making debugging difficult. By using fixtures, each + test has a fresh set of variables that's different (but with the same + names). Thus, tests are kept independent of each other. +2. Global variables pollute the global namespace. +3. Test fixtures can be reused via subclassing, which cannot be done easily + with global variables. This is useful if many test suites have something in + common. + +## What can the statement argument in ASSERT_DEATH() be? + +`ASSERT_DEATH(statement, matcher)` (or any death assertion macro) can be used +wherever *`statement`* is valid. So basically *`statement`* can be any C++ +statement that makes sense in the current context. In particular, it can +reference global and/or local variables, and can be: + +* a simple function call (often the case), +* a complex expression, or +* a compound statement. + +Some examples are shown here: + +```c++ +// A death test can be a simple function call. +TEST(MyDeathTest, FunctionCall) { + ASSERT_DEATH(Xyz(5), "Xyz failed"); +} + +// Or a complex expression that references variables and functions. +TEST(MyDeathTest, ComplexExpression) { + const bool c = Condition(); + ASSERT_DEATH((c ? Func1(0) : object2.Method("test")), + "(Func1|Method) failed"); +} + +// Death assertions can be used anywhere in a function. In +// particular, they can be inside a loop. +TEST(MyDeathTest, InsideLoop) { + // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die. + for (int i = 0; i < 5; i++) { + EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors", + ::testing::Message() << "where i is " << i); + } +} + +// A death assertion can contain a compound statement. +TEST(MyDeathTest, CompoundStatement) { + // Verifies that at lease one of Bar(0), Bar(1), ..., and + // Bar(4) dies. + ASSERT_DEATH({ + for (int i = 0; i < 5; i++) { + Bar(i); + } + }, + "Bar has \\d+ errors"); +} +``` + +## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why? + +GoogleTest needs to be able to create objects of your test fixture class, so it +must have a default constructor. Normally the compiler will define one for you. +However, there are cases where you have to define your own: + +* If you explicitly declare a non-default constructor for class `FooTest` + (`DISALLOW_EVIL_CONSTRUCTORS()` does this), then you need to define a + default constructor, even if it would be empty. +* If `FooTest` has a const non-static data member, then you have to define the + default constructor *and* initialize the const member in the initializer + list of the constructor. (Early versions of `gcc` doesn't force you to + initialize the const member. It's a bug that has been fixed in `gcc 4`.) + +## Why does ASSERT_DEATH complain about previous threads that were already joined? + +With the Linux pthread library, there is no turning back once you cross the line +from a single thread to multiple threads. The first time you create a thread, a +manager thread is created in addition, so you get 3, not 2, threads. Later when +the thread you create joins the main thread, the thread count decrements by 1, +but the manager thread will never be killed, so you still have 2 threads, which +means you cannot safely run a death test. + +The new NPTL thread library doesn't suffer from this problem, as it doesn't +create a manager thread. However, if you don't control which machine your test +runs on, you shouldn't depend on this. + +## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`? + +GoogleTest does not interleave tests from different test suites. That is, it +runs all tests in one test suite first, and then runs all tests in the next test +suite, and so on. GoogleTest does this because it needs to set up a test suite +before the first test in it is run, and tear it down afterwards. Splitting up +the test case would require multiple set-up and tear-down processes, which is +inefficient and makes the semantics unclean. + +If we were to determine the order of tests based on test name instead of test +case name, then we would have a problem with the following situation: + +```c++ +TEST_F(FooTest, AbcDeathTest) { ... } +TEST_F(FooTest, Uvw) { ... } + +TEST_F(BarTest, DefDeathTest) { ... } +TEST_F(BarTest, Xyz) { ... } +``` + +Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't +interleave tests from different test suites, we need to run all tests in the +`FooTest` case before running any test in the `BarTest` case. This contradicts +with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`. + +## But I don't like calling my entire test suite `*DeathTest` when it contains both death tests and non-death tests. What do I do? + +You don't have to, but if you like, you may split up the test suite into +`FooTest` and `FooDeathTest`, where the names make it clear that they are +related: + +```c++ +class FooTest : public ::testing::Test { ... }; + +TEST_F(FooTest, Abc) { ... } +TEST_F(FooTest, Def) { ... } + +using FooDeathTest = FooTest; + +TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... } +TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... } +``` + +## GoogleTest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds? + +Printing the LOG messages generated by the statement inside `EXPECT_DEATH()` +makes it harder to search for real problems in the parent's log. Therefore, +GoogleTest only prints them when the death test has failed. + +If you really need to see such LOG messages, a workaround is to temporarily +break the death test (e.g. by changing the regex pattern it is expected to +match). Admittedly, this is a hack. We'll consider a more permanent solution +after the fork-and-exec-style death tests are implemented. + +## The compiler complains about `no match for 'operator<<'` when I use an assertion. What gives? + +If you use a user-defined type `FooType` in an assertion, you must make sure +there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function +defined such that we can print a value of `FooType`. + +In addition, if `FooType` is declared in a name space, the `<<` operator also +needs to be defined in the *same* name space. See +[Tip of the Week #49](https://abseil.io/tips/49) for details. + +## How do I suppress the memory leak messages on Windows? + +Since the statically initialized GoogleTest singleton requires allocations on +the heap, the Visual C++ memory leak detector will report memory leaks at the +end of the program run. The easiest way to avoid this is to use the +`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any +statically initialized heap objects. See MSDN for more details and additional +heap check/debug routines. + +## How can my code detect if it is running in a test? + +If you write code that sniffs whether it's running in a test and does different +things accordingly, you are leaking test-only logic into production code and +there is no easy way to ensure that the test-only code paths aren't run by +mistake in production. Such cleverness also leads to +[Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug). Therefore we strongly +advise against the practice, and GoogleTest doesn't provide a way to do it. + +In general, the recommended way to cause the code to behave differently under +test is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). You can inject +different functionality from the test and from the production code. Since your +production code doesn't link in the for-test logic at all (the +[`testonly`](https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure +that), there is no danger in accidentally running it. + +However, if you *really*, *really*, *really* have no choice, and if you follow +the rule of ending your test program names with `_test`, you can use the +*horrible* hack of sniffing your executable name (`argv[0]` in `main()`) to know +whether the code is under test. + +## How do I temporarily disable a test? + +If you have a broken test that you cannot fix right away, you can add the +`DISABLED_` prefix to its name. This will exclude it from execution. This is +better than commenting out the code or using `#if 0`, as disabled tests are +still compiled (and thus won't rot). + +To include disabled tests in test execution, just invoke the test program with +the `--gtest_also_run_disabled_tests` flag. + +## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces? + +Yes. + +The rule is **all test methods in the same test suite must use the same fixture +class**. This means that the following is **allowed** because both tests use the +same fixture class (`::testing::Test`). + +```c++ +namespace foo { +TEST(CoolTest, DoSomething) { + SUCCEED(); +} +} // namespace foo + +namespace bar { +TEST(CoolTest, DoSomething) { + SUCCEED(); +} +} // namespace bar +``` + +However, the following code is **not allowed** and will produce a runtime error +from GoogleTest because the test methods are using different test fixture +classes with the same test suite name. + +```c++ +namespace foo { +class CoolTest : public ::testing::Test {}; // Fixture foo::CoolTest +TEST_F(CoolTest, DoSomething) { + SUCCEED(); +} +} // namespace foo + +namespace bar { +class CoolTest : public ::testing::Test {}; // Fixture: bar::CoolTest +TEST_F(CoolTest, DoSomething) { + SUCCEED(); +} +} // namespace bar +``` diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cheat_sheet.md b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cheat_sheet.md new file mode 100644 index 00000000..ddafaaa2 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cheat_sheet.md @@ -0,0 +1,241 @@ +# gMock Cheat Sheet + +## Defining a Mock Class + +### Mocking a Normal Class {#MockClass} + +Given + +```cpp +class Foo { + public: + virtual ~Foo(); + virtual int GetSize() const = 0; + virtual string Describe(const char* name) = 0; + virtual string Describe(int type) = 0; + virtual bool Process(Bar elem, int count) = 0; +}; +``` + +(note that `~Foo()` **must** be virtual) we can define its mock as + +```cpp +#include + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, GetSize, (), (const, override)); + MOCK_METHOD(string, Describe, (const char* name), (override)); + MOCK_METHOD(string, Describe, (int type), (override)); + MOCK_METHOD(bool, Process, (Bar elem, int count), (override)); +}; +``` + +To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock, +which warns on all uninteresting calls, or a "strict" mock, which treats them as +failures: + +```cpp +using ::testing::NiceMock; +using ::testing::NaggyMock; +using ::testing::StrictMock; + +NiceMock nice_foo; // The type is a subclass of MockFoo. +NaggyMock naggy_foo; // The type is a subclass of MockFoo. +StrictMock strict_foo; // The type is a subclass of MockFoo. +``` + +{: .callout .note} +**Note:** A mock object is currently naggy by default. We may make it nice by +default in the future. + +### Mocking a Class Template {#MockTemplate} + +Class templates can be mocked just like any class. + +To mock + +```cpp +template +class StackInterface { + public: + virtual ~StackInterface(); + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; +``` + +(note that all member functions that are mocked, including `~StackInterface()` +**must** be virtual). + +```cpp +template +class MockStack : public StackInterface { + public: + MOCK_METHOD(int, GetSize, (), (const, override)); + MOCK_METHOD(void, Push, (const Elem& x), (override)); +}; +``` + +### Specifying Calling Conventions for Mock Functions + +If your mock function doesn't use the default calling convention, you can +specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter. +For example, + +```cpp + MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE))); + MOCK_METHOD(int, Bar, (double x, double y), + (const, Calltype(STDMETHODCALLTYPE))); +``` + +where `STDMETHODCALLTYPE` is defined by `` on Windows. + +## Using Mocks in Tests {#UsingMocks} + +The typical work flow is: + +1. Import the gMock names you need to use. All gMock symbols are in the + `testing` namespace unless they are macros or otherwise noted. +2. Create the mock objects. +3. Optionally, set the default actions of the mock objects. +4. Set your expectations on the mock objects (How will they be called? What + will they do?). +5. Exercise code that uses the mock objects; if necessary, check the result + using googletest assertions. +6. When a mock object is destructed, gMock automatically verifies that all + expectations on it have been satisfied. + +Here's an example: + +```cpp +using ::testing::Return; // #1 + +TEST(BarTest, DoesThis) { + MockFoo foo; // #2 + + ON_CALL(foo, GetSize()) // #3 + .WillByDefault(Return(1)); + // ... other default actions ... + + EXPECT_CALL(foo, Describe(5)) // #4 + .Times(3) + .WillRepeatedly(Return("Category 5")); + // ... other expectations ... + + EXPECT_EQ(MyProductionFunction(&foo), "good"); // #5 +} // #6 +``` + +## Setting Default Actions {#OnCall} + +gMock has a **built-in default action** for any function that returns `void`, +`bool`, a numeric value, or a pointer. In C++11, it will additionally returns +the default-constructed value, if one exists for the given type. + +To customize the default action for functions with return type `T`, use +[`DefaultValue`](reference/mocking.md#DefaultValue). For example: + +```cpp + // Sets the default action for return type std::unique_ptr to + // creating a new Buzz every time. + DefaultValue>::SetFactory( + [] { return std::make_unique(AccessLevel::kInternal); }); + + // When this fires, the default action of MakeBuzz() will run, which + // will return a new Buzz object. + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber()); + + auto buzz1 = mock_buzzer_.MakeBuzz("hello"); + auto buzz2 = mock_buzzer_.MakeBuzz("hello"); + EXPECT_NE(buzz1, nullptr); + EXPECT_NE(buzz2, nullptr); + EXPECT_NE(buzz1, buzz2); + + // Resets the default action for return type std::unique_ptr, + // to avoid interfere with other tests. + DefaultValue>::Clear(); +``` + +To customize the default action for a particular method of a specific mock +object, use [`ON_CALL`](reference/mocking.md#ON_CALL). `ON_CALL` has a similar +syntax to `EXPECT_CALL`, but it is used for setting default behaviors when you +do not require that the mock method is called. See +[Knowing When to Expect](gmock_cook_book.md#UseOnCall) for a more detailed +discussion. + +## Setting Expectations {#ExpectCall} + +See [`EXPECT_CALL`](reference/mocking.md#EXPECT_CALL) in the Mocking Reference. + +## Matchers {#MatcherList} + +See the [Matchers Reference](reference/matchers.md). + +## Actions {#ActionList} + +See the [Actions Reference](reference/actions.md). + +## Cardinalities {#CardinalityList} + +See the [`Times` clause](reference/mocking.md#EXPECT_CALL.Times) of +`EXPECT_CALL` in the Mocking Reference. + +## Expectation Order + +By default, expectations can be matched in *any* order. If some or all +expectations must be matched in a given order, you can use the +[`After` clause](reference/mocking.md#EXPECT_CALL.After) or +[`InSequence` clause](reference/mocking.md#EXPECT_CALL.InSequence) of +`EXPECT_CALL`, or use an [`InSequence` object](reference/mocking.md#InSequence). + +## Verifying and Resetting a Mock + +gMock will verify the expectations on a mock object when it is destructed, or +you can do it earlier: + +```cpp +using ::testing::Mock; +... +// Verifies and removes the expectations on mock_obj; +// returns true if and only if successful. +Mock::VerifyAndClearExpectations(&mock_obj); +... +// Verifies and removes the expectations on mock_obj; +// also removes the default actions set by ON_CALL(); +// returns true if and only if successful. +Mock::VerifyAndClear(&mock_obj); +``` + +Do not set new expectations after verifying and clearing a mock after its use. +Setting expectations after code that exercises the mock has undefined behavior. +See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more +information. + +You can also tell gMock that a mock object can be leaked and doesn't need to be +verified: + +```cpp +Mock::AllowLeak(&mock_obj); +``` + +## Mock Classes + +gMock defines a convenient mock class template + +```cpp +class MockFunction { + public: + MOCK_METHOD(R, Call, (A1, ..., An)); +}; +``` + +See this [recipe](gmock_cook_book.md#UsingCheckPoints) for one application of +it. + +## Flags + +| Flag | Description | +| :----------------------------- | :---------------------------------------- | +| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. | +| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. | diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cook_book.md b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cook_book.md new file mode 100644 index 00000000..f1b10b47 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_cook_book.md @@ -0,0 +1,4379 @@ +# gMock Cookbook + +You can find recipes for using gMock here. If you haven't yet, please read +[the dummy guide](gmock_for_dummies.md) first to make sure you understand the +basics. + +{: .callout .note} +**Note:** gMock lives in the `testing` name space. For readability, it is +recommended to write `using ::testing::Foo;` once in your file before using the +name `Foo` defined by gMock. We omit such `using` statements in this section for +brevity, but you should do it in your own code. + +## Creating Mock Classes + +Mock classes are defined as normal classes, using the `MOCK_METHOD` macro to +generate mocked methods. The macro gets 3 or 4 parameters: + +```cpp +class MyMock { + public: + MOCK_METHOD(ReturnType, MethodName, (Args...)); + MOCK_METHOD(ReturnType, MethodName, (Args...), (Specs...)); +}; +``` + +The first 3 parameters are simply the method declaration, split into 3 parts. +The 4th parameter accepts a closed list of qualifiers, which affect the +generated method: + +* **`const`** - Makes the mocked method a `const` method. Required if + overriding a `const` method. +* **`override`** - Marks the method with `override`. Recommended if overriding + a `virtual` method. +* **`noexcept`** - Marks the method with `noexcept`. Required if overriding a + `noexcept` method. +* **`Calltype(...)`** - Sets the call type for the method (e.g. to + `STDMETHODCALLTYPE`), useful in Windows. +* **`ref(...)`** - Marks the method with the reference qualification + specified. Required if overriding a method that has reference + qualifications. Eg `ref(&)` or `ref(&&)`. + +### Dealing with unprotected commas + +Unprotected commas, i.e. commas which are not surrounded by parentheses, prevent +`MOCK_METHOD` from parsing its arguments correctly: + +{: .bad} +```cpp +class MockFoo { + public: + MOCK_METHOD(std::pair, GetPair, ()); // Won't compile! + MOCK_METHOD(bool, CheckMap, (std::map, bool)); // Won't compile! +}; +``` + +Solution 1 - wrap with parentheses: + +{: .good} +```cpp +class MockFoo { + public: + MOCK_METHOD((std::pair), GetPair, ()); + MOCK_METHOD(bool, CheckMap, ((std::map), bool)); +}; +``` + +Note that wrapping a return or argument type with parentheses is, in general, +invalid C++. `MOCK_METHOD` removes the parentheses. + +Solution 2 - define an alias: + +{: .good} +```cpp +class MockFoo { + public: + using BoolAndInt = std::pair; + MOCK_METHOD(BoolAndInt, GetPair, ()); + using MapIntDouble = std::map; + MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool)); +}; +``` + +### Mocking Private or Protected Methods + +You must always put a mock method definition (`MOCK_METHOD`) in a `public:` +section of the mock class, regardless of the method being mocked being `public`, +`protected`, or `private` in the base class. This allows `ON_CALL` and +`EXPECT_CALL` to reference the mock function from outside of the mock class. +(Yes, C++ allows a subclass to change the access level of a virtual function in +the base class.) Example: + +```cpp +class Foo { + public: + ... + virtual bool Transform(Gadget* g) = 0; + + protected: + virtual void Resume(); + + private: + virtual int GetTimeOut(); +}; + +class MockFoo : public Foo { + public: + ... + MOCK_METHOD(bool, Transform, (Gadget* g), (override)); + + // The following must be in the public section, even though the + // methods are protected or private in the base class. + MOCK_METHOD(void, Resume, (), (override)); + MOCK_METHOD(int, GetTimeOut, (), (override)); +}; +``` + +### Mocking Overloaded Methods + +You can mock overloaded functions as usual. No special attention is required: + +```cpp +class Foo { + ... + + // Must be virtual as we'll inherit from Foo. + virtual ~Foo(); + + // Overloaded on the types and/or numbers of arguments. + virtual int Add(Element x); + virtual int Add(int times, Element x); + + // Overloaded on the const-ness of this object. + virtual Bar& GetBar(); + virtual const Bar& GetBar() const; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD(int, Add, (Element x), (override)); + MOCK_METHOD(int, Add, (int times, Element x), (override)); + + MOCK_METHOD(Bar&, GetBar, (), (override)); + MOCK_METHOD(const Bar&, GetBar, (), (const, override)); +}; +``` + +{: .callout .note} +**Note:** if you don't mock all versions of the overloaded method, the compiler +will give you a warning about some methods in the base class being hidden. To +fix that, use `using` to bring them in scope: + +```cpp +class MockFoo : public Foo { + ... + using Foo::Add; + MOCK_METHOD(int, Add, (Element x), (override)); + // We don't want to mock int Add(int times, Element x); + ... +}; +``` + +### Mocking Class Templates + +You can mock class templates just like any class. + +```cpp +template +class StackInterface { + ... + // Must be virtual as we'll inherit from StackInterface. + virtual ~StackInterface(); + + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; + +template +class MockStack : public StackInterface { + ... + MOCK_METHOD(int, GetSize, (), (override)); + MOCK_METHOD(void, Push, (const Elem& x), (override)); +}; +``` + +### Mocking Non-virtual Methods {#MockingNonVirtualMethods} + +gMock can mock non-virtual functions to be used in Hi-perf dependency injection. + +In this case, instead of sharing a common base class with the real class, your +mock class will be *unrelated* to the real class, but contain methods with the +same signatures. The syntax for mocking non-virtual methods is the *same* as +mocking virtual methods (just don't add `override`): + +```cpp +// A simple packet stream class. None of its members is virtual. +class ConcretePacketStream { + public: + void AppendPacket(Packet* new_packet); + const Packet* GetPacket(size_t packet_number) const; + size_t NumberOfPackets() const; + ... +}; + +// A mock packet stream class. It inherits from no other, but defines +// GetPacket() and NumberOfPackets(). +class MockPacketStream { + public: + MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const)); + MOCK_METHOD(size_t, NumberOfPackets, (), (const)); + ... +}; +``` + +Note that the mock class doesn't define `AppendPacket()`, unlike the real class. +That's fine as long as the test doesn't need to call it. + +Next, you need a way to say that you want to use `ConcretePacketStream` in +production code, and use `MockPacketStream` in tests. Since the functions are +not virtual and the two classes are unrelated, you must specify your choice at +*compile time* (as opposed to run time). + +One way to do it is to templatize your code that needs to use a packet stream. +More specifically, you will give your code a template type argument for the type +of the packet stream. In production, you will instantiate your template with +`ConcretePacketStream` as the type argument. In tests, you will instantiate the +same template with `MockPacketStream`. For example, you may write: + +```cpp +template +void CreateConnection(PacketStream* stream) { ... } + +template +class PacketReader { + public: + void ReadPackets(PacketStream* stream, size_t packet_num); +}; +``` + +Then you can use `CreateConnection()` and +`PacketReader` in production code, and use +`CreateConnection()` and `PacketReader` in +tests. + +```cpp + MockPacketStream mock_stream; + EXPECT_CALL(mock_stream, ...)...; + .. set more expectations on mock_stream ... + PacketReader reader(&mock_stream); + ... exercise reader ... +``` + +### Mocking Free Functions + +It is not possible to directly mock a free function (i.e. a C-style function or +a static method). If you need to, you can rewrite your code to use an interface +(abstract class). + +Instead of calling a free function (say, `OpenFile`) directly, introduce an +interface for it and have a concrete subclass that calls the free function: + +```cpp +class FileInterface { + public: + ... + virtual bool Open(const char* path, const char* mode) = 0; +}; + +class File : public FileInterface { + public: + ... + bool Open(const char* path, const char* mode) override { + return OpenFile(path, mode); + } +}; +``` + +Your code should talk to `FileInterface` to open a file. Now it's easy to mock +out the function. + +This may seem like a lot of hassle, but in practice you often have multiple +related functions that you can put in the same interface, so the per-function +syntactic overhead will be much lower. + +If you are concerned about the performance overhead incurred by virtual +functions, and profiling confirms your concern, you can combine this with the +recipe for [mocking non-virtual methods](#MockingNonVirtualMethods). + +Alternatively, instead of introducing a new interface, you can rewrite your code +to accept a std::function instead of the free function, and then use +[MockFunction](#MockFunction) to mock the std::function. + +### Old-Style `MOCK_METHODn` Macros + +Before the generic `MOCK_METHOD` macro +[was introduced in 2018](https://github.com/google/googletest/commit/c5f08bf91944ce1b19bcf414fa1760e69d20afc2), +mocks where created using a family of macros collectively called `MOCK_METHODn`. +These macros are still supported, though migration to the new `MOCK_METHOD` is +recommended. + +The macros in the `MOCK_METHODn` family differ from `MOCK_METHOD`: + +* The general structure is `MOCK_METHODn(MethodName, ReturnType(Args))`, + instead of `MOCK_METHOD(ReturnType, MethodName, (Args))`. +* The number `n` must equal the number of arguments. +* When mocking a const method, one must use `MOCK_CONST_METHODn`. +* When mocking a class template, the macro name must be suffixed with `_T`. +* In order to specify the call type, the macro name must be suffixed with + `_WITH_CALLTYPE`, and the call type is the first macro argument. + +Old macros and their new equivalents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Simple
OldMOCK_METHOD1(Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int))
Const Method
OldMOCK_CONST_METHOD1(Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (const))
Method in a Class Template
OldMOCK_METHOD1_T(Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int))
Const Method in a Class Template
OldMOCK_CONST_METHOD1_T(Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (const))
Method with Call Type
OldMOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (Calltype(STDMETHODCALLTYPE)))
Const Method with Call Type
OldMOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (const, Calltype(STDMETHODCALLTYPE)))
Method with Call Type in a Class Template
OldMOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (Calltype(STDMETHODCALLTYPE)))
Const Method with Call Type in a Class Template
OldMOCK_CONST_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))
NewMOCK_METHOD(bool, Foo, (int), (const, Calltype(STDMETHODCALLTYPE)))
+ +### The Nice, the Strict, and the Naggy {#NiceStrictNaggy} + +If a mock method has no `EXPECT_CALL` spec but is called, we say that it's an +"uninteresting call", and the default action (which can be specified using +`ON_CALL()`) of the method will be taken. Currently, an uninteresting call will +also by default cause gMock to print a warning. + +However, sometimes you may want to ignore these uninteresting calls, and +sometimes you may want to treat them as errors. gMock lets you make the decision +on a per-mock-object basis. + +Suppose your test uses a mock class `MockFoo`: + +```cpp +TEST(...) { + MockFoo mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +If a method of `mock_foo` other than `DoThis()` is called, you will get a +warning. However, if you rewrite your test to use `NiceMock` instead, +you can suppress the warning: + +```cpp +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +`NiceMock` is a subclass of `MockFoo`, so it can be used wherever +`MockFoo` is accepted. + +It also works if `MockFoo`'s constructor takes some arguments, as +`NiceMock` "inherits" `MockFoo`'s constructors: + +```cpp +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo(5, "hi"); // Calls MockFoo(5, "hi"). + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +The usage of `StrictMock` is similar, except that it makes all uninteresting +calls failures: + +```cpp +using ::testing::StrictMock; + +TEST(...) { + StrictMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... + + // The test will fail if a method of mock_foo other than DoThis() + // is called. +} +``` + +{: .callout .note} +NOTE: `NiceMock` and `StrictMock` only affects *uninteresting* calls (calls of +*methods* with no expectations); they do not affect *unexpected* calls (calls of +methods with expectations, but they don't match). See +[Understanding Uninteresting vs Unexpected Calls](#uninteresting-vs-unexpected). + +There are some caveats though (sadly they are side effects of C++'s +limitations): + +1. `NiceMock` and `StrictMock` only work for mock methods + defined using the `MOCK_METHOD` macro **directly** in the `MockFoo` class. + If a mock method is defined in a **base class** of `MockFoo`, the "nice" or + "strict" modifier may not affect it, depending on the compiler. In + particular, nesting `NiceMock` and `StrictMock` (e.g. + `NiceMock >`) is **not** supported. +2. `NiceMock` and `StrictMock` may not work correctly if the + destructor of `MockFoo` is not virtual. We would like to fix this, but it + requires cleaning up existing tests. + +Finally, you should be **very cautious** about when to use naggy or strict +mocks, as they tend to make tests more brittle and harder to maintain. When you +refactor your code without changing its externally visible behavior, ideally you +shouldn't need to update any tests. If your code interacts with a naggy mock, +however, you may start to get spammed with warnings as the result of your +change. Worse, if your code interacts with a strict mock, your tests may start +to fail and you'll be forced to fix them. Our general recommendation is to use +nice mocks (not yet the default) most of the time, use naggy mocks (the current +default) when developing or debugging tests, and use strict mocks only as the +last resort. + +### Simplifying the Interface without Breaking Existing Code {#SimplerInterfaces} + +Sometimes a method has a long list of arguments that is mostly uninteresting. +For example: + +```cpp +class LogSink { + public: + ... + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, + const struct tm* tm_time, + const char* message, size_t message_len) = 0; +}; +``` + +This method's argument list is lengthy and hard to work with (the `message` +argument is not even 0-terminated). If we mock it as is, using the mock will be +awkward. If, however, we try to simplify this interface, we'll need to fix all +clients depending on it, which is often infeasible. + +The trick is to redispatch the method in the mock class: + +```cpp +class ScopedMockLog : public LogSink { + public: + ... + void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, const tm* tm_time, + const char* message, size_t message_len) override { + // We are only interested in the log severity, full file name, and + // log message. + Log(severity, full_filename, std::string(message, message_len)); + } + + // Implements the mock method: + // + // void Log(LogSeverity severity, + // const string& file_path, + // const string& message); + MOCK_METHOD(void, Log, + (LogSeverity severity, const string& file_path, + const string& message)); +}; +``` + +By defining a new mock method with a trimmed argument list, we make the mock +class more user-friendly. + +This technique may also be applied to make overloaded methods more amenable to +mocking. For example, when overloads have been used to implement default +arguments: + +```cpp +class MockTurtleFactory : public TurtleFactory { + public: + Turtle* MakeTurtle(int length, int weight) override { ... } + Turtle* MakeTurtle(int length, int weight, int speed) override { ... } + + // the above methods delegate to this one: + MOCK_METHOD(Turtle*, DoMakeTurtle, ()); +}; +``` + +This allows tests that don't care which overload was invoked to avoid specifying +argument matchers: + +```cpp +ON_CALL(factory, DoMakeTurtle) + .WillByDefault(Return(MakeMockTurtle())); +``` + +### Alternative to Mocking Concrete Classes + +Often you may find yourself using classes that don't implement interfaces. In +order to test your code that uses such a class (let's call it `Concrete`), you +may be tempted to make the methods of `Concrete` virtual and then mock it. + +Try not to do that. + +Making a non-virtual function virtual is a big decision. It creates an extension +point where subclasses can tweak your class' behavior. This weakens your control +on the class because now it's harder to maintain the class invariants. You +should make a function virtual only when there is a valid reason for a subclass +to override it. + +Mocking concrete classes directly is problematic as it creates a tight coupling +between the class and the tests - any small change in the class may invalidate +your tests and make test maintenance a pain. + +To avoid such problems, many programmers have been practicing "coding to +interfaces": instead of talking to the `Concrete` class, your code would define +an interface and talk to it. Then you implement that interface as an adaptor on +top of `Concrete`. In tests, you can easily mock that interface to observe how +your code is doing. + +This technique incurs some overhead: + +* You pay the cost of virtual function calls (usually not a problem). +* There is more abstraction for the programmers to learn. + +However, it can also bring significant benefits in addition to better +testability: + +* `Concrete`'s API may not fit your problem domain very well, as you may not + be the only client it tries to serve. By designing your own interface, you + have a chance to tailor it to your need - you may add higher-level + functionalities, rename stuff, etc instead of just trimming the class. This + allows you to write your code (user of the interface) in a more natural way, + which means it will be more readable, more maintainable, and you'll be more + productive. +* If `Concrete`'s implementation ever has to change, you don't have to rewrite + everywhere it is used. Instead, you can absorb the change in your + implementation of the interface, and your other code and tests will be + insulated from this change. + +Some people worry that if everyone is practicing this technique, they will end +up writing lots of redundant code. This concern is totally understandable. +However, there are two reasons why it may not be the case: + +* Different projects may need to use `Concrete` in different ways, so the best + interfaces for them will be different. Therefore, each of them will have its + own domain-specific interface on top of `Concrete`, and they will not be the + same code. +* If enough projects want to use the same interface, they can always share it, + just like they have been sharing `Concrete`. You can check in the interface + and the adaptor somewhere near `Concrete` (perhaps in a `contrib` + sub-directory) and let many projects use it. + +You need to weigh the pros and cons carefully for your particular problem, but +I'd like to assure you that the Java community has been practicing this for a +long time and it's a proven effective technique applicable in a wide variety of +situations. :-) + +### Delegating Calls to a Fake {#DelegatingToFake} + +Some times you have a non-trivial fake implementation of an interface. For +example: + +```cpp +class Foo { + public: + virtual ~Foo() {} + virtual char DoThis(int n) = 0; + virtual void DoThat(const char* s, int* p) = 0; +}; + +class FakeFoo : public Foo { + public: + char DoThis(int n) override { + return (n > 0) ? '+' : + (n < 0) ? '-' : '0'; + } + + void DoThat(const char* s, int* p) override { + *p = strlen(s); + } +}; +``` + +Now you want to mock this interface such that you can set expectations on it. +However, you also want to use `FakeFoo` for the default behavior, as duplicating +it in the mock object is, well, a lot of work. + +When you define the mock class using gMock, you can have it delegate its default +action to a fake class you already have, using this pattern: + +```cpp +class MockFoo : public Foo { + public: + // Normal mock method definitions using gMock. + MOCK_METHOD(char, DoThis, (int n), (override)); + MOCK_METHOD(void, DoThat, (const char* s, int* p), (override)); + + // Delegates the default actions of the methods to a FakeFoo object. + // This must be called *before* the custom ON_CALL() statements. + void DelegateToFake() { + ON_CALL(*this, DoThis).WillByDefault([this](int n) { + return fake_.DoThis(n); + }); + ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) { + fake_.DoThat(s, p); + }); + } + + private: + FakeFoo fake_; // Keeps an instance of the fake in the mock. +}; +``` + +With that, you can use `MockFoo` in your tests as usual. Just remember that if +you don't explicitly set an action in an `ON_CALL()` or `EXPECT_CALL()`, the +fake will be called upon to do it.: + +```cpp +using ::testing::_; + +TEST(AbcTest, Xyz) { + MockFoo foo; + + foo.DelegateToFake(); // Enables the fake for delegation. + + // Put your ON_CALL(foo, ...)s here, if any. + + // No action specified, meaning to use the default action. + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(foo, DoThat(_, _)); + + int n = 0; + EXPECT_EQ(foo.DoThis(5), '+'); // FakeFoo::DoThis() is invoked. + foo.DoThat("Hi", &n); // FakeFoo::DoThat() is invoked. + EXPECT_EQ(n, 2); +} +``` + +**Some tips:** + +* If you want, you can still override the default action by providing your own + `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`. +* In `DelegateToFake()`, you only need to delegate the methods whose fake + implementation you intend to use. + +* The general technique discussed here works for overloaded methods, but + you'll need to tell the compiler which version you mean. To disambiguate a + mock function (the one you specify inside the parentheses of `ON_CALL()`), + use [this technique](#SelectOverload); to disambiguate a fake function (the + one you place inside `Invoke()`), use a `static_cast` to specify the + function's type. For instance, if class `Foo` has methods `char DoThis(int + n)` and `bool DoThis(double x) const`, and you want to invoke the latter, + you need to write `Invoke(&fake_, static_cast(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)` + (The strange-looking thing inside the angled brackets of `static_cast` is + the type of a function pointer to the second `DoThis()` method.). + +* Having to mix a mock and a fake is often a sign of something gone wrong. + Perhaps you haven't got used to the interaction-based way of testing yet. Or + perhaps your interface is taking on too many roles and should be split up. + Therefore, **don't abuse this**. We would only recommend to do it as an + intermediate step when you are refactoring your code. + +Regarding the tip on mixing a mock and a fake, here's an example on why it may +be a bad sign: Suppose you have a class `System` for low-level system +operations. In particular, it does file and I/O operations. And suppose you want +to test how your code uses `System` to do I/O, and you just want the file +operations to work normally. If you mock out the entire `System` class, you'll +have to provide a fake implementation for the file operation part, which +suggests that `System` is taking on too many roles. + +Instead, you can define a `FileOps` interface and an `IOOps` interface and split +`System`'s functionalities into the two. Then you can mock `IOOps` without +mocking `FileOps`. + +### Delegating Calls to a Real Object + +When using testing doubles (mocks, fakes, stubs, and etc), sometimes their +behaviors will differ from those of the real objects. This difference could be +either intentional (as in simulating an error such that you can test the error +handling code) or unintentional. If your mocks have different behaviors than the +real objects by mistake, you could end up with code that passes the tests but +fails in production. + +You can use the *delegating-to-real* technique to ensure that your mock has the +same behavior as the real object while retaining the ability to validate calls. +This technique is very similar to the [delegating-to-fake](#DelegatingToFake) +technique, the difference being that we use a real object instead of a fake. +Here's an example: + +```cpp +using ::testing::AtLeast; + +class MockFoo : public Foo { + public: + MockFoo() { + // By default, all calls are delegated to the real object. + ON_CALL(*this, DoThis).WillByDefault([this](int n) { + return real_.DoThis(n); + }); + ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) { + real_.DoThat(s, p); + }); + ... + } + MOCK_METHOD(char, DoThis, ...); + MOCK_METHOD(void, DoThat, ...); + ... + private: + Foo real_; +}; + +... + MockFoo mock; + EXPECT_CALL(mock, DoThis()) + .Times(3); + EXPECT_CALL(mock, DoThat("Hi")) + .Times(AtLeast(1)); + ... use mock in test ... +``` + +With this, gMock will verify that your code made the right calls (with the right +arguments, in the right order, called the right number of times, etc), and a +real object will answer the calls (so the behavior will be the same as in +production). This gives you the best of both worlds. + +### Delegating Calls to a Parent Class + +Ideally, you should code to interfaces, whose methods are all pure virtual. In +reality, sometimes you do need to mock a virtual method that is not pure (i.e, +it already has an implementation). For example: + +```cpp +class Foo { + public: + virtual ~Foo(); + + virtual void Pure(int n) = 0; + virtual int Concrete(const char* str) { ... } +}; + +class MockFoo : public Foo { + public: + // Mocking a pure method. + MOCK_METHOD(void, Pure, (int n), (override)); + // Mocking a concrete method. Foo::Concrete() is shadowed. + MOCK_METHOD(int, Concrete, (const char* str), (override)); +}; +``` + +Sometimes you may want to call `Foo::Concrete()` instead of +`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub action, or +perhaps your test doesn't need to mock `Concrete()` at all (but it would be +oh-so painful to have to define a new mock class whenever you don't need to mock +one of its methods). + +You can call `Foo::Concrete()` inside an action by: + +```cpp +... + EXPECT_CALL(foo, Concrete).WillOnce([&foo](const char* str) { + return foo.Foo::Concrete(str); + }); +``` + +or tell the mock object that you don't want to mock `Concrete()`: + +```cpp +... + ON_CALL(foo, Concrete).WillByDefault([&foo](const char* str) { + return foo.Foo::Concrete(str); + }); +``` + +(Why don't we just write `{ return foo.Concrete(str); }`? If you do that, +`MockFoo::Concrete()` will be called (and cause an infinite recursion) since +`Foo::Concrete()` is virtual. That's just how C++ works.) + +## Using Matchers + +### Matching Argument Values Exactly + +You can specify exactly which arguments a mock method is expecting: + +```cpp +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(5)) + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", bar)); +``` + +### Using Simple Matchers + +You can use matchers to match arguments that have a certain property: + +```cpp +using ::testing::NotNull; +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(Ge(5))) // The argument must be >= 5. + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", NotNull())); + // The second argument must not be NULL. +``` + +A frequently used matcher is `_`, which matches anything: + +```cpp + EXPECT_CALL(foo, DoThat(_, NotNull())); +``` + +### Combining Matchers {#CombiningMatchers} + +You can build complex matchers from existing ones using `AllOf()`, +`AllOfArray()`, `AnyOf()`, `AnyOfArray()` and `Not()`: + +```cpp +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::HasSubstr; +using ::testing::Ne; +using ::testing::Not; +... + // The argument must be > 5 and != 10. + EXPECT_CALL(foo, DoThis(AllOf(Gt(5), + Ne(10)))); + + // The first argument must not contain sub-string "blah". + EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")), + NULL)); +``` + +Matchers are function objects, and parametrized matchers can be composed just +like any other function. However because their types can be long and rarely +provide meaningful information, it can be easier to express them with C++14 +generic lambdas to avoid specifying types. For example, + +```cpp +using ::testing::Contains; +using ::testing::Property; + +inline constexpr auto HasFoo = [](const auto& f) { + return Property("foo", &MyClass::foo, Contains(f)); +}; +... + EXPECT_THAT(x, HasFoo("blah")); +``` + +### Casting Matchers {#SafeMatcherCast} + +gMock matchers are statically typed, meaning that the compiler can catch your +mistake if you use a matcher of the wrong type (for example, if you use `Eq(5)` +to match a `string` argument). Good for you! + +Sometimes, however, you know what you're doing and want the compiler to give you +some slack. One example is that you have a matcher for `long` and the argument +you want to match is `int`. While the two types aren't exactly the same, there +is nothing really wrong with using a `Matcher` to match an `int` - after +all, we can first convert the `int` argument to a `long` losslessly before +giving it to the matcher. + +To support this need, gMock gives you the `SafeMatcherCast(m)` function. It +casts a matcher `m` to type `Matcher`. To ensure safety, gMock checks that +(let `U` be the type `m` accepts : + +1. Type `T` can be *implicitly* cast to type `U`; +2. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and + floating-point numbers), the conversion from `T` to `U` is not lossy (in + other words, any value representable by `T` can also be represented by `U`); + and +3. When `U` is a reference, `T` must also be a reference (as the underlying + matcher may be interested in the address of the `U` value). + +The code won't compile if any of these conditions isn't met. + +Here's one example: + +```cpp +using ::testing::SafeMatcherCast; + +// A base class and a child class. +class Base { ... }; +class Derived : public Base { ... }; + +class MockFoo : public Foo { + public: + MOCK_METHOD(void, DoThis, (Derived* derived), (override)); +}; + +... + MockFoo foo; + // m is a Matcher we got from somewhere. + EXPECT_CALL(foo, DoThis(SafeMatcherCast(m))); +``` + +If you find `SafeMatcherCast(m)` too limiting, you can use a similar function +`MatcherCast(m)`. The difference is that `MatcherCast` works as long as you +can `static_cast` type `T` to type `U`. + +`MatcherCast` essentially lets you bypass C++'s type system (`static_cast` isn't +always safe as it could throw away information, for example), so be careful not +to misuse/abuse it. + +### Selecting Between Overloaded Functions {#SelectOverload} + +If you expect an overloaded function to be called, the compiler may need some +help on which overloaded version it is. + +To disambiguate functions overloaded on the const-ness of this object, use the +`Const()` argument wrapper. + +```cpp +using ::testing::ReturnRef; + +class MockFoo : public Foo { + ... + MOCK_METHOD(Bar&, GetBar, (), (override)); + MOCK_METHOD(const Bar&, GetBar, (), (const, override)); +}; + +... + MockFoo foo; + Bar bar1, bar2; + EXPECT_CALL(foo, GetBar()) // The non-const GetBar(). + .WillOnce(ReturnRef(bar1)); + EXPECT_CALL(Const(foo), GetBar()) // The const GetBar(). + .WillOnce(ReturnRef(bar2)); +``` + +(`Const()` is defined by gMock and returns a `const` reference to its argument.) + +To disambiguate overloaded functions with the same number of arguments but +different argument types, you may need to specify the exact type of a matcher, +either by wrapping your matcher in `Matcher()`, or using a matcher whose +type is fixed (`TypedEq`, `An()`, etc): + +```cpp +using ::testing::An; +using ::testing::Matcher; +using ::testing::TypedEq; + +class MockPrinter : public Printer { + public: + MOCK_METHOD(void, Print, (int n), (override)); + MOCK_METHOD(void, Print, (char c), (override)); +}; + +TEST(PrinterTest, Print) { + MockPrinter printer; + + EXPECT_CALL(printer, Print(An())); // void Print(int); + EXPECT_CALL(printer, Print(Matcher(Lt(5)))); // void Print(int); + EXPECT_CALL(printer, Print(TypedEq('a'))); // void Print(char); + + printer.Print(3); + printer.Print(6); + printer.Print('a'); +} +``` + +### Performing Different Actions Based on the Arguments + +When a mock method is called, the *last* matching expectation that's still +active will be selected (think "newer overrides older"). So, you can make a +method do different things depending on its argument values like this: + +```cpp +using ::testing::_; +using ::testing::Lt; +using ::testing::Return; +... + // The default case. + EXPECT_CALL(foo, DoThis(_)) + .WillRepeatedly(Return('b')); + // The more specific case. + EXPECT_CALL(foo, DoThis(Lt(5))) + .WillRepeatedly(Return('a')); +``` + +Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will be +returned; otherwise `'b'` will be returned. + +### Matching Multiple Arguments as a Whole + +Sometimes it's not enough to match the arguments individually. For example, we +may want to say that the first argument must be less than the second argument. +The `With()` clause allows us to match all arguments of a mock function as a +whole. For example, + +```cpp +using ::testing::_; +using ::testing::Ne; +using ::testing::Lt; +... + EXPECT_CALL(foo, InRange(Ne(0), _)) + .With(Lt()); +``` + +says that the first argument of `InRange()` must not be 0, and must be less than +the second argument. + +The expression inside `With()` must be a matcher of type `Matcher>`, where `A1`, ..., `An` are the types of the function arguments. + +You can also write `AllArgs(m)` instead of `m` inside `.With()`. The two forms +are equivalent, but `.With(AllArgs(Lt()))` is more readable than `.With(Lt())`. + +You can use `Args(m)` to match the `n` selected arguments (as a +tuple) against `m`. For example, + +```cpp +using ::testing::_; +using ::testing::AllOf; +using ::testing::Args; +using ::testing::Lt; +... + EXPECT_CALL(foo, Blah) + .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt()))); +``` + +says that `Blah` will be called with arguments `x`, `y`, and `z` where `x < y < +z`. Note that in this example, it wasn't necessary to specify the positional +matchers. + +As a convenience and example, gMock provides some matchers for 2-tuples, +including the `Lt()` matcher above. See +[Multi-argument Matchers](reference/matchers.md#MultiArgMatchers) for the +complete list. + +Note that if you want to pass the arguments to a predicate of your own (e.g. +`.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be written to +take a `std::tuple` as its argument; gMock will pass the `n` selected arguments +as *one* single tuple to the predicate. + +### Using Matchers as Predicates + +Have you noticed that a matcher is just a fancy predicate that also knows how to +describe itself? Many existing algorithms take predicates as arguments (e.g. +those defined in STL's `` header), and it would be a shame if gMock +matchers were not allowed to participate. + +Luckily, you can use a matcher where a unary predicate functor is expected by +wrapping it inside the `Matches()` function. For example, + +```cpp +#include +#include + +using ::testing::Matches; +using ::testing::Ge; + +vector v; +... +// How many elements in v are >= 10? +const int count = count_if(v.begin(), v.end(), Matches(Ge(10))); +``` + +Since you can build complex matchers from simpler ones easily using gMock, this +gives you a way to conveniently construct composite predicates (doing the same +using STL's `` header is just painful). For example, here's a +predicate that's satisfied by any number that is >= 0, <= 100, and != 50: + +```cpp +using ::testing::AllOf; +using ::testing::Ge; +using ::testing::Le; +using ::testing::Matches; +using ::testing::Ne; +... +Matches(AllOf(Ge(0), Le(100), Ne(50))) +``` + +### Using Matchers in googletest Assertions + +See [`EXPECT_THAT`](reference/assertions.md#EXPECT_THAT) in the Assertions +Reference. + +### Using Predicates as Matchers + +gMock provides a set of built-in matchers for matching arguments with expected +values—see the [Matchers Reference](reference/matchers.md) for more information. +In case you find the built-in set lacking, you can use an arbitrary unary +predicate function or functor as a matcher - as long as the predicate accepts a +value of the type you want. You do this by wrapping the predicate inside the +`Truly()` function, for example: + +```cpp +using ::testing::Truly; + +int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; } +... + // Bar() must be called with an even number. + EXPECT_CALL(foo, Bar(Truly(IsEven))); +``` + +Note that the predicate function / functor doesn't have to return `bool`. It +works as long as the return value can be used as the condition in the statement +`if (condition) ...`. + +### Matching Arguments that Are Not Copyable + +When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, gMock saves away a copy of +`bar`. When `Foo()` is called later, gMock compares the argument to `Foo()` with +the saved copy of `bar`. This way, you don't need to worry about `bar` being +modified or destroyed after the `EXPECT_CALL()` is executed. The same is true +when you use matchers like `Eq(bar)`, `Le(bar)`, and so on. + +But what if `bar` cannot be copied (i.e. has no copy constructor)? You could +define your own matcher function or callback and use it with `Truly()`, as the +previous couple of recipes have shown. Or, you may be able to get away from it +if you can guarantee that `bar` won't be changed after the `EXPECT_CALL()` is +executed. Just tell gMock that it should save a reference to `bar`, instead of a +copy of it. Here's how: + +```cpp +using ::testing::Eq; +using ::testing::Lt; +... + // Expects that Foo()'s argument == bar. + EXPECT_CALL(mock_obj, Foo(Eq(std::ref(bar)))); + + // Expects that Foo()'s argument < bar. + EXPECT_CALL(mock_obj, Foo(Lt(std::ref(bar)))); +``` + +Remember: if you do this, don't change `bar` after the `EXPECT_CALL()`, or the +result is undefined. + +### Validating a Member of an Object + +Often a mock function takes a reference to object as an argument. When matching +the argument, you may not want to compare the entire object against a fixed +object, as that may be over-specification. Instead, you may need to validate a +certain member variable or the result of a certain getter method of the object. +You can do this with `Field()` and `Property()`. More specifically, + +```cpp +Field(&Foo::bar, m) +``` + +is a matcher that matches a `Foo` object whose `bar` member variable satisfies +matcher `m`. + +```cpp +Property(&Foo::baz, m) +``` + +is a matcher that matches a `Foo` object whose `baz()` method returns a value +that satisfies matcher `m`. + +For example: + +| Expression | Description | +| :--------------------------- | :--------------------------------------- | +| `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. | +| `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. | + +Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no argument +and be declared as `const`. Don't use `Property()` against member functions that +you do not own, because taking addresses of functions is fragile and generally +not part of the contract of the function. + +`Field()` and `Property()` can also match plain pointers to objects. For +instance, + +```cpp +using ::testing::Field; +using ::testing::Ge; +... +Field(&Foo::number, Ge(3)) +``` + +matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`, the match +will always fail regardless of the inner matcher. + +What if you want to validate more than one members at the same time? Remember +that there are [`AllOf()` and `AllOfArray()`](#CombiningMatchers). + +Finally `Field()` and `Property()` provide overloads that take the field or +property names as the first argument to include it in the error message. This +can be useful when creating combined matchers. + +```cpp +using ::testing::AllOf; +using ::testing::Field; +using ::testing::Matcher; +using ::testing::SafeMatcherCast; + +Matcher IsFoo(const Foo& foo) { + return AllOf(Field("some_field", &Foo::some_field, foo.some_field), + Field("other_field", &Foo::other_field, foo.other_field), + Field("last_field", &Foo::last_field, foo.last_field)); +} +``` + +### Validating the Value Pointed to by a Pointer Argument + +C++ functions often take pointers as arguments. You can use matchers like +`IsNull()`, `NotNull()`, and other comparison matchers to match a pointer, but +what if you want to make sure the value *pointed to* by the pointer, instead of +the pointer itself, has a certain property? Well, you can use the `Pointee(m)` +matcher. + +`Pointee(m)` matches a pointer if and only if `m` matches the value the pointer +points to. For example: + +```cpp +using ::testing::Ge; +using ::testing::Pointee; +... + EXPECT_CALL(foo, Bar(Pointee(Ge(3)))); +``` + +expects `foo.Bar()` to be called with a pointer that points to a value greater +than or equal to 3. + +One nice thing about `Pointee()` is that it treats a `NULL` pointer as a match +failure, so you can write `Pointee(m)` instead of + +```cpp +using ::testing::AllOf; +using ::testing::NotNull; +using ::testing::Pointee; +... + AllOf(NotNull(), Pointee(m)) +``` + +without worrying that a `NULL` pointer will crash your test. + +Also, did we tell you that `Pointee()` works with both raw pointers **and** +smart pointers (`std::unique_ptr`, `std::shared_ptr`, etc)? + +What if you have a pointer to pointer? You guessed it - you can use nested +`Pointee()` to probe deeper inside the value. For example, +`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer that points +to a number less than 3 (what a mouthful...). + +### Defining a Custom Matcher Class {#CustomMatcherClass} + +Most matchers can be simply defined using [the MATCHER* macros](#NewMatchers), +which are terse and flexible, and produce good error messages. However, these +macros are not very explicit about the interfaces they create and are not always +suitable, especially for matchers that will be widely reused. + +For more advanced cases, you may need to define your own matcher class. A custom +matcher allows you to test a specific invariant property of that object. Let's +take a look at how to do so. + +Imagine you have a mock function that takes an object of type `Foo`, which has +an `int bar()` method and an `int baz()` method. You want to constrain that the +argument's `bar()` value plus its `baz()` value is a given number. (This is an +invariant.) Here's how we can write and use a matcher class to do so: + +```cpp +class BarPlusBazEqMatcher { + public: + using is_gtest_matcher = void; + + explicit BarPlusBazEqMatcher(int expected_sum) + : expected_sum_(expected_sum) {} + + bool MatchAndExplain(const Foo& foo, + std::ostream* /* listener */) const { + return (foo.bar() + foo.baz()) == expected_sum_; + } + + void DescribeTo(std::ostream* os) const { + *os << "bar() + baz() equals " << expected_sum_; + } + + void DescribeNegationTo(std::ostream* os) const { + *os << "bar() + baz() does not equal " << expected_sum_; + } + private: + const int expected_sum_; +}; + +::testing::Matcher BarPlusBazEq(int expected_sum) { + return BarPlusBazEqMatcher(expected_sum); +} + +... + Foo foo; + EXPECT_THAT(foo, BarPlusBazEq(5))...; +``` + +### Matching Containers + +Sometimes an STL container (e.g. list, vector, map, ...) is passed to a mock +function and you may want to validate it. Since most STL containers support the +`==` operator, you can write `Eq(expected_container)` or simply +`expected_container` to match a container exactly. + +Sometimes, though, you may want to be more flexible (for example, the first +element must be an exact match, but the second element can be any positive +number, and so on). Also, containers used in tests often have a small number of +elements, and having to define the expected container out-of-line is a bit of a +hassle. + +You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in such +cases: + +```cpp +using ::testing::_; +using ::testing::ElementsAre; +using ::testing::Gt; +... + MOCK_METHOD(void, Foo, (const vector& numbers), (override)); +... + EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5))); +``` + +The above matcher says that the container must have 4 elements, which must be 1, +greater than 0, anything, and 5 respectively. + +If you instead write: + +```cpp +using ::testing::_; +using ::testing::Gt; +using ::testing::UnorderedElementsAre; +... + MOCK_METHOD(void, Foo, (const vector& numbers), (override)); +... + EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5))); +``` + +It means that the container must have 4 elements, which (under some permutation) +must be 1, greater than 0, anything, and 5 respectively. + +As an alternative you can place the arguments in a C-style array and use +`ElementsAreArray()` or `UnorderedElementsAreArray()` instead: + +```cpp +using ::testing::ElementsAreArray; +... + // ElementsAreArray accepts an array of element values. + const int expected_vector1[] = {1, 5, 2, 4, ...}; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1))); + + // Or, an array of element matchers. + Matcher expected_vector2[] = {1, Gt(2), _, 3, ...}; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2))); +``` + +In case the array needs to be dynamically created (and therefore the array size +cannot be inferred by the compiler), you can give `ElementsAreArray()` an +additional argument to specify the array size: + +```cpp +using ::testing::ElementsAreArray; +... + int* const expected_vector3 = new int[count]; + ... fill expected_vector3 with values ... + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count))); +``` + +Use `Pair` when comparing maps or other associative containers. + +{% raw %} + +```cpp +using ::testing::UnorderedElementsAre; +using ::testing::Pair; +... + absl::flat_hash_map m = {{"a", 1}, {"b", 2}, {"c", 3}}; + EXPECT_THAT(m, UnorderedElementsAre( + Pair("a", 1), Pair("b", 2), Pair("c", 3))); +``` + +{% endraw %} + +**Tips:** + +* `ElementsAre*()` can be used to match *any* container that implements the + STL iterator pattern (i.e. it has a `const_iterator` type and supports + `begin()/end()`), not just the ones defined in STL. It will even work with + container types yet to be written - as long as they follows the above + pattern. +* You can use nested `ElementsAre*()` to match nested (multi-dimensional) + containers. +* If the container is passed by pointer instead of by reference, just write + `Pointee(ElementsAre*(...))`. +* The order of elements *matters* for `ElementsAre*()`. If you are using it + with containers whose element order are undefined (such as a + `std::unordered_map`) you should use `UnorderedElementsAre`. + +### Sharing Matchers + +Under the hood, a gMock matcher object consists of a pointer to a ref-counted +implementation object. Copying matchers is allowed and very efficient, as only +the pointer is copied. When the last matcher that references the implementation +object dies, the implementation object will be deleted. + +Therefore, if you have some complex matcher that you want to use again and +again, there is no need to build it every time. Just assign it to a matcher +variable and use that variable repeatedly! For example, + +```cpp +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::Le; +using ::testing::Matcher; +... + Matcher in_range = AllOf(Gt(5), Le(10)); + ... use in_range as a matcher in multiple EXPECT_CALLs ... +``` + +### Matchers must have no side-effects {#PureMatchers} + +{: .callout .warning} +WARNING: gMock does not guarantee when or how many times a matcher will be +invoked. Therefore, all matchers must be *purely functional*: they cannot have +any side effects, and the match result must not depend on anything other than +the matcher's parameters and the value being matched. + +This requirement must be satisfied no matter how a matcher is defined (e.g., if +it is one of the standard matchers, or a custom matcher). In particular, a +matcher can never call a mock function, as that will affect the state of the +mock object and gMock. + +## Setting Expectations + +### Knowing When to Expect {#UseOnCall} + +**`ON_CALL`** is likely the *single most under-utilized construct* in gMock. + +There are basically two constructs for defining the behavior of a mock object: +`ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when +a mock method is called, but doesn't imply any expectation on the method +being called. `EXPECT_CALL` not only defines the behavior, but also sets an +expectation that the method will be called with the given arguments, for the +given number of times (and *in the given order* when you specify the order +too). + +Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every +`EXPECT_CALL` adds a constraint on the behavior of the code under test. Having +more constraints than necessary is *baaad* - even worse than not having enough +constraints. + +This may be counter-intuitive. How could tests that verify more be worse than +tests that verify less? Isn't verification the whole point of tests? + +The answer lies in *what* a test should verify. **A good test verifies the +contract of the code.** If a test over-specifies, it doesn't leave enough +freedom to the implementation. As a result, changing the implementation without +breaking the contract (e.g. refactoring and optimization), which should be +perfectly fine to do, can break such tests. Then you have to spend time fixing +them, only to see them broken again the next time the implementation is changed. + +Keep in mind that one doesn't have to verify more than one property in one test. +In fact, **it's a good style to verify only one thing in one test.** If you do +that, a bug will likely break only one or two tests instead of dozens (which +case would you rather debug?). If you are also in the habit of giving tests +descriptive names that tell what they verify, you can often easily guess what's +wrong just from the test log itself. + +So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend +to verify that the call is made. For example, you may have a bunch of `ON_CALL`s +in your test fixture to set the common mock behavior shared by all tests in the +same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s +to verify different aspects of the code's behavior. Compared with the style +where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more +resilient to implementational changes (and thus less likely to require +maintenance) and makes the intent of the tests more obvious (so they are easier +to maintain when you do need to maintain them). + +If you are bothered by the "Uninteresting mock function call" message printed +when a mock method without an `EXPECT_CALL` is called, you may use a `NiceMock` +instead to suppress all such messages for the mock object, or suppress the +message for specific methods by adding `EXPECT_CALL(...).Times(AnyNumber())`. DO +NOT suppress it by blindly adding an `EXPECT_CALL(...)`, or you'll have a test +that's a pain to maintain. + +### Ignoring Uninteresting Calls + +If you are not interested in how a mock method is called, just don't say +anything about it. In this case, if the method is ever called, gMock will +perform its default action to allow the test program to continue. If you are not +happy with the default action taken by gMock, you can override it using +`DefaultValue::Set()` (described [here](#DefaultValue)) or `ON_CALL()`. + +Please note that once you expressed interest in a particular mock method (via +`EXPECT_CALL()`), all invocations to it must match some expectation. If this +function is called but the arguments don't match any `EXPECT_CALL()` statement, +it will be an error. + +### Disallowing Unexpected Calls + +If a mock method shouldn't be called at all, explicitly say so: + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + +If some calls to the method are allowed, but the rest are not, just list all the +expected calls: + +```cpp +using ::testing::AnyNumber; +using ::testing::Gt; +... + EXPECT_CALL(foo, Bar(5)); + EXPECT_CALL(foo, Bar(Gt(10))) + .Times(AnyNumber()); +``` + +A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()` statements +will be an error. + +### Understanding Uninteresting vs Unexpected Calls {#uninteresting-vs-unexpected} + +*Uninteresting* calls and *unexpected* calls are different concepts in gMock. +*Very* different. + +A call `x.Y(...)` is **uninteresting** if there's *not even a single* +`EXPECT_CALL(x, Y(...))` set. In other words, the test isn't interested in the +`x.Y()` method at all, as evident in that the test doesn't care to say anything +about it. + +A call `x.Y(...)` is **unexpected** if there are *some* `EXPECT_CALL(x, +Y(...))`s set, but none of them matches the call. Put another way, the test is +interested in the `x.Y()` method (therefore it explicitly sets some +`EXPECT_CALL` to verify how it's called); however, the verification fails as the +test doesn't expect this particular call to happen. + +**An unexpected call is always an error,** as the code under test doesn't behave +the way the test expects it to behave. + +**By default, an uninteresting call is not an error,** as it violates no +constraint specified by the test. (gMock's philosophy is that saying nothing +means there is no constraint.) However, it leads to a warning, as it *might* +indicate a problem (e.g. the test author might have forgotten to specify a +constraint). + +In gMock, `NiceMock` and `StrictMock` can be used to make a mock class "nice" or +"strict". How does this affect uninteresting calls and unexpected calls? + +A **nice mock** suppresses uninteresting call *warnings*. It is less chatty than +the default mock, but otherwise is the same. If a test fails with a default +mock, it will also fail using a nice mock instead. And vice versa. Don't expect +making a mock nice to change the test's result. + +A **strict mock** turns uninteresting call warnings into errors. So making a +mock strict may change the test's result. + +Let's look at an example: + +```cpp +TEST(...) { + NiceMock mock_registry; + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); + + // Use mock_registry in code under test. + ... &mock_registry ... +} +``` + +The sole `EXPECT_CALL` here says that all calls to `GetDomainOwner()` must have +`"google.com"` as the argument. If `GetDomainOwner("yahoo.com")` is called, it +will be an unexpected call, and thus an error. *Having a nice mock doesn't +change the severity of an unexpected call.* + +So how do we tell gMock that `GetDomainOwner()` can be called with some other +arguments as well? The standard technique is to add a "catch all" `EXPECT_CALL`: + +```cpp + EXPECT_CALL(mock_registry, GetDomainOwner(_)) + .Times(AnyNumber()); // catches all other calls to this method. + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); +``` + +Remember that `_` is the wildcard matcher that matches anything. With this, if +`GetDomainOwner("google.com")` is called, it will do what the second +`EXPECT_CALL` says; if it is called with a different argument, it will do what +the first `EXPECT_CALL` says. + +Note that the order of the two `EXPECT_CALL`s is important, as a newer +`EXPECT_CALL` takes precedence over an older one. + +For more on uninteresting calls, nice mocks, and strict mocks, read +["The Nice, the Strict, and the Naggy"](#NiceStrictNaggy). + +### Ignoring Uninteresting Arguments {#ParameterlessExpectations} + +If your test doesn't care about the parameters (it only cares about the number +or order of calls), you can often simply omit the parameter list: + +```cpp + // Expect foo.Bar( ... ) twice with any arguments. + EXPECT_CALL(foo, Bar).Times(2); + + // Delegate to the given method whenever the factory is invoked. + ON_CALL(foo_factory, MakeFoo) + .WillByDefault(&BuildFooForTest); +``` + +This functionality is only available when a method is not overloaded; to prevent +unexpected behavior it is a compilation error to try to set an expectation on a +method where the specific overload is ambiguous. You can work around this by +supplying a [simpler mock interface](#SimplerInterfaces) than the mocked class +provides. + +This pattern is also useful when the arguments are interesting, but match logic +is substantially complex. You can leave the argument list unspecified and use +SaveArg actions to [save the values for later verification](#SaveArgVerify). If +you do that, you can easily differentiate calling the method the wrong number of +times from calling it with the wrong arguments. + +### Expecting Ordered Calls {#OrderedCalls} + +Although an `EXPECT_CALL()` statement defined later takes precedence when gMock +tries to match a function call with an expectation, by default calls don't have +to happen in the order `EXPECT_CALL()` statements are written. For example, if +the arguments match the matchers in the second `EXPECT_CALL()`, but not those in +the first and third, then the second expectation will be used. + +If you would rather have all calls occur in the order of the expectations, put +the `EXPECT_CALL()` statements in a block where you define a variable of type +`InSequence`: + +```cpp +using ::testing::_; +using ::testing::InSequence; + + { + InSequence s; + + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(bar, DoThat(_)) + .Times(2); + EXPECT_CALL(foo, DoThis(6)); + } +``` + +In this example, we expect a call to `foo.DoThis(5)`, followed by two calls to +`bar.DoThat()` where the argument can be anything, which are in turn followed by +a call to `foo.DoThis(6)`. If a call occurred out-of-order, gMock will report an +error. + +### Expecting Partially Ordered Calls {#PartialOrder} + +Sometimes requiring everything to occur in a predetermined order can lead to +brittle tests. For example, we may care about `A` occurring before both `B` and +`C`, but aren't interested in the relative order of `B` and `C`. In this case, +the test should reflect our real intent, instead of being overly constraining. + +gMock allows you to impose an arbitrary DAG (directed acyclic graph) on the +calls. One way to express the DAG is to use the +[`After` clause](reference/mocking.md#EXPECT_CALL.After) of `EXPECT_CALL`. + +Another way is via the `InSequence()` clause (not the same as the `InSequence` +class), which we borrowed from jMock 2. It's less flexible than `After()`, but +more convenient when you have long chains of sequential calls, as it doesn't +require you to come up with different names for the expectations in the chains. +Here's how it works: + +If we view `EXPECT_CALL()` statements as nodes in a graph, and add an edge from +node A to node B wherever A must occur before B, we can get a DAG. We use the +term "sequence" to mean a directed path in this DAG. Now, if we decompose the +DAG into sequences, we just need to know which sequences each `EXPECT_CALL()` +belongs to in order to be able to reconstruct the original DAG. + +So, to specify the partial order on the expectations we need to do two things: +first to define some `Sequence` objects, and then for each `EXPECT_CALL()` say +which `Sequence` objects it is part of. + +Expectations in the same sequence must occur in the order they are written. For +example, + +```cpp +using ::testing::Sequence; +... + Sequence s1, s2; + + EXPECT_CALL(foo, A()) + .InSequence(s1, s2); + EXPECT_CALL(bar, B()) + .InSequence(s1); + EXPECT_CALL(bar, C()) + .InSequence(s2); + EXPECT_CALL(foo, D()) + .InSequence(s2); +``` + +specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A -> C -> D`): + +```text + +---> B + | + A ---| + | + +---> C ---> D +``` + +This means that A must occur before B and C, and C must occur before D. There's +no restriction about the order other than these. + +### Controlling When an Expectation Retires + +When a mock method is called, gMock only considers expectations that are still +active. An expectation is active when created, and becomes inactive (aka +*retires*) when a call that has to occur later has occurred. For example, in + +```cpp +using ::testing::_; +using ::testing::Sequence; +... + Sequence s1, s2; + + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #1 + .Times(AnyNumber()) + .InSequence(s1, s2); + EXPECT_CALL(log, Log(WARNING, _, "Data set is empty.")) // #2 + .InSequence(s1); + EXPECT_CALL(log, Log(WARNING, _, "User not found.")) // #3 + .InSequence(s2); +``` + +as soon as either #2 or #3 is matched, #1 will retire. If a warning `"File too +large."` is logged after this, it will be an error. + +Note that an expectation doesn't retire automatically when it's saturated. For +example, + +```cpp +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")); // #2 +``` + +says that there will be exactly one warning with the message `"File too +large."`. If the second warning contains this message too, #2 will match again +and result in an upper-bound-violated error. + +If this is not what you want, you can ask an expectation to retire as soon as it +becomes saturated: + +```cpp +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #2 + .RetiresOnSaturation(); +``` + +Here #2 can be used only once, so if you have two warnings with the message +`"File too large."`, the first will match #2 and the second will match #1 - +there will be no error. + +## Using Actions + +### Returning References from Mock Methods + +If a mock function's return type is a reference, you need to use `ReturnRef()` +instead of `Return()` to return a result: + +```cpp +using ::testing::ReturnRef; + +class MockFoo : public Foo { + public: + MOCK_METHOD(Bar&, GetBar, (), (override)); +}; +... + MockFoo foo; + Bar bar; + EXPECT_CALL(foo, GetBar()) + .WillOnce(ReturnRef(bar)); +... +``` + +### Returning Live Values from Mock Methods + +The `Return(x)` action saves a copy of `x` when the action is created, and +always returns the same value whenever it's executed. Sometimes you may want to +instead return the *live* value of `x` (i.e. its value at the time when the +action is *executed*.). Use either `ReturnRef()` or `ReturnPointee()` for this +purpose. + +If the mock function's return type is a reference, you can do it using +`ReturnRef(x)`, as shown in the previous recipe ("Returning References from Mock +Methods"). However, gMock doesn't let you use `ReturnRef()` in a mock function +whose return type is not a reference, as doing that usually indicates a user +error. So, what shall you do? + +Though you may be tempted, DO NOT use `std::ref()`: + +```cpp +using ::testing::Return; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, GetValue, (), (override)); +}; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(Return(std::ref(x))); // Wrong! + x = 42; + EXPECT_EQ(foo.GetValue(), 42); +``` + +Unfortunately, it doesn't work here. The above code will fail with error: + +```text +Value of: foo.GetValue() + Actual: 0 +Expected: 42 +``` + +The reason is that `Return(*value*)` converts `value` to the actual return type +of the mock function at the time when the action is *created*, not when it is +*executed*. (This behavior was chosen for the action to be safe when `value` is +a proxy object that references some temporary objects.) As a result, +`std::ref(x)` is converted to an `int` value (instead of a `const int&`) when +the expectation is set, and `Return(std::ref(x))` will always return 0. + +`ReturnPointee(pointer)` was provided to solve this problem specifically. It +returns the value pointed to by `pointer` at the time the action is *executed*: + +```cpp +using ::testing::ReturnPointee; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(ReturnPointee(&x)); // Note the & here. + x = 42; + EXPECT_EQ(foo.GetValue(), 42); // This will succeed now. +``` + +### Combining Actions + +Want to do more than one thing when a function is called? That's fine. `DoAll()` +allows you to do a sequence of actions every time. Only the return value of the +last action in the sequence will be used. + +```cpp +using ::testing::_; +using ::testing::DoAll; + +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, Bar, (int n), (override)); +}; +... + EXPECT_CALL(foo, Bar(_)) + .WillOnce(DoAll(action_1, + action_2, + ... + action_n)); +``` + +The return value of the last action **must** match the return type of the mocked +method. In the example above, `action_n` could be `Return(true)`, or a lambda +that returns a `bool`, but not `SaveArg`, which returns `void`. Otherwise the +signature of `DoAll` would not match the signature expected by `WillOnce`, which +is the signature of the mocked method, and it wouldn't compile. + +### Verifying Complex Arguments {#SaveArgVerify} + +If you want to verify that a method is called with a particular argument but the +match criteria is complex, it can be difficult to distinguish between +cardinality failures (calling the method the wrong number of times) and argument +match failures. Similarly, if you are matching multiple parameters, it may not +be easy to distinguishing which argument failed to match. For example: + +```cpp + // Not ideal: this could fail because of a problem with arg1 or arg2, or maybe + // just the method wasn't called. + EXPECT_CALL(foo, SendValues(_, ElementsAre(1, 4, 4, 7), EqualsProto( ... ))); +``` + +You can instead save the arguments and test them individually: + +```cpp + EXPECT_CALL(foo, SendValues) + .WillOnce(DoAll(SaveArg<1>(&actual_array), SaveArg<2>(&actual_proto))); + ... run the test + EXPECT_THAT(actual_array, ElementsAre(1, 4, 4, 7)); + EXPECT_THAT(actual_proto, EqualsProto( ... )); +``` + +### Mocking Side Effects {#MockingSideEffects} + +Sometimes a method exhibits its effect not via returning a value but via side +effects. For example, it may change some global state or modify an output +argument. To mock side effects, in general you can define your own action by +implementing `::testing::ActionInterface`. + +If all you need to do is to change an output argument, the built-in +`SetArgPointee()` action is convenient: + +```cpp +using ::testing::_; +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + MOCK_METHOD(void, Mutate, (bool mutate, int* value), (override)); + ... +} +... + MockMutator mutator; + EXPECT_CALL(mutator, Mutate(true, _)) + .WillOnce(SetArgPointee<1>(5)); +``` + +In this example, when `mutator.Mutate()` is called, we will assign 5 to the +`int` variable pointed to by argument #1 (0-based). + +`SetArgPointee()` conveniently makes an internal copy of the value you pass to +it, removing the need to keep the value in scope and alive. The implication +however is that the value must have a copy constructor and assignment operator. + +If the mock method also needs to return a value as well, you can chain +`SetArgPointee()` with `Return()` using `DoAll()`, remembering to put the +`Return()` statement last: + +```cpp +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + ... + MOCK_METHOD(bool, MutateInt, (int* value), (override)); +} +... + MockMutator mutator; + EXPECT_CALL(mutator, MutateInt(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), + Return(true))); +``` + +Note, however, that if you use the `ReturnOKWith()` method, it will override the +values provided by `SetArgPointee()` in the response parameters of your function +call. + +If the output argument is an array, use the `SetArrayArgument(first, last)` +action instead. It copies the elements in source range `[first, last)` to the +array pointed to by the `N`-th (0-based) argument: + +```cpp +using ::testing::NotNull; +using ::testing::SetArrayArgument; + +class MockArrayMutator : public ArrayMutator { + public: + MOCK_METHOD(void, Mutate, (int* values, int num_values), (override)); + ... +} +... + MockArrayMutator mutator; + int values[5] = {1, 2, 3, 4, 5}; + EXPECT_CALL(mutator, Mutate(NotNull(), 5)) + .WillOnce(SetArrayArgument<0>(values, values + 5)); +``` + +This also works when the argument is an output iterator: + +```cpp +using ::testing::_; +using ::testing::SetArrayArgument; + +class MockRolodex : public Rolodex { + public: + MOCK_METHOD(void, GetNames, (std::back_insert_iterator>), + (override)); + ... +} +... + MockRolodex rolodex; + vector names = {"George", "John", "Thomas"}; + EXPECT_CALL(rolodex, GetNames(_)) + .WillOnce(SetArrayArgument<0>(names.begin(), names.end())); +``` + +### Changing a Mock Object's Behavior Based on the State + +If you expect a call to change the behavior of a mock object, you can use +`::testing::InSequence` to specify different behaviors before and after the +call: + +```cpp +using ::testing::InSequence; +using ::testing::Return; + +... + { + InSequence seq; + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(my_mock, Flush()); + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(false)); + } + my_mock.FlushIfDirty(); +``` + +This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called +and return `false` afterwards. + +If the behavior change is more complex, you can store the effects in a variable +and make a mock method get its return value from that variable: + +```cpp +using ::testing::_; +using ::testing::SaveArg; +using ::testing::Return; + +ACTION_P(ReturnPointee, p) { return *p; } +... + int previous_value = 0; + EXPECT_CALL(my_mock, GetPrevValue) + .WillRepeatedly(ReturnPointee(&previous_value)); + EXPECT_CALL(my_mock, UpdateValue) + .WillRepeatedly(SaveArg<0>(&previous_value)); + my_mock.DoSomethingToUpdateValue(); +``` + +Here `my_mock.GetPrevValue()` will always return the argument of the last +`UpdateValue()` call. + +### Setting the Default Value for a Return Type {#DefaultValue} + +If a mock method's return type is a built-in C++ type or pointer, by default it +will return 0 when invoked. Also, in C++ 11 and above, a mock method whose +return type has a default constructor will return a default-constructed value by +default. You only need to specify an action if this default value doesn't work +for you. + +Sometimes, you may want to change this default value, or you may want to specify +a default value for types gMock doesn't know about. You can do this using the +`::testing::DefaultValue` class template: + +```cpp +using ::testing::DefaultValue; + +class MockFoo : public Foo { + public: + MOCK_METHOD(Bar, CalculateBar, (), (override)); +}; + + +... + Bar default_bar; + // Sets the default return value for type Bar. + DefaultValue::Set(default_bar); + + MockFoo foo; + + // We don't need to specify an action here, as the default + // return value works for us. + EXPECT_CALL(foo, CalculateBar()); + + foo.CalculateBar(); // This should return default_bar. + + // Unsets the default return value. + DefaultValue::Clear(); +``` + +Please note that changing the default value for a type can make your tests hard +to understand. We recommend you to use this feature judiciously. For example, +you may want to make sure the `Set()` and `Clear()` calls are right next to the +code that uses your mock. + +### Setting the Default Actions for a Mock Method + +You've learned how to change the default value of a given type. However, this +may be too coarse for your purpose: perhaps you have two mock methods with the +same return type and you want them to have different behaviors. The `ON_CALL()` +macro allows you to customize your mock's behavior at the method level: + +```cpp +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Gt; +using ::testing::Return; +... + ON_CALL(foo, Sign(_)) + .WillByDefault(Return(-1)); + ON_CALL(foo, Sign(0)) + .WillByDefault(Return(0)); + ON_CALL(foo, Sign(Gt(0))) + .WillByDefault(Return(1)); + + EXPECT_CALL(foo, Sign(_)) + .Times(AnyNumber()); + + foo.Sign(5); // This should return 1. + foo.Sign(-9); // This should return -1. + foo.Sign(0); // This should return 0. +``` + +As you may have guessed, when there are more than one `ON_CALL()` statements, +the newer ones in the order take precedence over the older ones. In other words, +the **last** one that matches the function arguments will be used. This matching +order allows you to set up the common behavior in a mock object's constructor or +the test fixture's set-up phase and specialize the mock's behavior later. + +Note that both `ON_CALL` and `EXPECT_CALL` have the same "later statements take +precedence" rule, but they don't interact. That is, `EXPECT_CALL`s have their +own precedence order distinct from the `ON_CALL` precedence order. + +### Using Functions/Methods/Functors/Lambdas as Actions {#FunctionsAsActions} + +If the built-in actions don't suit you, you can use an existing callable +(function, `std::function`, method, functor, lambda) as an action. + +```cpp +using ::testing::_; using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, Sum, (int x, int y), (override)); + MOCK_METHOD(bool, ComplexJob, (int x), (override)); +}; + +int CalculateSum(int x, int y) { return x + y; } +int Sum3(int x, int y, int z) { return x + y + z; } + +class Helper { + public: + bool ComplexJob(int x); +}; + +... + MockFoo foo; + Helper helper; + EXPECT_CALL(foo, Sum(_, _)) + .WillOnce(&CalculateSum) + .WillRepeatedly(Invoke(NewPermanentCallback(Sum3, 1))); + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce(Invoke(&helper, &Helper::ComplexJob)) + .WillOnce([] { return true; }) + .WillRepeatedly([](int x) { return x > 0; }); + + foo.Sum(5, 6); // Invokes CalculateSum(5, 6). + foo.Sum(2, 3); // Invokes Sum3(1, 2, 3). + foo.ComplexJob(10); // Invokes helper.ComplexJob(10). + foo.ComplexJob(-1); // Invokes the inline lambda. +``` + +The only requirement is that the type of the function, etc must be *compatible* +with the signature of the mock function, meaning that the latter's arguments (if +it takes any) can be implicitly converted to the corresponding arguments of the +former, and the former's return type can be implicitly converted to that of the +latter. So, you can invoke something whose type is *not* exactly the same as the +mock function, as long as it's safe to do so - nice, huh? + +Note that: + +* The action takes ownership of the callback and will delete it when the + action itself is destructed. +* If the type of a callback is derived from a base callback type `C`, you need + to implicitly cast it to `C` to resolve the overloading, e.g. + + ```cpp + using ::testing::Invoke; + ... + ResultCallback* is_ok = ...; + ... Invoke(is_ok) ...; // This works. + + BlockingClosure* done = new BlockingClosure; + ... Invoke(implicit_cast(done)) ...; // The cast is necessary. + ``` + +### Using Functions with Extra Info as Actions + +The function or functor you call using `Invoke()` must have the same number of +arguments as the mock function you use it for. Sometimes you may have a function +that takes more arguments, and you are willing to pass in the extra arguments +yourself to fill the gap. You can do this in gMock using callbacks with +pre-bound arguments. Here's an example: + +```cpp +using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MOCK_METHOD(char, DoThis, (int n), (override)); +}; + +char SignOfSum(int x, int y) { + const int sum = x + y; + return (sum > 0) ? '+' : (sum < 0) ? '-' : '0'; +} + +TEST_F(FooTest, Test) { + MockFoo foo; + + EXPECT_CALL(foo, DoThis(2)) + .WillOnce(Invoke(NewPermanentCallback(SignOfSum, 5))); + EXPECT_EQ(foo.DoThis(2), '+'); // Invokes SignOfSum(5, 2). +} +``` + +### Invoking a Function/Method/Functor/Lambda/Callback Without Arguments + +`Invoke()` passes the mock function's arguments to the function, etc being +invoked such that the callee has the full context of the call to work with. If +the invoked function is not interested in some or all of the arguments, it can +simply ignore them. + +Yet, a common pattern is that a test author wants to invoke a function without +the arguments of the mock function. She could do that using a wrapper function +that throws away the arguments before invoking an underlining nullary function. +Needless to say, this can be tedious and obscures the intent of the test. + +There are two solutions to this problem. First, you can pass any callable of +zero args as an action. Alternatively, use `InvokeWithoutArgs()`, which is like +`Invoke()` except that it doesn't pass the mock function's arguments to the +callee. Here's an example of each: + +```cpp +using ::testing::_; +using ::testing::InvokeWithoutArgs; + +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, ComplexJob, (int n), (override)); +}; + +bool Job1() { ... } +bool Job2(int n, char c) { ... } + +... + MockFoo foo; + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce([] { Job1(); }); + .WillOnce(InvokeWithoutArgs(NewPermanentCallback(Job2, 5, 'a'))); + + foo.ComplexJob(10); // Invokes Job1(). + foo.ComplexJob(20); // Invokes Job2(5, 'a'). +``` + +Note that: + +* The action takes ownership of the callback and will delete it when the + action itself is destructed. +* If the type of a callback is derived from a base callback type `C`, you need + to implicitly cast it to `C` to resolve the overloading, e.g. + + ```cpp + using ::testing::InvokeWithoutArgs; + ... + ResultCallback* is_ok = ...; + ... InvokeWithoutArgs(is_ok) ...; // This works. + + BlockingClosure* done = ...; + ... InvokeWithoutArgs(implicit_cast(done)) ...; + // The cast is necessary. + ``` + +### Invoking an Argument of the Mock Function + +Sometimes a mock function will receive a function pointer, a functor (in other +words, a "callable") as an argument, e.g. + +```cpp +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, DoThis, (int n, (ResultCallback1* callback)), + (override)); +}; +``` + +and you may want to invoke this callable argument: + +```cpp +using ::testing::_; +... + MockFoo foo; + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(...); + // Will execute callback->Run(5), where callback is the + // second argument DoThis() receives. +``` + +{: .callout .note} +NOTE: The section below is legacy documentation from before C++ had lambdas: + +Arghh, you need to refer to a mock function argument but C++ has no lambda +(yet), so you have to define your own action. :-( Or do you really? + +Well, gMock has an action to solve *exactly* this problem: + +```cpp +InvokeArgument(arg_1, arg_2, ..., arg_m) +``` + +will invoke the `N`-th (0-based) argument the mock function receives, with +`arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is a function +pointer, a functor, or a callback. gMock handles them all. + +With that, you could write: + +```cpp +using ::testing::_; +using ::testing::InvokeArgument; +... + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(InvokeArgument<1>(5)); + // Will execute callback->Run(5), where callback is the + // second argument DoThis() receives. +``` + +What if the callable takes an argument by reference? No problem - just wrap it +inside `std::ref()`: + +```cpp + ... + MOCK_METHOD(bool, Bar, + ((ResultCallback2* callback)), + (override)); + ... + using ::testing::_; + using ::testing::InvokeArgument; + ... + MockFoo foo; + Helper helper; + ... + EXPECT_CALL(foo, Bar(_)) + .WillOnce(InvokeArgument<0>(5, std::ref(helper))); + // std::ref(helper) guarantees that a reference to helper, not a copy of + // it, will be passed to the callback. +``` + +What if the callable takes an argument by reference and we do **not** wrap the +argument in `std::ref()`? Then `InvokeArgument()` will *make a copy* of the +argument, and pass a *reference to the copy*, instead of a reference to the +original value, to the callable. This is especially handy when the argument is a +temporary value: + +```cpp + ... + MOCK_METHOD(bool, DoThat, (bool (*f)(const double& x, const string& s)), + (override)); + ... + using ::testing::_; + using ::testing::InvokeArgument; + ... + MockFoo foo; + ... + EXPECT_CALL(foo, DoThat(_)) + .WillOnce(InvokeArgument<0>(5.0, string("Hi"))); + // Will execute (*f)(5.0, string("Hi")), where f is the function pointer + // DoThat() receives. Note that the values 5.0 and string("Hi") are + // temporary and dead once the EXPECT_CALL() statement finishes. Yet + // it's fine to perform this action later, since a copy of the values + // are kept inside the InvokeArgument action. +``` + +### Ignoring an Action's Result + +Sometimes you have an action that returns *something*, but you need an action +that returns `void` (perhaps you want to use it in a mock function that returns +`void`, or perhaps it needs to be used in `DoAll()` and it's not the last in the +list). `IgnoreResult()` lets you do that. For example: + +```cpp +using ::testing::_; +using ::testing::DoAll; +using ::testing::IgnoreResult; +using ::testing::Return; + +int Process(const MyData& data); +string DoSomething(); + +class MockFoo : public Foo { + public: + MOCK_METHOD(void, Abc, (const MyData& data), (override)); + MOCK_METHOD(bool, Xyz, (), (override)); +}; + + ... + MockFoo foo; + EXPECT_CALL(foo, Abc(_)) + // .WillOnce(Invoke(Process)); + // The above line won't compile as Process() returns int but Abc() needs + // to return void. + .WillOnce(IgnoreResult(Process)); + EXPECT_CALL(foo, Xyz()) + .WillOnce(DoAll(IgnoreResult(DoSomething), + // Ignores the string DoSomething() returns. + Return(true))); +``` + +Note that you **cannot** use `IgnoreResult()` on an action that already returns +`void`. Doing so will lead to ugly compiler errors. + +### Selecting an Action's Arguments {#SelectingArgs} + +Say you have a mock function `Foo()` that takes seven arguments, and you have a +custom action that you want to invoke when `Foo()` is called. Trouble is, the +custom action only wants three arguments: + +```cpp +using ::testing::_; +using ::testing::Invoke; +... + MOCK_METHOD(bool, Foo, + (bool visible, const string& name, int x, int y, + (const map>), double& weight, double min_weight, + double max_wight)); +... +bool IsVisibleInQuadrant1(bool visible, int x, int y) { + return visible && x >= 0 && y >= 0; +} +... + EXPECT_CALL(mock, Foo) + .WillOnce(Invoke(IsVisibleInQuadrant1)); // Uh, won't compile. :-( +``` + +To please the compiler God, you need to define an "adaptor" that has the same +signature as `Foo()` and calls the custom action with the right arguments: + +```cpp +using ::testing::_; +using ::testing::Invoke; +... +bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y, + const map, double>& weight, + double min_weight, double max_wight) { + return IsVisibleInQuadrant1(visible, x, y); +} +... + EXPECT_CALL(mock, Foo) + .WillOnce(Invoke(MyIsVisibleInQuadrant1)); // Now it works. +``` + +But isn't this awkward? + +gMock provides a generic *action adaptor*, so you can spend your time minding +more important business than writing your own adaptors. Here's the syntax: + +```cpp +WithArgs(action) +``` + +creates an action that passes the arguments of the mock function at the given +indices (0-based) to the inner `action` and performs it. Using `WithArgs`, our +original example can be written as: + +```cpp +using ::testing::_; +using ::testing::Invoke; +using ::testing::WithArgs; +... + EXPECT_CALL(mock, Foo) + .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1))); // No need to define your own adaptor. +``` + +For better readability, gMock also gives you: + +* `WithoutArgs(action)` when the inner `action` takes *no* argument, and +* `WithArg(action)` (no `s` after `Arg`) when the inner `action` takes + *one* argument. + +As you may have realized, `InvokeWithoutArgs(...)` is just syntactic sugar for +`WithoutArgs(Invoke(...))`. + +Here are more tips: + +* The inner action used in `WithArgs` and friends does not have to be + `Invoke()` -- it can be anything. +* You can repeat an argument in the argument list if necessary, e.g. + `WithArgs<2, 3, 3, 5>(...)`. +* You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`. +* The types of the selected arguments do *not* have to match the signature of + the inner action exactly. It works as long as they can be implicitly + converted to the corresponding arguments of the inner action. For example, + if the 4-th argument of the mock function is an `int` and `my_action` takes + a `double`, `WithArg<4>(my_action)` will work. + +### Ignoring Arguments in Action Functions + +The [selecting-an-action's-arguments](#SelectingArgs) recipe showed us one way +to make a mock function and an action with incompatible argument lists fit +together. The downside is that wrapping the action in `WithArgs<...>()` can get +tedious for people writing the tests. + +If you are defining a function (or method, functor, lambda, callback) to be used +with `Invoke*()`, and you are not interested in some of its arguments, an +alternative to `WithArgs` is to declare the uninteresting arguments as `Unused`. +This makes the definition less cluttered and less fragile in case the types of +the uninteresting arguments change. It could also increase the chance the action +function can be reused. For example, given + +```cpp + public: + MOCK_METHOD(double, Foo, double(const string& label, double x, double y), + (override)); + MOCK_METHOD(double, Bar, (int index, double x, double y), (override)); +``` + +instead of + +```cpp +using ::testing::_; +using ::testing::Invoke; + +double DistanceToOriginWithLabel(const string& label, double x, double y) { + return sqrt(x*x + y*y); +} +double DistanceToOriginWithIndex(int index, double x, double y) { + return sqrt(x*x + y*y); +} +... + EXPECT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOriginWithLabel)); + EXPECT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOriginWithIndex)); +``` + +you could write + +```cpp +using ::testing::_; +using ::testing::Invoke; +using ::testing::Unused; + +double DistanceToOrigin(Unused, double x, double y) { + return sqrt(x*x + y*y); +} +... + EXPECT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOrigin)); + EXPECT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOrigin)); +``` + +### Sharing Actions + +Just like matchers, a gMock action object consists of a pointer to a ref-counted +implementation object. Therefore copying actions is also allowed and very +efficient. When the last action that references the implementation object dies, +the implementation object will be deleted. + +If you have some complex action that you want to use again and again, you may +not have to build it from scratch every time. If the action doesn't have an +internal state (i.e. if it always does the same thing no matter how many times +it has been called), you can assign it to an action variable and use that +variable repeatedly. For example: + +```cpp +using ::testing::Action; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +... + Action set_flag = DoAll(SetArgPointee<0>(5), + Return(true)); + ... use set_flag in .WillOnce() and .WillRepeatedly() ... +``` + +However, if the action has its own state, you may be surprised if you share the +action object. Suppose you have an action factory `IncrementCounter(init)` which +creates an action that increments and returns a counter whose initial value is +`init`, using two actions created from the same expression and using a shared +action will exhibit different behaviors. Example: + +```cpp + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(IncrementCounter(0)); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(IncrementCounter(0)); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 1 - DoThat() uses a different + // counter than DoThis()'s. +``` + +versus + +```cpp +using ::testing::Action; +... + Action increment = IncrementCounter(0); + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(increment); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(increment); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 3 - the counter is shared. +``` + +### Testing Asynchronous Behavior + +One oft-encountered problem with gMock is that it can be hard to test +asynchronous behavior. Suppose you had a `EventQueue` class that you wanted to +test, and you created a separate `EventDispatcher` interface so that you could +easily mock it out. However, the implementation of the class fired all the +events on a background thread, which made test timings difficult. You could just +insert `sleep()` statements and hope for the best, but that makes your test +behavior nondeterministic. A better way is to use gMock actions and +`Notification` objects to force your asynchronous test to behave synchronously. + +```cpp +class MockEventDispatcher : public EventDispatcher { + MOCK_METHOD(bool, DispatchEvent, (int32), (override)); +}; + +TEST(EventQueueTest, EnqueueEventTest) { + MockEventDispatcher mock_event_dispatcher; + EventQueue event_queue(&mock_event_dispatcher); + + const int32 kEventId = 321; + absl::Notification done; + EXPECT_CALL(mock_event_dispatcher, DispatchEvent(kEventId)) + .WillOnce([&done] { done.Notify(); }); + + event_queue.EnqueueEvent(kEventId); + done.WaitForNotification(); +} +``` + +In the example above, we set our normal gMock expectations, but then add an +additional action to notify the `Notification` object. Now we can just call +`Notification::WaitForNotification()` in the main thread to wait for the +asynchronous call to finish. After that, our test suite is complete and we can +safely exit. + +{: .callout .note} +Note: this example has a downside: namely, if the expectation is not satisfied, +our test will run forever. It will eventually time-out and fail, but it will +take longer and be slightly harder to debug. To alleviate this problem, you can +use `WaitForNotificationWithTimeout(ms)` instead of `WaitForNotification()`. + +## Misc Recipes on Using gMock + +### Mocking Methods That Use Move-Only Types + +C++11 introduced *move-only types*. A move-only-typed value can be moved from +one object to another, but cannot be copied. `std::unique_ptr` is probably +the most commonly used move-only type. + +Mocking a method that takes and/or returns move-only types presents some +challenges, but nothing insurmountable. This recipe shows you how you can do it. +Note that the support for move-only method arguments was only introduced to +gMock in April 2017; in older code, you may find more complex +[workarounds](#LegacyMoveOnly) for lack of this feature. + +Let’s say we are working on a fictional project that lets one post and share +snippets called “buzzes”. Your code uses these types: + +```cpp +enum class AccessLevel { kInternal, kPublic }; + +class Buzz { + public: + explicit Buzz(AccessLevel access) { ... } + ... +}; + +class Buzzer { + public: + virtual ~Buzzer() {} + virtual std::unique_ptr MakeBuzz(StringPiece text) = 0; + virtual bool ShareBuzz(std::unique_ptr buzz, int64_t timestamp) = 0; + ... +}; +``` + +A `Buzz` object represents a snippet being posted. A class that implements the +`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in +`Buzzer` may return a `unique_ptr` or take a `unique_ptr`. Now we +need to mock `Buzzer` in our tests. + +To mock a method that accepts or returns move-only types, you just use the +familiar `MOCK_METHOD` syntax as usual: + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD(std::unique_ptr, MakeBuzz, (StringPiece text), (override)); + MOCK_METHOD(bool, ShareBuzz, (std::unique_ptr buzz, int64_t timestamp), + (override)); +}; +``` + +Now that we have the mock class defined, we can use it in tests. In the +following code examples, we assume that we have defined a `MockBuzzer` object +named `mock_buzzer_`: + +```cpp + MockBuzzer mock_buzzer_; +``` + +First let’s see how we can set expectations on the `MakeBuzz()` method, which +returns a `unique_ptr`. + +As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or +`.WillRepeatedly()` clause), when that expectation fires, the default action for +that method will be taken. Since `unique_ptr<>` has a default constructor that +returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an +action: + +```cpp +using ::testing::IsNull; +... + // Use the default action. + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")); + + // Triggers the previous EXPECT_CALL. + EXPECT_THAT(mock_buzzer_.MakeBuzz("hello"), IsNull()); +``` + +If you are not happy with the default action, you can tweak it as usual; see +[Setting Default Actions](#OnCall). + +If you just need to return a move-only value, you can use it in combination with +`WillOnce`. For example: + +```cpp + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")) + .WillOnce(Return(std::make_unique(AccessLevel::kInternal))); + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("hello")); +``` + +Quiz time! What do you think will happen if a `Return` action is performed more +than once (e.g. you write `... .WillRepeatedly(Return(std::move(...)));`)? Come +think of it, after the first time the action runs, the source value will be +consumed (since it’s a move-only value), so the next time around, there’s no +value to move from -- you’ll get a run-time error that `Return(std::move(...))` +can only be run once. + +If you need your mock method to do more than just moving a pre-defined value, +remember that you can always use a lambda or a callable object, which can do +pretty much anything you want: + +```cpp + EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) + .WillRepeatedly([](StringPiece text) { + return std::make_unique(AccessLevel::kInternal); + }); + + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); +``` + +Every time this `EXPECT_CALL` fires, a new `unique_ptr` will be created +and returned. You cannot do this with `Return(std::make_unique<...>(...))`. + +That covers returning move-only values; but how do we work with methods +accepting move-only arguments? The answer is that they work normally, although +some actions will not compile when any of method's arguments are move-only. You +can always use `Return`, or a [lambda or functor](#FunctionsAsActions): + +```cpp + using ::testing::Unused; + + EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)).WillOnce(Return(true)); + EXPECT_TRUE(mock_buzzer_.ShareBuzz(std::make_unique(AccessLevel::kInternal)), + 0); + + EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)).WillOnce( + [](std::unique_ptr buzz, Unused) { return buzz != nullptr; }); + EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0)); +``` + +Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...) +could in principle support move-only arguments, but the support for this is not +implemented yet. If this is blocking you, please file a bug. + +A few actions (e.g. `DoAll`) copy their arguments internally, so they can never +work with non-copyable objects; you'll have to use functors instead. + +#### Legacy workarounds for move-only types {#LegacyMoveOnly} + +Support for move-only function arguments was only introduced to gMock in April +of 2017. In older code, you may encounter the following workaround for the lack +of this feature (it is no longer necessary - we're including it just for +reference): + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD(bool, DoShareBuzz, (Buzz* buzz, Time timestamp)); + bool ShareBuzz(std::unique_ptr buzz, Time timestamp) override { + return DoShareBuzz(buzz.get(), timestamp); + } +}; +``` + +The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call +it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of +setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock +method: + +```cpp + MockBuzzer mock_buzzer_; + EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); + + // When one calls ShareBuzz() on the MockBuzzer like this, the call is + // forwarded to DoShareBuzz(), which is mocked. Therefore this statement + // will trigger the above EXPECT_CALL. + mock_buzzer_.ShareBuzz(std::make_unique(AccessLevel::kInternal), 0); +``` + +### Making the Compilation Faster + +Believe it or not, the *vast majority* of the time spent on compiling a mock +class is in generating its constructor and destructor, as they perform +non-trivial tasks (e.g. verification of the expectations). What's more, mock +methods with different signatures have different types and thus their +constructors/destructors need to be generated by the compiler separately. As a +result, if you mock many different types of methods, compiling your mock class +can get really slow. + +If you are experiencing slow compilation, you can move the definition of your +mock class' constructor and destructor out of the class body and into a `.cc` +file. This way, even if you `#include` your mock class in N files, the compiler +only needs to generate its constructor and destructor once, resulting in a much +faster compilation. + +Let's illustrate the idea using an example. Here's the definition of a mock +class before applying this recipe: + +```cpp +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // Since we don't declare the constructor or the destructor, + // the compiler will generate them in every translation unit + // where this mock class is used. + + MOCK_METHOD(int, DoThis, (), (override)); + MOCK_METHOD(bool, DoThat, (const char* str), (override)); + ... more mock methods ... +}; +``` + +After the change, it would look like: + +```cpp +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // The constructor and destructor are declared, but not defined, here. + MockFoo(); + virtual ~MockFoo(); + + MOCK_METHOD(int, DoThis, (), (override)); + MOCK_METHOD(bool, DoThat, (const char* str), (override)); + ... more mock methods ... +}; +``` + +and + +```cpp +// File mock_foo.cc. +#include "path/to/mock_foo.h" + +// The definitions may appear trivial, but the functions actually do a +// lot of things through the constructors/destructors of the member +// variables used to implement the mock methods. +MockFoo::MockFoo() {} +MockFoo::~MockFoo() {} +``` + +### Forcing a Verification + +When it's being destroyed, your friendly mock object will automatically verify +that all expectations on it have been satisfied, and will generate googletest +failures if not. This is convenient as it leaves you with one less thing to +worry about. That is, unless you are not sure if your mock object will be +destroyed. + +How could it be that your mock object won't eventually be destroyed? Well, it +might be created on the heap and owned by the code you are testing. Suppose +there's a bug in that code and it doesn't delete the mock object properly - you +could end up with a passing test when there's actually a bug. + +Using a heap checker is a good idea and can alleviate the concern, but its +implementation is not 100% reliable. So, sometimes you do want to *force* gMock +to verify a mock object before it is (hopefully) destructed. You can do this +with `Mock::VerifyAndClearExpectations(&mock_object)`: + +```cpp +TEST(MyServerTest, ProcessesRequest) { + using ::testing::Mock; + + MockFoo* const foo = new MockFoo; + EXPECT_CALL(*foo, ...)...; + // ... other expectations ... + + // server now owns foo. + MyServer server(foo); + server.ProcessRequest(...); + + // In case that server's destructor will forget to delete foo, + // this will verify the expectations anyway. + Mock::VerifyAndClearExpectations(foo); +} // server is destroyed when it goes out of scope here. +``` + +{: .callout .tip} +**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a `bool` to +indicate whether the verification was successful (`true` for yes), so you can +wrap that function call inside a `ASSERT_TRUE()` if there is no point going +further when the verification has failed. + +Do not set new expectations after verifying and clearing a mock after its use. +Setting expectations after code that exercises the mock has undefined behavior. +See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more +information. + +### Using Checkpoints {#UsingCheckPoints} + +Sometimes you might want to test a mock object's behavior in phases whose sizes +are each manageable, or you might want to set more detailed expectations about +which API calls invoke which mock functions. + +A technique you can use is to put the expectations in a sequence and insert +calls to a dummy "checkpoint" function at specific places. Then you can verify +that the mock function calls do happen at the right time. For example, if you +are exercising the code: + +```cpp + Foo(1); + Foo(2); + Foo(3); +``` + +and want to verify that `Foo(1)` and `Foo(3)` both invoke `mock.Bar("a")`, but +`Foo(2)` doesn't invoke anything, you can write: + +```cpp +using ::testing::MockFunction; + +TEST(FooTest, InvokesBarCorrectly) { + MyMock mock; + // Class MockFunction has exactly one mock method. It is named + // Call() and has type F. + MockFunction check; + { + InSequence s; + + EXPECT_CALL(mock, Bar("a")); + EXPECT_CALL(check, Call("1")); + EXPECT_CALL(check, Call("2")); + EXPECT_CALL(mock, Bar("a")); + } + Foo(1); + check.Call("1"); + Foo(2); + check.Call("2"); + Foo(3); +} +``` + +The expectation spec says that the first `Bar("a")` call must happen before +checkpoint "1", the second `Bar("a")` call must happen after checkpoint "2", and +nothing should happen between the two checkpoints. The explicit checkpoints make +it clear which `Bar("a")` is called by which call to `Foo()`. + +### Mocking Destructors + +Sometimes you want to make sure a mock object is destructed at the right time, +e.g. after `bar->A()` is called but before `bar->B()` is called. We already know +that you can specify constraints on the [order](#OrderedCalls) of mock function +calls, so all we need to do is to mock the destructor of the mock function. + +This sounds simple, except for one problem: a destructor is a special function +with special syntax and special semantics, and the `MOCK_METHOD` macro doesn't +work for it: + +```cpp +MOCK_METHOD(void, ~MockFoo, ()); // Won't compile! +``` + +The good news is that you can use a simple pattern to achieve the same effect. +First, add a mock function `Die()` to your mock class and call it in the +destructor, like this: + +```cpp +class MockFoo : public Foo { + ... + // Add the following two lines to the mock class. + MOCK_METHOD(void, Die, ()); + ~MockFoo() override { Die(); } +}; +``` + +(If the name `Die()` clashes with an existing symbol, choose another name.) Now, +we have translated the problem of testing when a `MockFoo` object dies to +testing when its `Die()` method is called: + +```cpp + MockFoo* foo = new MockFoo; + MockBar* bar = new MockBar; + ... + { + InSequence s; + + // Expects *foo to die after bar->A() and before bar->B(). + EXPECT_CALL(*bar, A()); + EXPECT_CALL(*foo, Die()); + EXPECT_CALL(*bar, B()); + } +``` + +And that's that. + +### Using gMock and Threads {#UsingThreads} + +In a **unit** test, it's best if you could isolate and test a piece of code in a +single-threaded context. That avoids race conditions and dead locks, and makes +debugging your test much easier. + +Yet most programs are multi-threaded, and sometimes to test something we need to +pound on it from more than one thread. gMock works for this purpose too. + +Remember the steps for using a mock: + +1. Create a mock object `foo`. +2. Set its default actions and expectations using `ON_CALL()` and + `EXPECT_CALL()`. +3. The code under test calls methods of `foo`. +4. Optionally, verify and reset the mock. +5. Destroy the mock yourself, or let the code under test destroy it. The + destructor will automatically verify it. + +If you follow the following simple rules, your mocks and threads can live +happily together: + +* Execute your *test code* (as opposed to the code being tested) in *one* + thread. This makes your test easy to follow. +* Obviously, you can do step #1 without locking. +* When doing step #2 and #5, make sure no other thread is accessing `foo`. + Obvious too, huh? +* #3 and #4 can be done either in one thread or in multiple threads - anyway + you want. gMock takes care of the locking, so you don't have to do any - + unless required by your test logic. + +If you violate the rules (for example, if you set expectations on a mock while +another thread is calling its methods), you get undefined behavior. That's not +fun, so don't do it. + +gMock guarantees that the action for a mock function is done in the same thread +that called the mock function. For example, in + +```cpp + EXPECT_CALL(mock, Foo(1)) + .WillOnce(action1); + EXPECT_CALL(mock, Foo(2)) + .WillOnce(action2); +``` + +if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2, gMock will +execute `action1` in thread 1 and `action2` in thread 2. + +gMock does *not* impose a sequence on actions performed in different threads +(doing so may create deadlocks as the actions may need to cooperate). This means +that the execution of `action1` and `action2` in the above example *may* +interleave. If this is a problem, you should add proper synchronization logic to +`action1` and `action2` to make the test thread-safe. + +Also, remember that `DefaultValue` is a global resource that potentially +affects *all* living mock objects in your program. Naturally, you won't want to +mess with it from multiple threads or when there still are mocks in action. + +### Controlling How Much Information gMock Prints + +When gMock sees something that has the potential of being an error (e.g. a mock +function with no expectation is called, a.k.a. an uninteresting call, which is +allowed but perhaps you forgot to explicitly ban the call), it prints some +warning messages, including the arguments of the function, the return value, and +the stack trace. Hopefully this will remind you to take a look and see if there +is indeed a problem. + +Sometimes you are confident that your tests are correct and may not appreciate +such friendly messages. Some other times, you are debugging your tests or +learning about the behavior of the code you are testing, and wish you could +observe every mock call that happens (including argument values, the return +value, and the stack trace). Clearly, one size doesn't fit all. + +You can control how much gMock tells you using the `--gmock_verbose=LEVEL` +command-line flag, where `LEVEL` is a string with three possible values: + +* `info`: gMock will print all informational messages, warnings, and errors + (most verbose). At this setting, gMock will also log any calls to the + `ON_CALL/EXPECT_CALL` macros. It will include a stack trace in + "uninteresting call" warnings. +* `warning`: gMock will print both warnings and errors (less verbose); it will + omit the stack traces in "uninteresting call" warnings. This is the default. +* `error`: gMock will print errors only (least verbose). + +Alternatively, you can adjust the value of that flag from within your tests like +so: + +```cpp + ::testing::FLAGS_gmock_verbose = "error"; +``` + +If you find gMock printing too many stack frames with its informational or +warning messages, remember that you can control their amount with the +`--gtest_stack_trace_depth=max_depth` flag. + +Now, judiciously use the right flag to enable gMock serve you better! + +### Gaining Super Vision into Mock Calls + +You have a test using gMock. It fails: gMock tells you some expectations aren't +satisfied. However, you aren't sure why: Is there a typo somewhere in the +matchers? Did you mess up the order of the `EXPECT_CALL`s? Or is the code under +test doing something wrong? How can you find out the cause? + +Won't it be nice if you have X-ray vision and can actually see the trace of all +`EXPECT_CALL`s and mock method calls as they are made? For each call, would you +like to see its actual argument values and which `EXPECT_CALL` gMock thinks it +matches? If you still need some help to figure out who made these calls, how +about being able to see the complete stack trace at each mock call? + +You can unlock this power by running your test with the `--gmock_verbose=info` +flag. For example, given the test program: + +```cpp +#include + +using ::testing::_; +using ::testing::HasSubstr; +using ::testing::Return; + +class MockFoo { + public: + MOCK_METHOD(void, F, (const string& x, const string& y)); +}; + +TEST(Foo, Bar) { + MockFoo mock; + EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return()); + EXPECT_CALL(mock, F("a", "b")); + EXPECT_CALL(mock, F("c", HasSubstr("d"))); + + mock.F("a", "good"); + mock.F("a", "b"); +} +``` + +if you run it with `--gmock_verbose=info`, you will see this output: + +```shell +[ RUN ] Foo.Bar + +foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked +Stack trace: ... + +foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked +Stack trace: ... + +foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked +Stack trace: ... + +foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))... + Function call: F(@0x7fff7c8dad40"a",@0x7fff7c8dad10"good") +Stack trace: ... + +foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))... + Function call: F(@0x7fff7c8dada0"a",@0x7fff7c8dad70"b") +Stack trace: ... + +foo_test.cc:16: Failure +Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))... + Expected: to be called once + Actual: never called - unsatisfied and active +[ FAILED ] Foo.Bar +``` + +Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo and +should actually be `"a"`. With the above message, you should see that the actual +`F("a", "good")` call is matched by the first `EXPECT_CALL`, not the third as +you thought. From that it should be obvious that the third `EXPECT_CALL` is +written wrong. Case solved. + +If you are interested in the mock call trace but not the stack traces, you can +combine `--gmock_verbose=info` with `--gtest_stack_trace_depth=0` on the test +command line. + +### Running Tests in Emacs + +If you build and run your tests in Emacs using the `M-x google-compile` command +(as many googletest users do), the source file locations of gMock and googletest +errors will be highlighted. Just press `` on one of them and you'll be +taken to the offending line. Or, you can just type `C-x`` to jump to the next +error. + +To make it even easier, you can add the following lines to your `~/.emacs` file: + +```text +(global-set-key "\M-m" 'google-compile) ; m is for make +(global-set-key [M-down] 'next-error) +(global-set-key [M-up] '(lambda () (interactive) (next-error -1))) +``` + +Then you can type `M-m` to start a build (if you want to run the test as well, +just make sure `foo_test.run` or `runtests` is in the build command you supply +after typing `M-m`), or `M-up`/`M-down` to move back and forth between errors. + +## Extending gMock + +### Writing New Matchers Quickly {#NewMatchers} + +{: .callout .warning} +WARNING: gMock does not guarantee when or how many times a matcher will be +invoked. Therefore, all matchers must be functionally pure. See +[this section](#PureMatchers) for more details. + +The `MATCHER*` family of macros can be used to define custom matchers easily. +The syntax: + +```cpp +MATCHER(name, description_string_expression) { statements; } +``` + +will define a matcher with the given name that executes the statements, which +must return a `bool` to indicate if the match succeeds. Inside the statements, +you can refer to the value being matched by `arg`, and refer to its type by +`arg_type`. + +The *description string* is a `string`-typed expression that documents what the +matcher does, and is used to generate the failure message when the match fails. +It can (and should) reference the special `bool` variable `negation`, and should +evaluate to the description of the matcher when `negation` is `false`, or that +of the matcher's negation when `negation` is `true`. + +For convenience, we allow the description string to be empty (`""`), in which +case gMock will use the sequence of words in the matcher name as the +description. + +#### Basic Example + +```cpp +MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; } +``` + +allows you to write + +```cpp + // Expects mock_foo.Bar(n) to be called where n is divisible by 7. + EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7())); +``` + +or, + +```cpp + using ::testing::Not; + ... + // Verifies that a value is divisible by 7 and the other is not. + EXPECT_THAT(some_expression, IsDivisibleBy7()); + EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7())); +``` + +If the above assertions fail, they will print something like: + +```shell + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 + ... + Value of: some_other_expression + Expected: not (is divisible by 7) + Actual: 21 +``` + +where the descriptions `"is divisible by 7"` and `"not (is divisible by 7)"` are +automatically calculated from the matcher name `IsDivisibleBy7`. + +#### Adding Custom Failure Messages + +As you may have noticed, the auto-generated descriptions (especially those for +the negation) may not be so great. You can always override them with a `string` +expression of your own: + +```cpp +MATCHER(IsDivisibleBy7, + absl::StrCat(negation ? "isn't" : "is", " divisible by 7")) { + return (arg % 7) == 0; +} +``` + +Optionally, you can stream additional information to a hidden argument named +`result_listener` to explain the match result. For example, a better definition +of `IsDivisibleBy7` is: + +```cpp +MATCHER(IsDivisibleBy7, "") { + if ((arg % 7) == 0) + return true; + + *result_listener << "the remainder is " << (arg % 7); + return false; +} +``` + +With this definition, the above assertion will give a better message: + +```shell + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 (the remainder is 6) +``` + +#### Using EXPECT_ Statements in Matchers + +You can also use `EXPECT_...` (and `ASSERT_...`) statements inside custom +matcher definitions. In many cases, this allows you to write your matcher more +concisely while still providing an informative error message. For example: + +```cpp +MATCHER(IsDivisibleBy7, "") { + const auto remainder = arg % 7; + EXPECT_EQ(remainder, 0); + return true; +} +``` + +If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`, +you will get an error something like the following: + +```shell +Expected equality of these values: + remainder + Which is: 6 + 0 +``` + +#### `MatchAndExplain` + +You should let `MatchAndExplain()` print *any additional information* that can +help a user understand the match result. Note that it should explain why the +match succeeds in case of a success (unless it's obvious) - this is useful when +the matcher is used inside `Not()`. There is no need to print the argument value +itself, as gMock already prints it for you. + +#### Argument Types + +The type of the value being matched (`arg_type`) is determined by the +context in which you use the matcher and is supplied to you by the compiler, so +you don't need to worry about declaring it (nor can you). This allows the +matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match +any type where the value of `(arg % 7) == 0` can be implicitly converted to a +`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an +`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will +be `unsigned long`; and so on. + +### Writing New Parameterized Matchers Quickly + +Sometimes you'll want to define a matcher that has parameters. For that you can +use the macro: + +```cpp +MATCHER_P(name, param_name, description_string) { statements; } +``` + +where the description string can be either `""` or a `string` expression that +references `negation` and `param_name`. + +For example: + +```cpp +MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +``` + +will allow you to write: + +```cpp + EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +``` + +which may lead to this message (assuming `n` is 10): + +```shell + Value of: Blah("a") + Expected: has absolute value 10 + Actual: -9 +``` + +Note that both the matcher description and its parameter are printed, making the +message human-friendly. + +In the matcher definition body, you can write `foo_type` to reference the type +of a parameter named `foo`. For example, in the body of +`MATCHER_P(HasAbsoluteValue, value)` above, you can write `value_type` to refer +to the type of `value`. + +gMock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to `MATCHER_P10` to +support multi-parameter matchers: + +```cpp +MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; } +``` + +Please note that the custom description string is for a particular *instance* of +the matcher, where the parameters have been bound to actual values. Therefore +usually you'll want the parameter values to be part of the description. gMock +lets you do that by referencing the matcher parameters in the description string +expression. + +For example, + +```cpp +using ::testing::PrintToString; +MATCHER_P2(InClosedRange, low, hi, + absl::StrFormat("%s in range [%s, %s]", negation ? "isn't" : "is", + PrintToString(low), PrintToString(hi))) { + return low <= arg && arg <= hi; +} +... +EXPECT_THAT(3, InClosedRange(4, 6)); +``` + +would generate a failure that contains the message: + +```shell + Expected: is in range [4, 6] +``` + +If you specify `""` as the description, the failure message will contain the +sequence of words in the matcher name followed by the parameter values printed +as a tuple. For example, + +```cpp + MATCHER_P2(InClosedRange, low, hi, "") { ... } + ... + EXPECT_THAT(3, InClosedRange(4, 6)); +``` + +would generate a failure that contains the text: + +```shell + Expected: in closed range (4, 6) +``` + +For the purpose of typing, you can view + +```cpp +MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +``` + +as shorthand for + +```cpp +template +FooMatcherPk +Foo(p1_type p1, ..., pk_type pk) { ... } +``` + +When you write `Foo(v1, ..., vk)`, the compiler infers the types of the +parameters `v1`, ..., and `vk` for you. If you are not happy with the result of +the type inference, you can specify the types by explicitly instantiating the +template, as in `Foo(5, false)`. As said earlier, you don't get to +(or need to) specify `arg_type` as that's determined by the context in which the +matcher is used. + +You can assign the result of expression `Foo(p1, ..., pk)` to a variable of type +`FooMatcherPk`. This can be useful when composing +matchers. Matchers that don't have a parameter or have only one parameter have +special types: you can assign `Foo()` to a `FooMatcher`-typed variable, and +assign `Foo(p)` to a `FooMatcherP`-typed variable. + +While you can instantiate a matcher template with reference types, passing the +parameters by pointer usually makes your code more readable. If, however, you +still want to pass a parameter by reference, be aware that in the failure +message generated by the matcher you will see the value of the referenced object +but not its address. + +You can overload matchers with different numbers of parameters: + +```cpp +MATCHER_P(Blah, a, description_string_1) { ... } +MATCHER_P2(Blah, a, b, description_string_2) { ... } +``` + +While it's tempting to always use the `MATCHER*` macros when defining a new +matcher, you should also consider implementing the matcher interface directly +instead (see the recipes that follow), especially if you need to use the matcher +a lot. While these approaches require more work, they give you more control on +the types of the value being matched and the matcher parameters, which in +general leads to better compiler error messages that pay off in the long run. +They also allow overloading matchers based on parameter types (as opposed to +just based on the number of parameters). + +### Writing New Monomorphic Matchers + +A matcher of argument type `T` implements the matcher interface for `T` and does +two things: it tests whether a value of type `T` matches the matcher, and can +describe what kind of values it matches. The latter ability is used for +generating readable error messages when expectations are violated. + +A matcher of `T` must declare a typedef like: + +```cpp +using is_gtest_matcher = void; +``` + +and supports the following operations: + +```cpp +// Match a value and optionally explain into an ostream. +bool matched = matcher.MatchAndExplain(value, maybe_os); +// where `value` is of type `T` and +// `maybe_os` is of type `std::ostream*`, where it can be null if the caller +// is not interested in there textual explanation. + +matcher.DescribeTo(os); +matcher.DescribeNegationTo(os); +// where `os` is of type `std::ostream*`. +``` + +If you need a custom matcher but `Truly()` is not a good option (for example, +you may not be happy with the way `Truly(predicate)` describes itself, or you +may want your matcher to be polymorphic as `Eq(value)` is), you can define a +matcher to do whatever you want in two steps: first implement the matcher +interface, and then define a factory function to create a matcher instance. The +second step is not strictly needed but it makes the syntax of using the matcher +nicer. + +For example, you can define a matcher to test whether an `int` is divisible by 7 +and then use it like this: + +```cpp +using ::testing::Matcher; + +class DivisibleBy7Matcher { + public: + using is_gtest_matcher = void; + + bool MatchAndExplain(int n, std::ostream*) const { + return (n % 7) == 0; + } + + void DescribeTo(std::ostream* os) const { + *os << "is divisible by 7"; + } + + void DescribeNegationTo(std::ostream* os) const { + *os << "is not divisible by 7"; + } +}; + +Matcher DivisibleBy7() { + return DivisibleBy7Matcher(); +} + +... + EXPECT_CALL(foo, Bar(DivisibleBy7())); +``` + +You may improve the matcher message by streaming additional information to the +`os` argument in `MatchAndExplain()`: + +```cpp +class DivisibleBy7Matcher { + public: + bool MatchAndExplain(int n, std::ostream* os) const { + const int remainder = n % 7; + if (remainder != 0 && os != nullptr) { + *os << "the remainder is " << remainder; + } + return remainder == 0; + } + ... +}; +``` + +Then, `EXPECT_THAT(x, DivisibleBy7());` may generate a message like this: + +```shell +Value of: x +Expected: is divisible by 7 + Actual: 23 (the remainder is 2) +``` + +{: .callout .tip} +Tip: for convenience, `MatchAndExplain()` can take a `MatchResultListener*` +instead of `std::ostream*`. + +### Writing New Polymorphic Matchers + +Expanding what we learned above to *polymorphic* matchers is now just as simple +as adding templates in the right place. + +```cpp + +class NotNullMatcher { + public: + using is_gtest_matcher = void; + + // To implement a polymorphic matcher, we just need to make MatchAndExplain a + // template on its first argument. + + // In this example, we want to use NotNull() with any pointer, so + // MatchAndExplain() accepts a pointer of any type as its first argument. + // In general, you can define MatchAndExplain() as an ordinary method or + // a method template, or even overload it. + template + bool MatchAndExplain(T* p, std::ostream*) const { + return p != nullptr; + } + + // Describes the property of a value matching this matcher. + void DescribeTo(std::ostream* os) const { *os << "is not NULL"; } + + // Describes the property of a value NOT matching this matcher. + void DescribeNegationTo(std::ostream* os) const { *os << "is NULL"; } +}; + +NotNullMatcher NotNull() { + return NotNullMatcher(); +} + +... + + EXPECT_CALL(foo, Bar(NotNull())); // The argument must be a non-NULL pointer. +``` + +### Legacy Matcher Implementation + +Defining matchers used to be somewhat more complicated, in which it required +several supporting classes and virtual functions. To implement a matcher for +type `T` using the legacy API you have to derive from `MatcherInterface` and +call `MakeMatcher` to construct the object. + +The interface looks like this: + +```cpp +class MatchResultListener { + public: + ... + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template + MatchResultListener& operator<<(const T& x); + + // Returns the underlying ostream. + std::ostream* stream(); +}; + +template +class MatcherInterface { + public: + virtual ~MatcherInterface(); + + // Returns true if and only if the matcher matches x; also explains the match + // result to 'listener'. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Describes this matcher to an ostream. + virtual void DescribeTo(std::ostream* os) const = 0; + + // Describes the negation of this matcher to an ostream. + virtual void DescribeNegationTo(std::ostream* os) const; +}; +``` + +Fortunately, most of the time you can define a polymorphic matcher easily with +the help of `MakePolymorphicMatcher()`. Here's how you can define `NotNull()` as +an example: + +```cpp +using ::testing::MakePolymorphicMatcher; +using ::testing::MatchResultListener; +using ::testing::PolymorphicMatcher; + +class NotNullMatcher { + public: + // To implement a polymorphic matcher, first define a COPYABLE class + // that has three members MatchAndExplain(), DescribeTo(), and + // DescribeNegationTo(), like the following. + + // In this example, we want to use NotNull() with any pointer, so + // MatchAndExplain() accepts a pointer of any type as its first argument. + // In general, you can define MatchAndExplain() as an ordinary method or + // a method template, or even overload it. + template + bool MatchAndExplain(T* p, + MatchResultListener* /* listener */) const { + return p != NULL; + } + + // Describes the property of a value matching this matcher. + void DescribeTo(std::ostream* os) const { *os << "is not NULL"; } + + // Describes the property of a value NOT matching this matcher. + void DescribeNegationTo(std::ostream* os) const { *os << "is NULL"; } +}; + +// To construct a polymorphic matcher, pass an instance of the class +// to MakePolymorphicMatcher(). Note the return type. +PolymorphicMatcher NotNull() { + return MakePolymorphicMatcher(NotNullMatcher()); +} + +... + + EXPECT_CALL(foo, Bar(NotNull())); // The argument must be a non-NULL pointer. +``` + +{: .callout .note} +**Note:** Your polymorphic matcher class does **not** need to inherit from +`MatcherInterface` or any other class, and its methods do **not** need to be +virtual. + +Like in a monomorphic matcher, you may explain the match result by streaming +additional information to the `listener` argument in `MatchAndExplain()`. + +### Writing New Cardinalities + +A cardinality is used in `Times()` to tell gMock how many times you expect a +call to occur. It doesn't have to be exact. For example, you can say +`AtLeast(5)` or `Between(2, 4)`. + +If the [built-in set](gmock_cheat_sheet.md#CardinalityList) of cardinalities +doesn't suit you, you are free to define your own by implementing the following +interface (in namespace `testing`): + +```cpp +class CardinalityInterface { + public: + virtual ~CardinalityInterface(); + + // Returns true if and only if call_count calls will satisfy this cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true if and only if call_count calls will saturate this + // cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(std::ostream* os) const = 0; +}; +``` + +For example, to specify that a call must occur even number of times, you can +write + +```cpp +using ::testing::Cardinality; +using ::testing::CardinalityInterface; +using ::testing::MakeCardinality; + +class EvenNumberCardinality : public CardinalityInterface { + public: + bool IsSatisfiedByCallCount(int call_count) const override { + return (call_count % 2) == 0; + } + + bool IsSaturatedByCallCount(int call_count) const override { + return false; + } + + void DescribeTo(std::ostream* os) const { + *os << "called even number of times"; + } +}; + +Cardinality EvenNumber() { + return MakeCardinality(new EvenNumberCardinality); +} + +... + EXPECT_CALL(foo, Bar(3)) + .Times(EvenNumber()); +``` + +### Writing New Actions {#QuickNewActions} + +If the built-in actions don't work for you, you can easily define your own one. +All you need is a call operator with a signature compatible with the mocked +function. So you can use a lambda: + +```cpp +MockFunction mock; +EXPECT_CALL(mock, Call).WillOnce([](const int input) { return input * 7; }); +EXPECT_EQ(mock.AsStdFunction()(2), 14); +``` + +Or a struct with a call operator (even a templated one): + +```cpp +struct MultiplyBy { + template + T operator()(T arg) { return arg * multiplier; } + + int multiplier; +}; + +// Then use: +// EXPECT_CALL(...).WillOnce(MultiplyBy{7}); +``` + +It's also fine for the callable to take no arguments, ignoring the arguments +supplied to the mock function: + +```cpp +MockFunction mock; +EXPECT_CALL(mock, Call).WillOnce([] { return 17; }); +EXPECT_EQ(mock.AsStdFunction()(0), 17); +``` + +When used with `WillOnce`, the callable can assume it will be called at most +once and is allowed to be a move-only type: + +```cpp +// An action that contains move-only types and has an &&-qualified operator, +// demanding in the type system that it be called at most once. This can be +// used with WillOnce, but the compiler will reject it if handed to +// WillRepeatedly. +struct MoveOnlyAction { + std::unique_ptr move_only_state; + std::unique_ptr operator()() && { return std::move(move_only_state); } +}; + +MockFunction()> mock; +EXPECT_CALL(mock, Call).WillOnce(MoveOnlyAction{std::make_unique(17)}); +EXPECT_THAT(mock.AsStdFunction()(), Pointee(Eq(17))); +``` + +More generally, to use with a mock function whose signature is `R(Args...)` the +object can be anything convertible to `OnceAction` or +`Action. The difference between the two is that `OnceAction` has +weaker requirements (`Action` requires a copy-constructible input that can be +called repeatedly whereas `OnceAction` requires only move-constructible and +supports `&&`-qualified call operators), but can be used only with `WillOnce`. +`OnceAction` is typically relevant only when supporting move-only types or +actions that want a type-system guarantee that they will be called at most once. + +Typically the `OnceAction` and `Action` templates need not be referenced +directly in your actions: a struct or class with a call operator is sufficient, +as in the examples above. But fancier polymorphic actions that need to know the +specific return type of the mock function can define templated conversion +operators to make that possible. See `gmock-actions.h` for examples. + +#### Legacy macro-based Actions + +Before C++11, the functor-based actions were not supported; the old way of +writing actions was through a set of `ACTION*` macros. We suggest to avoid them +in new code; they hide a lot of logic behind the macro, potentially leading to +harder-to-understand compiler errors. Nevertheless, we cover them here for +completeness. + +By writing + +```cpp +ACTION(name) { statements; } +``` + +in a namespace scope (i.e. not inside a class or function), you will define an +action with the given name that executes the statements. The value returned by +`statements` will be used as the return value of the action. Inside the +statements, you can refer to the K-th (0-based) argument of the mock function as +`argK`. For example: + +```cpp +ACTION(IncrementArg1) { return ++(*arg1); } +``` + +allows you to write + +```cpp +... WillOnce(IncrementArg1()); +``` + +Note that you don't need to specify the types of the mock function arguments. +Rest assured that your code is type-safe though: you'll get a compiler error if +`*arg1` doesn't support the `++` operator, or if the type of `++(*arg1)` isn't +compatible with the mock function's return type. + +Another example: + +```cpp +ACTION(Foo) { + (*arg2)(5); + Blah(); + *arg1 = 0; + return arg0; +} +``` + +defines an action `Foo()` that invokes argument #2 (a function pointer) with 5, +calls function `Blah()`, sets the value pointed to by argument #1 to 0, and +returns argument #0. + +For more convenience and flexibility, you can also use the following pre-defined +symbols in the body of `ACTION`: + +`argK_type` | The type of the K-th (0-based) argument of the mock function +:-------------- | :----------------------------------------------------------- +`args` | All arguments of the mock function as a tuple +`args_type` | The type of all arguments of the mock function as a tuple +`return_type` | The return type of the mock function +`function_type` | The type of the mock function + +For example, when using an `ACTION` as a stub action for mock function: + +```cpp +int DoSomething(bool flag, int* ptr); +``` + +we have: + +Pre-defined Symbol | Is Bound To +------------------ | --------------------------------- +`arg0` | the value of `flag` +`arg0_type` | the type `bool` +`arg1` | the value of `ptr` +`arg1_type` | the type `int*` +`args` | the tuple `(flag, ptr)` +`args_type` | the type `std::tuple` +`return_type` | the type `int` +`function_type` | the type `int(bool, int*)` + +#### Legacy macro-based parameterized Actions + +Sometimes you'll want to parameterize an action you define. For that we have +another macro + +```cpp +ACTION_P(name, param) { statements; } +``` + +For example, + +```cpp +ACTION_P(Add, n) { return arg0 + n; } +``` + +will allow you to write + +```cpp +// Returns argument #0 + 5. +... WillOnce(Add(5)); +``` + +For convenience, we use the term *arguments* for the values used to invoke the +mock function, and the term *parameters* for the values used to instantiate an +action. + +Note that you don't need to provide the type of the parameter either. Suppose +the parameter is named `param`, you can also use the gMock-defined symbol +`param_type` to refer to the type of the parameter as inferred by the compiler. +For example, in the body of `ACTION_P(Add, n)` above, you can write `n_type` for +the type of `n`. + +gMock also provides `ACTION_P2`, `ACTION_P3`, and etc to support multi-parameter +actions. For example, + +```cpp +ACTION_P2(ReturnDistanceTo, x, y) { + double dx = arg0 - x; + double dy = arg1 - y; + return sqrt(dx*dx + dy*dy); +} +``` + +lets you write + +```cpp +... WillOnce(ReturnDistanceTo(5.0, 26.5)); +``` + +You can view `ACTION` as a degenerated parameterized action where the number of +parameters is 0. + +You can also easily define actions overloaded on the number of parameters: + +```cpp +ACTION_P(Plus, a) { ... } +ACTION_P2(Plus, a, b) { ... } +``` + +### Restricting the Type of an Argument or Parameter in an ACTION + +For maximum brevity and reusability, the `ACTION*` macros don't ask you to +provide the types of the mock function arguments and the action parameters. +Instead, we let the compiler infer the types for us. + +Sometimes, however, we may want to be more explicit about the types. There are +several tricks to do that. For example: + +```cpp +ACTION(Foo) { + // Makes sure arg0 can be converted to int. + int n = arg0; + ... use n instead of arg0 here ... +} + +ACTION_P(Bar, param) { + // Makes sure the type of arg1 is const char*. + ::testing::StaticAssertTypeEq(); + + // Makes sure param can be converted to bool. + bool flag = param; +} +``` + +where `StaticAssertTypeEq` is a compile-time assertion in googletest that +verifies two types are the same. + +### Writing New Action Templates Quickly + +Sometimes you want to give an action explicit template parameters that cannot be +inferred from its value parameters. `ACTION_TEMPLATE()` supports that and can be +viewed as an extension to `ACTION()` and `ACTION_P*()`. + +The syntax: + +```cpp +ACTION_TEMPLATE(ActionName, + HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), + AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +``` + +defines an action template that takes *m* explicit template parameters and *n* +value parameters, where *m* is in [1, 10] and *n* is in [0, 10]. `name_i` is the +name of the *i*-th template parameter, and `kind_i` specifies whether it's a +`typename`, an integral constant, or a template. `p_i` is the name of the *i*-th +value parameter. + +Example: + +```cpp +// DuplicateArg(output) converts the k-th argument of the mock +// function to type T and copies it to *output. +ACTION_TEMPLATE(DuplicateArg, + // Note the comma between int and k: + HAS_2_TEMPLATE_PARAMS(int, k, typename, T), + AND_1_VALUE_PARAMS(output)) { + *output = T(std::get(args)); +} +``` + +To create an instance of an action template, write: + +```cpp +ActionName(v1, ..., v_n) +``` + +where the `t`s are the template arguments and the `v`s are the value arguments. +The value argument types are inferred by the compiler. For example: + +```cpp +using ::testing::_; +... + int n; + EXPECT_CALL(mock, Foo).WillOnce(DuplicateArg<1, unsigned char>(&n)); +``` + +If you want to explicitly specify the value argument types, you can provide +additional template arguments: + +```cpp +ActionName(v1, ..., v_n) +``` + +where `u_i` is the desired type of `v_i`. + +`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the number of +value parameters, but not on the number of template parameters. Without the +restriction, the meaning of the following is unclear: + +```cpp + OverloadedAction(x); +``` + +Are we using a single-template-parameter action where `bool` refers to the type +of `x`, or a two-template-parameter action where the compiler is asked to infer +the type of `x`? + +### Using the ACTION Object's Type + +If you are writing a function that returns an `ACTION` object, you'll need to +know its type. The type depends on the macro used to define the action and the +parameter types. The rule is relatively simple: + + +| Given Definition | Expression | Has Type | +| ----------------------------- | ------------------- | --------------------- | +| `ACTION(Foo)` | `Foo()` | `FooAction` | +| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` | `Foo()` | `FooAction` | +| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP` | +| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar(int_value)` | `BarActionP` | +| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2` | +| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz(bool_value, int_value)` | `BazActionP2` | +| ... | ... | ... | + + +Note that we have to pick different suffixes (`Action`, `ActionP`, `ActionP2`, +and etc) for actions with different numbers of value parameters, or the action +definitions cannot be overloaded on the number of them. + +### Writing New Monomorphic Actions {#NewMonoActions} + +While the `ACTION*` macros are very convenient, sometimes they are +inappropriate. For example, despite the tricks shown in the previous recipes, +they don't let you directly specify the types of the mock function arguments and +the action parameters, which in general leads to unoptimized compiler error +messages that can baffle unfamiliar users. They also don't allow overloading +actions based on parameter types without jumping through some hoops. + +An alternative to the `ACTION*` macros is to implement +`::testing::ActionInterface`, where `F` is the type of the mock function in +which the action will be used. For example: + +```cpp +template +class ActionInterface { + public: + virtual ~ActionInterface(); + + // Performs the action. Result is the return type of function type + // F, and ArgumentTuple is the tuple of arguments of F. + // + + // For example, if F is int(bool, const string&), then Result would + // be int, and ArgumentTuple would be std::tuple. + virtual Result Perform(const ArgumentTuple& args) = 0; +}; +``` + +```cpp +using ::testing::_; +using ::testing::Action; +using ::testing::ActionInterface; +using ::testing::MakeAction; + +typedef int IncrementMethod(int*); + +class IncrementArgumentAction : public ActionInterface { + public: + int Perform(const std::tuple& args) override { + int* p = std::get<0>(args); // Grabs the first argument. + return *p++; + } +}; + +Action IncrementArgument() { + return MakeAction(new IncrementArgumentAction); +} + +... + EXPECT_CALL(foo, Baz(_)) + .WillOnce(IncrementArgument()); + + int n = 5; + foo.Baz(&n); // Should return 5 and change n to 6. +``` + +### Writing New Polymorphic Actions {#NewPolyActions} + +The previous recipe showed you how to define your own action. This is all good, +except that you need to know the type of the function in which the action will +be used. Sometimes that can be a problem. For example, if you want to use the +action in functions with *different* types (e.g. like `Return()` and +`SetArgPointee()`). + +If an action can be used in several types of mock functions, we say it's +*polymorphic*. The `MakePolymorphicAction()` function template makes it easy to +define such an action: + +```cpp +namespace testing { +template +PolymorphicAction MakePolymorphicAction(const Impl& impl); +} // namespace testing +``` + +As an example, let's define an action that returns the second argument in the +mock function's argument list. The first step is to define an implementation +class: + +```cpp +class ReturnSecondArgumentAction { + public: + template + Result Perform(const ArgumentTuple& args) const { + // To get the i-th (0-based) argument, use std::get(args). + return std::get<1>(args); + } +}; +``` + +This implementation class does *not* need to inherit from any particular class. +What matters is that it must have a `Perform()` method template. This method +template takes the mock function's arguments as a tuple in a **single** +argument, and returns the result of the action. It can be either `const` or not, +but must be invocable with exactly one template argument, which is the result +type. In other words, you must be able to call `Perform(args)` where `R` is +the mock function's return type and `args` is its arguments in a tuple. + +Next, we use `MakePolymorphicAction()` to turn an instance of the implementation +class into the polymorphic action we need. It will be convenient to have a +wrapper for this: + +```cpp +using ::testing::MakePolymorphicAction; +using ::testing::PolymorphicAction; + +PolymorphicAction ReturnSecondArgument() { + return MakePolymorphicAction(ReturnSecondArgumentAction()); +} +``` + +Now, you can use this polymorphic action the same way you use the built-in ones: + +```cpp +using ::testing::_; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, DoThis, (bool flag, int n), (override)); + MOCK_METHOD(string, DoThat, (int x, const char* str1, const char* str2), + (override)); +}; + + ... + MockFoo foo; + EXPECT_CALL(foo, DoThis).WillOnce(ReturnSecondArgument()); + EXPECT_CALL(foo, DoThat).WillOnce(ReturnSecondArgument()); + ... + foo.DoThis(true, 5); // Will return 5. + foo.DoThat(1, "Hi", "Bye"); // Will return "Hi". +``` + +### Teaching gMock How to Print Your Values + +When an uninteresting or unexpected call occurs, gMock prints the argument +values and the stack trace to help you debug. Assertion macros like +`EXPECT_THAT` and `EXPECT_EQ` also print the values in question when the +assertion fails. gMock and googletest do this using googletest's user-extensible +value printer. + +This printer knows how to print built-in C++ types, native arrays, STL +containers, and any type that supports the `<<` operator. For other types, it +prints the raw bytes in the value and hopes that you the user can figure it out. +[The GoogleTest advanced guide](advanced.md#teaching-googletest-how-to-print-your-values) +explains how to extend the printer to do a better job at printing your +particular type than to dump the bytes. + +## Useful Mocks Created Using gMock + + + + +### Mock std::function {#MockFunction} + +`std::function` is a general function type introduced in C++11. It is a +preferred way of passing callbacks to new interfaces. Functions are copyable, +and are not usually passed around by pointer, which makes them tricky to mock. +But fear not - `MockFunction` can help you with that. + +`MockFunction` has a mock method `Call()` with the signature: + +```cpp + R Call(T1, ..., Tn); +``` + +It also has a `AsStdFunction()` method, which creates a `std::function` proxy +forwarding to Call: + +```cpp + std::function AsStdFunction(); +``` + +To use `MockFunction`, first create `MockFunction` object and set up +expectations on its `Call` method. Then pass proxy obtained from +`AsStdFunction()` to the code you are testing. For example: + +```cpp +TEST(FooTest, RunsCallbackWithBarArgument) { + // 1. Create a mock object. + MockFunction mock_function; + + // 2. Set expectations on Call() method. + EXPECT_CALL(mock_function, Call("bar")).WillOnce(Return(1)); + + // 3. Exercise code that uses std::function. + Foo(mock_function.AsStdFunction()); + // Foo's signature can be either of: + // void Foo(const std::function& fun); + // void Foo(std::function fun); + + // 4. All expectations will be verified when mock_function + // goes out of scope and is destroyed. +} +``` + +Remember that function objects created with `AsStdFunction()` are just +forwarders. If you create multiple of them, they will share the same set of +expectations. + +Although `std::function` supports unlimited number of arguments, `MockFunction` +implementation is limited to ten. If you ever hit that limit... well, your +callback has bigger problems than being mockable. :-) diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_faq.md b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_faq.md new file mode 100644 index 00000000..8f220bf7 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_faq.md @@ -0,0 +1,390 @@ +# Legacy gMock FAQ + +### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem? + +In order for a method to be mocked, it must be *virtual*, unless you use the +[high-perf dependency injection technique](gmock_cook_book.md#MockingNonVirtualMethods). + +### Can I mock a variadic function? + +You cannot mock a variadic function (i.e. a function taking ellipsis (`...`) +arguments) directly in gMock. + +The problem is that in general, there is *no way* for a mock object to know how +many arguments are passed to the variadic method, and what the arguments' types +are. Only the *author of the base class* knows the protocol, and we cannot look +into his or her head. + +Therefore, to mock such a function, the *user* must teach the mock object how to +figure out the number of arguments and their types. One way to do it is to +provide overloaded versions of the function. + +Ellipsis arguments are inherited from C and not really a C++ feature. They are +unsafe to use and don't work with arguments that have constructors or +destructors. Therefore we recommend to avoid them in C++ as much as possible. + +### MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter. Why? + +If you compile this using Microsoft Visual C++ 2005 SP1: + +```cpp +class Foo { + ... + virtual void Bar(const int i) = 0; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD(void, Bar, (const int i), (override)); +}; +``` + +You may get the following warning: + +```shell +warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier +``` + +This is a MSVC bug. The same code compiles fine with gcc, for example. If you +use Visual C++ 2008 SP1, you would get the warning: + +```shell +warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers +``` + +In C++, if you *declare* a function with a `const` parameter, the `const` +modifier is ignored. Therefore, the `Foo` base class above is equivalent to: + +```cpp +class Foo { + ... + virtual void Bar(int i) = 0; // int or const int? Makes no difference. +}; +``` + +In fact, you can *declare* `Bar()` with an `int` parameter, and define it with a +`const int` parameter. The compiler will still match them up. + +Since making a parameter `const` is meaningless in the method declaration, we +recommend to remove it in both `Foo` and `MockFoo`. That should workaround the +VC bug. + +Note that we are talking about the *top-level* `const` modifier here. If the +function parameter is passed by pointer or reference, declaring the pointee or +referee as `const` is still meaningful. For example, the following two +declarations are *not* equivalent: + +```cpp +void Bar(int* p); // Neither p nor *p is const. +void Bar(const int* p); // p is not const, but *p is. +``` + +### I can't figure out why gMock thinks my expectations are not satisfied. What should I do? + +You might want to run your test with `--gmock_verbose=info`. This flag lets +gMock print a trace of every mock function call it receives. By studying the +trace, you'll gain insights on why the expectations you set are not met. + +If you see the message "The mock function has no default action set, and its +return type has no default value set.", then try +[adding a default action](gmock_cheat_sheet.md#OnCall). Due to a known issue, +unexpected calls on mocks without default actions don't print out a detailed +comparison between the actual arguments and the expected arguments. + +### My program crashed and `ScopedMockLog` spit out tons of messages. Is it a gMock bug? + +gMock and `ScopedMockLog` are likely doing the right thing here. + +When a test crashes, the failure signal handler will try to log a lot of +information (the stack trace, and the address map, for example). The messages +are compounded if you have many threads with depth stacks. When `ScopedMockLog` +intercepts these messages and finds that they don't match any expectations, it +prints an error for each of them. + +You can learn to ignore the errors, or you can rewrite your expectations to make +your test more robust, for example, by adding something like: + +```cpp +using ::testing::AnyNumber; +using ::testing::Not; +... + // Ignores any log not done by us. + EXPECT_CALL(log, Log(_, Not(EndsWith("/my_file.cc")), _)) + .Times(AnyNumber()); +``` + +### How can I assert that a function is NEVER called? + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + +### I have a failed test where gMock tells me TWICE that a particular expectation is not satisfied. Isn't this redundant? + +When gMock detects a failure, it prints relevant information (the mock function +arguments, the state of relevant expectations, and etc) to help the user debug. +If another failure is detected, gMock will do the same, including printing the +state of relevant expectations. + +Sometimes an expectation's state didn't change between two failures, and you'll +see the same description of the state twice. They are however *not* redundant, +as they refer to *different points in time*. The fact they are the same *is* +interesting information. + +### I get a heapcheck failure when using a mock object, but using a real object is fine. What can be wrong? + +Does the class (hopefully a pure interface) you are mocking have a virtual +destructor? + +Whenever you derive from a base class, make sure its destructor is virtual. +Otherwise Bad Things will happen. Consider the following code: + +```cpp +class Base { + public: + // Not virtual, but should be. + ~Base() { ... } + ... +}; + +class Derived : public Base { + public: + ... + private: + std::string value_; +}; + +... + Base* p = new Derived; + ... + delete p; // Surprise! ~Base() will be called, but ~Derived() will not + // - value_ is leaked. +``` + +By changing `~Base()` to virtual, `~Derived()` will be correctly called when +`delete p` is executed, and the heap checker will be happy. + +### The "newer expectations override older ones" rule makes writing expectations awkward. Why does gMock do that? + +When people complain about this, often they are referring to code like: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. However, I have to write the expectations in the + // reverse order. This sucks big time!!! + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); +``` + +The problem, is that they didn't pick the **best** way to express the test's +intent. + +By default, expectations don't have to be matched in *any* particular order. If +you want them to match in a certain order, you need to be explicit. This is +gMock's (and jMock's) fundamental philosophy: it's easy to accidentally +over-specify your tests, and we want to make it harder to do so. + +There are two better ways to write the test spec. You could either put the +expectations in sequence: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. Using a sequence, we can write the expectations + // in their natural order. + { + InSequence s; + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); + } +``` + +or you can put the sequence of actions in the same expectation: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .WillOnce(Return(2)) + .RetiresOnSaturation(); +``` + +Back to the original questions: why does gMock search the expectations (and +`ON_CALL`s) from back to front? Because this allows a user to set up a mock's +behavior for the common case early (e.g. in the mock's constructor or the test +fixture's set-up phase) and customize it with more specific rules later. If +gMock searches from front to back, this very useful pattern won't be possible. + +### gMock prints a warning when a function without EXPECT_CALL is called, even if I have set its behavior using ON_CALL. Would it be reasonable not to show the warning in this case? + +When choosing between being neat and being safe, we lean toward the latter. So +the answer is that we think it's better to show the warning. + +Often people write `ON_CALL`s in the mock object's constructor or `SetUp()`, as +the default behavior rarely changes from test to test. Then in the test body +they set the expectations, which are often different for each test. Having an +`ON_CALL` in the set-up part of a test doesn't mean that the calls are expected. +If there's no `EXPECT_CALL` and the method is called, it's possibly an error. If +we quietly let the call go through without notifying the user, bugs may creep in +unnoticed. + +If, however, you are sure that the calls are OK, you can write + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .WillRepeatedly(...); +``` + +instead of + +```cpp +using ::testing::_; +... + ON_CALL(foo, Bar(_)) + .WillByDefault(...); +``` + +This tells gMock that you do expect the calls and no warning should be printed. + +Also, you can control the verbosity by specifying `--gmock_verbose=error`. Other +values are `info` and `warning`. If you find the output too noisy when +debugging, just choose a less verbose level. + +### How can I delete the mock function's argument in an action? + +If your mock function takes a pointer argument and you want to delete that +argument, you can use testing::DeleteArg() to delete the N'th (zero-indexed) +argument: + +```cpp +using ::testing::_; + ... + MOCK_METHOD(void, Bar, (X* x, const Y& y)); + ... + EXPECT_CALL(mock_foo_, Bar(_, _)) + .WillOnce(testing::DeleteArg<0>())); +``` + +### How can I perform an arbitrary action on a mock function's argument? + +If you find yourself needing to perform some action that's not supported by +gMock directly, remember that you can define your own actions using +[`MakeAction()`](#NewMonoActions) or +[`MakePolymorphicAction()`](#NewPolyActions), or you can write a stub function +and invoke it using [`Invoke()`](#FunctionsAsActions). + +```cpp +using ::testing::_; +using ::testing::Invoke; + ... + MOCK_METHOD(void, Bar, (X* p)); + ... + EXPECT_CALL(mock_foo_, Bar(_)) + .WillOnce(Invoke(MyAction(...))); +``` + +### My code calls a static/global function. Can I mock it? + +You can, but you need to make some changes. + +In general, if you find yourself needing to mock a static function, it's a sign +that your modules are too tightly coupled (and less flexible, less reusable, +less testable, etc). You are probably better off defining a small interface and +call the function through that interface, which then can be easily mocked. It's +a bit of work initially, but usually pays for itself quickly. + +This Google Testing Blog +[post](https://testing.googleblog.com/2008/06/defeat-static-cling.html) says it +excellently. Check it out. + +### My mock object needs to do complex stuff. It's a lot of pain to specify the actions. gMock sucks! + +I know it's not a question, but you get an answer for free any way. :-) + +With gMock, you can create mocks in C++ easily. And people might be tempted to +use them everywhere. Sometimes they work great, and sometimes you may find them, +well, a pain to use. So, what's wrong in the latter case? + +When you write a test without using mocks, you exercise the code and assert that +it returns the correct value or that the system is in an expected state. This is +sometimes called "state-based testing". + +Mocks are great for what some call "interaction-based" testing: instead of +checking the system state at the very end, mock objects verify that they are +invoked the right way and report an error as soon as it arises, giving you a +handle on the precise context in which the error was triggered. This is often +more effective and economical to do than state-based testing. + +If you are doing state-based testing and using a test double just to simulate +the real object, you are probably better off using a fake. Using a mock in this +case causes pain, as it's not a strong point for mocks to perform complex +actions. If you experience this and think that mocks suck, you are just not +using the right tool for your problem. Or, you might be trying to solve the +wrong problem. :-) + +### I got a warning "Uninteresting function call encountered - default action taken.." Should I panic? + +By all means, NO! It's just an FYI. :-) + +What it means is that you have a mock function, you haven't set any expectations +on it (by gMock's rule this means that you are not interested in calls to this +function and therefore it can be called any number of times), and it is called. +That's OK - you didn't say it's not OK to call the function! + +What if you actually meant to disallow this function to be called, but forgot to +write `EXPECT_CALL(foo, Bar()).Times(0)`? While one can argue that it's the +user's fault, gMock tries to be nice and prints you a note. + +So, when you see the message and believe that there shouldn't be any +uninteresting calls, you should investigate what's going on. To make your life +easier, gMock dumps the stack trace when an uninteresting call is encountered. +From that you can figure out which mock function it is, and how it is called. + +### I want to define a custom action. Should I use Invoke() or implement the ActionInterface interface? + +Either way is fine - you want to choose the one that's more convenient for your +circumstance. + +Usually, if your action is for a particular function type, defining it using +`Invoke()` should be easier; if your action can be used in functions of +different types (e.g. if you are defining `Return(*value*)`), +`MakePolymorphicAction()` is easiest. Sometimes you want precise control on what +types of functions the action can be used in, and implementing `ActionInterface` +is the way to go here. See the implementation of `Return()` in `gmock-actions.h` +for an example. + +### I use SetArgPointee() in WillOnce(), but gcc complains about "conflicting return type specified". What does it mean? + +You got this error as gMock has no idea what value it should return when the +mock method is called. `SetArgPointee()` says what the side effect is, but +doesn't say what the return value should be. You need `DoAll()` to chain a +`SetArgPointee()` with a `Return()` that provides a value appropriate to the API +being mocked. + +See this [recipe](gmock_cook_book.md#mocking-side-effects) for more details and +an example. + +### I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do? + +We've noticed that when the `/clr` compiler flag is used, Visual C++ uses 5~6 +times as much memory when compiling a mock class. We suggest to avoid `/clr` +when compiling native C++ mocks. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_for_dummies.md b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_for_dummies.md new file mode 100644 index 00000000..ed2297c2 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/gmock_for_dummies.md @@ -0,0 +1,702 @@ +# gMock for Dummies + +## What Is gMock? + +When you write a prototype or test, often it's not feasible or wise to rely on +real objects entirely. A **mock object** implements the same interface as a real +object (so it can be used as one), but lets you specify at run time how it will +be used and what it should do (which methods will be called? in which order? how +many times? with what arguments? what will they return? etc). + +It is easy to confuse the term *fake objects* with mock objects. Fakes and mocks +actually mean very different things in the Test-Driven Development (TDD) +community: + +* **Fake** objects have working implementations, but usually take some + shortcut (perhaps to make the operations less expensive), which makes them + not suitable for production. An in-memory file system would be an example of + a fake. +* **Mocks** are objects pre-programmed with *expectations*, which form a + specification of the calls they are expected to receive. + +If all this seems too abstract for you, don't worry - the most important thing +to remember is that a mock allows you to check the *interaction* between itself +and code that uses it. The difference between fakes and mocks shall become much +clearer once you start to use mocks. + +**gMock** is a library (sometimes we also call it a "framework" to make it sound +cool) for creating mock classes and using them. It does to C++ what +jMock/EasyMock does to Java (well, more or less). + +When using gMock, + +1. first, you use some simple macros to describe the interface you want to + mock, and they will expand to the implementation of your mock class; +2. next, you create some mock objects and specify its expectations and behavior + using an intuitive syntax; +3. then you exercise code that uses the mock objects. gMock will catch any + violation to the expectations as soon as it arises. + +## Why gMock? + +While mock objects help you remove unnecessary dependencies in tests and make +them fast and reliable, using mocks manually in C++ is *hard*: + +* Someone has to implement the mocks. The job is usually tedious and + error-prone. No wonder people go great distance to avoid it. +* The quality of those manually written mocks is a bit, uh, unpredictable. You + may see some really polished ones, but you may also see some that were + hacked up in a hurry and have all sorts of ad hoc restrictions. +* The knowledge you gained from using one mock doesn't transfer to the next + one. + +In contrast, Java and Python programmers have some fine mock frameworks (jMock, +EasyMock, etc), which automate the creation of mocks. As a result, mocking is a +proven effective technique and widely adopted practice in those communities. +Having the right tool absolutely makes the difference. + +gMock was built to help C++ programmers. It was inspired by jMock and EasyMock, +but designed with C++'s specifics in mind. It is your friend if any of the +following problems is bothering you: + +* You are stuck with a sub-optimal design and wish you had done more + prototyping before it was too late, but prototyping in C++ is by no means + "rapid". +* Your tests are slow as they depend on too many libraries or use expensive + resources (e.g. a database). +* Your tests are brittle as some resources they use are unreliable (e.g. the + network). +* You want to test how your code handles a failure (e.g. a file checksum + error), but it's not easy to cause one. +* You need to make sure that your module interacts with other modules in the + right way, but it's hard to observe the interaction; therefore you resort to + observing the side effects at the end of the action, but it's awkward at + best. +* You want to "mock out" your dependencies, except that they don't have mock + implementations yet; and, frankly, you aren't thrilled by some of those + hand-written mocks. + +We encourage you to use gMock as + +* a *design* tool, for it lets you experiment with your interface design early + and often. More iterations lead to better designs! +* a *testing* tool to cut your tests' outbound dependencies and probe the + interaction between your module and its collaborators. + +## Getting Started + +gMock is bundled with googletest. + +## A Case for Mock Turtles + +Let's look at an example. Suppose you are developing a graphics program that +relies on a [LOGO](https://en.wikipedia.org/wiki/Logo_programming_language)-like +API for drawing. How would you test that it does the right thing? Well, you can +run it and compare the screen with a golden screen snapshot, but let's admit it: +tests like this are expensive to run and fragile (What if you just upgraded to a +shiny new graphics card that has better anti-aliasing? Suddenly you have to +update all your golden images.). It would be too painful if all your tests are +like this. Fortunately, you learned about +[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) and know the right thing +to do: instead of having your application talk to the system API directly, wrap +the API in an interface (say, `Turtle`) and code to that interface: + +```cpp +class Turtle { + ... + virtual ~Turtle() {} + virtual void PenUp() = 0; + virtual void PenDown() = 0; + virtual void Forward(int distance) = 0; + virtual void Turn(int degrees) = 0; + virtual void GoTo(int x, int y) = 0; + virtual int GetX() const = 0; + virtual int GetY() const = 0; +}; +``` + +(Note that the destructor of `Turtle` **must** be virtual, as is the case for +**all** classes you intend to inherit from - otherwise the destructor of the +derived class will not be called when you delete an object through a base +pointer, and you'll get corrupted program states like memory leaks.) + +You can control whether the turtle's movement will leave a trace using `PenUp()` +and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and +`GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the +turtle. + +Your program will normally use a real implementation of this interface. In +tests, you can use a mock implementation instead. This allows you to easily +check what drawing primitives your program is calling, with what arguments, and +in which order. Tests written this way are much more robust (they won't break +because your new machine does anti-aliasing differently), easier to read and +maintain (the intent of a test is expressed in the code, not in some binary +images), and run *much, much faster*. + +## Writing the Mock Class + +If you are lucky, the mocks you need to use have already been implemented by +some nice people. If, however, you find yourself in the position to write a mock +class, relax - gMock turns this task into a fun game! (Well, almost.) + +### How to Define It + +Using the `Turtle` interface as example, here are the simple steps you need to +follow: + +* Derive a class `MockTurtle` from `Turtle`. +* Take a *virtual* function of `Turtle` (while it's possible to + [mock non-virtual methods using templates](gmock_cook_book.md#MockingNonVirtualMethods), + it's much more involved). +* In the `public:` section of the child class, write `MOCK_METHOD();` +* Now comes the fun part: you take the function signature, cut-and-paste it + into the macro, and add two commas - one between the return type and the + name, another between the name and the argument list. +* If you're mocking a const method, add a 4th parameter containing `(const)` + (the parentheses are required). +* Since you're overriding a virtual method, we suggest adding the `override` + keyword. For const methods the 4th parameter becomes `(const, override)`, + for non-const methods just `(override)`. This isn't mandatory. +* Repeat until all virtual functions you want to mock are done. (It goes + without saying that *all* pure virtual methods in your abstract class must + be either mocked or overridden.) + +After the process, you should have something like: + +```cpp +#include // Brings in gMock. + +class MockTurtle : public Turtle { + public: + ... + MOCK_METHOD(void, PenUp, (), (override)); + MOCK_METHOD(void, PenDown, (), (override)); + MOCK_METHOD(void, Forward, (int distance), (override)); + MOCK_METHOD(void, Turn, (int degrees), (override)); + MOCK_METHOD(void, GoTo, (int x, int y), (override)); + MOCK_METHOD(int, GetX, (), (const, override)); + MOCK_METHOD(int, GetY, (), (const, override)); +}; +``` + +You don't need to define these mock methods somewhere else - the `MOCK_METHOD` +macro will generate the definitions for you. It's that simple! + +### Where to Put It + +When you define a mock class, you need to decide where to put its definition. +Some people put it in a `_test.cc`. This is fine when the interface being mocked +(say, `Foo`) is owned by the same person or team. Otherwise, when the owner of +`Foo` changes it, your test could break. (You can't really expect `Foo`'s +maintainer to fix every test that uses `Foo`, can you?) + +Generally, you should not mock classes you don't own. If you must mock such a +class owned by others, define the mock class in `Foo`'s Bazel package (usually +the same directory or a `testing` sub-directory), and put it in a `.h` and a +`cc_library` with `testonly=True`. Then everyone can reference them from their +tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and +only tests that depend on the changed methods need to be fixed. + +Another way to do it: you can introduce a thin layer `FooAdaptor` on top of +`Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb +changes in `Foo` much more easily. While this is more work initially, carefully +choosing the adaptor interface can make your code easier to write and more +readable (a net win in the long run), as you can choose `FooAdaptor` to fit your +specific domain much better than `Foo` does. + +## Using Mocks in Tests + +Once you have a mock class, using it is easy. The typical work flow is: + +1. Import the gMock names from the `testing` namespace such that you can use + them unqualified (You only have to do it once per file). Remember that + namespaces are a good idea. +2. Create some mock objects. +3. Specify your expectations on them (How many times will a method be called? + With what arguments? What should it do? etc.). +4. Exercise some code that uses the mocks; optionally, check the result using + googletest assertions. If a mock method is called more than expected or with + wrong arguments, you'll get an error immediately. +5. When a mock is destructed, gMock will automatically check whether all + expectations on it have been satisfied. + +Here's an example: + +```cpp +#include "path/to/mock-turtle.h" +#include +#include + +using ::testing::AtLeast; // #1 + +TEST(PainterTest, CanDrawSomething) { + MockTurtle turtle; // #2 + EXPECT_CALL(turtle, PenDown()) // #3 + .Times(AtLeast(1)); + + Painter painter(&turtle); // #4 + + EXPECT_TRUE(painter.DrawCircle(0, 0, 10)); // #5 +} +``` + +As you might have guessed, this test checks that `PenDown()` is called at least +once. If the `painter` object didn't call this method, your test will fail with +a message like this: + +```text +path/to/my_test.cc:119: Failure +Actual function call count doesn't match this expectation: +Actually: never called; +Expected: called at least once. +Stack trace: +... +``` + +**Tip 1:** If you run the test from an Emacs buffer, you can hit `` on +the line number to jump right to the failed expectation. + +**Tip 2:** If your mock objects are never deleted, the final verification won't +happen. Therefore it's a good idea to turn on the heap checker in your tests +when you allocate mocks on the heap. You get that automatically if you use the +`gtest_main` library already. + +###### Expectation Ordering + +**Important note:** gMock requires expectations to be set **before** the mock +functions are called, otherwise the behavior is **undefined**. Do not alternate +between calls to `EXPECT_CALL()` and calls to the mock functions, and do not set +any expectations on a mock after passing the mock to an API. + +This means `EXPECT_CALL()` should be read as expecting that a call will occur +*in the future*, not that a call has occurred. Why does gMock work like that? +Well, specifying the expectation beforehand allows gMock to report a violation +as soon as it rises, when the context (stack trace, etc) is still available. +This makes debugging much easier. + +Admittedly, this test is contrived and doesn't do much. You can easily achieve +the same effect without using gMock. However, as we shall reveal soon, gMock +allows you to do *so much more* with the mocks. + +## Setting Expectations + +The key to using a mock object successfully is to set the *right expectations* +on it. If you set the expectations too strict, your test will fail as the result +of unrelated changes. If you set them too loose, bugs can slip through. You want +to do it just right such that your test can catch exactly the kind of bugs you +intend it to catch. gMock provides the necessary means for you to do it "just +right." + +### General Syntax + +In gMock we use the `EXPECT_CALL()` macro to set an expectation on a mock +method. The general syntax is: + +```cpp +EXPECT_CALL(mock_object, method(matchers)) + .Times(cardinality) + .WillOnce(action) + .WillRepeatedly(action); +``` + +The macro has two arguments: first the mock object, and then the method and its +arguments. Note that the two are separated by a comma (`,`), not a period (`.`). +(Why using a comma? The answer is that it was necessary for technical reasons.) +If the method is not overloaded, the macro can also be called without matchers: + +```cpp +EXPECT_CALL(mock_object, non-overloaded-method) + .Times(cardinality) + .WillOnce(action) + .WillRepeatedly(action); +``` + +This syntax allows the test writer to specify "called with any arguments" +without explicitly specifying the number or types of arguments. To avoid +unintended ambiguity, this syntax may only be used for methods that are not +overloaded. + +Either form of the macro can be followed by some optional *clauses* that provide +more information about the expectation. We'll discuss how each clause works in +the coming sections. + +This syntax is designed to make an expectation read like English. For example, +you can probably guess that + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .Times(5) + .WillOnce(Return(100)) + .WillOnce(Return(150)) + .WillRepeatedly(Return(200)); +``` + +says that the `turtle` object's `GetX()` method will be called five times, it +will return 100 the first time, 150 the second time, and then 200 every time. +Some people like to call this style of syntax a Domain-Specific Language (DSL). + +{: .callout .note} +**Note:** Why do we use a macro to do this? Well it serves two purposes: first +it makes expectations easily identifiable (either by `grep` or by a human +reader), and second it allows gMock to include the source file location of a +failed expectation in messages, making debugging easier. + +### Matchers: What Arguments Do We Expect? + +When a mock function takes arguments, we may specify what arguments we are +expecting, for example: + +```cpp +// Expects the turtle to move forward by 100 units. +EXPECT_CALL(turtle, Forward(100)); +``` + +Oftentimes you do not want to be too specific. Remember that talk about tests +being too rigid? Over specification leads to brittle tests and obscures the +intent of tests. Therefore we encourage you to specify only what's necessary—no +more, no less. If you aren't interested in the value of an argument, write `_` +as the argument, which means "anything goes": + +```cpp +using ::testing::_; +... +// Expects that the turtle jumps to somewhere on the x=50 line. +EXPECT_CALL(turtle, GoTo(50, _)); +``` + +`_` is an instance of what we call **matchers**. A matcher is like a predicate +and can test whether an argument is what we'd expect. You can use a matcher +inside `EXPECT_CALL()` wherever a function argument is expected. `_` is a +convenient way of saying "any value". + +In the above examples, `100` and `50` are also matchers; implicitly, they are +the same as `Eq(100)` and `Eq(50)`, which specify that the argument must be +equal (using `operator==`) to the matcher argument. There are many +[built-in matchers](reference/matchers.md) for common types (as well as +[custom matchers](gmock_cook_book.md#NewMatchers)); for example: + +```cpp +using ::testing::Ge; +... +// Expects the turtle moves forward by at least 100. +EXPECT_CALL(turtle, Forward(Ge(100))); +``` + +If you don't care about *any* arguments, rather than specify `_` for each of +them you may instead omit the parameter list: + +```cpp +// Expects the turtle to move forward. +EXPECT_CALL(turtle, Forward); +// Expects the turtle to jump somewhere. +EXPECT_CALL(turtle, GoTo); +``` + +This works for all non-overloaded methods; if a method is overloaded, you need +to help gMock resolve which overload is expected by specifying the number of +arguments and possibly also the +[types of the arguments](gmock_cook_book.md#SelectOverload). + +### Cardinalities: How Many Times Will It Be Called? + +The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We +call its argument a **cardinality** as it tells *how many times* the call should +occur. It allows us to repeat an expectation many times without actually writing +it as many times. More importantly, a cardinality can be "fuzzy", just like a +matcher can be. This allows a user to express the intent of a test exactly. + +An interesting special case is when we say `Times(0)`. You may have guessed - it +means that the function shouldn't be called with the given arguments at all, and +gMock will report a googletest failure whenever the function is (wrongfully) +called. + +We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the +list of built-in cardinalities you can use, see +[here](gmock_cheat_sheet.md#CardinalityList). + +The `Times()` clause can be omitted. **If you omit `Times()`, gMock will infer +the cardinality for you.** The rules are easy to remember: + +* If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the + `EXPECT_CALL()`, the inferred cardinality is `Times(1)`. +* If there are *n* `WillOnce()`'s but **no** `WillRepeatedly()`, where *n* >= + 1, the cardinality is `Times(n)`. +* If there are *n* `WillOnce()`'s and **one** `WillRepeatedly()`, where *n* >= + 0, the cardinality is `Times(AtLeast(n))`. + +**Quick quiz:** what do you think will happen if a function is expected to be +called twice but actually called four times? + +### Actions: What Should It Do? + +Remember that a mock object doesn't really have a working implementation? We as +users have to tell it what to do when a method is invoked. This is easy in +gMock. + +First, if the return type of a mock function is a built-in type or a pointer, +the function has a **default action** (a `void` function will just return, a +`bool` function will return `false`, and other functions will return 0). In +addition, in C++ 11 and above, a mock function whose return type is +default-constructible (i.e. has a default constructor) has a default action of +returning a default-constructed value. If you don't say anything, this behavior +will be used. + +Second, if a mock function doesn't have a default action, or the default action +doesn't suit you, you can specify the action to be taken each time the +expectation matches using a series of `WillOnce()` clauses followed by an +optional `WillRepeatedly()`. For example, + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillOnce(Return(300)); +``` + +says that `turtle.GetX()` will be called *exactly three times* (gMock inferred +this from how many `WillOnce()` clauses we've written, since we didn't +explicitly write `Times()`), and will return 100, 200, and 300 respectively. + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillRepeatedly(Return(300)); +``` + +says that `turtle.GetY()` will be called *at least twice* (gMock knows this as +we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no +explicit `Times()`), will return 100 and 200 respectively the first two times, +and 300 from the third time on. + +Of course, if you explicitly write a `Times()`, gMock will not try to infer the +cardinality itself. What if the number you specified is larger than there are +`WillOnce()` clauses? Well, after all `WillOnce()`s are used up, gMock will do +the *default* action for the function every time (unless, of course, you have a +`WillRepeatedly()`.). + +What can we do inside `WillOnce()` besides `Return()`? You can return a +reference using `ReturnRef(`*`variable`*`)`, or invoke a pre-defined function, +among [others](gmock_cook_book.md#using-actions). + +**Important note:** The `EXPECT_CALL()` statement evaluates the action clause +only once, even though the action may be performed many times. Therefore you +must be careful about side effects. The following may not do what you want: + +```cpp +using ::testing::Return; +... +int n = 100; +EXPECT_CALL(turtle, GetX()) + .Times(4) + .WillRepeatedly(Return(n++)); +``` + +Instead of returning 100, 101, 102, ..., consecutively, this mock function will +always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` +will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will +return the same pointer every time. If you want the side effect to happen every +time, you need to define a custom action, which we'll teach in the +[cook book](gmock_cook_book.md). + +Time for another quiz! What do you think the following means? + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) + .Times(4) + .WillOnce(Return(100)); +``` + +Obviously `turtle.GetY()` is expected to be called four times. But if you think +it will return 100 every time, think twice! Remember that one `WillOnce()` +clause will be consumed each time the function is invoked and the default action +will be taken afterwards. So the right answer is that `turtle.GetY()` will +return 100 the first time, but **return 0 from the second time on**, as +returning 0 is the default action for `int` functions. + +### Using Multiple Expectations {#MultiExpectations} + +So far we've only shown examples where you have a single expectation. More +realistically, you'll specify expectations on multiple mock methods which may be +from multiple mock objects. + +By default, when a mock method is invoked, gMock will search the expectations in +the **reverse order** they are defined, and stop when an active expectation that +matches the arguments is found (you can think of it as "newer rules override +older ones."). If the matching expectation cannot take any more calls, you will +get an upper-bound-violated failure. Here's an example: + +```cpp +using ::testing::_; +... +EXPECT_CALL(turtle, Forward(_)); // #1 +EXPECT_CALL(turtle, Forward(10)) // #2 + .Times(2); +``` + +If `Forward(10)` is called three times in a row, the third time it will be an +error, as the last matching expectation (#2) has been saturated. If, however, +the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, +as now #1 will be the matching expectation. + +{: .callout .note} +**Note:** Why does gMock search for a match in the *reverse* order of the +expectations? The reason is that this allows a user to set up the default +expectations in a mock object's constructor or the test fixture's set-up phase +and then customize the mock by writing more specific expectations in the test +body. So, if you have two expectations on the same method, you want to put the +one with more specific matchers **after** the other, or the more specific rule +would be shadowed by the more general one that comes after it. + +{: .callout .tip} +**Tip:** It is very common to start with a catch-all expectation for a method +and `Times(AnyNumber())` (omitting arguments, or with `_` for all arguments, if +overloaded). This makes any calls to the method expected. This is not necessary +for methods that are not mentioned at all (these are "uninteresting"), but is +useful for methods that have some expectations, but for which other calls are +ok. See +[Understanding Uninteresting vs Unexpected Calls](gmock_cook_book.md#uninteresting-vs-unexpected). + +### Ordered vs Unordered Calls {#OrderedCalls} + +By default, an expectation can match a call even though an earlier expectation +hasn't been satisfied. In other words, the calls don't have to occur in the +order the expectations are specified. + +Sometimes, you may want all the expected calls to occur in a strict order. To +say this in gMock is easy: + +```cpp +using ::testing::InSequence; +... +TEST(FooTest, DrawsLineSegment) { + ... + { + InSequence seq; + + EXPECT_CALL(turtle, PenDown()); + EXPECT_CALL(turtle, Forward(100)); + EXPECT_CALL(turtle, PenUp()); + } + Foo(); +} +``` + +By creating an object of type `InSequence`, all expectations in its scope are +put into a *sequence* and have to occur *sequentially*. Since we are just +relying on the constructor and destructor of this object to do the actual work, +its name is really irrelevant. + +In this example, we test that `Foo()` calls the three expected functions in the +order as written. If a call is made out-of-order, it will be an error. + +(What if you care about the relative order of some of the calls, but not all of +them? Can you specify an arbitrary partial order? The answer is ... yes! The +details can be found [here](gmock_cook_book.md#OrderedCalls).) + +### All Expectations Are Sticky (Unless Said Otherwise) {#StickyExpectations} + +Now let's do a quick quiz to see how well you can use this mock stuff already. +How would you test that the turtle is asked to go to the origin *exactly twice* +(you want to ignore any other instructions it receives)? + +After you've come up with your answer, take a look at ours and compare notes +(solve it yourself first - don't cheat!): + +```cpp +using ::testing::_; +using ::testing::AnyNumber; +... +EXPECT_CALL(turtle, GoTo(_, _)) // #1 + .Times(AnyNumber()); +EXPECT_CALL(turtle, GoTo(0, 0)) // #2 + .Times(2); +``` + +Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, gMock will +see that the arguments match expectation #2 (remember that we always pick the +last matching expectation). Now, since we said that there should be only two +such calls, gMock will report an error immediately. This is basically what we've +told you in the [Using Multiple Expectations](#MultiExpectations) section above. + +This example shows that **expectations in gMock are "sticky" by default**, in +the sense that they remain active even after we have reached their invocation +upper bounds. This is an important rule to remember, as it affects the meaning +of the spec, and is **different** to how it's done in many other mocking +frameworks (Why'd we do that? Because we think our rule makes the common cases +easier to express and understand.). + +Simple? Let's see if you've really understood it: what does the following code +say? + +```cpp +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)); +} +``` + +If you think it says that `turtle.GetX()` will be called `n` times and will +return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we +said, expectations are sticky. So, the second time `turtle.GetX()` is called, +the last (latest) `EXPECT_CALL()` statement will match, and will immediately +lead to an "upper bound violated" error - this piece of code is not very useful! + +One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is +to explicitly say that the expectations are *not* sticky. In other words, they +should *retire* as soon as they are saturated: + +```cpp +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); +} +``` + +And, there's a better way to do it: in this case, we expect the calls to occur +in a specific order, and we line up the actions to match the order. Since the +order is important here, we should make it explicit using a sequence: + +```cpp +using ::testing::InSequence; +using ::testing::Return; +... +{ + InSequence s; + + for (int i = 1; i <= n; i++) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); + } +} +``` + +By the way, the other situation where an expectation may *not* be sticky is when +it's in a sequence - as soon as another expectation that comes after it in the +sequence has been used, it automatically retires (and will never be used to +match any call). + +### Uninteresting Calls + +A mock object may have many methods, and not all of them are that interesting. +For example, in some tests we may not care about how many times `GetX()` and +`GetY()` get called. + +In gMock, if you are not interested in a method, just don't say anything about +it. If a call to this method occurs, you'll see a warning in the test output, +but it won't be a failure. This is called "naggy" behavior; to change, see +[The Nice, the Strict, and the Naggy](gmock_cook_book.md#NiceStrictNaggy). diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/index.md b/test/ios/iOSUnitTesting/extern/googletest/docs/index.md new file mode 100644 index 00000000..b162c740 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/index.md @@ -0,0 +1,22 @@ +# GoogleTest User's Guide + +## Welcome to GoogleTest! + +GoogleTest is Google's C++ testing and mocking framework. This user's guide has +the following contents: + +* [GoogleTest Primer](primer.md) - Teaches you how to write simple tests using + GoogleTest. Read this first if you are new to GoogleTest. +* [GoogleTest Advanced](advanced.md) - Read this when you've finished the + Primer and want to utilize GoogleTest to its full potential. +* [GoogleTest Samples](samples.md) - Describes some GoogleTest samples. +* [GoogleTest FAQ](faq.md) - Have a question? Want some tips? Check here + first. +* [Mocking for Dummies](gmock_for_dummies.md) - Teaches you how to create mock + objects and use them in tests. +* [Mocking Cookbook](gmock_cook_book.md) - Includes tips and approaches to + common mocking use cases. +* [Mocking Cheat Sheet](gmock_cheat_sheet.md) - A handy reference for + matchers, actions, invariants, and more. +* [Mocking FAQ](gmock_faq.md) - Contains answers to some mocking-specific + questions. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/pkgconfig.md b/test/ios/iOSUnitTesting/extern/googletest/docs/pkgconfig.md new file mode 100644 index 00000000..bf05d593 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/pkgconfig.md @@ -0,0 +1,144 @@ +## Using GoogleTest from various build systems + +GoogleTest comes with pkg-config files that can be used to determine all +necessary flags for compiling and linking to GoogleTest (and GoogleMock). +Pkg-config is a standardised plain-text format containing + +* the includedir (-I) path +* necessary macro (-D) definitions +* further required flags (-pthread) +* the library (-L) path +* the library (-l) to link to + +All current build systems support pkg-config in one way or another. For all +examples here we assume you want to compile the sample +`samples/sample3_unittest.cc`. + +### CMake + +Using `pkg-config` in CMake is fairly easy: + +```cmake +find_package(PkgConfig) +pkg_search_module(GTEST REQUIRED gtest_main) + +add_executable(testapp) +target_sources(testapp PRIVATE samples/sample3_unittest.cc) +target_link_libraries(testapp PRIVATE ${GTEST_LDFLAGS}) +target_compile_options(testapp PRIVATE ${GTEST_CFLAGS}) + +enable_testing() +add_test(first_and_only_test testapp) +``` + +It is generally recommended that you use `target_compile_options` + `_CFLAGS` +over `target_include_directories` + `_INCLUDE_DIRS` as the former includes not +just -I flags (GoogleTest might require a macro indicating to internal headers +that all libraries have been compiled with threading enabled. In addition, +GoogleTest might also require `-pthread` in the compiling step, and as such +splitting the pkg-config `Cflags` variable into include dirs and macros for +`target_compile_definitions()` might still miss this). The same recommendation +goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens +to discard `-L` flags and `-pthread`. + +### Help! pkg-config can't find GoogleTest! + +Let's say you have a `CMakeLists.txt` along the lines of the one in this +tutorial and you try to run `cmake`. It is very possible that you get a failure +along the lines of: + +``` +-- Checking for one of the modules 'gtest_main' +CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message): + None of the required 'gtest_main' found +``` + +These failures are common if you installed GoogleTest yourself and have not +sourced it from a distro or other package manager. If so, you need to tell +pkg-config where it can find the `.pc` files containing the information. Say you +installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are +installed under `/usr/local/lib64/pkgconfig`. If you set + +``` +export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig +``` + +pkg-config will also try to look in `PKG_CONFIG_PATH` to find `gtest_main.pc`. + +### Using pkg-config in a cross-compilation setting + +Pkg-config can be used in a cross-compilation setting too. To do this, let's +assume the final prefix of the cross-compiled installation will be `/usr`, and +your sysroot is `/home/MYUSER/sysroot`. Configure and install GTest using + +``` +mkdir build && cmake -DCMAKE_INSTALL_PREFIX=/usr .. +``` + +Install into the sysroot using `DESTDIR`: + +``` +make -j install DESTDIR=/home/MYUSER/sysroot +``` + +Before we continue, it is recommended to **always** define the following two +variables for pkg-config in a cross-compilation setting: + +``` +export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=yes +export PKG_CONFIG_ALLOW_SYSTEM_LIBS=yes +``` + +otherwise `pkg-config` will filter `-I` and `-L` flags against standard prefixes +such as `/usr` (see https://bugs.freedesktop.org/show_bug.cgi?id=28264#c3 for +reasons why this stripping needs to occur usually). + +If you look at the generated pkg-config file, it will look something like + +``` +libdir=/usr/lib64 +includedir=/usr/include + +Name: gtest +Description: GoogleTest (without main() function) +Version: 1.11.0 +URL: https://github.com/google/googletest +Libs: -L${libdir} -lgtest -lpthread +Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=1 -lpthread +``` + +Notice that the sysroot is not included in `libdir` and `includedir`! If you try +to run `pkg-config` with the correct +`PKG_CONFIG_LIBDIR=/home/MYUSER/sysroot/usr/lib64/pkgconfig` against this `.pc` +file, you will get + +``` +$ pkg-config --cflags gtest +-DGTEST_HAS_PTHREAD=1 -lpthread -I/usr/include +$ pkg-config --libs gtest +-L/usr/lib64 -lgtest -lpthread +``` + +which is obviously wrong and points to the `CBUILD` and not `CHOST` root. In +order to use this in a cross-compilation setting, we need to tell pkg-config to +inject the actual sysroot into `-I` and `-L` variables. Let us now tell +pkg-config about the actual sysroot + +``` +export PKG_CONFIG_DIR= +export PKG_CONFIG_SYSROOT_DIR=/home/MYUSER/sysroot +export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib64/pkgconfig +``` + +and running `pkg-config` again we get + +``` +$ pkg-config --cflags gtest +-DGTEST_HAS_PTHREAD=1 -lpthread -I/home/MYUSER/sysroot/usr/include +$ pkg-config --libs gtest +-L/home/MYUSER/sysroot/usr/lib64 -lgtest -lpthread +``` + +which contains the correct sysroot now. For a more comprehensive guide to also +including `${CHOST}` in build system calls, see the excellent tutorial by Diego +Elio Pettenò: diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/platforms.md b/test/ios/iOSUnitTesting/extern/googletest/docs/platforms.md new file mode 100644 index 00000000..d35a7be0 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/platforms.md @@ -0,0 +1,8 @@ +# Supported Platforms + +GoogleTest follows Google's +[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support). +See +[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) +for a list of currently supported versions compilers, platforms, and build +tools. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/primer.md b/test/ios/iOSUnitTesting/extern/googletest/docs/primer.md new file mode 100644 index 00000000..61806be6 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/primer.md @@ -0,0 +1,482 @@ +# GoogleTest Primer + +## Introduction: Why GoogleTest? + +*GoogleTest* helps you write better C++ tests. + +GoogleTest is a testing framework developed by the Testing Technology team with +Google's specific requirements and constraints in mind. Whether you work on +Linux, Windows, or a Mac, if you write C++ code, GoogleTest can help you. And it +supports *any* kind of tests, not just unit tests. + +So what makes a good test, and how does GoogleTest fit in? We believe: + +1. Tests should be *independent* and *repeatable*. It's a pain to debug a test + that succeeds or fails as a result of other tests. GoogleTest isolates the + tests by running each of them on a different object. When a test fails, + GoogleTest allows you to run it in isolation for quick debugging. +2. Tests should be well *organized* and reflect the structure of the tested + code. GoogleTest groups related tests into test suites that can share data + and subroutines. This common pattern is easy to recognize and makes tests + easy to maintain. Such consistency is especially helpful when people switch + projects and start to work on a new code base. +3. Tests should be *portable* and *reusable*. Google has a lot of code that is + platform-neutral; its tests should also be platform-neutral. GoogleTest + works on different OSes, with different compilers, with or without + exceptions, so GoogleTest tests can work with a variety of configurations. +4. When tests fail, they should provide as much *information* about the problem + as possible. GoogleTest doesn't stop at the first test failure. Instead, it + only stops the current test and continues with the next. You can also set up + tests that report non-fatal failures after which the current test continues. + Thus, you can detect and fix multiple bugs in a single run-edit-compile + cycle. +5. The testing framework should liberate test writers from housekeeping chores + and let them focus on the test *content*. GoogleTest automatically keeps + track of all tests defined, and doesn't require the user to enumerate them + in order to run them. +6. Tests should be *fast*. With GoogleTest, you can reuse shared resources + across tests and pay for the set-up/tear-down only once, without making + tests depend on each other. + +Since GoogleTest is based on the popular xUnit architecture, you'll feel right +at home if you've used JUnit or PyUnit before. If not, it will take you about 10 +minutes to learn the basics and get started. So let's go! + +## Beware of the Nomenclature + +{: .callout .note} +*Note:* There might be some confusion arising from different definitions of the +terms *Test*, *Test Case* and *Test Suite*, so beware of misunderstanding these. + +Historically, GoogleTest started to use the term *Test Case* for grouping +related tests, whereas current publications, including International Software +Testing Qualifications Board ([ISTQB](https://www.istqb.org/)) materials and +various textbooks on software quality, use the term +*[Test Suite][istqb test suite]* for this. + +The related term *Test*, as it is used in GoogleTest, corresponds to the term +*[Test Case][istqb test case]* of ISTQB and others. + +The term *Test* is commonly of broad enough sense, including ISTQB's definition +of *Test Case*, so it's not much of a problem here. But the term *Test Case* as +was used in Google Test is of contradictory sense and thus confusing. + +GoogleTest recently started replacing the term *Test Case* with *Test Suite*. +The preferred API is *TestSuite*. The older TestCase API is being slowly +deprecated and refactored away. + +So please be aware of the different definitions of the terms: + + +Meaning | GoogleTest Term | [ISTQB](https://www.istqb.org/) Term +:----------------------------------------------------------------------------------- | :---------------------- | :---------------------------------- +Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case] + + +[istqb test case]: https://glossary.istqb.org/en_US/term/test-case-2 +[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite-1-3 + +## Basic Concepts + +When using GoogleTest, you start by writing *assertions*, which are statements +that check whether a condition is true. An assertion's result can be *success*, +*nonfatal failure*, or *fatal failure*. If a fatal failure occurs, it aborts the +current function; otherwise the program continues normally. + +*Tests* use assertions to verify the tested code's behavior. If a test crashes +or has a failed assertion, then it *fails*; otherwise it *succeeds*. + +A *test suite* contains one or many tests. You should group your tests into test +suites that reflect the structure of the tested code. When multiple tests in a +test suite need to share common objects and subroutines, you can put them into a +*test fixture* class. + +A *test program* can contain multiple test suites. + +We'll now explain how to write a test program, starting at the individual +assertion level and building up to tests and test suites. + +## Assertions + +GoogleTest assertions are macros that resemble function calls. You test a class +or function by making assertions about its behavior. When an assertion fails, +GoogleTest prints the assertion's source file and line number location, along +with a failure message. You may also supply a custom failure message which will +be appended to GoogleTest's message. + +The assertions come in pairs that test the same thing but have different effects +on the current function. `ASSERT_*` versions generate fatal failures when they +fail, and **abort the current function**. `EXPECT_*` versions generate nonfatal +failures, which don't abort the current function. Usually `EXPECT_*` are +preferred, as they allow more than one failure to be reported in a test. +However, you should use `ASSERT_*` if it doesn't make sense to continue when the +assertion in question fails. + +Since a failed `ASSERT_*` returns from the current function immediately, +possibly skipping clean-up code that comes after it, it may cause a space leak. +Depending on the nature of the leak, it may or may not be worth fixing - so keep +this in mind if you get a heap checker error in addition to assertion errors. + +To provide a custom failure message, simply stream it into the macro using the +`<<` operator or a sequence of such operators. See the following example, using +the [`ASSERT_EQ` and `EXPECT_EQ`](reference/assertions.md#EXPECT_EQ) macros to +verify value equality: + +```c++ +ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length"; + +for (int i = 0; i < x.size(); ++i) { + EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i; +} +``` + +Anything that can be streamed to an `ostream` can be streamed to an assertion +macro--in particular, C strings and `string` objects. If a wide string +(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is +streamed to an assertion, it will be translated to UTF-8 when printed. + +GoogleTest provides a collection of assertions for verifying the behavior of +your code in various ways. You can check Boolean conditions, compare values +based on relational operators, verify string values, floating-point values, and +much more. There are even assertions that enable you to verify more complex +states by providing custom predicates. For the complete list of assertions +provided by GoogleTest, see the [Assertions Reference](reference/assertions.md). + +## Simple Tests + +To create a test: + +1. Use the `TEST()` macro to define and name a test function. These are + ordinary C++ functions that don't return a value. +2. In this function, along with any valid C++ statements you want to include, + use the various GoogleTest assertions to check values. +3. The test's result is determined by the assertions; if any assertion in the + test fails (either fatally or non-fatally), or if the test crashes, the + entire test fails. Otherwise, it succeeds. + +```c++ +TEST(TestSuiteName, TestName) { + ... test body ... +} +``` + +`TEST()` arguments go from general to specific. The *first* argument is the name +of the test suite, and the *second* argument is the test's name within the test +suite. Both names must be valid C++ identifiers, and they should not contain any +underscores (`_`). A test's *full name* consists of its containing test suite +and its individual name. Tests from different test suites can have the same +individual name. + +For example, let's take a simple integer function: + +```c++ +int Factorial(int n); // Returns the factorial of n +``` + +A test suite for this function might look like: + +```c++ +// Tests factorial of 0. +TEST(FactorialTest, HandlesZeroInput) { + EXPECT_EQ(Factorial(0), 1); +} + +// Tests factorial of positive numbers. +TEST(FactorialTest, HandlesPositiveInput) { + EXPECT_EQ(Factorial(1), 1); + EXPECT_EQ(Factorial(2), 2); + EXPECT_EQ(Factorial(3), 6); + EXPECT_EQ(Factorial(8), 40320); +} +``` + +GoogleTest groups the test results by test suites, so logically related tests +should be in the same test suite; in other words, the first argument to their +`TEST()` should be the same. In the above example, we have two tests, +`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test +suite `FactorialTest`. + +When naming your test suites and tests, you should follow the same convention as +for +[naming functions and classes](https://google.github.io/styleguide/cppguide.html#Function_Names). + +**Availability**: Linux, Windows, Mac. + +## Test Fixtures: Using the Same Data Configuration for Multiple Tests {#same-data-multiple-tests} + +If you find yourself writing two or more tests that operate on similar data, you +can use a *test fixture*. This allows you to reuse the same configuration of +objects for several different tests. + +To create a fixture: + +1. Derive a class from `testing::Test` . Start its body with `protected:`, as + we'll want to access fixture members from sub-classes. +2. Inside the class, declare any objects you plan to use. +3. If necessary, write a default constructor or `SetUp()` function to prepare + the objects for each test. A common mistake is to spell `SetUp()` as + **`Setup()`** with a small `u` - Use `override` in C++11 to make sure you + spelled it correctly. +4. If necessary, write a destructor or `TearDown()` function to release any + resources you allocated in `SetUp()` . To learn when you should use the + constructor/destructor and when you should use `SetUp()/TearDown()`, read + the [FAQ](faq.md#CtorVsSetUp). +5. If needed, define subroutines for your tests to share. + +When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to +access objects and subroutines in the test fixture: + +```c++ +TEST_F(TestFixtureClassName, TestName) { + ... test body ... +} +``` + +Unlike `TEST()`, in `TEST_F()` the first argument must be the name of the test +fixture class. (`_F` stands for "Fixture"). No test suite name is specified for +this macro. + +Unfortunately, the C++ macro system does not allow us to create a single macro +that can handle both types of tests. Using the wrong macro causes a compiler +error. + +Also, you must first define a test fixture class before using it in a +`TEST_F()`, or you'll get the compiler error "`virtual outside class +declaration`". + +For each test defined with `TEST_F()`, GoogleTest will create a *fresh* test +fixture at runtime, immediately initialize it via `SetUp()`, run the test, clean +up by calling `TearDown()`, and then delete the test fixture. Note that +different tests in the same test suite have different test fixture objects, and +GoogleTest always deletes a test fixture before it creates the next one. +GoogleTest does **not** reuse the same test fixture for multiple tests. Any +changes one test makes to the fixture do not affect other tests. + +As an example, let's write tests for a FIFO queue class named `Queue`, which has +the following interface: + +```c++ +template // E is the element type. +class Queue { + public: + Queue(); + void Enqueue(const E& element); + E* Dequeue(); // Returns NULL if the queue is empty. + size_t size() const; + ... +}; +``` + +First, define a fixture class. By convention, you should give it the name +`FooTest` where `Foo` is the class being tested. + +```c++ +class QueueTest : public testing::Test { + protected: + QueueTest() { + // q0_ remains empty + q1_.Enqueue(1); + q2_.Enqueue(2); + q2_.Enqueue(3); + } + + // ~QueueTest() override = default; + + Queue q0_; + Queue q1_; + Queue q2_; +}; +``` + +In this case, we don't need to define a destructor or a `TearDown()` method, +because the implicit destructor generated by the compiler will perform all of +the necessary cleanup. + +Now we'll write tests using `TEST_F()` and this fixture. + +```c++ +TEST_F(QueueTest, IsEmptyInitially) { + EXPECT_EQ(q0_.size(), 0); +} + +TEST_F(QueueTest, DequeueWorks) { + int* n = q0_.Dequeue(); + EXPECT_EQ(n, nullptr); + + n = q1_.Dequeue(); + ASSERT_NE(n, nullptr); + EXPECT_EQ(*n, 1); + EXPECT_EQ(q1_.size(), 0); + delete n; + + n = q2_.Dequeue(); + ASSERT_NE(n, nullptr); + EXPECT_EQ(*n, 2); + EXPECT_EQ(q2_.size(), 1); + delete n; +} +``` + +The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is +to use `EXPECT_*` when you want the test to continue to reveal more errors after +the assertion failure, and use `ASSERT_*` when continuing after failure doesn't +make sense. For example, the second assertion in the `Dequeue` test is +`ASSERT_NE(n, nullptr)`, as we need to dereference the pointer `n` later, which +would lead to a segfault when `n` is `NULL`. + +When these tests run, the following happens: + +1. GoogleTest constructs a `QueueTest` object (let's call it `t1`). +2. The first test (`IsEmptyInitially`) runs on `t1`. +3. `t1` is destructed. +4. The above steps are repeated on another `QueueTest` object, this time + running the `DequeueWorks` test. + +**Availability**: Linux, Windows, Mac. + +## Invoking the Tests + +`TEST()` and `TEST_F()` implicitly register their tests with GoogleTest. So, +unlike with many other C++ testing frameworks, you don't have to re-list all +your defined tests in order to run them. + +After defining your tests, you can run them with `RUN_ALL_TESTS()`, which +returns `0` if all the tests are successful, or `1` otherwise. Note that +`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from different +test suites, or even different source files. + +When invoked, the `RUN_ALL_TESTS()` macro: + +* Saves the state of all GoogleTest flags. + +* Creates a test fixture object for the first test. + +* Initializes it via `SetUp()`. + +* Runs the test on the fixture object. + +* Cleans up the fixture via `TearDown()`. + +* Deletes the fixture. + +* Restores the state of all GoogleTest flags. + +* Repeats the above steps for the next test, until all tests have run. + +If a fatal failure happens the subsequent steps will be skipped. + +{: .callout .important} +> IMPORTANT: You must **not** ignore the return value of `RUN_ALL_TESTS()`, or +> you will get a compiler error. The rationale for this design is that the +> automated testing service determines whether a test has passed based on its +> exit code, not on its stdout/stderr output; thus your `main()` function must +> return the value of `RUN_ALL_TESTS()`. +> +> Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than +> once conflicts with some advanced GoogleTest features (e.g., thread-safe +> [death tests](advanced.md#death-tests)) and thus is not supported. + +**Availability**: Linux, Windows, Mac. + +## Writing the main() Function + +Most users should *not* need to write their own `main` function and instead link +with `gtest_main` (as opposed to with `gtest`), which defines a suitable entry +point. See the end of this section for details. The remainder of this section +should only apply when you need to do something custom before the tests run that +cannot be expressed within the framework of fixtures and test suites. + +If you write your own `main` function, it should return the value of +`RUN_ALL_TESTS()`. + +You can start from this boilerplate: + +```c++ +#include "this/package/foo.h" + +#include + +namespace my { +namespace project { +namespace { + +// The fixture for testing class Foo. +class FooTest : public testing::Test { + protected: + // You can remove any or all of the following functions if their bodies would + // be empty. + + FooTest() { + // You can do set-up work for each test here. + } + + ~FooTest() override { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + void SetUp() override { + // Code here will be called immediately after the constructor (right + // before each test). + } + + void TearDown() override { + // Code here will be called immediately after each test (right + // before the destructor). + } + + // Class members declared here can be used by all tests in the test suite + // for Foo. +}; + +// Tests that the Foo::Bar() method does Abc. +TEST_F(FooTest, MethodBarDoesAbc) { + const std::string input_filepath = "this/package/testdata/myinputfile.dat"; + const std::string output_filepath = "this/package/testdata/myoutputfile.dat"; + Foo f; + EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0); +} + +// Tests that Foo does Xyz. +TEST_F(FooTest, DoesXyz) { + // Exercises the Xyz feature of Foo. +} + +} // namespace +} // namespace project +} // namespace my + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +``` + +The `testing::InitGoogleTest()` function parses the command line for GoogleTest +flags, and removes all recognized flags. This allows the user to control a test +program's behavior via various flags, which we'll cover in the +[AdvancedGuide](advanced.md). You **must** call this function before calling +`RUN_ALL_TESTS()`, or the flags won't be properly initialized. + +On Windows, `InitGoogleTest()` also works with wide strings, so it can be used +in programs compiled in `UNICODE` mode as well. + +But maybe you think that writing all those `main` functions is too much work? We +agree with you completely, and that's why Google Test provides a basic +implementation of main(). If it fits your needs, then just link your test with +the `gtest_main` library and you are good to go. + +{: .callout .note} +NOTE: `ParseGUnitFlags()` is deprecated in favor of `InitGoogleTest()`. + +## Known Limitations + +* Google Test is designed to be thread-safe. The implementation is thread-safe + on systems where the `pthreads` library is available. It is currently + *unsafe* to use Google Test assertions from two threads concurrently on + other systems (e.g. Windows). In most tests this is not an issue as usually + the assertions are done in the main thread. If you want to help, you can + volunteer to implement the necessary synchronization primitives in + `gtest-port.h` for your platform. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-bazel.md b/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-bazel.md new file mode 100644 index 00000000..5750f026 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-bazel.md @@ -0,0 +1,146 @@ +# Quickstart: Building with Bazel + +This tutorial aims to get you up and running with GoogleTest using the Bazel +build system. If you're using GoogleTest for the first time or need a refresher, +we recommend this tutorial as a starting point. + +## Prerequisites + +To complete this tutorial, you'll need: + +* A compatible operating system (e.g. Linux, macOS, Windows). +* A compatible C++ compiler that supports at least C++14. +* [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used + by the GoogleTest team. + +See [Supported Platforms](platforms.md) for more information about platforms +compatible with GoogleTest. + +If you don't already have Bazel installed, see the +[Bazel installation guide](https://bazel.build/install). + +{: .callout .note} Note: The terminal commands in this tutorial show a Unix +shell prompt, but the commands work on the Windows command line as well. + +## Set up a Bazel workspace + +A +[Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace) +is a directory on your filesystem that you use to manage source files for the +software you want to build. Each workspace directory has a text file named +`MODULE.bazel` which may be empty, or may contain references to external +dependencies required to build the outputs. + +First, create a directory for your workspace: + +``` +$ mkdir my_workspace && cd my_workspace +``` + +Next, you’ll create the `MODULE.bazel` file to specify dependencies. As of Bazel +7.0, the recommended way to consume GoogleTest is through the +[Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do +this, create a `MODULE.bazel` file in the root directory of your Bazel workspace +with the following content: + +``` +# MODULE.bazel + +# Choose the most recent version available at +# https://registry.bazel.build/modules/googletest +bazel_dep(name = "googletest", version = "1.15.2") +``` + +Now you're ready to build C++ code that uses GoogleTest. + +## Create and run a binary + +With your Bazel workspace set up, you can now use GoogleTest code within your +own project. + +As an example, create a file named `hello_test.cc` in your `my_workspace` +directory with the following contents: + +```cpp +#include + +// Demonstrate some basic assertions. +TEST(HelloTest, BasicAssertions) { + // Expect two strings not to be equal. + EXPECT_STRNE("hello", "world"); + // Expect equality. + EXPECT_EQ(7 * 6, 42); +} +``` + +GoogleTest provides [assertions](primer.md#assertions) that you use to test the +behavior of your code. The above sample includes the main GoogleTest header file +and demonstrates some basic assertions. + +To build the code, create a file named `BUILD` in the same directory with the +following contents: + +``` +cc_test( + name = "hello_test", + size = "small", + srcs = ["hello_test.cc"], + deps = [ + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) +``` + +This `cc_test` rule declares the C++ test binary you want to build, and links to +the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()` +function (`@googletest//:gtest_main`). For more information about Bazel `BUILD` +files, see the +[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html). + +{: .callout .note} +NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++14` +to ensure that GoogleTest is compiled as C++14 instead of the compiler's default +setting (which could be C++11). For MSVC, the equivalent would be +`--cxxopt=/std:c++14`. See [Supported Platforms](platforms.md) for more details +on supported language versions. + +Now you can build and run your test: + +
+$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test
+INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
+INFO: Found 1 test target...
+INFO: From Testing //:hello_test:
+==================== Test output for //:hello_test:
+Running main() from gmock_main.cc
+[==========] Running 1 test from 1 test suite.
+[----------] Global test environment set-up.
+[----------] 1 test from HelloTest
+[ RUN      ] HelloTest.BasicAssertions
+[       OK ] HelloTest.BasicAssertions (0 ms)
+[----------] 1 test from HelloTest (0 ms total)
+
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test suite ran. (0 ms total)
+[  PASSED  ] 1 test.
+================================================================================
+Target //:hello_test up-to-date:
+  bazel-bin/hello_test
+INFO: Elapsed time: 4.190s, Critical Path: 3.05s
+INFO: 27 processes: 8 internal, 19 linux-sandbox.
+INFO: Build completed successfully, 27 total actions
+//:hello_test                                                     PASSED in 0.1s
+
+INFO: Build completed successfully, 27 total actions
+
+ +Congratulations! You've successfully built and run a test binary using +GoogleTest. + +## Next steps + +* [Check out the Primer](primer.md) to start learning how to write simple + tests. +* [See the code samples](samples.md) for more examples showing how to use a + variety of GoogleTest features. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-cmake.md b/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-cmake.md new file mode 100644 index 00000000..4e422b74 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/quickstart-cmake.md @@ -0,0 +1,157 @@ +# Quickstart: Building with CMake + +This tutorial aims to get you up and running with GoogleTest using CMake. If +you're using GoogleTest for the first time or need a refresher, we recommend +this tutorial as a starting point. If your project uses Bazel, see the +[Quickstart for Bazel](quickstart-bazel.md) instead. + +## Prerequisites + +To complete this tutorial, you'll need: + +* A compatible operating system (e.g. Linux, macOS, Windows). +* A compatible C++ compiler that supports at least C++14. +* [CMake](https://cmake.org/) and a compatible build tool for building the + project. + * Compatible build tools include + [Make](https://www.gnu.org/software/make/), + [Ninja](https://ninja-build.org/), and others - see + [CMake Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) + for more information. + +See [Supported Platforms](platforms.md) for more information about platforms +compatible with GoogleTest. + +If you don't already have CMake installed, see the +[CMake installation guide](https://cmake.org/install). + +{: .callout .note} +Note: The terminal commands in this tutorial show a Unix shell prompt, but the +commands work on the Windows command line as well. + +## Set up a project + +CMake uses a file named `CMakeLists.txt` to configure the build system for a +project. You'll use this file to set up your project and declare a dependency on +GoogleTest. + +First, create a directory for your project: + +``` +$ mkdir my_project && cd my_project +``` + +Next, you'll create the `CMakeLists.txt` file and declare a dependency on +GoogleTest. There are many ways to express dependencies in the CMake ecosystem; +in this quickstart, you'll use the +[`FetchContent` CMake module](https://cmake.org/cmake/help/latest/module/FetchContent.html). +To do this, in your project directory (`my_project`), create a file named +`CMakeLists.txt` with the following contents: + +```cmake +cmake_minimum_required(VERSION 3.14) +project(my_project) + +# GoogleTest requires at least C++14 +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) +``` + +The above configuration declares a dependency on GoogleTest which is downloaded +from GitHub. In the above example, `03597a01ee50ed33e9dfd640b249b4be3799d395` is +the Git commit hash of the GoogleTest version to use; we recommend updating the +hash often to point to the latest version. + +For more information about how to create `CMakeLists.txt` files, see the +[CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html). + +## Create and run a binary + +With GoogleTest declared as a dependency, you can use GoogleTest code within +your own project. + +As an example, create a file named `hello_test.cc` in your `my_project` +directory with the following contents: + +```cpp +#include + +// Demonstrate some basic assertions. +TEST(HelloTest, BasicAssertions) { + // Expect two strings not to be equal. + EXPECT_STRNE("hello", "world"); + // Expect equality. + EXPECT_EQ(7 * 6, 42); +} +``` + +GoogleTest provides [assertions](primer.md#assertions) that you use to test the +behavior of your code. The above sample includes the main GoogleTest header file +and demonstrates some basic assertions. + +To build the code, add the following to the end of your `CMakeLists.txt` file: + +```cmake +enable_testing() + +add_executable( + hello_test + hello_test.cc +) +target_link_libraries( + hello_test + GTest::gtest_main +) + +include(GoogleTest) +gtest_discover_tests(hello_test) +``` + +The above configuration enables testing in CMake, declares the C++ test binary +you want to build (`hello_test`), and links it to GoogleTest (`gtest_main`). The +last two lines enable CMake's test runner to discover the tests included in the +binary, using the +[`GoogleTest` CMake module](https://cmake.org/cmake/help/git-stage/module/GoogleTest.html). + +Now you can build and run your test: + +
+my_project$ cmake -S . -B build
+-- The C compiler identification is GNU 10.2.1
+-- The CXX compiler identification is GNU 10.2.1
+...
+-- Build files have been written to: .../my_project/build
+
+my_project$ cmake --build build
+Scanning dependencies of target gtest
+...
+[100%] Built target gmock_main
+
+my_project$ cd build && ctest
+Test project .../my_project/build
+    Start 1: HelloTest.BasicAssertions
+1/1 Test #1: HelloTest.BasicAssertions ........   Passed    0.00 sec
+
+100% tests passed, 0 tests failed out of 1
+
+Total Test time (real) =   0.01 sec
+
+ +Congratulations! You've successfully built and run a test binary using +GoogleTest. + +## Next steps + +* [Check out the Primer](primer.md) to start learning how to write simple + tests. +* [See the code samples](samples.md) for more examples showing how to use a + variety of GoogleTest features. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/reference/actions.md b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/actions.md new file mode 100644 index 00000000..ab81a129 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/actions.md @@ -0,0 +1,115 @@ +# Actions Reference + +[**Actions**](../gmock_for_dummies.md#actions-what-should-it-do) specify what a +mock function should do when invoked. This page lists the built-in actions +provided by GoogleTest. All actions are defined in the `::testing` namespace. + +## Returning a Value + +| Action | Description | +| :-------------------------------- | :-------------------------------------------- | +| `Return()` | Return from a `void` mock function. | +| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type at the time the expectation is set, not when the action is executed. | +| `ReturnArg()` | Return the `N`-th (0-based) argument. | +| `ReturnNew(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. | +| `ReturnNull()` | Return a null pointer. | +| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. | +| `ReturnRef(variable)` | Return a reference to `variable`. | +| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. | +| `ReturnRoundRobin({a1, ..., ak})` | Each call will return the next `ai` in the list, starting at the beginning when the end of the list is reached. | + +## Side Effects + +| Action | Description | +| :--------------------------------- | :-------------------------------------- | +| `Assign(&variable, value)` | Assign `value` to variable. | +| `DeleteArg()` | Delete the `N`-th (0-based) argument, which must be a pointer. | +| `SaveArg(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. | +| `SaveArgPointee(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. | +| `SetArgReferee(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. | +| `SetArgPointee(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. | +| `SetArgumentPointee(value)` | Same as `SetArgPointee(value)`. Deprecated. Will be removed in v1.7.0. | +| `SetArrayArgument(first, last)` | Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. | +| `SetErrnoAndReturn(error, value)` | Set `errno` to `error` and return `value`. | +| `Throw(exception)` | Throws the given exception, which can be any copyable value. Available since v1.1.0. | + +## Using a Function, Functor, or Lambda as an Action + +In the following, by "callable" we mean a free function, `std::function`, +functor, or lambda. + +| Action | Description | +| :---------------------------------- | :------------------------------------- | +| `f` | Invoke `f` with the arguments passed to the mock function, where `f` is a callable. | +| `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. | +| `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. | +| `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. | +| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. | +| `InvokeArgument(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. | + +The return value of the invoked function is used as the return value of the +action. + +When defining a callable to be used with `Invoke*()`, you can declare any unused +parameters as `Unused`: + +```cpp +using ::testing::Invoke; +double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); } +... +EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance)); +``` + +`Invoke(callback)` and `InvokeWithoutArgs(callback)` take ownership of +`callback`, which must be permanent. The type of `callback` must be a base +callback type instead of a derived one, e.g. + +```cpp + BlockingClosure* done = new BlockingClosure; + ... Invoke(done) ...; // This won't compile! + + Closure* done2 = new BlockingClosure; + ... Invoke(done2) ...; // This works. +``` + +In `InvokeArgument(...)`, if an argument needs to be passed by reference, +wrap it inside `std::ref()`. For example, + +```cpp +using ::testing::InvokeArgument; +... +InvokeArgument<2>(5, string("Hi"), std::ref(foo)) +``` + +calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by +value, and `foo` by reference. + +## Default Action + +| Action | Description | +| :------------ | :----------------------------------------------------- | +| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). | + +{: .callout .note} +**Note:** due to technical reasons, `DoDefault()` cannot be used inside a +composite action - trying to do so will result in a run-time error. + +## Composite Actions + +| Action | Description | +| :----------------------------- | :------------------------------------------ | +| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void and will receive a readonly view of the arguments. | +| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. | +| `WithArg(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. | +| `WithArgs(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. | +| `WithoutArgs(a)` | Perform action `a` without any arguments. | + +## Defining Actions + +| Macro | Description | +| :--------------------------------- | :-------------------------------------- | +| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. | +| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. | +| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. | + +The `ACTION*` macros cannot be used inside a function or class. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/reference/assertions.md b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/assertions.md new file mode 100644 index 00000000..492ff5ef --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/assertions.md @@ -0,0 +1,633 @@ +# Assertions Reference + +This page lists the assertion macros provided by GoogleTest for verifying code +behavior. To use them, add `#include `. + +The majority of the macros listed below come as a pair with an `EXPECT_` variant +and an `ASSERT_` variant. Upon failure, `EXPECT_` macros generate nonfatal +failures and allow the current function to continue running, while `ASSERT_` +macros generate fatal failures and abort the current function. + +All assertion macros support streaming a custom failure message into them with +the `<<` operator, for example: + +```cpp +EXPECT_TRUE(my_condition) << "My condition is not true"; +``` + +Anything that can be streamed to an `ostream` can be streamed to an assertion +macro—in particular, C strings and string objects. If a wide string (`wchar_t*`, +`TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is streamed to an +assertion, it will be translated to UTF-8 when printed. + +## Explicit Success and Failure {#success-failure} + +The assertions in this section generate a success or failure directly instead of +testing a value or expression. These are useful when control flow, rather than a +Boolean expression, determines the test's success or failure, as shown by the +following example: + +```c++ +switch(expression) { + case 1: + ... some checks ... + case 2: + ... some other checks ... + default: + FAIL() << "We shouldn't get here."; +} +``` + +### SUCCEED {#SUCCEED} + +`SUCCEED()` + +Generates a success. This *does not* make the overall test succeed. A test is +considered successful only if none of its assertions fail during its execution. + +The `SUCCEED` assertion is purely documentary and currently doesn't generate any +user-visible output. However, we may add `SUCCEED` messages to GoogleTest output +in the future. + +### FAIL {#FAIL} + +`FAIL()` + +Generates a fatal failure, which returns from the current function. + +Can only be used in functions that return `void`. See +[Assertion Placement](../advanced.md#assertion-placement) for more information. + +### ADD_FAILURE {#ADD_FAILURE} + +`ADD_FAILURE()` + +Generates a nonfatal failure, which allows the current function to continue +running. + +### ADD_FAILURE_AT {#ADD_FAILURE_AT} + +`ADD_FAILURE_AT(`*`file_path`*`,`*`line_number`*`)` + +Generates a nonfatal failure at the file and line number specified. + +## Generalized Assertion {#generalized} + +The following assertion allows [matchers](matchers.md) to be used to verify +values. + +### EXPECT_THAT {#EXPECT_THAT} + +`EXPECT_THAT(`*`value`*`,`*`matcher`*`)` \ +`ASSERT_THAT(`*`value`*`,`*`matcher`*`)` + +Verifies that *`value`* matches the [matcher](matchers.md) *`matcher`*. + +For example, the following code verifies that the string `value1` starts with +`"Hello"`, `value2` matches a regular expression, and `value3` is between 5 and +10: + +```cpp +#include + +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::Lt; +using ::testing::MatchesRegex; +using ::testing::StartsWith; + +... +EXPECT_THAT(value1, StartsWith("Hello")); +EXPECT_THAT(value2, MatchesRegex("Line \\d+")); +ASSERT_THAT(value3, AllOf(Gt(5), Lt(10))); +``` + +Matchers enable assertions of this form to read like English and generate +informative failure messages. For example, if the above assertion on `value1` +fails, the resulting message will be similar to the following: + +``` +Value of: value1 + Actual: "Hi, world!" +Expected: starts with "Hello" +``` + +GoogleTest provides a built-in library of matchers—see the +[Matchers Reference](matchers.md). It is also possible to write your own +matchers—see [Writing New Matchers Quickly](../gmock_cook_book.md#NewMatchers). +The use of matchers makes `EXPECT_THAT` a powerful, extensible assertion. + +*The idea for this assertion was borrowed from Joe Walnes' Hamcrest project, +which adds `assertThat()` to JUnit.* + +## Boolean Conditions {#boolean} + +The following assertions test Boolean conditions. + +### EXPECT_TRUE {#EXPECT_TRUE} + +`EXPECT_TRUE(`*`condition`*`)` \ +`ASSERT_TRUE(`*`condition`*`)` + +Verifies that *`condition`* is true. + +### EXPECT_FALSE {#EXPECT_FALSE} + +`EXPECT_FALSE(`*`condition`*`)` \ +`ASSERT_FALSE(`*`condition`*`)` + +Verifies that *`condition`* is false. + +## Binary Comparison {#binary-comparison} + +The following assertions compare two values. The value arguments must be +comparable by the assertion's comparison operator, otherwise a compiler error +will result. + +If an argument supports the `<<` operator, it will be called to print the +argument when the assertion fails. Otherwise, GoogleTest will attempt to print +them in the best way it can—see +[Teaching GoogleTest How to Print Your Values](../advanced.md#teaching-googletest-how-to-print-your-values). + +Arguments are always evaluated exactly once, so it's OK for the arguments to +have side effects. However, the argument evaluation order is undefined and +programs should not depend on any particular argument evaluation order. + +These assertions work with both narrow and wide string objects (`string` and +`wstring`). + +See also the [Floating-Point Comparison](#floating-point) assertions to compare +floating-point numbers and avoid problems caused by rounding. + +### EXPECT_EQ {#EXPECT_EQ} + +`EXPECT_EQ(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_EQ(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`==`*`val2`*. + +Does pointer equality on pointers. If used on two C strings, it tests if they +are in the same memory location, not if they have the same value. Use +[`EXPECT_STREQ`](#EXPECT_STREQ) to compare C strings (e.g. `const char*`) by +value. + +When comparing a pointer to `NULL`, use `EXPECT_EQ(`*`ptr`*`, nullptr)` instead +of `EXPECT_EQ(`*`ptr`*`, NULL)`. + +### EXPECT_NE {#EXPECT_NE} + +`EXPECT_NE(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_NE(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`!=`*`val2`*. + +Does pointer equality on pointers. If used on two C strings, it tests if they +are in different memory locations, not if they have different values. Use +[`EXPECT_STRNE`](#EXPECT_STRNE) to compare C strings (e.g. `const char*`) by +value. + +When comparing a pointer to `NULL`, use `EXPECT_NE(`*`ptr`*`, nullptr)` instead +of `EXPECT_NE(`*`ptr`*`, NULL)`. + +### EXPECT_LT {#EXPECT_LT} + +`EXPECT_LT(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_LT(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`<`*`val2`*. + +### EXPECT_LE {#EXPECT_LE} + +`EXPECT_LE(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_LE(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`<=`*`val2`*. + +### EXPECT_GT {#EXPECT_GT} + +`EXPECT_GT(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_GT(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`>`*`val2`*. + +### EXPECT_GE {#EXPECT_GE} + +`EXPECT_GE(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_GE(`*`val1`*`,`*`val2`*`)` + +Verifies that *`val1`*`>=`*`val2`*. + +## String Comparison {#c-strings} + +The following assertions compare two **C strings**. To compare two `string` +objects, use [`EXPECT_EQ`](#EXPECT_EQ) or [`EXPECT_NE`](#EXPECT_NE) instead. + +These assertions also accept wide C strings (`wchar_t*`). If a comparison of two +wide strings fails, their values will be printed as UTF-8 narrow strings. + +To compare a C string with `NULL`, use `EXPECT_EQ(`*`c_string`*`, nullptr)` or +`EXPECT_NE(`*`c_string`*`, nullptr)`. + +### EXPECT_STREQ {#EXPECT_STREQ} + +`EXPECT_STREQ(`*`str1`*`,`*`str2`*`)` \ +`ASSERT_STREQ(`*`str1`*`,`*`str2`*`)` + +Verifies that the two C strings *`str1`* and *`str2`* have the same contents. + +### EXPECT_STRNE {#EXPECT_STRNE} + +`EXPECT_STRNE(`*`str1`*`,`*`str2`*`)` \ +`ASSERT_STRNE(`*`str1`*`,`*`str2`*`)` + +Verifies that the two C strings *`str1`* and *`str2`* have different contents. + +### EXPECT_STRCASEEQ {#EXPECT_STRCASEEQ} + +`EXPECT_STRCASEEQ(`*`str1`*`,`*`str2`*`)` \ +`ASSERT_STRCASEEQ(`*`str1`*`,`*`str2`*`)` + +Verifies that the two C strings *`str1`* and *`str2`* have the same contents, +ignoring case. + +### EXPECT_STRCASENE {#EXPECT_STRCASENE} + +`EXPECT_STRCASENE(`*`str1`*`,`*`str2`*`)` \ +`ASSERT_STRCASENE(`*`str1`*`,`*`str2`*`)` + +Verifies that the two C strings *`str1`* and *`str2`* have different contents, +ignoring case. + +## Floating-Point Comparison {#floating-point} + +The following assertions compare two floating-point values. + +Due to rounding errors, it is very unlikely that two floating-point values will +match exactly, so `EXPECT_EQ` is not suitable. In general, for floating-point +comparison to make sense, the user needs to carefully choose the error bound. + +GoogleTest also provides assertions that use a default error bound based on +Units in the Last Place (ULPs). To learn more about ULPs, see the article +[Comparing Floating Point Numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/). + +### EXPECT_FLOAT_EQ {#EXPECT_FLOAT_EQ} + +`EXPECT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)` + +Verifies that the two `float` values *`val1`* and *`val2`* are approximately +equal, to within 4 ULPs from each other. + +### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ} + +`EXPECT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)` \ +`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)` + +Verifies that the two `double` values *`val1`* and *`val2`* are approximately +equal, to within 4 ULPs from each other. + +### EXPECT_NEAR {#EXPECT_NEAR} + +`EXPECT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)` \ +`ASSERT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)` + +Verifies that the difference between *`val1`* and *`val2`* does not exceed the +absolute error bound *`abs_error`*. + +## Exception Assertions {#exceptions} + +The following assertions verify that a piece of code throws, or does not throw, +an exception. Usage requires exceptions to be enabled in the build environment. + +Note that the piece of code under test can be a compound statement, for example: + +```cpp +EXPECT_NO_THROW({ + int n = 5; + DoSomething(&n); +}); +``` + +### EXPECT_THROW {#EXPECT_THROW} + +`EXPECT_THROW(`*`statement`*`,`*`exception_type`*`)` \ +`ASSERT_THROW(`*`statement`*`,`*`exception_type`*`)` + +Verifies that *`statement`* throws an exception of type *`exception_type`*. + +### EXPECT_ANY_THROW {#EXPECT_ANY_THROW} + +`EXPECT_ANY_THROW(`*`statement`*`)` \ +`ASSERT_ANY_THROW(`*`statement`*`)` + +Verifies that *`statement`* throws an exception of any type. + +### EXPECT_NO_THROW {#EXPECT_NO_THROW} + +`EXPECT_NO_THROW(`*`statement`*`)` \ +`ASSERT_NO_THROW(`*`statement`*`)` + +Verifies that *`statement`* does not throw any exception. + +## Predicate Assertions {#predicates} + +The following assertions enable more complex predicates to be verified while +printing a more clear failure message than if `EXPECT_TRUE` were used alone. + +### EXPECT_PRED* {#EXPECT_PRED} + +`EXPECT_PRED1(`*`pred`*`,`*`val1`*`)` \ +`EXPECT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \ +`EXPECT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \ +`EXPECT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \ +`EXPECT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)` + +`ASSERT_PRED1(`*`pred`*`,`*`val1`*`)` \ +`ASSERT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \ +`ASSERT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \ +`ASSERT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \ +`ASSERT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)` + +Verifies that the predicate *`pred`* returns `true` when passed the given values +as arguments. + +The parameter *`pred`* is a function or functor that accepts as many arguments +as the corresponding macro accepts values. If *`pred`* returns `true` for the +given arguments, the assertion succeeds, otherwise the assertion fails. + +When the assertion fails, it prints the value of each argument. Arguments are +always evaluated exactly once. + +As an example, see the following code: + +```cpp +// Returns true if m and n have no common divisors except 1. +bool MutuallyPrime(int m, int n) { ... } +... +const int a = 3; +const int b = 4; +const int c = 10; +... +EXPECT_PRED2(MutuallyPrime, a, b); // Succeeds +EXPECT_PRED2(MutuallyPrime, b, c); // Fails +``` + +In the above example, the first assertion succeeds, and the second fails with +the following message: + +``` +MutuallyPrime(b, c) is false, where +b is 4 +c is 10 +``` + +Note that if the given predicate is an overloaded function or a function +template, the assertion macro might not be able to determine which version to +use, and it might be necessary to explicitly specify the type of the function. +For example, for a Boolean function `IsPositive()` overloaded to take either a +single `int` or `double` argument, it would be necessary to write one of the +following: + +```cpp +EXPECT_PRED1(static_cast(IsPositive), 5); +EXPECT_PRED1(static_cast(IsPositive), 3.14); +``` + +Writing simply `EXPECT_PRED1(IsPositive, 5);` would result in a compiler error. +Similarly, to use a template function, specify the template arguments: + +```cpp +template +bool IsNegative(T x) { + return x < 0; +} +... +EXPECT_PRED1(IsNegative, -5); // Must specify type for IsNegative +``` + +If a template has multiple parameters, wrap the predicate in parentheses so the +macro arguments are parsed correctly: + +```cpp +ASSERT_PRED2((MyPredicate), 5, 0); +``` + +### EXPECT_PRED_FORMAT* {#EXPECT_PRED_FORMAT} + +`EXPECT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \ +`EXPECT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \ +`EXPECT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \ +`EXPECT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` +\ +`EXPECT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)` + +`ASSERT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \ +`ASSERT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \ +`ASSERT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \ +`ASSERT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` +\ +`ASSERT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)` + +Verifies that the predicate *`pred_formatter`* succeeds when passed the given +values as arguments. + +The parameter *`pred_formatter`* is a *predicate-formatter*, which is a function +or functor with the signature: + +```cpp +testing::AssertionResult PredicateFormatter(const char* expr1, + const char* expr2, + ... + const char* exprn, + T1 val1, + T2 val2, + ... + Tn valn); +``` + +where *`val1`*, *`val2`*, ..., *`valn`* are the values of the predicate +arguments, and *`expr1`*, *`expr2`*, ..., *`exprn`* are the corresponding +expressions as they appear in the source code. The types `T1`, `T2`, ..., `Tn` +can be either value types or reference types; if an argument has type `T`, it +can be declared as either `T` or `const T&`, whichever is appropriate. For more +about the return type `testing::AssertionResult`, see +[Using a Function That Returns an AssertionResult](../advanced.md#using-a-function-that-returns-an-assertionresult). + +As an example, see the following code: + +```cpp +// Returns the smallest prime common divisor of m and n, +// or 1 when m and n are mutually prime. +int SmallestPrimeCommonDivisor(int m, int n) { ... } + +// Returns true if m and n have no common divisors except 1. +bool MutuallyPrime(int m, int n) { ... } + +// A predicate-formatter for asserting that two integers are mutually prime. +testing::AssertionResult AssertMutuallyPrime(const char* m_expr, + const char* n_expr, + int m, + int n) { + if (MutuallyPrime(m, n)) return testing::AssertionSuccess(); + + return testing::AssertionFailure() << m_expr << " and " << n_expr + << " (" << m << " and " << n << ") are not mutually prime, " + << "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n); +} + +... +const int a = 3; +const int b = 4; +const int c = 10; +... +EXPECT_PRED_FORMAT2(AssertMutuallyPrime, a, b); // Succeeds +EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c); // Fails +``` + +In the above example, the final assertion fails and the predicate-formatter +produces the following failure message: + +``` +b and c (4 and 10) are not mutually prime, as they have a common divisor 2 +``` + +## Windows HRESULT Assertions {#HRESULT} + +The following assertions test for `HRESULT` success or failure. For example: + +```cpp +CComPtr shell; +ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application")); +CComVariant empty; +ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty)); +``` + +The generated output contains the human-readable error message associated with +the returned `HRESULT` code. + +### EXPECT_HRESULT_SUCCEEDED {#EXPECT_HRESULT_SUCCEEDED} + +`EXPECT_HRESULT_SUCCEEDED(`*`expression`*`)` \ +`ASSERT_HRESULT_SUCCEEDED(`*`expression`*`)` + +Verifies that *`expression`* is a success `HRESULT`. + +### EXPECT_HRESULT_FAILED {#EXPECT_HRESULT_FAILED} + +`EXPECT_HRESULT_FAILED(`*`expression`*`)` \ +`ASSERT_HRESULT_FAILED(`*`expression`*`)` + +Verifies that *`expression`* is a failure `HRESULT`. + +## Death Assertions {#death} + +The following assertions verify that a piece of code causes the process to +terminate. For context, see [Death Tests](../advanced.md#death-tests). + +These assertions spawn a new process and execute the code under test in that +process. How that happens depends on the platform and the variable +`::testing::GTEST_FLAG(death_test_style)`, which is initialized from the +command-line flag `--gtest_death_test_style`. + +* On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the + child, after which: + * If the variable's value is `"fast"`, the death test statement is + immediately executed. + * If the variable's value is `"threadsafe"`, the child process re-executes + the unit test binary just as it was originally invoked, but with some + extra flags to cause just the single death test under consideration to + be run. +* On Windows, the child is spawned using the `CreateProcess()` API, and + re-executes the binary to cause just the single death test under + consideration to be run - much like the `"threadsafe"` mode on POSIX. + +Other values for the variable are illegal and will cause the death test to fail. +Currently, the flag's default value is +**`"fast"`**. + +If the death test statement runs to completion without dying, the child process +will nonetheless terminate, and the assertion fails. + +Note that the piece of code under test can be a compound statement, for example: + +```cpp +EXPECT_DEATH({ + int n = 5; + DoSomething(&n); +}, "Error on line .* of DoSomething()"); +``` + +### EXPECT_DEATH {#EXPECT_DEATH} + +`EXPECT_DEATH(`*`statement`*`,`*`matcher`*`)` \ +`ASSERT_DEATH(`*`statement`*`,`*`matcher`*`)` + +Verifies that *`statement`* causes the process to terminate with a nonzero exit +status and produces `stderr` output that matches *`matcher`*. + +The parameter *`matcher`* is either a [matcher](matchers.md) for a `const +std::string&`, or a regular expression (see +[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare +string *`s`* (with no matcher) is treated as +[`ContainsRegex(s)`](matchers.md#string-matchers), **not** +[`Eq(s)`](matchers.md#generic-comparison). + +For example, the following code verifies that calling `DoSomething(42)` causes +the process to die with an error message that contains the text `My error`: + +```cpp +EXPECT_DEATH(DoSomething(42), "My error"); +``` + +### EXPECT_DEATH_IF_SUPPORTED {#EXPECT_DEATH_IF_SUPPORTED} + +`EXPECT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)` \ +`ASSERT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)` + +If death tests are supported, behaves the same as +[`EXPECT_DEATH`](#EXPECT_DEATH). Otherwise, verifies nothing. + +### EXPECT_DEBUG_DEATH {#EXPECT_DEBUG_DEATH} + +`EXPECT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)` \ +`ASSERT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)` + +In debug mode, behaves the same as [`EXPECT_DEATH`](#EXPECT_DEATH). When not in +debug mode (i.e. `NDEBUG` is defined), just executes *`statement`*. + +### EXPECT_EXIT {#EXPECT_EXIT} + +`EXPECT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)` \ +`ASSERT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)` + +Verifies that *`statement`* causes the process to terminate with an exit status +that satisfies *`predicate`*, and produces `stderr` output that matches +*`matcher`*. + +The parameter *`predicate`* is a function or functor that accepts an `int` exit +status and returns a `bool`. GoogleTest provides two predicates to handle common +cases: + +```cpp +// Returns true if the program exited normally with the given exit status code. +::testing::ExitedWithCode(exit_code); + +// Returns true if the program was killed by the given signal. +// Not available on Windows. +::testing::KilledBySignal(signal_number); +``` + +The parameter *`matcher`* is either a [matcher](matchers.md) for a `const +std::string&`, or a regular expression (see +[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare +string *`s`* (with no matcher) is treated as +[`ContainsRegex(s)`](matchers.md#string-matchers), **not** +[`Eq(s)`](matchers.md#generic-comparison). + +For example, the following code verifies that calling `NormalExit()` causes the +process to print a message containing the text `Success` to `stderr` and exit +with exit status code 0: + +```cpp +EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success"); +``` diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/reference/matchers.md b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/matchers.md new file mode 100644 index 00000000..243e3f95 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/matchers.md @@ -0,0 +1,302 @@ +# Matchers Reference + +A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or +`EXPECT_CALL()`, or use it to validate a value directly using two macros: + +| Macro | Description | +| :----------------------------------- | :------------------------------------ | +| `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. | +| `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. | + +{: .callout .warning} +**WARNING:** Equality matching via `EXPECT_THAT(actual_value, expected_value)` +is supported, however note that implicit conversions can cause surprising +results. For example, `EXPECT_THAT(some_bool, "some string")` will compile and +may pass unintentionally. + +**BEST PRACTICE:** Prefer to make the comparison explicit via +`EXPECT_THAT(actual_value, Eq(expected_value))` or `EXPECT_EQ(actual_value, +expected_value)`. + +Built-in matchers (where `argument` is the function argument, e.g. +`actual_value` in the example above, or when used in the context of +`EXPECT_CALL(mock_object, method(matchers))`, the arguments of `method`) are +divided into several categories. All matchers are defined in the `::testing` +namespace unless otherwise noted. + +## Wildcard + +Matcher | Description +:-------------------------- | :----------------------------------------------- +`_` | `argument` can be any value of the correct type. +`A()` or `An()` | `argument` can be any value of type `type`. + +## Generic Comparison + +| Matcher | Description | +| :--------------------- | :-------------------------------------------------- | +| `Eq(value)` or `value` | `argument == value` | +| `Ge(value)` | `argument >= value` | +| `Gt(value)` | `argument > value` | +| `Le(value)` | `argument <= value` | +| `Lt(value)` | `argument < value` | +| `Ne(value)` | `argument != value` | +| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. | +| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. | +| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). | +| `NotNull()` | `argument` is a non-null pointer (raw or smart). | +| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)| +| `VariantWith(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. | +| `Ref(variable)` | `argument` is a reference to `variable`. | +| `TypedEq(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. | + +Except `Ref()`, these matchers make a *copy* of `value` in case it's modified or +destructed later. If the compiler complains that `value` doesn't have a public +copy constructor, try wrap it in `std::ref()`, e.g. +`Eq(std::ref(non_copyable_value))`. If you do that, make sure +`non_copyable_value` is not changed afterwards, or the meaning of your matcher +will be changed. + +`IsTrue` and `IsFalse` are useful when you need to use a matcher, or for types +that can be explicitly converted to Boolean, but are not implicitly converted to +Boolean. In other cases, you can use the basic +[`EXPECT_TRUE` and `EXPECT_FALSE`](assertions.md#boolean) assertions. + +## Floating-Point Matchers {#FpMatchers} + +| Matcher | Description | +| :------------------------------- | :--------------------------------- | +| `DoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal. | +| `FloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. | +| `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. | +| `NanSensitiveFloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. | +| `IsNan()` | `argument` is any floating-point type with a NaN value. | + +The above matchers use ULP-based comparison (the same as used in googletest). +They automatically pick a reasonable error bound based on the absolute value of +the expected value. `DoubleEq()` and `FloatEq()` conform to the IEEE standard, +which requires comparing two NaNs for equality to return false. The +`NanSensitive*` version instead treats two NaNs as equal, which is often what a +user wants. + +| Matcher | Description | +| :------------------------------------------------ | :----------------------- | +| `DoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal. | +| `FloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. | +| `NanSensitiveDoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. | +| `NanSensitiveFloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. | + +## String Matchers + +The `argument` can be either a C string or a C++ string object: + +| Matcher | Description | +| :---------------------- | :------------------------------------------------- | +| `ContainsRegex(string)` | `argument` matches the given regular expression. | +| `EndsWith(suffix)` | `argument` ends with string `suffix`. | +| `HasSubstr(string)` | `argument` contains `string` as a sub-string. | +| `IsEmpty()` | `argument` is an empty string. | +| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. | +| `StartsWith(prefix)` | `argument` starts with string `prefix`. | +| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. | +| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. | +| `StrEq(string)` | `argument` is equal to `string`. | +| `StrNe(string)` | `argument` is not equal to `string`. | +| `WhenBase64Unescaped(m)` | `argument` is a base-64 escaped string whose unescaped string matches `m`. The web-safe format from [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648#section-5) is supported. | + +`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They +use the regular expression syntax defined +[here](../advanced.md#regular-expression-syntax). All of these matchers, except +`ContainsRegex()` and `MatchesRegex()` work for wide strings as well. + +## Container Matchers + +Most STL-style containers support `==`, so you can use `Eq(expected_container)` +or simply `expected_container` to match a container exactly. If you want to +write the elements in-line, match them more flexibly, or get more informative +messages, you can use: + +| Matcher | Description | +| :---------------------------------------- | :------------------------------- | +| `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. | +| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. | +| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. | +| `Contains(e).Times(n)` | `argument` contains elements that match `e`, which can be either a value or a matcher, and the number of matches is `n`, which can be either a value or a matcher. Unlike the plain `Contains` and `Each` this allows to check for arbitrary occurrences including testing for absence with `Contains(e).Times(0)`. | +| `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. | +| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. | +| `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `IsEmpty()` | `argument` is an empty container (`container.empty()`). | +| `IsSubsetOf({e0, e1, ..., en})`, `IsSubsetOf(a_container)`, `IsSubsetOf(begin, end)`, `IsSubsetOf(array)`, or `IsSubsetOf(array, count)` | `argument` matches `UnorderedElementsAre(x0, x1, ..., xk)` for some subset `{x0, x1, ..., xk}` of the expected matchers. | +| `IsSupersetOf({e0, e1, ..., en})`, `IsSupersetOf(a_container)`, `IsSupersetOf(begin, end)`, `IsSupersetOf(array)`, or `IsSupersetOf(array, count)` | Some subset of `argument` matches `UnorderedElementsAre(`expected matchers`)`. | +| `Pointwise(m, container)`, `Pointwise(m, {e0, e1, ..., en})` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. | +| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. | +| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under *some* permutation of the elements, each element matches an `ei` (for a different `i`), which can be a value or a matcher. | +| `UnorderedElementsAreArray({e0, e1, ..., en})`, `UnorderedElementsAreArray(a_container)`, `UnorderedElementsAreArray(begin, end)`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `UnorderedPointwise(m, container)`, `UnorderedPointwise(m, {e0, e1, ..., en})` | Like `Pointwise(m, container)`, but ignores the order of elements. | +| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements 1, 2, and 3, ignoring order. | +| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. | + +**Notes:** + +* These matchers can also match: + 1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), + and + 2. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, + int len)` -- see [Multi-argument Matchers](#MultiArgMatchers)). +* The array being matched may be multi-dimensional (i.e. its elements can be + arrays). +* `m` in `Pointwise(m, ...)` and `UnorderedPointwise(m, ...)` should be a + matcher for `::std::tuple` where `T` and `U` are the element type of + the actual container and the expected container, respectively. For example, + to compare two `Foo` containers where `Foo` doesn't support `operator==`, + one might write: + + ```cpp + MATCHER(FooEq, "") { + return std::get<0>(arg).Equals(std::get<1>(arg)); + } + ... + EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos)); + ``` + +## Member Matchers + +| Matcher | Description | +| :------------------------------ | :----------------------------------------- | +| `Field(&class::field, m)` | `argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. | +| `Field(field_name, &class::field, m)` | The same as the two-parameter version, but provides a better error message. | +| `Key(e)` | `argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`. | +| `Pair(m1, m2)` | `argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. | +| `FieldsAre(m...)` | `argument` is a compatible object where each field matches piecewise with the matchers `m...`. A compatible object is any that supports the `std::tuple_size`+`get(obj)` protocol. In C++17 and up this also supports types compatible with structured bindings, like aggregates. | +| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. | +| `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message. + +**Notes:** + +* You can use `FieldsAre()` to match any type that supports structured + bindings, such as `std::tuple`, `std::pair`, `std::array`, and aggregate + types. For example: + + ```cpp + std::tuple my_tuple{7, "hello world"}; + EXPECT_THAT(my_tuple, FieldsAre(Ge(0), HasSubstr("hello"))); + + struct MyStruct { + int value = 42; + std::string greeting = "aloha"; + }; + MyStruct s; + EXPECT_THAT(s, FieldsAre(42, "aloha")); + ``` + +* Don't use `Property()` against member functions that you do not own, because + taking addresses of functions is fragile and generally not part of the + contract of the function. + +## Matching the Result of a Function, Functor, or Callback + +| Matcher | Description | +| :--------------- | :------------------------------------------------ | +| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. | +| `ResultOf(result_description, f, m)` | The same as the two-parameter version, but provides a better error message. + +## Pointer Matchers + +| Matcher | Description | +| :------------------------ | :---------------------------------------------- | +| `Address(m)` | the result of `std::addressof(argument)` matches `m`. | +| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. | +| `Pointer(m)` | `argument` (either a smart pointer or a raw pointer) contains a pointer that matches `m`. `m` will match against the raw pointer regardless of the type of `argument`. | +| `WhenDynamicCastTo(m)` | when `argument` is passed through `dynamic_cast()`, it matches matcher `m`. | + +## Multi-argument Matchers {#MultiArgMatchers} + +Technically, all matchers match a *single* value. A "multi-argument" matcher is +just one that matches a *tuple*. The following matchers can be used to match a +tuple `(x, y)`: + +Matcher | Description +:------ | :---------- +`Eq()` | `x == y` +`Ge()` | `x >= y` +`Gt()` | `x > y` +`Le()` | `x <= y` +`Lt()` | `x < y` +`Ne()` | `x != y` + +You can use the following selectors to pick a subset of the arguments (or +reorder them) to participate in the matching: + +| Matcher | Description | +| :------------------------- | :---------------------------------------------- | +| `AllArgs(m)` | Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`. | +| `Args(m)` | The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`. | + +## Composite Matchers + +You can make a matcher from one or more other matchers: + +| Matcher | Description | +| :------------------------------- | :-------------------------------------- | +| `AllOf(m1, m2, ..., mn)` | `argument` matches all of the matchers `m1` to `mn`. | +| `AllOfArray({m0, m1, ..., mn})`, `AllOfArray(a_container)`, `AllOfArray(begin, end)`, `AllOfArray(array)`, or `AllOfArray(array, count)` | The same as `AllOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. | +| `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `Not(m)` | `argument` doesn't match matcher `m`. | +| `Conditional(cond, m1, m2)` | Matches matcher `m1` if `cond` evaluates to true, else matches `m2`.| + +## Adapters for Matchers + +| Matcher | Description | +| :---------------------- | :------------------------------------ | +| `MatcherCast(m)` | casts matcher `m` to type `Matcher`. | +| `SafeMatcherCast(m)` | [safely casts](../gmock_cook_book.md#SafeMatcherCast) matcher `m` to type `Matcher`. | +| `Truly(predicate)` | `predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor. | + +`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`, +which must be a permanent callback. + +## Using Matchers as Predicates {#MatchersAsPredicatesCheat} + +| Matcher | Description | +| :---------------------------- | :------------------------------------------ | +| `Matches(m)(value)` | evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor. | +| `ExplainMatchResult(m, value, result_listener)` | evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. | +| `Value(value, m)` | evaluates to `true` if `value` matches `m`. | + +## Defining Matchers + +| Macro | Description | +| :----------------------------------- | :------------------------------------ | +| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. | +| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a matcher `IsDivisibleBy(n)` to match a number divisible by `n`. | +| `MATCHER_P2(IsBetween, a, b, absl::StrCat(negation ? "isn't" : "is", " between ", PrintToString(a), " and ", PrintToString(b))) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. | + +**Notes:** + +1. The `MATCHER*` macros cannot be used inside a function or class. +2. The matcher body must be *purely functional* (i.e. it cannot have any side + effect, and the result must not depend on anything other than the value + being matched and the matcher parameters). +3. You can use `PrintToString(x)` to convert a value `x` of any type to a + string. +4. You can use `ExplainMatchResult()` in a custom matcher to wrap another + matcher, for example: + + ```cpp + MATCHER_P(NestedPropertyMatches, matcher, "") { + return ExplainMatchResult(matcher, arg.nested().property(), result_listener); + } + ``` + +5. You can use `DescribeMatcher<>` to describe another matcher. For example: + + ```cpp + MATCHER_P(XAndYThat, matcher, + "X that " + DescribeMatcher(matcher, negation) + + (negation ? " or" : " and") + " Y that " + + DescribeMatcher(matcher, negation)) { + return ExplainMatchResult(matcher, arg.x(), result_listener) && + ExplainMatchResult(matcher, arg.y(), result_listener); + } + ``` diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/reference/mocking.md b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/mocking.md new file mode 100644 index 00000000..ab37ebf3 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/mocking.md @@ -0,0 +1,588 @@ +# Mocking Reference + +This page lists the facilities provided by GoogleTest for creating and working +with mock objects. To use them, add `#include `. + +## Macros {#macros} + +GoogleTest defines the following macros for working with mocks. + +### MOCK_METHOD {#MOCK_METHOD} + +`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`));` \ +`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`), +(`*`specs...`*`));` + +Defines a mock method *`method_name`* with arguments `(`*`args...`*`)` and +return type *`return_type`* within a mock class. + +The parameters of `MOCK_METHOD` mirror the method declaration. The optional +fourth parameter *`specs...`* is a comma-separated list of qualifiers. The +following qualifiers are accepted: + +| Qualifier | Meaning | +| -------------------------- | -------------------------------------------- | +| `const` | Makes the mocked method a `const` method. Required if overriding a `const` method. | +| `override` | Marks the method with `override`. Recommended if overriding a `virtual` method. | +| `noexcept` | Marks the method with `noexcept`. Required if overriding a `noexcept` method. | +| `Calltype(`*`calltype`*`)` | Sets the call type for the method, for example `Calltype(STDMETHODCALLTYPE)`. Useful on Windows. | +| `ref(`*`qualifier`*`)` | Marks the method with the given reference qualifier, for example `ref(&)` or `ref(&&)`. Required if overriding a method that has a reference qualifier. | + +Note that commas in arguments prevent `MOCK_METHOD` from parsing the arguments +correctly if they are not appropriately surrounded by parentheses. See the +following example: + +```cpp +class MyMock { + public: + // The following 2 lines will not compile due to commas in the arguments: + MOCK_METHOD(std::pair, GetPair, ()); // Error! + MOCK_METHOD(bool, CheckMap, (std::map, bool)); // Error! + + // One solution - wrap arguments that contain commas in parentheses: + MOCK_METHOD((std::pair), GetPair, ()); + MOCK_METHOD(bool, CheckMap, ((std::map), bool)); + + // Another solution - use type aliases: + using BoolAndInt = std::pair; + MOCK_METHOD(BoolAndInt, GetPair, ()); + using MapIntDouble = std::map; + MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool)); +}; +``` + +`MOCK_METHOD` must be used in the `public:` section of a mock class definition, +regardless of whether the method being mocked is `public`, `protected`, or +`private` in the base class. + +### EXPECT_CALL {#EXPECT_CALL} + +`EXPECT_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))` + +Creates an [expectation](../gmock_for_dummies.md#setting-expectations) that the +method *`method_name`* of the object *`mock_object`* is called with arguments +that match the given matchers *`matchers...`*. `EXPECT_CALL` must precede any +code that exercises the mock object. + +The parameter *`matchers...`* is a comma-separated list of +[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that +correspond to each argument of the method *`method_name`*. The expectation will +apply only to calls of *`method_name`* whose arguments match all of the +matchers. If `(`*`matchers...`*`)` is omitted, the expectation behaves as if +each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard). +See the [Matchers Reference](matchers.md) for a list of all built-in matchers. + +The following chainable clauses can be used to modify the expectation, and they +must be used in the following order: + +```cpp +EXPECT_CALL(mock_object, method_name(matchers...)) + .With(multi_argument_matcher) // Can be used at most once + .Times(cardinality) // Can be used at most once + .InSequence(sequences...) // Can be used any number of times + .After(expectations...) // Can be used any number of times + .WillOnce(action) // Can be used any number of times + .WillRepeatedly(action) // Can be used at most once + .RetiresOnSaturation(); // Can be used at most once +``` + +See details for each modifier clause below. + +#### With {#EXPECT_CALL.With} + +`.With(`*`multi_argument_matcher`*`)` + +Restricts the expectation to apply only to mock function calls whose arguments +as a whole match the multi-argument matcher *`multi_argument_matcher`*. + +GoogleTest passes all of the arguments as one tuple into the matcher. The +parameter *`multi_argument_matcher`* must thus be a matcher of type +`Matcher>`, where `A1, ..., An` are the types of the +function arguments. + +For example, the following code sets the expectation that +`my_mock.SetPosition()` is called with any two arguments, the first argument +being less than the second: + +```cpp +using ::testing::_; +using ::testing::Lt; +... +EXPECT_CALL(my_mock, SetPosition(_, _)) + .With(Lt()); +``` + +GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()` +matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers). + +The `With` clause can be used at most once on an expectation and must be the +first clause. + +#### Times {#EXPECT_CALL.Times} + +`.Times(`*`cardinality`*`)` + +Specifies how many times the mock function call is expected. + +The parameter *`cardinality`* represents the number of expected calls and can be +one of the following, all defined in the `::testing` namespace: + +| Cardinality | Meaning | +| ------------------- | --------------------------------------------------- | +| `AnyNumber()` | The function can be called any number of times. | +| `AtLeast(n)` | The function call is expected at least *n* times. | +| `AtMost(n)` | The function call is expected at most *n* times. | +| `Between(m, n)` | The function call is expected between *m* and *n* times, inclusive. | +| `Exactly(n)` or `n` | The function call is expected exactly *n* times. If *n* is 0, the call should never happen. | + +If the `Times` clause is omitted, GoogleTest infers the cardinality as follows: + +* If neither [`WillOnce`](#EXPECT_CALL.WillOnce) nor + [`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) are specified, the inferred + cardinality is `Times(1)`. +* If there are *n* `WillOnce` clauses and no `WillRepeatedly` clause, where + *n* >= 1, the inferred cardinality is `Times(n)`. +* If there are *n* `WillOnce` clauses and one `WillRepeatedly` clause, where + *n* >= 0, the inferred cardinality is `Times(AtLeast(n))`. + +The `Times` clause can be used at most once on an expectation. + +#### InSequence {#EXPECT_CALL.InSequence} + +`.InSequence(`*`sequences...`*`)` + +Specifies that the mock function call is expected in a certain sequence. + +The parameter *`sequences...`* is any number of [`Sequence`](#Sequence) objects. +Expected calls assigned to the same sequence are expected to occur in the order +the expectations are declared. + +For example, the following code sets the expectation that the `Reset()` method +of `my_mock` is called before both `GetSize()` and `Describe()`, and `GetSize()` +and `Describe()` can occur in any order relative to each other: + +```cpp +using ::testing::Sequence; +Sequence s1, s2; +... +EXPECT_CALL(my_mock, Reset()) + .InSequence(s1, s2); +EXPECT_CALL(my_mock, GetSize()) + .InSequence(s1); +EXPECT_CALL(my_mock, Describe()) + .InSequence(s2); +``` + +The `InSequence` clause can be used any number of times on an expectation. + +See also the [`InSequence` class](#InSequence). + +#### After {#EXPECT_CALL.After} + +`.After(`*`expectations...`*`)` + +Specifies that the mock function call is expected to occur after one or more +other calls. + +The parameter *`expectations...`* can be up to five +[`Expectation`](#Expectation) or [`ExpectationSet`](#ExpectationSet) objects. +The mock function call is expected to occur after all of the given expectations. + +For example, the following code sets the expectation that the `Describe()` +method of `my_mock` is called only after both `InitX()` and `InitY()` have been +called. + +```cpp +using ::testing::Expectation; +... +Expectation init_x = EXPECT_CALL(my_mock, InitX()); +Expectation init_y = EXPECT_CALL(my_mock, InitY()); +EXPECT_CALL(my_mock, Describe()) + .After(init_x, init_y); +``` + +The `ExpectationSet` object is helpful when the number of prerequisites for an +expectation is large or variable, for example: + +```cpp +using ::testing::ExpectationSet; +... +ExpectationSet all_inits; +// Collect all expectations of InitElement() calls +for (int i = 0; i < element_count; i++) { + all_inits += EXPECT_CALL(my_mock, InitElement(i)); +} +EXPECT_CALL(my_mock, Describe()) + .After(all_inits); // Expect Describe() call after all InitElement() calls +``` + +The `After` clause can be used any number of times on an expectation. + +#### WillOnce {#EXPECT_CALL.WillOnce} + +`.WillOnce(`*`action`*`)` + +Specifies the mock function's actual behavior when invoked, for a single +matching function call. + +The parameter *`action`* represents the +[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function +call will perform. See the [Actions Reference](actions.md) for a list of +built-in actions. + +The use of `WillOnce` implicitly sets a cardinality on the expectation when +`Times` is not specified. See [`Times`](#EXPECT_CALL.Times). + +Each matching function call will perform the next action in the order declared. +For example, the following code specifies that `my_mock.GetNumber()` is expected +to be called exactly 3 times and will return `1`, `2`, and `3` respectively on +the first, second, and third calls: + +```cpp +using ::testing::Return; +... +EXPECT_CALL(my_mock, GetNumber()) + .WillOnce(Return(1)) + .WillOnce(Return(2)) + .WillOnce(Return(3)); +``` + +The `WillOnce` clause can be used any number of times on an expectation. Unlike +`WillRepeatedly`, the action fed to each `WillOnce` call will be called at most +once, so may be a move-only type and/or have an `&&`-qualified call operator. + +#### WillRepeatedly {#EXPECT_CALL.WillRepeatedly} + +`.WillRepeatedly(`*`action`*`)` + +Specifies the mock function's actual behavior when invoked, for all subsequent +matching function calls. Takes effect after the actions specified in the +[`WillOnce`](#EXPECT_CALL.WillOnce) clauses, if any, have been performed. + +The parameter *`action`* represents the +[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function +call will perform. See the [Actions Reference](actions.md) for a list of +built-in actions. + +The use of `WillRepeatedly` implicitly sets a cardinality on the expectation +when `Times` is not specified. See [`Times`](#EXPECT_CALL.Times). + +If any `WillOnce` clauses have been specified, matching function calls will +perform those actions before the action specified by `WillRepeatedly`. See the +following example: + +```cpp +using ::testing::Return; +... +EXPECT_CALL(my_mock, GetName()) + .WillRepeatedly(Return("John Doe")); // Return "John Doe" on all calls + +EXPECT_CALL(my_mock, GetNumber()) + .WillOnce(Return(42)) // Return 42 on the first call + .WillRepeatedly(Return(7)); // Return 7 on all subsequent calls +``` + +The `WillRepeatedly` clause can be used at most once on an expectation. + +#### RetiresOnSaturation {#EXPECT_CALL.RetiresOnSaturation} + +`.RetiresOnSaturation()` + +Indicates that the expectation will no longer be active after the expected +number of matching function calls has been reached. + +The `RetiresOnSaturation` clause is only meaningful for expectations with an +upper-bounded cardinality. The expectation will *retire* (no longer match any +function calls) after it has been *saturated* (the upper bound has been +reached). See the following example: + +```cpp +using ::testing::_; +using ::testing::AnyNumber; +... +EXPECT_CALL(my_mock, SetNumber(_)) // Expectation 1 + .Times(AnyNumber()); +EXPECT_CALL(my_mock, SetNumber(7)) // Expectation 2 + .Times(2) + .RetiresOnSaturation(); +``` + +In the above example, the first two calls to `my_mock.SetNumber(7)` match +expectation 2, which then becomes inactive and no longer matches any calls. A +third call to `my_mock.SetNumber(7)` would then match expectation 1. Without +`RetiresOnSaturation()` on expectation 2, a third call to `my_mock.SetNumber(7)` +would match expectation 2 again, producing a failure since the limit of 2 calls +was exceeded. + +The `RetiresOnSaturation` clause can be used at most once on an expectation and +must be the last clause. + +### ON_CALL {#ON_CALL} + +`ON_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))` + +Defines what happens when the method *`method_name`* of the object +*`mock_object`* is called with arguments that match the given matchers +*`matchers...`*. Requires a modifier clause to specify the method's behavior. +*Does not* set any expectations that the method will be called. + +The parameter *`matchers...`* is a comma-separated list of +[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that +correspond to each argument of the method *`method_name`*. The `ON_CALL` +specification will apply only to calls of *`method_name`* whose arguments match +all of the matchers. If `(`*`matchers...`*`)` is omitted, the behavior is as if +each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard). +See the [Matchers Reference](matchers.md) for a list of all built-in matchers. + +The following chainable clauses can be used to set the method's behavior, and +they must be used in the following order: + +```cpp +ON_CALL(mock_object, method_name(matchers...)) + .With(multi_argument_matcher) // Can be used at most once + .WillByDefault(action); // Required +``` + +See details for each modifier clause below. + +#### With {#ON_CALL.With} + +`.With(`*`multi_argument_matcher`*`)` + +Restricts the specification to only mock function calls whose arguments as a +whole match the multi-argument matcher *`multi_argument_matcher`*. + +GoogleTest passes all of the arguments as one tuple into the matcher. The +parameter *`multi_argument_matcher`* must thus be a matcher of type +`Matcher>`, where `A1, ..., An` are the types of the +function arguments. + +For example, the following code sets the default behavior when +`my_mock.SetPosition()` is called with any two arguments, the first argument +being less than the second: + +```cpp +using ::testing::_; +using ::testing::Lt; +using ::testing::Return; +... +ON_CALL(my_mock, SetPosition(_, _)) + .With(Lt()) + .WillByDefault(Return(true)); +``` + +GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()` +matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers). + +The `With` clause can be used at most once with each `ON_CALL` statement. + +#### WillByDefault {#ON_CALL.WillByDefault} + +`.WillByDefault(`*`action`*`)` + +Specifies the default behavior of a matching mock function call. + +The parameter *`action`* represents the +[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function +call will perform. See the [Actions Reference](actions.md) for a list of +built-in actions. + +For example, the following code specifies that by default, a call to +`my_mock.Greet()` will return `"hello"`: + +```cpp +using ::testing::Return; +... +ON_CALL(my_mock, Greet()) + .WillByDefault(Return("hello")); +``` + +The action specified by `WillByDefault` is superseded by the actions specified +on a matching `EXPECT_CALL` statement, if any. See the +[`WillOnce`](#EXPECT_CALL.WillOnce) and +[`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) clauses of `EXPECT_CALL`. + +The `WillByDefault` clause must be used exactly once with each `ON_CALL` +statement. + +## Classes {#classes} + +GoogleTest defines the following classes for working with mocks. + +### DefaultValue {#DefaultValue} + +`::testing::DefaultValue` + +Allows a user to specify the default value for a type `T` that is both copyable +and publicly destructible (i.e. anything that can be used as a function return +type). For mock functions with a return type of `T`, this default value is +returned from function calls that do not specify an action. + +Provides the static methods `Set()`, `SetFactory()`, and `Clear()` to manage the +default value: + +```cpp +// Sets the default value to be returned. T must be copy constructible. +DefaultValue::Set(value); + +// Sets a factory. Will be invoked on demand. T must be move constructible. +T MakeT(); +DefaultValue::SetFactory(&MakeT); + +// Unsets the default value. +DefaultValue::Clear(); +``` + +### NiceMock {#NiceMock} + +`::testing::NiceMock` + +Represents a mock object that suppresses warnings on +[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The +template parameter `T` is any mock class, except for another `NiceMock`, +`NaggyMock`, or `StrictMock`. + +Usage of `NiceMock` is analogous to usage of `T`. `NiceMock` is a subclass +of `T`, so it can be used wherever an object of type `T` is accepted. In +addition, `NiceMock` can be constructed with any arguments that a constructor +of `T` accepts. + +For example, the following code suppresses warnings on the mock `my_mock` of +type `MockClass` if a method other than `DoSomething()` is called: + +```cpp +using ::testing::NiceMock; +... +NiceMock my_mock("some", "args"); +EXPECT_CALL(my_mock, DoSomething()); +... code that uses my_mock ... +``` + +`NiceMock` only works for mock methods defined using the `MOCK_METHOD` macro +directly in the definition of class `T`. If a mock method is defined in a base +class of `T`, a warning might still be generated. + +`NiceMock` might not work correctly if the destructor of `T` is not virtual. + +### NaggyMock {#NaggyMock} + +`::testing::NaggyMock` + +Represents a mock object that generates warnings on +[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The +template parameter `T` is any mock class, except for another `NiceMock`, +`NaggyMock`, or `StrictMock`. + +Usage of `NaggyMock` is analogous to usage of `T`. `NaggyMock` is a +subclass of `T`, so it can be used wherever an object of type `T` is accepted. +In addition, `NaggyMock` can be constructed with any arguments that a +constructor of `T` accepts. + +For example, the following code generates warnings on the mock `my_mock` of type +`MockClass` if a method other than `DoSomething()` is called: + +```cpp +using ::testing::NaggyMock; +... +NaggyMock my_mock("some", "args"); +EXPECT_CALL(my_mock, DoSomething()); +... code that uses my_mock ... +``` + +Mock objects of type `T` by default behave the same way as `NaggyMock`. + +### StrictMock {#StrictMock} + +`::testing::StrictMock` + +Represents a mock object that generates test failures on +[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The +template parameter `T` is any mock class, except for another `NiceMock`, +`NaggyMock`, or `StrictMock`. + +Usage of `StrictMock` is analogous to usage of `T`. `StrictMock` is a +subclass of `T`, so it can be used wherever an object of type `T` is accepted. +In addition, `StrictMock` can be constructed with any arguments that a +constructor of `T` accepts. + +For example, the following code generates a test failure on the mock `my_mock` +of type `MockClass` if a method other than `DoSomething()` is called: + +```cpp +using ::testing::StrictMock; +... +StrictMock my_mock("some", "args"); +EXPECT_CALL(my_mock, DoSomething()); +... code that uses my_mock ... +``` + +`StrictMock` only works for mock methods defined using the `MOCK_METHOD` +macro directly in the definition of class `T`. If a mock method is defined in a +base class of `T`, a failure might not be generated. + +`StrictMock` might not work correctly if the destructor of `T` is not +virtual. + +### Sequence {#Sequence} + +`::testing::Sequence` + +Represents a chronological sequence of expectations. See the +[`InSequence`](#EXPECT_CALL.InSequence) clause of `EXPECT_CALL` for usage. + +### InSequence {#InSequence} + +`::testing::InSequence` + +An object of this type causes all expectations encountered in its scope to be +put in an anonymous sequence. + +This allows more convenient expression of multiple expectations in a single +sequence: + +```cpp +using ::testing::InSequence; +{ + InSequence seq; + + // The following are expected to occur in the order declared. + EXPECT_CALL(...); + EXPECT_CALL(...); + ... + EXPECT_CALL(...); +} +``` + +The name of the `InSequence` object does not matter. + +### Expectation {#Expectation} + +`::testing::Expectation` + +Represents a mock function call expectation as created by +[`EXPECT_CALL`](#EXPECT_CALL): + +```cpp +using ::testing::Expectation; +Expectation my_expectation = EXPECT_CALL(...); +``` + +Useful for specifying sequences of expectations; see the +[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`. + +### ExpectationSet {#ExpectationSet} + +`::testing::ExpectationSet` + +Represents a set of mock function call expectations. + +Use the `+=` operator to add [`Expectation`](#Expectation) objects to the set: + +```cpp +using ::testing::ExpectationSet; +ExpectationSet my_expectations; +my_expectations += EXPECT_CALL(...); +``` + +Useful for specifying sequences of expectations; see the +[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`. diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/reference/testing.md b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/testing.md new file mode 100644 index 00000000..3ed52111 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/reference/testing.md @@ -0,0 +1,1453 @@ +# Testing Reference + + + +This page lists the facilities provided by GoogleTest for writing test programs. +To use them, add `#include `. + +## Macros + +GoogleTest defines the following macros for writing tests. + +### TEST {#TEST} + +
+TEST(TestSuiteName, TestName) {
+  ... statements ...
+}
+
+ +Defines an individual test named *`TestName`* in the test suite +*`TestSuiteName`*, consisting of the given statements. + +Both arguments *`TestSuiteName`* and *`TestName`* must be valid C++ identifiers +and must not contain underscores (`_`). Tests in different test suites can have +the same individual name. + +The statements within the test body can be any code under test. +[Assertions](assertions.md) used within the test body determine the outcome of +the test. + +### TEST_F {#TEST_F} + +
+TEST_F(TestFixtureName, TestName) {
+  ... statements ...
+}
+
+ +Defines an individual test named *`TestName`* that uses the test fixture class +*`TestFixtureName`*. The test suite name is *`TestFixtureName`*. + +Both arguments *`TestFixtureName`* and *`TestName`* must be valid C++ +identifiers and must not contain underscores (`_`). *`TestFixtureName`* must be +the name of a test fixture class—see +[Test Fixtures](../primer.md#same-data-multiple-tests). + +The statements within the test body can be any code under test. +[Assertions](assertions.md) used within the test body determine the outcome of +the test. + +### TEST_P {#TEST_P} + +
+TEST_P(TestFixtureName, TestName) {
+  ... statements ...
+}
+
+ +Defines an individual value-parameterized test named *`TestName`* that uses the +test fixture class *`TestFixtureName`*. The test suite name is +*`TestFixtureName`*. + +Both arguments *`TestFixtureName`* and *`TestName`* must be valid C++ +identifiers and must not contain underscores (`_`). *`TestFixtureName`* must be +the name of a value-parameterized test fixture class—see +[Value-Parameterized Tests](../advanced.md#value-parameterized-tests). + +The statements within the test body can be any code under test. Within the test +body, the test parameter can be accessed with the `GetParam()` function (see +[`WithParamInterface`](#WithParamInterface)). For example: + +```cpp +TEST_P(MyTestSuite, DoesSomething) { + ... + EXPECT_TRUE(DoSomething(GetParam())); + ... +} +``` + +[Assertions](assertions.md) used within the test body determine the outcome of +the test. + +See also [`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P). + +### INSTANTIATE_TEST_SUITE_P {#INSTANTIATE_TEST_SUITE_P} + +`INSTANTIATE_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`param_generator`*`)` +\ +`INSTANTIATE_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`param_generator`*`,`*`name_generator`*`)` + +Instantiates the value-parameterized test suite *`TestSuiteName`* (defined with +[`TEST_P`](#TEST_P)). + +The argument *`InstantiationName`* is a unique name for the instantiation of the +test suite, to distinguish between multiple instantiations. In test output, the +instantiation name is added as a prefix to the test suite name +*`TestSuiteName`*. If *`InstantiationName`* is empty +(`INSTANTIATE_TEST_SUITE_P(, ...)`), no prefix is added. + +The argument *`param_generator`* is one of the following GoogleTest-provided +functions that generate the test parameters, all defined in the `::testing` +namespace: + + + +| Parameter Generator | Behavior | +| ------------------- | ---------------------------------------------------- | +| `Range(begin, end [, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. | +| `Values(v1, v2, ..., vN)` | Yields values `{v1, v2, ..., vN}`. | +| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. | +| `Bool()` | Yields sequence `{false, true}`. | +| `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. | +| `ConvertGenerator(g)` | Yields values generated by generator `g`, `static_cast` to `T`. | + +The optional last argument *`name_generator`* is a function or functor that +generates custom test name suffixes based on the test parameters. The function +must accept an argument of type +[`TestParamInfo`](#TestParamInfo) and return a `std::string`. +The test name suffix can only contain alphanumeric characters and underscores. +GoogleTest provides [`PrintToStringParamName`](#PrintToStringParamName), or a +custom function can be used for more control: + +```cpp +INSTANTIATE_TEST_SUITE_P( + MyInstantiation, MyTestSuite, + testing::Values(...), + [](const testing::TestParamInfo& info) { + // Can use info.param here to generate the test suffix + std::string name = ... + return name; + }); +``` + +For more information, see +[Value-Parameterized Tests](../advanced.md#value-parameterized-tests). + +See also +[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST). + +### TYPED_TEST_SUITE {#TYPED_TEST_SUITE} + +`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)` +`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`,`*`NameGenerator`*`)` + +Defines a typed test suite based on the test fixture *`TestFixtureName`*. The +test suite name is *`TestFixtureName`*. + +The argument *`TestFixtureName`* is a fixture class template, parameterized by a +type, for example: + +```cpp +template +class MyFixture : public testing::Test { + public: + ... + using List = std::list; + static T shared_; + T value_; +}; +``` + +The argument *`Types`* is a [`Types`](#Types) object representing the list of +types to run the tests on, for example: + +```cpp +using MyTypes = ::testing::Types; +TYPED_TEST_SUITE(MyFixture, MyTypes); +``` + +The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE` +macro to parse correctly. + +The optional third argument *`NameGenerator`* allows specifying a class that +exposes a templated static function `GetName(int)`. For example: + +```cpp +class NameGenerator { + public: + template + static std::string GetName(int) { + if constexpr (std::is_same_v) return "char"; + if constexpr (std::is_same_v) return "int"; + if constexpr (std::is_same_v) return "unsignedInt"; + } +}; +TYPED_TEST_SUITE(MyFixture, MyTypes, NameGenerator); +``` + +See also [`TYPED_TEST`](#TYPED_TEST) and +[Typed Tests](../advanced.md#typed-tests) for more information. + +### TYPED_TEST {#TYPED_TEST} + +
+TYPED_TEST(TestSuiteName, TestName) {
+  ... statements ...
+}
+
+ +Defines an individual typed test named *`TestName`* in the typed test suite +*`TestSuiteName`*. The test suite must be defined with +[`TYPED_TEST_SUITE`](#TYPED_TEST_SUITE). + +Within the test body, the special name `TypeParam` refers to the type parameter, +and `TestFixture` refers to the fixture class. See the following example: + +```cpp +TYPED_TEST(MyFixture, Example) { + // Inside a test, refer to the special name TypeParam to get the type + // parameter. Since we are inside a derived class template, C++ requires + // us to visit the members of MyFixture via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the 'TestFixture::' + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the 'typename TestFixture::' + // prefix. The 'typename' is required to satisfy the compiler. + typename TestFixture::List values; + + values.push_back(n); + ... +} +``` + +For more information, see [Typed Tests](../advanced.md#typed-tests). + +### TYPED_TEST_SUITE_P {#TYPED_TEST_SUITE_P} + +`TYPED_TEST_SUITE_P(`*`TestFixtureName`*`)` + +Defines a type-parameterized test suite based on the test fixture +*`TestFixtureName`*. The test suite name is *`TestFixtureName`*. + +The argument *`TestFixtureName`* is a fixture class template, parameterized by a +type. See [`TYPED_TEST_SUITE`](#TYPED_TEST_SUITE) for an example. + +See also [`TYPED_TEST_P`](#TYPED_TEST_P) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more +information. + +### TYPED_TEST_P {#TYPED_TEST_P} + +
+TYPED_TEST_P(TestSuiteName, TestName) {
+  ... statements ...
+}
+
+ +Defines an individual type-parameterized test named *`TestName`* in the +type-parameterized test suite *`TestSuiteName`*. The test suite must be defined +with [`TYPED_TEST_SUITE_P`](#TYPED_TEST_SUITE_P). + +Within the test body, the special name `TypeParam` refers to the type parameter, +and `TestFixture` refers to the fixture class. See [`TYPED_TEST`](#TYPED_TEST) +for an example. + +See also [`REGISTER_TYPED_TEST_SUITE_P`](#REGISTER_TYPED_TEST_SUITE_P) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more +information. + +### REGISTER_TYPED_TEST_SUITE_P {#REGISTER_TYPED_TEST_SUITE_P} + +`REGISTER_TYPED_TEST_SUITE_P(`*`TestSuiteName`*`,`*`TestNames...`*`)` + +Registers the type-parameterized tests *`TestNames...`* of the test suite +*`TestSuiteName`*. The test suite and tests must be defined with +[`TYPED_TEST_SUITE_P`](#TYPED_TEST_SUITE_P) and [`TYPED_TEST_P`](#TYPED_TEST_P). + +For example: + +```cpp +// Define the test suite and tests. +TYPED_TEST_SUITE_P(MyFixture); +TYPED_TEST_P(MyFixture, HasPropertyA) { ... } +TYPED_TEST_P(MyFixture, HasPropertyB) { ... } + +// Register the tests in the test suite. +REGISTER_TYPED_TEST_SUITE_P(MyFixture, HasPropertyA, HasPropertyB); +``` + +See also [`INSTANTIATE_TYPED_TEST_SUITE_P`](#INSTANTIATE_TYPED_TEST_SUITE_P) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more +information. + +### INSTANTIATE_TYPED_TEST_SUITE_P {#INSTANTIATE_TYPED_TEST_SUITE_P} + +`INSTANTIATE_TYPED_TEST_SUITE_P(`*`InstantiationName`*`,`*`TestSuiteName`*`,`*`Types`*`)` + +Instantiates the type-parameterized test suite *`TestSuiteName`*. The test suite +must be registered with +[`REGISTER_TYPED_TEST_SUITE_P`](#REGISTER_TYPED_TEST_SUITE_P). + +The argument *`InstantiationName`* is a unique name for the instantiation of the +test suite, to distinguish between multiple instantiations. In test output, the +instantiation name is added as a prefix to the test suite name +*`TestSuiteName`*. If *`InstantiationName`* is empty +(`INSTANTIATE_TYPED_TEST_SUITE_P(, ...)`), no prefix is added. + +The argument *`Types`* is a [`Types`](#Types) object representing the list of +types to run the tests on, for example: + +```cpp +using MyTypes = ::testing::Types; +INSTANTIATE_TYPED_TEST_SUITE_P(MyInstantiation, MyFixture, MyTypes); +``` + +The type alias (`using` or `typedef`) is necessary for the +`INSTANTIATE_TYPED_TEST_SUITE_P` macro to parse correctly. + +For more information, see +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests). + +### FRIEND_TEST {#FRIEND_TEST} + +`FRIEND_TEST(`*`TestSuiteName`*`,`*`TestName`*`)` + +Within a class body, declares an individual test as a friend of the class, +enabling the test to access private class members. + +If the class is defined in a namespace, then in order to be friends of the +class, test fixtures and tests must be defined in the exact same namespace, +without inline or anonymous namespaces. + +For example, if the class definition looks like the following: + +```cpp +namespace my_namespace { + +class MyClass { + friend class MyClassTest; + FRIEND_TEST(MyClassTest, HasPropertyA); + FRIEND_TEST(MyClassTest, HasPropertyB); + ... definition of class MyClass ... +}; + +} // namespace my_namespace +``` + +Then the test code should look like: + +```cpp +namespace my_namespace { + +class MyClassTest : public testing::Test { + ... +}; + +TEST_F(MyClassTest, HasPropertyA) { ... } +TEST_F(MyClassTest, HasPropertyB) { ... } + +} // namespace my_namespace +``` + +See [Testing Private Code](../advanced.md#testing-private-code) for more +information. + +### SCOPED_TRACE {#SCOPED_TRACE} + +`SCOPED_TRACE(`*`message`*`)` + +Causes the current file name, line number, and the given message *`message`* to +be added to the failure message for each assertion failure that occurs in the +scope. + +For more information, see +[Adding Traces to Assertions](../advanced.md#adding-traces-to-assertions). + +See also the [`ScopedTrace` class](#ScopedTrace). + +### GTEST_SKIP {#GTEST_SKIP} + +`GTEST_SKIP()` + +Prevents further test execution at runtime. + +Can be used in individual test cases or in the `SetUp()` methods of test +environments or test fixtures (classes derived from the +[`Environment`](#Environment) or [`Test`](#Test) classes). If used in a global +test environment `SetUp()` method, it skips all tests in the test program. If +used in a test fixture `SetUp()` method, it skips all tests in the corresponding +test suite. + +Similar to assertions, `GTEST_SKIP` allows streaming a custom message into it. + +See [Skipping Test Execution](../advanced.md#skipping-test-execution) for more +information. + +### GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST {#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST} + +`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(`*`TestSuiteName`*`)` + +Allows the value-parameterized test suite *`TestSuiteName`* to be +uninstantiated. + +By default, every [`TEST_P`](#TEST_P) call without a corresponding +[`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P) call causes a failing +test in the test suite `GoogleTestVerification`. +`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST` suppresses this failure for the +given test suite. + +## Classes and types + +GoogleTest defines the following classes and types to help with writing tests. + +### AssertionResult {#AssertionResult} + +`testing::AssertionResult` + +A class for indicating whether an assertion was successful. + +When the assertion wasn't successful, the `AssertionResult` object stores a +non-empty failure message that can be retrieved with the object's `message()` +method. + +To create an instance of this class, use one of the factory functions +[`AssertionSuccess()`](#AssertionSuccess) or +[`AssertionFailure()`](#AssertionFailure). + +### AssertionException {#AssertionException} + +`testing::AssertionException` + +Exception which can be thrown from +[`TestEventListener::OnTestPartResult`](#TestEventListener::OnTestPartResult). + +### EmptyTestEventListener {#EmptyTestEventListener} + +`testing::EmptyTestEventListener` + +Provides an empty implementation of all methods in the +[`TestEventListener`](#TestEventListener) interface, such that a subclass only +needs to override the methods it cares about. + +### Environment {#Environment} + +`testing::Environment` + +Represents a global test environment. See +[Global Set-Up and Tear-Down](../advanced.md#global-set-up-and-tear-down). + +#### Protected Methods {#Environment-protected} + +##### SetUp {#Environment::SetUp} + +`virtual void Environment::SetUp()` + +Override this to define how to set up the environment. + +##### TearDown {#Environment::TearDown} + +`virtual void Environment::TearDown()` + +Override this to define how to tear down the environment. + +### ScopedTrace {#ScopedTrace} + +`testing::ScopedTrace` + +An instance of this class causes a trace to be included in every test failure +message generated by code in the scope of the lifetime of the `ScopedTrace` +instance. The effect is undone with the destruction of the instance. + +The `ScopedTrace` constructor has the following form: + +```cpp +template +ScopedTrace(const char* file, int line, const T& message) +``` + +Example usage: + +```cpp +testing::ScopedTrace trace("file.cc", 123, "message"); +``` + +The resulting trace includes the given source file path and line number, and the +given message. The `message` argument can be anything streamable to +`std::ostream`. + +See also [`SCOPED_TRACE`](#SCOPED_TRACE). + +### Test {#Test} + +`testing::Test` + +The abstract class that all tests inherit from. `Test` is not copyable. + +#### Public Methods {#Test-public} + +##### SetUpTestSuite {#Test::SetUpTestSuite} + +`static void Test::SetUpTestSuite()` + +Performs shared setup for all tests in the test suite. GoogleTest calls +`SetUpTestSuite()` before running the first test in the test suite. + +##### TearDownTestSuite {#Test::TearDownTestSuite} + +`static void Test::TearDownTestSuite()` + +Performs shared teardown for all tests in the test suite. GoogleTest calls +`TearDownTestSuite()` after running the last test in the test suite. + +##### HasFatalFailure {#Test::HasFatalFailure} + +`static bool Test::HasFatalFailure()` + +Returns true if and only if the current test has a fatal failure. + +##### HasNonfatalFailure {#Test::HasNonfatalFailure} + +`static bool Test::HasNonfatalFailure()` + +Returns true if and only if the current test has a nonfatal failure. + +##### HasFailure {#Test::HasFailure} + +`static bool Test::HasFailure()` + +Returns true if and only if the current test has any failure, either fatal or +nonfatal. + +##### IsSkipped {#Test::IsSkipped} + +`static bool Test::IsSkipped()` + +Returns true if and only if the current test was skipped. + +##### RecordProperty {#Test::RecordProperty} + +`static void Test::RecordProperty(const std::string& key, const std::string& +value)` \ +`static void Test::RecordProperty(const std::string& key, int value)` + +Logs a property for the current test, test suite, or entire invocation of the +test program. Only the last value for a given key is logged. + +The key must be a valid XML attribute name, and cannot conflict with the ones +already used by GoogleTest (`name`, `file`, `line`, `status`, `time`, +`classname`, `type_param`, and `value_param`). + +`RecordProperty` is `public static` so it can be called from utility functions +that are not members of the test fixture. + +Calls to `RecordProperty` made during the lifespan of the test (from the moment +its constructor starts to the moment its destructor finishes) are output in XML +as attributes of the `` element. Properties recorded from a fixture's +`SetUpTestSuite` or `TearDownTestSuite` methods are logged as attributes of the +corresponding `` element. Calls to `RecordProperty` made in the +global context (before or after invocation of `RUN_ALL_TESTS` or from the +`SetUp`/`TearDown` methods of registered `Environment` objects) are output as +attributes of the `` element. + +#### Protected Methods {#Test-protected} + +##### SetUp {#Test::SetUp} + +`virtual void Test::SetUp()` + +Override this to perform test fixture setup. GoogleTest calls `SetUp()` before +running each individual test. + +##### TearDown {#Test::TearDown} + +`virtual void Test::TearDown()` + +Override this to perform test fixture teardown. GoogleTest calls `TearDown()` +after running each individual test. + +### TestWithParam {#TestWithParam} + +`testing::TestWithParam` + +A convenience class which inherits from both [`Test`](#Test) and +[`WithParamInterface`](#WithParamInterface). + +### TestSuite {#TestSuite} + +Represents a test suite. `TestSuite` is not copyable. + +#### Public Methods {#TestSuite-public} + +##### name {#TestSuite::name} + +`const char* TestSuite::name() const` + +Gets the name of the test suite. + +##### type_param {#TestSuite::type_param} + +`const char* TestSuite::type_param() const` + +Returns the name of the parameter type, or `NULL` if this is not a typed or +type-parameterized test suite. See [Typed Tests](../advanced.md#typed-tests) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests). + +##### should_run {#TestSuite::should_run} + +`bool TestSuite::should_run() const` + +Returns true if any test in this test suite should run. + +##### successful_test_count {#TestSuite::successful_test_count} + +`int TestSuite::successful_test_count() const` + +Gets the number of successful tests in this test suite. + +##### skipped_test_count {#TestSuite::skipped_test_count} + +`int TestSuite::skipped_test_count() const` + +Gets the number of skipped tests in this test suite. + +##### failed_test_count {#TestSuite::failed_test_count} + +`int TestSuite::failed_test_count() const` + +Gets the number of failed tests in this test suite. + +##### reportable_disabled_test_count {#TestSuite::reportable_disabled_test_count} + +`int TestSuite::reportable_disabled_test_count() const` + +Gets the number of disabled tests that will be reported in the XML report. + +##### disabled_test_count {#TestSuite::disabled_test_count} + +`int TestSuite::disabled_test_count() const` + +Gets the number of disabled tests in this test suite. + +##### reportable_test_count {#TestSuite::reportable_test_count} + +`int TestSuite::reportable_test_count() const` + +Gets the number of tests to be printed in the XML report. + +##### test_to_run_count {#TestSuite::test_to_run_count} + +`int TestSuite::test_to_run_count() const` + +Get the number of tests in this test suite that should run. + +##### total_test_count {#TestSuite::total_test_count} + +`int TestSuite::total_test_count() const` + +Gets the number of all tests in this test suite. + +##### Passed {#TestSuite::Passed} + +`bool TestSuite::Passed() const` + +Returns true if and only if the test suite passed. + +##### Failed {#TestSuite::Failed} + +`bool TestSuite::Failed() const` + +Returns true if and only if the test suite failed. + +##### elapsed_time {#TestSuite::elapsed_time} + +`TimeInMillis TestSuite::elapsed_time() const` + +Returns the elapsed time, in milliseconds. + +##### start_timestamp {#TestSuite::start_timestamp} + +`TimeInMillis TestSuite::start_timestamp() const` + +Gets the time of the test suite start, in ms from the start of the UNIX epoch. + +##### GetTestInfo {#TestSuite::GetTestInfo} + +`const TestInfo* TestSuite::GetTestInfo(int i) const` + +Returns the [`TestInfo`](#TestInfo) for the `i`-th test among all the tests. `i` +can range from 0 to `total_test_count() - 1`. If `i` is not in that range, +returns `NULL`. + +##### ad_hoc_test_result {#TestSuite::ad_hoc_test_result} + +`const TestResult& TestSuite::ad_hoc_test_result() const` + +Returns the [`TestResult`](#TestResult) that holds test properties recorded +during execution of `SetUpTestSuite` and `TearDownTestSuite`. + +### TestInfo {#TestInfo} + +`testing::TestInfo` + +Stores information about a test. + +#### Public Methods {#TestInfo-public} + +##### test_suite_name {#TestInfo::test_suite_name} + +`const char* TestInfo::test_suite_name() const` + +Returns the test suite name. + +##### name {#TestInfo::name} + +`const char* TestInfo::name() const` + +Returns the test name. + +##### type_param {#TestInfo::type_param} + +`const char* TestInfo::type_param() const` + +Returns the name of the parameter type, or `NULL` if this is not a typed or +type-parameterized test. See [Typed Tests](../advanced.md#typed-tests) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests). + +##### value_param {#TestInfo::value_param} + +`const char* TestInfo::value_param() const` + +Returns the text representation of the value parameter, or `NULL` if this is not +a value-parameterized test. See +[Value-Parameterized Tests](../advanced.md#value-parameterized-tests). + +##### file {#TestInfo::file} + +`const char* TestInfo::file() const` + +Returns the file name where this test is defined. + +##### line {#TestInfo::line} + +`int TestInfo::line() const` + +Returns the line where this test is defined. + +##### is_in_another_shard {#TestInfo::is_in_another_shard} + +`bool TestInfo::is_in_another_shard() const` + +Returns true if this test should not be run because it's in another shard. + +##### should_run {#TestInfo::should_run} + +`bool TestInfo::should_run() const` + +Returns true if this test should run, that is if the test is not disabled (or it +is disabled but the `also_run_disabled_tests` flag has been specified) and its +full name matches the user-specified filter. + +GoogleTest allows the user to filter the tests by their full names. Only the +tests that match the filter will run. See +[Running a Subset of the Tests](../advanced.md#running-a-subset-of-the-tests) +for more information. + +##### is_reportable {#TestInfo::is_reportable} + +`bool TestInfo::is_reportable() const` + +Returns true if and only if this test will appear in the XML report. + +##### result {#TestInfo::result} + +`const TestResult* TestInfo::result() const` + +Returns the result of the test. See [`TestResult`](#TestResult). + +### TestParamInfo {#TestParamInfo} + +`testing::TestParamInfo` + +Describes a parameter to a value-parameterized test. The type `T` is the type of +the parameter. + +Contains the fields `param` and `index` which hold the value of the parameter +and its integer index respectively. + +### UnitTest {#UnitTest} + +`testing::UnitTest` + +This class contains information about the test program. + +`UnitTest` is a singleton class. The only instance is created when +`UnitTest::GetInstance()` is first called. This instance is never deleted. + +`UnitTest` is not copyable. + +#### Public Methods {#UnitTest-public} + +##### GetInstance {#UnitTest::GetInstance} + +`static UnitTest* UnitTest::GetInstance()` + +Gets the singleton `UnitTest` object. The first time this method is called, a +`UnitTest` object is constructed and returned. Consecutive calls will return the +same object. + +##### original_working_dir {#UnitTest::original_working_dir} + +`const char* UnitTest::original_working_dir() const` + +Returns the working directory when the first [`TEST()`](#TEST) or +[`TEST_F()`](#TEST_F) was executed. The `UnitTest` object owns the string. + +##### current_test_suite {#UnitTest::current_test_suite} + +`const TestSuite* UnitTest::current_test_suite() const` + +Returns the [`TestSuite`](#TestSuite) object for the test that's currently +running, or `NULL` if no test is running. + +##### current_test_info {#UnitTest::current_test_info} + +`const TestInfo* UnitTest::current_test_info() const` + +Returns the [`TestInfo`](#TestInfo) object for the test that's currently +running, or `NULL` if no test is running. + +##### random_seed {#UnitTest::random_seed} + +`int UnitTest::random_seed() const` + +Returns the random seed used at the start of the current test run. + +##### successful_test_suite_count {#UnitTest::successful_test_suite_count} + +`int UnitTest::successful_test_suite_count() const` + +Gets the number of successful test suites. + +##### failed_test_suite_count {#UnitTest::failed_test_suite_count} + +`int UnitTest::failed_test_suite_count() const` + +Gets the number of failed test suites. + +##### total_test_suite_count {#UnitTest::total_test_suite_count} + +`int UnitTest::total_test_suite_count() const` + +Gets the number of all test suites. + +##### test_suite_to_run_count {#UnitTest::test_suite_to_run_count} + +`int UnitTest::test_suite_to_run_count() const` + +Gets the number of all test suites that contain at least one test that should +run. + +##### successful_test_count {#UnitTest::successful_test_count} + +`int UnitTest::successful_test_count() const` + +Gets the number of successful tests. + +##### skipped_test_count {#UnitTest::skipped_test_count} + +`int UnitTest::skipped_test_count() const` + +Gets the number of skipped tests. + +##### failed_test_count {#UnitTest::failed_test_count} + +`int UnitTest::failed_test_count() const` + +Gets the number of failed tests. + +##### reportable_disabled_test_count {#UnitTest::reportable_disabled_test_count} + +`int UnitTest::reportable_disabled_test_count() const` + +Gets the number of disabled tests that will be reported in the XML report. + +##### disabled_test_count {#UnitTest::disabled_test_count} + +`int UnitTest::disabled_test_count() const` + +Gets the number of disabled tests. + +##### reportable_test_count {#UnitTest::reportable_test_count} + +`int UnitTest::reportable_test_count() const` + +Gets the number of tests to be printed in the XML report. + +##### total_test_count {#UnitTest::total_test_count} + +`int UnitTest::total_test_count() const` + +Gets the number of all tests. + +##### test_to_run_count {#UnitTest::test_to_run_count} + +`int UnitTest::test_to_run_count() const` + +Gets the number of tests that should run. + +##### start_timestamp {#UnitTest::start_timestamp} + +`TimeInMillis UnitTest::start_timestamp() const` + +Gets the time of the test program start, in ms from the start of the UNIX epoch. + +##### elapsed_time {#UnitTest::elapsed_time} + +`TimeInMillis UnitTest::elapsed_time() const` + +Gets the elapsed time, in milliseconds. + +##### Passed {#UnitTest::Passed} + +`bool UnitTest::Passed() const` + +Returns true if and only if the unit test passed (i.e. all test suites passed). + +##### Failed {#UnitTest::Failed} + +`bool UnitTest::Failed() const` + +Returns true if and only if the unit test failed (i.e. some test suite failed or +something outside of all tests failed). + +##### GetTestSuite {#UnitTest::GetTestSuite} + +`const TestSuite* UnitTest::GetTestSuite(int i) const` + +Gets the [`TestSuite`](#TestSuite) object for the `i`-th test suite among all +the test suites. `i` can range from 0 to `total_test_suite_count() - 1`. If `i` +is not in that range, returns `NULL`. + +##### ad_hoc_test_result {#UnitTest::ad_hoc_test_result} + +`const TestResult& UnitTest::ad_hoc_test_result() const` + +Returns the [`TestResult`](#TestResult) containing information on test failures +and properties logged outside of individual test suites. + +##### listeners {#UnitTest::listeners} + +`TestEventListeners& UnitTest::listeners()` + +Returns the list of event listeners that can be used to track events inside +GoogleTest. See [`TestEventListeners`](#TestEventListeners). + +### TestEventListener {#TestEventListener} + +`testing::TestEventListener` + +The interface for tracing execution of tests. The methods below are listed in +the order the corresponding events are fired. + +#### Public Methods {#TestEventListener-public} + +##### OnTestProgramStart {#TestEventListener::OnTestProgramStart} + +`virtual void TestEventListener::OnTestProgramStart(const UnitTest& unit_test)` + +Fired before any test activity starts. + +##### OnTestIterationStart {#TestEventListener::OnTestIterationStart} + +`virtual void TestEventListener::OnTestIterationStart(const UnitTest& unit_test, +int iteration)` + +Fired before each iteration of tests starts. There may be more than one +iteration if `GTEST_FLAG(repeat)` is set. `iteration` is the iteration index, +starting from 0. + +##### OnEnvironmentsSetUpStart {#TestEventListener::OnEnvironmentsSetUpStart} + +`virtual void TestEventListener::OnEnvironmentsSetUpStart(const UnitTest& +unit_test)` + +Fired before environment set-up for each iteration of tests starts. + +##### OnEnvironmentsSetUpEnd {#TestEventListener::OnEnvironmentsSetUpEnd} + +`virtual void TestEventListener::OnEnvironmentsSetUpEnd(const UnitTest& +unit_test)` + +Fired after environment set-up for each iteration of tests ends. + +##### OnTestSuiteStart {#TestEventListener::OnTestSuiteStart} + +`virtual void TestEventListener::OnTestSuiteStart(const TestSuite& test_suite)` + +Fired before the test suite starts. + +##### OnTestStart {#TestEventListener::OnTestStart} + +`virtual void TestEventListener::OnTestStart(const TestInfo& test_info)` + +Fired before the test starts. + +##### OnTestPartResult {#TestEventListener::OnTestPartResult} + +`virtual void TestEventListener::OnTestPartResult(const TestPartResult& +test_part_result)` + +Fired after a failed assertion or a `SUCCEED()` invocation. If you want to throw +an exception from this function to skip to the next test, it must be an +[`AssertionException`](#AssertionException) or inherited from it. + +##### OnTestEnd {#TestEventListener::OnTestEnd} + +`virtual void TestEventListener::OnTestEnd(const TestInfo& test_info)` + +Fired after the test ends. + +##### OnTestSuiteEnd {#TestEventListener::OnTestSuiteEnd} + +`virtual void TestEventListener::OnTestSuiteEnd(const TestSuite& test_suite)` + +Fired after the test suite ends. + +##### OnEnvironmentsTearDownStart {#TestEventListener::OnEnvironmentsTearDownStart} + +`virtual void TestEventListener::OnEnvironmentsTearDownStart(const UnitTest& +unit_test)` + +Fired before environment tear-down for each iteration of tests starts. + +##### OnEnvironmentsTearDownEnd {#TestEventListener::OnEnvironmentsTearDownEnd} + +`virtual void TestEventListener::OnEnvironmentsTearDownEnd(const UnitTest& +unit_test)` + +Fired after environment tear-down for each iteration of tests ends. + +##### OnTestIterationEnd {#TestEventListener::OnTestIterationEnd} + +`virtual void TestEventListener::OnTestIterationEnd(const UnitTest& unit_test, +int iteration)` + +Fired after each iteration of tests finishes. + +##### OnTestProgramEnd {#TestEventListener::OnTestProgramEnd} + +`virtual void TestEventListener::OnTestProgramEnd(const UnitTest& unit_test)` + +Fired after all test activities have ended. + +### TestEventListeners {#TestEventListeners} + +`testing::TestEventListeners` + +Lets users add listeners to track events in GoogleTest. + +#### Public Methods {#TestEventListeners-public} + +##### Append {#TestEventListeners::Append} + +`void TestEventListeners::Append(TestEventListener* listener)` + +Appends an event listener to the end of the list. GoogleTest assumes ownership +of the listener (i.e. it will delete the listener when the test program +finishes). + +##### Release {#TestEventListeners::Release} + +`TestEventListener* TestEventListeners::Release(TestEventListener* listener)` + +Removes the given event listener from the list and returns it. It then becomes +the caller's responsibility to delete the listener. Returns `NULL` if the +listener is not found in the list. + +##### default_result_printer {#TestEventListeners::default_result_printer} + +`TestEventListener* TestEventListeners::default_result_printer() const` + +Returns the standard listener responsible for the default console output. Can be +removed from the listeners list to shut down default console output. Note that +removing this object from the listener list with +[`Release()`](#TestEventListeners::Release) transfers its ownership to the +caller and makes this function return `NULL` the next time. + +##### default_xml_generator {#TestEventListeners::default_xml_generator} + +`TestEventListener* TestEventListeners::default_xml_generator() const` + +Returns the standard listener responsible for the default XML output controlled +by the `--gtest_output=xml` flag. Can be removed from the listeners list by +users who want to shut down the default XML output controlled by this flag and +substitute it with custom one. Note that removing this object from the listener +list with [`Release()`](#TestEventListeners::Release) transfers its ownership to +the caller and makes this function return `NULL` the next time. + +### TestPartResult {#TestPartResult} + +`testing::TestPartResult` + +A copyable object representing the result of a test part (i.e. an assertion or +an explicit `FAIL()`, `ADD_FAILURE()`, or `SUCCESS()`). + +#### Public Methods {#TestPartResult-public} + +##### type {#TestPartResult::type} + +`Type TestPartResult::type() const` + +Gets the outcome of the test part. + +The return type `Type` is an enum defined as follows: + +```cpp +enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure, // Failed and the test should be terminated. + kSkip // Skipped. +}; +``` + +##### file_name {#TestPartResult::file_name} + +`const char* TestPartResult::file_name() const` + +Gets the name of the source file where the test part took place, or `NULL` if +it's unknown. + +##### line_number {#TestPartResult::line_number} + +`int TestPartResult::line_number() const` + +Gets the line in the source file where the test part took place, or `-1` if it's +unknown. + +##### summary {#TestPartResult::summary} + +`const char* TestPartResult::summary() const` + +Gets the summary of the failure message. + +##### message {#TestPartResult::message} + +`const char* TestPartResult::message() const` + +Gets the message associated with the test part. + +##### skipped {#TestPartResult::skipped} + +`bool TestPartResult::skipped() const` + +Returns true if and only if the test part was skipped. + +##### passed {#TestPartResult::passed} + +`bool TestPartResult::passed() const` + +Returns true if and only if the test part passed. + +##### nonfatally_failed {#TestPartResult::nonfatally_failed} + +`bool TestPartResult::nonfatally_failed() const` + +Returns true if and only if the test part non-fatally failed. + +##### fatally_failed {#TestPartResult::fatally_failed} + +`bool TestPartResult::fatally_failed() const` + +Returns true if and only if the test part fatally failed. + +##### failed {#TestPartResult::failed} + +`bool TestPartResult::failed() const` + +Returns true if and only if the test part failed. + +### TestProperty {#TestProperty} + +`testing::TestProperty` + +A copyable object representing a user-specified test property which can be +output as a key/value string pair. + +#### Public Methods {#TestProperty-public} + +##### key {#key} + +`const char* key() const` + +Gets the user-supplied key. + +##### value {#value} + +`const char* value() const` + +Gets the user-supplied value. + +##### SetValue {#SetValue} + +`void SetValue(const std::string& new_value)` + +Sets a new value, overriding the previous one. + +### TestResult {#TestResult} + +`testing::TestResult` + +Contains information about the result of a single test. + +`TestResult` is not copyable. + +#### Public Methods {#TestResult-public} + +##### total_part_count {#TestResult::total_part_count} + +`int TestResult::total_part_count() const` + +Gets the number of all test parts. This is the sum of the number of successful +test parts and the number of failed test parts. + +##### test_property_count {#TestResult::test_property_count} + +`int TestResult::test_property_count() const` + +Returns the number of test properties. + +##### Passed {#TestResult::Passed} + +`bool TestResult::Passed() const` + +Returns true if and only if the test passed (i.e. no test part failed). + +##### Skipped {#TestResult::Skipped} + +`bool TestResult::Skipped() const` + +Returns true if and only if the test was skipped. + +##### Failed {#TestResult::Failed} + +`bool TestResult::Failed() const` + +Returns true if and only if the test failed. + +##### HasFatalFailure {#TestResult::HasFatalFailure} + +`bool TestResult::HasFatalFailure() const` + +Returns true if and only if the test fatally failed. + +##### HasNonfatalFailure {#TestResult::HasNonfatalFailure} + +`bool TestResult::HasNonfatalFailure() const` + +Returns true if and only if the test has a non-fatal failure. + +##### elapsed_time {#TestResult::elapsed_time} + +`TimeInMillis TestResult::elapsed_time() const` + +Returns the elapsed time, in milliseconds. + +##### start_timestamp {#TestResult::start_timestamp} + +`TimeInMillis TestResult::start_timestamp() const` + +Gets the time of the test case start, in ms from the start of the UNIX epoch. + +##### GetTestPartResult {#TestResult::GetTestPartResult} + +`const TestPartResult& TestResult::GetTestPartResult(int i) const` + +Returns the [`TestPartResult`](#TestPartResult) for the `i`-th test part result +among all the results. `i` can range from 0 to `total_part_count() - 1`. If `i` +is not in that range, aborts the program. + +##### GetTestProperty {#TestResult::GetTestProperty} + +`const TestProperty& TestResult::GetTestProperty(int i) const` + +Returns the [`TestProperty`](#TestProperty) object for the `i`-th test property. +`i` can range from 0 to `test_property_count() - 1`. If `i` is not in that +range, aborts the program. + +### TimeInMillis {#TimeInMillis} + +`testing::TimeInMillis` + +An integer type representing time in milliseconds. + +### Types {#Types} + +`testing::Types` + +Represents a list of types for use in typed tests and type-parameterized tests. + +The template argument `T...` can be any number of types, for example: + +``` +testing::Types +``` + +See [Typed Tests](../advanced.md#typed-tests) and +[Type-Parameterized Tests](../advanced.md#type-parameterized-tests) for more +information. + +### WithParamInterface {#WithParamInterface} + +`testing::WithParamInterface` + +The pure interface class that all value-parameterized tests inherit from. + +A value-parameterized test fixture class must inherit from both [`Test`](#Test) +and `WithParamInterface`. In most cases that just means inheriting from +[`TestWithParam`](#TestWithParam), but more complicated test hierarchies may +need to inherit from `Test` and `WithParamInterface` at different levels. + +This interface defines the type alias `ParamType` for the parameter type `T` and +has support for accessing the test parameter value via the `GetParam()` method: + +``` +static const ParamType& GetParam() +``` + +For more information, see +[Value-Parameterized Tests](../advanced.md#value-parameterized-tests). + +## Functions + +GoogleTest defines the following functions to help with writing and running +tests. + +### InitGoogleTest {#InitGoogleTest} + +`void testing::InitGoogleTest(int* argc, char** argv)` \ +`void testing::InitGoogleTest(int* argc, wchar_t** argv)` \ +`void testing::InitGoogleTest()` + +Initializes GoogleTest. This must be called before calling +[`RUN_ALL_TESTS()`](#RUN_ALL_TESTS). In particular, it parses the command line +for the flags that GoogleTest recognizes. Whenever a GoogleTest flag is seen, it +is removed from `argv`, and `*argc` is decremented. Keep in mind that `argv` +must terminate with a `NULL` pointer (i.e. `argv[argc]` is `NULL`), which is +already the case with the default `argv` passed to `main`. + +No value is returned. Instead, the GoogleTest flag variables are updated. + +The `InitGoogleTest(int* argc, wchar_t** argv)` overload can be used in Windows +programs compiled in `UNICODE` mode. + +The argument-less `InitGoogleTest()` overload can be used on Arduino/embedded +platforms where there is no `argc`/`argv`. + +### AddGlobalTestEnvironment {#AddGlobalTestEnvironment} + +`Environment* testing::AddGlobalTestEnvironment(Environment* env)` + +Adds a test environment to the test program. Must be called before +[`RUN_ALL_TESTS()`](#RUN_ALL_TESTS) is called. See +[Global Set-Up and Tear-Down](../advanced.md#global-set-up-and-tear-down) for +more information. + +See also [`Environment`](#Environment). + +### RegisterTest {#RegisterTest} + +```cpp +template +TestInfo* testing::RegisterTest(const char* test_suite_name, const char* test_name, + const char* type_param, const char* value_param, + const char* file, int line, Factory factory) +``` + +Dynamically registers a test with the framework. + +The `factory` argument is a factory callable (move-constructible) object or +function pointer that creates a new instance of the `Test` object. It handles +ownership to the caller. The signature of the callable is `Fixture*()`, where +`Fixture` is the test fixture class for the test. All tests registered with the +same `test_suite_name` must return the same fixture type. This is checked at +runtime. + +The framework will infer the fixture class from the factory and will call the +`SetUpTestSuite` and `TearDownTestSuite` methods for it. + +Must be called before [`RUN_ALL_TESTS()`](#RUN_ALL_TESTS) is invoked, otherwise +behavior is undefined. + +See +[Registering tests programmatically](../advanced.md#registering-tests-programmatically) +for more information. + +### RUN_ALL_TESTS {#RUN_ALL_TESTS} + +`int RUN_ALL_TESTS()` + +Use this function in `main()` to run all tests. It returns `0` if all tests are +successful, or `1` otherwise. + +`RUN_ALL_TESTS()` should be invoked after the command line has been parsed by +[`InitGoogleTest()`](#InitGoogleTest). + +This function was formerly a macro; thus, it is in the global namespace and has +an all-caps name. + +### AssertionSuccess {#AssertionSuccess} + +`AssertionResult testing::AssertionSuccess()` + +Creates a successful assertion result. See +[`AssertionResult`](#AssertionResult). + +### AssertionFailure {#AssertionFailure} + +`AssertionResult testing::AssertionFailure()` + +Creates a failed assertion result. Use the `<<` operator to store a failure +message: + +```cpp +testing::AssertionFailure() << "My failure message"; +``` + +See [`AssertionResult`](#AssertionResult). + +### StaticAssertTypeEq {#StaticAssertTypeEq} + +`testing::StaticAssertTypeEq()` + +Compile-time assertion for type equality. Compiles if and only if `T1` and `T2` +are the same type. The value it returns is irrelevant. + +See [Type Assertions](../advanced.md#type-assertions) for more information. + +### PrintToString {#PrintToString} + +`std::string testing::PrintToString(x)` + +Prints any value `x` using GoogleTest's value printer. + +See +[Teaching GoogleTest How to Print Your Values](../advanced.md#teaching-googletest-how-to-print-your-values) +for more information. + +### PrintToStringParamName {#PrintToStringParamName} + +`std::string testing::PrintToStringParamName(TestParamInfo& info)` + +A built-in parameterized test name generator which returns the result of +[`PrintToString`](#PrintToString) called on `info.param`. Does not work when the +test parameter is a `std::string` or C string. See +[Specifying Names for Value-Parameterized Test Parameters](../advanced.md#specifying-names-for-value-parameterized-test-parameters) +for more information. + +See also [`TestParamInfo`](#TestParamInfo) and +[`INSTANTIATE_TEST_SUITE_P`](#INSTANTIATE_TEST_SUITE_P). diff --git a/test/ios/iOSUnitTesting/extern/googletest/docs/samples.md b/test/ios/iOSUnitTesting/extern/googletest/docs/samples.md new file mode 100644 index 00000000..dedc5909 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/docs/samples.md @@ -0,0 +1,22 @@ +# Googletest Samples + +If you're like us, you'd like to look at +[googletest samples.](https://github.com/google/googletest/blob/main/googletest/samples) +The sample directory has a number of well-commented samples showing how to use a +variety of googletest features. + +* Sample #1 shows the basic steps of using googletest to test C++ functions. +* Sample #2 shows a more complex unit test for a class with multiple member + functions. +* Sample #3 uses a test fixture. +* Sample #4 teaches you how to use googletest and `googletest.h` together to + get the best of both libraries. +* Sample #5 puts shared testing logic in a base test fixture, and reuses it in + derived fixtures. +* Sample #6 demonstrates type-parameterized tests. +* Sample #7 teaches the basics of value-parameterized tests. +* Sample #8 shows using `Combine()` in value-parameterized tests. +* Sample #9 shows use of the listener API to modify Google Test's console + output and the use of its reflection API to inspect test results. +* Sample #10 shows use of the listener API to implement a primitive memory + leak checker. diff --git a/test/ios/iOSUnitTesting/extern/googletest/fake_fuchsia_sdk.bzl b/test/ios/iOSUnitTesting/extern/googletest/fake_fuchsia_sdk.bzl new file mode 100644 index 00000000..2024dc6c --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/fake_fuchsia_sdk.bzl @@ -0,0 +1,33 @@ +"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available. + +This is needed since bazel queries on targets that depend on //:gtest (eg: +`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not +defined when bazel is evaluating the transitive closure of the query target. + +See https://github.com/google/googletest/issues/4472. +""" + +def _fake_fuchsia_sdk_impl(repo_ctx): + for stub_target in repo_ctx.attr._stub_build_targets: + stub_package = stub_target + stub_target_name = stub_target.split("/")[-1] + repo_ctx.file("%s/BUILD.bazel" % stub_package, """ +filegroup( + name = "%s", +) +""" % stub_target_name) + +fake_fuchsia_sdk = repository_rule( + doc = "Used to create a fake @fuchsia_sdk repository with stub build targets.", + implementation = _fake_fuchsia_sdk_impl, + attrs = { + "_stub_build_targets": attr.string_list( + doc = "The stub build targets to initialize.", + default = [ + "pkg/fdio", + "pkg/syslog", + "pkg/zx", + ], + ), + }, +) diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/CMakeLists.txt b/test/ios/iOSUnitTesting/extern/googletest/googlemock/CMakeLists.txt new file mode 100644 index 00000000..99b2411f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/CMakeLists.txt @@ -0,0 +1,210 @@ +######################################################################## +# Note: CMake support is community-based. The maintainers do not use CMake +# internally. +# +# CMake build script for Google Mock. +# +# To run the tests for Google Mock itself on Linux, use 'make test' or +# ctest. You can select which tests to run using 'ctest -R regex'. +# For more options, run 'ctest --help'. + +option(gmock_build_tests "Build all of Google Mock's own tests." OFF) + +# A directory to find Google Test sources. +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt") + set(gtest_dir gtest) +else() + set(gtest_dir ../googletest) +endif() + +# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build(). +include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL) + +if (COMMAND pre_project_set_up_hermetic_build) + # Google Test also calls hermetic setup functions from add_subdirectory, + # although its changes will not affect things at the current scope. + pre_project_set_up_hermetic_build() +endif() + +######################################################################## +# +# Project-wide settings + +# Name of the project. +# +# CMake files in this project can refer to the root source directory +# as ${gmock_SOURCE_DIR} and to the root binary directory as +# ${gmock_BINARY_DIR}. +# Language "C" is required for find_package(Threads). +cmake_minimum_required(VERSION 3.13) +project(gmock VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C) + +if (COMMAND set_up_hermetic_build) + set_up_hermetic_build() +endif() + +# Instructs CMake to process Google Test's CMakeLists.txt and add its +# targets to the current scope. We are placing Google Test's binary +# directory in a subdirectory of our own as VC compilation may break +# if they are the same (the default). +add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/${gtest_dir}") + + +# These commands only run if this is the main project +if(CMAKE_PROJECT_NAME STREQUAL "gmock" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution") + # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to + # make it prominent in the GUI. + option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF) +else() + mark_as_advanced(gmock_build_tests) +endif() + +# Although Google Test's CMakeLists.txt calls this function, the +# changes there don't affect the current scope. Therefore we have to +# call it again here. +config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake + +# Adds Google Mock's and Google Test's header directories to the search path. +# Get Google Test's include dirs from the target, gtest_SOURCE_DIR is broken +# when using fetch-content with the name "GTest". +get_target_property(gtest_include_dirs gtest INCLUDE_DIRECTORIES) +set(gmock_build_include_dirs + "${gmock_SOURCE_DIR}/include" + "${gmock_SOURCE_DIR}" + "${gtest_include_dirs}") +include_directories(${gmock_build_include_dirs}) + +######################################################################## +# +# Defines the gmock & gmock_main libraries. User tests should link +# with one of them. + +# Google Mock libraries. We build them using more strict warnings than what +# are used for other targets, to ensure that Google Mock can be compiled by +# a user aggressive about warnings. +if (MSVC) + cxx_library(gmock + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc) + + cxx_library(gmock_main + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc + src/gmock_main.cc) +else() + cxx_library(gmock "${cxx_strict}" src/gmock-all.cc) + target_link_libraries(gmock PUBLIC gtest) + set_target_properties(gmock PROPERTIES VERSION ${GOOGLETEST_VERSION}) + cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc) + target_link_libraries(gmock_main PUBLIC gmock) + set_target_properties(gmock_main PROPERTIES VERSION ${GOOGLETEST_VERSION}) +endif() + +string(REPLACE ";" "$" dirs "${gmock_build_include_dirs}") +target_include_directories(gmock SYSTEM INTERFACE + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") +target_include_directories(gmock_main SYSTEM INTERFACE + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") + +######################################################################## +# +# Install rules. +install_project(gmock gmock_main) + +######################################################################## +# +# Google Mock's own tests. +# +# You can skip this section if you aren't interested in testing +# Google Mock itself. +# +# The tests are not built by default. To build them, set the +# gmock_build_tests option to ON. You can do it by running ccmake +# or specifying the -Dgmock_build_tests=ON flag when running cmake. + +if (gmock_build_tests) + # This must be set in the root directory for the tests to be run by + # 'make test' or ctest. + enable_testing() + + if (MINGW OR CYGWIN) + add_compile_options("-Wa,-mbig-obj") + endif() + + ############################################################ + # C++ tests built with standard compiler flags. + + cxx_test(gmock-actions_test gmock_main) + cxx_test(gmock-cardinalities_test gmock_main) + cxx_test(gmock_ex_test gmock_main) + cxx_test(gmock-function-mocker_test gmock_main) + cxx_test(gmock-internal-utils_test gmock_main) + cxx_test(gmock-matchers-arithmetic_test gmock_main) + cxx_test(gmock-matchers-comparisons_test gmock_main) + cxx_test(gmock-matchers-containers_test gmock_main) + cxx_test(gmock-matchers-misc_test gmock_main) + cxx_test(gmock-more-actions_test gmock_main) + cxx_test(gmock-nice-strict_test gmock_main) + cxx_test(gmock-port_test gmock_main) + cxx_test(gmock-spec-builders_test gmock_main) + cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc) + cxx_test(gmock_test gmock_main) + + if (DEFINED GTEST_HAS_PTHREAD) + cxx_test(gmock_stress_test gmock) + endif() + + # gmock_all_test is commented to save time building and running tests. + # Uncomment if necessary. + # cxx_test(gmock_all_test gmock_main) + + ############################################################ + # C++ tests built with non-standard compiler flags. + + if (MSVC) + cxx_library(gmock_main_no_exception "${cxx_no_exception}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + else() + cxx_library(gmock_main_no_exception "${cxx_no_exception}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_exception PUBLIC gmock) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_rtti PUBLIC gmock) + endif() + cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}" + gmock_main_no_exception test/gmock-more-actions_test.cc) + + cxx_test_with_flags(gmock_no_rtti_test "${cxx_no_rtti}" + gmock_main_no_rtti test/gmock-spec-builders_test.cc) + + cxx_shared_library(shared_gmock_main "${cxx_default}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + # Tests that a binary can be built with Google Mock as a shared library. On + # some system configurations, it may not possible to run the binary without + # knowing more details about the system configurations. We do not try to run + # this binary. To get a more robust shared library coverage, configure with + # -DBUILD_SHARED_LIBS=ON. + cxx_executable_with_flags(shared_gmock_test_ "${cxx_default}" + shared_gmock_main test/gmock-spec-builders_test.cc) + set_target_properties(shared_gmock_test_ + PROPERTIES + COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") + + ############################################################ + # Python tests. + + cxx_executable(gmock_leak_test_ test gmock_main) + py_test(gmock_leak_test) + + cxx_executable(gmock_output_test_ test gmock) + py_test(gmock_output_test) +endif() diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/README.md b/test/ios/iOSUnitTesting/extern/googletest/googlemock/README.md new file mode 100644 index 00000000..e1103b16 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/README.md @@ -0,0 +1,40 @@ +# Googletest Mocking (gMock) Framework + +### Overview + +Google's framework for writing and using C++ mock classes. It can help you +derive better designs of your system and write better tests. + +It is inspired by: + +* [jMock](http://www.jmock.org/) +* [EasyMock](https://easymock.org/) +* [Hamcrest](https://code.google.com/p/hamcrest/) + +It is designed with C++'s specifics in mind. + +gMock: + +- Provides a declarative syntax for defining mocks. +- Can define partial (hybrid) mocks, which are a cross of real and mock + objects. +- Handles functions of arbitrary types and overloaded functions. +- Comes with a rich set of matchers for validating function arguments. +- Uses an intuitive syntax for controlling the behavior of a mock. +- Does automatic verification of expectations (no record-and-replay needed). +- Allows arbitrary (partial) ordering constraints on function calls to be + expressed. +- Lets a user extend it by defining new matchers and actions. +- Does not use exceptions. +- Is easy to learn and use. + +Details and examples can be found here: + +* [gMock for Dummies](https://google.github.io/googletest/gmock_for_dummies.html) +* [Legacy gMock FAQ](https://google.github.io/googletest/gmock_faq.html) +* [gMock Cookbook](https://google.github.io/googletest/gmock_cook_book.html) +* [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html) + +GoogleMock is a part of +[GoogleTest C++ testing framework](https://github.com/google/googletest/) and a +subject to the same requirements. diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock.pc.in b/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock.pc.in new file mode 100644 index 00000000..23c67b5c --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock.pc.in @@ -0,0 +1,10 @@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: gmock +Description: GoogleMock (without main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Requires: gtest = @PROJECT_VERSION@ +Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock_main.pc.in b/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock_main.pc.in new file mode 100644 index 00000000..66ffea7f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/cmake/gmock_main.pc.in @@ -0,0 +1,10 @@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: gmock_main +Description: GoogleMock (with main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Requires: gmock = @PROJECT_VERSION@ +Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/docs/README.md b/test/ios/iOSUnitTesting/extern/googletest/googlemock/docs/README.md new file mode 100644 index 00000000..1bc57b79 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/docs/README.md @@ -0,0 +1,4 @@ +# Content Moved + +We are working on updates to the GoogleTest documentation, which has moved to +the top-level [docs](../../docs) directory. diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-actions.h b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-actions.h new file mode 100644 index 00000000..aa470799 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-actions.h @@ -0,0 +1,2360 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template +// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// Users can, however, define any local functors (e.g. a lambda) that +// can be used as actions. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' on +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md + +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* + +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ + +#ifndef _WIN32_WCE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" +#include "gmock/internal/gmock-pp.h" + +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100) + +namespace testing { + +// To implement an action Foo, define: +// 1. a class FooAction that implements the ActionInterface interface, and +// 2. a factory function that creates an Action object from a +// const FooAction*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Action objects can now be copied like plain values. + +namespace internal { + +// BuiltInDefaultValueGetter::Get() returns a +// default-constructed T value. BuiltInDefaultValueGetter::Get() crashes with an error. +// +// This primary template is used when kDefaultConstructible is true. +template +struct BuiltInDefaultValueGetter { + static T Get() { return T(); } +}; +template +struct BuiltInDefaultValueGetter { + static T Get() { + Assert(false, __FILE__, __LINE__, + "Default action undefined for the function return type."); +#if defined(__GNUC__) || defined(__clang__) + __builtin_unreachable(); +#elif defined(_MSC_VER) + __assume(0); +#else + return Invalid(); + // The above statement will never be reached, but is required in + // order for this function to compile. +#endif + } +}; + +// BuiltInDefaultValue::Get() returns the "built-in" default value +// for type T, which is NULL when T is a raw pointer type, 0 when T is +// a numeric type, false when T is bool, or "" when T is string or +// std::string. In addition, in C++11 and above, it turns a +// default-constructed T value if T is default constructible. For any +// other type T, the built-in default T value is undefined, and the +// function will abort the process. +template +class BuiltInDefaultValue { + public: + // This function returns true if and only if type T has a built-in default + // value. + static bool Exists() { return ::std::is_default_constructible::value; } + + static T Get() { + return BuiltInDefaultValueGetter< + T, ::std::is_default_constructible::value>::Get(); + } +}; + +// This partial specialization says that we use the same built-in +// default value for T and const T. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return BuiltInDefaultValue::Exists(); } + static T Get() { return BuiltInDefaultValue::Get(); } +}; + +// This partial specialization defines the default values for pointer +// types. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return true; } + static T* Get() { return nullptr; } +}; + +// The following specializations define the default values for +// specific types we care about. +#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ + template <> \ + class BuiltInDefaultValue { \ + public: \ + static bool Exists() { return true; } \ + static type Get() { return value; } \ + } + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, ""); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0'); + +// There's no need for a default action for signed wchar_t, as that +// type is the same as wchar_t for gcc, and invalid for MSVC. +// +// There's also no need for a default action for unsigned wchar_t, as +// that type is the same as unsigned int for gcc, and invalid for +// MSVC. +#if GMOCK_WCHAR_T_IS_NATIVE_ +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT +#endif + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long long, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); + +#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ + +// Partial implementations of metaprogramming types from the standard library +// not available in C++11. + +template +struct negation + // NOLINTNEXTLINE + : std::integral_constant {}; + +// Base case: with zero predicates the answer is always true. +template +struct conjunction : std::true_type {}; + +// With a single predicate, the answer is that predicate. +template +struct conjunction : P1 {}; + +// With multiple predicates the answer is the first predicate if that is false, +// and we recurse otherwise. +template +struct conjunction + : std::conditional, P1>::type {}; + +template +struct disjunction : std::false_type {}; + +template +struct disjunction : P1 {}; + +template +struct disjunction + // NOLINTNEXTLINE + : std::conditional, P1>::type {}; + +template +using void_t = void; + +// Detects whether an expression of type `From` can be implicitly converted to +// `To` according to [conv]. In C++17, [conv]/3 defines this as follows: +// +// An expression e can be implicitly converted to a type T if and only if +// the declaration T t=e; is well-formed, for some invented temporary +// variable t ([dcl.init]). +// +// [conv]/2 implies we can use function argument passing to detect whether this +// initialization is valid. +// +// Note that this is distinct from is_convertible, which requires this be valid: +// +// To test() { +// return declval(); +// } +// +// In particular, is_convertible doesn't give the correct answer when `To` and +// `From` are the same non-moveable type since `declval` will be an rvalue +// reference, defeating the guaranteed copy elision that would otherwise make +// this function work. +// +// REQUIRES: `From` is not cv void. +template +struct is_implicitly_convertible { + private: + // A function that accepts a parameter of type T. This can be called with type + // U successfully only if U is implicitly convertible to T. + template + static void Accept(T); + + // A function that creates a value of type T. + template + static T Make(); + + // An overload be selected when implicit conversion from T to To is possible. + template (Make()))> + static std::true_type TestImplicitConversion(int); + + // A fallback overload selected in all other cases. + template + static std::false_type TestImplicitConversion(...); + + public: + using type = decltype(TestImplicitConversion(0)); + static constexpr bool value = type::value; +}; + +// Like std::invoke_result_t from C++17, but works only for objects with call +// operators (not e.g. member function pointers, which we don't need specific +// support for in OnceAction because std::function deals with them). +template +using call_result_t = decltype(std::declval()(std::declval()...)); + +template +struct is_callable_r_impl : std::false_type {}; + +// Specialize the struct for those template arguments where call_result_t is +// well-formed. When it's not, the generic template above is chosen, resulting +// in std::false_type. +template +struct is_callable_r_impl>, R, F, Args...> + : std::conditional< + std::is_void::value, // + std::true_type, // + is_implicitly_convertible, R>>::type {}; + +// Like std::is_invocable_r from C++17, but works only for objects with call +// operators. See the note on call_result_t. +template +using is_callable_r = is_callable_r_impl; + +// Like std::as_const from C++17. +template +typename std::add_const::type& as_const(T& t) { + return t; +} + +} // namespace internal + +// Specialized for function types below. +template +class OnceAction; + +// An action that can only be used once. +// +// This is accepted by WillOnce, which doesn't require the underlying action to +// be copy-constructible (only move-constructible), and promises to invoke it as +// an rvalue reference. This allows the action to work with move-only types like +// std::move_only_function in a type-safe manner. +// +// For example: +// +// // Assume we have some API that needs to accept a unique pointer to some +// // non-copyable object Foo. +// void AcceptUniquePointer(std::unique_ptr foo); +// +// // We can define an action that provides a Foo to that API. Because It +// // has to give away its unique pointer, it must not be called more than +// // once, so its call operator is &&-qualified. +// struct ProvideFoo { +// std::unique_ptr foo; +// +// void operator()() && { +// AcceptUniquePointer(std::move(Foo)); +// } +// }; +// +// // This action can be used with WillOnce. +// EXPECT_CALL(mock, Call) +// .WillOnce(ProvideFoo{std::make_unique(...)}); +// +// // But a call to WillRepeatedly will fail to compile. This is correct, +// // since the action cannot correctly be used repeatedly. +// EXPECT_CALL(mock, Call) +// .WillRepeatedly(ProvideFoo{std::make_unique(...)}); +// +// A less-contrived example would be an action that returns an arbitrary type, +// whose &&-qualified call operator is capable of dealing with move-only types. +template +class OnceAction final { + private: + // True iff we can use the given callable type (or lvalue reference) directly + // via StdFunctionAdaptor. + template + using IsDirectlyCompatible = internal::conjunction< + // It must be possible to capture the callable in StdFunctionAdaptor. + std::is_constructible::type, Callable>, + // The callable must be compatible with our signature. + internal::is_callable_r::type, + Args...>>; + + // True iff we can use the given callable type via StdFunctionAdaptor once we + // ignore incoming arguments. + template + using IsCompatibleAfterIgnoringArguments = internal::conjunction< + // It must be possible to capture the callable in a lambda. + std::is_constructible::type, Callable>, + // The callable must be invocable with zero arguments, returning something + // convertible to Result. + internal::is_callable_r::type>>; + + public: + // Construct from a callable that is directly compatible with our mocked + // signature: it accepts our function type's arguments and returns something + // convertible to our result type. + template ::type>>, + IsDirectlyCompatible> // + ::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + : function_(StdFunctionAdaptor::type>( + {}, std::forward(callable))) {} + + // As above, but for a callable that ignores the mocked function's arguments. + template ::type>>, + // Exclude callables for which the overload above works. + // We'd rather provide the arguments if possible. + internal::negation>, + IsCompatibleAfterIgnoringArguments>::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + // Call the constructor above with a callable + // that ignores the input arguments. + : OnceAction(IgnoreIncomingArguments::type>{ + std::forward(callable)}) {} + + // We are naturally copyable because we store only an std::function, but + // semantically we should not be copyable. + OnceAction(const OnceAction&) = delete; + OnceAction& operator=(const OnceAction&) = delete; + OnceAction(OnceAction&&) = default; + + // Invoke the underlying action callable with which we were constructed, + // handing it the supplied arguments. + Result Call(Args... args) && { + return function_(std::forward(args)...); + } + + private: + // An adaptor that wraps a callable that is compatible with our signature and + // being invoked as an rvalue reference so that it can be used as an + // StdFunctionAdaptor. This throws away type safety, but that's fine because + // this is only used by WillOnce, which we know calls at most once. + // + // Once we have something like std::move_only_function from C++23, we can do + // away with this. + template + class StdFunctionAdaptor final { + public: + // A tag indicating that the (otherwise universal) constructor is accepting + // the callable itself, instead of e.g. stealing calls for the move + // constructor. + struct CallableTag final {}; + + template + explicit StdFunctionAdaptor(CallableTag, F&& callable) + : callable_(std::make_shared(std::forward(callable))) {} + + // Rather than explicitly returning Result, we return whatever the wrapped + // callable returns. This allows for compatibility with existing uses like + // the following, when the mocked function returns void: + // + // EXPECT_CALL(mock_fn_, Call) + // .WillOnce([&] { + // [...] + // return 0; + // }); + // + // Such a callable can be turned into std::function. If we use an + // explicit return type of Result here then it *doesn't* work with + // std::function, because we'll get a "void function should not return a + // value" error. + // + // We need not worry about incompatible result types because the SFINAE on + // OnceAction already checks this for us. std::is_invocable_r_v itself makes + // the same allowance for void result types. + template + internal::call_result_t operator()( + ArgRefs&&... args) const { + return std::move(*callable_)(std::forward(args)...); + } + + private: + // We must put the callable on the heap so that we are copyable, which + // std::function needs. + std::shared_ptr callable_; + }; + + // An adaptor that makes a callable that accepts zero arguments callable with + // our mocked arguments. + template + struct IgnoreIncomingArguments { + internal::call_result_t operator()(Args&&...) { + return std::move(callable)(); + } + + Callable callable; + }; + + std::function function_; +}; + +// When an unexpected function call is encountered, Google Mock will +// let it return a default value if the user has specified one for its +// return type, or if the return type has a built-in default value; +// otherwise Google Mock won't know what value to return and will have +// to abort the process. +// +// The DefaultValue class allows a user to specify the +// default value for a type T that is both copyable and publicly +// destructible (i.e. anything that can be used as a function return +// type). The usage is: +// +// // Sets the default value for type T to be foo. +// DefaultValue::Set(foo); +template +class DefaultValue { + public: + // Sets the default value for type T; requires T to be + // copy-constructable and have a public destructor. + static void Set(T x) { + delete producer_; + producer_ = new FixedValueProducer(x); + } + + // Provides a factory function to be called to generate the default value. + // This method can be used even if T is only move-constructible, but it is not + // limited to that case. + typedef T (*FactoryFunction)(); + static void SetFactory(FactoryFunction factory) { + delete producer_; + producer_ = new FactoryValueProducer(factory); + } + + // Unsets the default value for type T. + static void Clear() { + delete producer_; + producer_ = nullptr; + } + + // Returns true if and only if the user has set the default value for type T. + static bool IsSet() { return producer_ != nullptr; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T if the user has set one; + // otherwise returns the built-in default value. Requires that Exists() + // is true, which ensures that the return value is well-defined. + static T Get() { + return producer_ == nullptr ? internal::BuiltInDefaultValue::Get() + : producer_->Produce(); + } + + private: + class ValueProducer { + public: + virtual ~ValueProducer() = default; + virtual T Produce() = 0; + }; + + class FixedValueProducer : public ValueProducer { + public: + explicit FixedValueProducer(T value) : value_(value) {} + T Produce() override { return value_; } + + private: + const T value_; + FixedValueProducer(const FixedValueProducer&) = delete; + FixedValueProducer& operator=(const FixedValueProducer&) = delete; + }; + + class FactoryValueProducer : public ValueProducer { + public: + explicit FactoryValueProducer(FactoryFunction factory) + : factory_(factory) {} + T Produce() override { return factory_(); } + + private: + const FactoryFunction factory_; + FactoryValueProducer(const FactoryValueProducer&) = delete; + FactoryValueProducer& operator=(const FactoryValueProducer&) = delete; + }; + + static ValueProducer* producer_; +}; + +// This partial specialization allows a user to set default values for +// reference types. +template +class DefaultValue { + public: + // Sets the default value for type T&. + static void Set(T& x) { // NOLINT + address_ = &x; + } + + // Unsets the default value for type T&. + static void Clear() { address_ = nullptr; } + + // Returns true if and only if the user has set the default value for type T&. + static bool IsSet() { return address_ != nullptr; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T& if the user has set one; + // otherwise returns the built-in default value if there is one; + // otherwise aborts the process. + static T& Get() { + return address_ == nullptr ? internal::BuiltInDefaultValue::Get() + : *address_; + } + + private: + static T* address_; +}; + +// This specialization allows DefaultValue::Get() to +// compile. +template <> +class DefaultValue { + public: + static bool Exists() { return true; } + static void Get() {} +}; + +// Points to the user-set default value for type T. +template +typename DefaultValue::ValueProducer* DefaultValue::producer_ = nullptr; + +// Points to the user-set default value for type T&. +template +T* DefaultValue::address_ = nullptr; + +// Implement this interface to define an action for function type F. +template +class ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + ActionInterface() = default; + virtual ~ActionInterface() = default; + + // Performs the action. This method is not const, as in general an + // action can have side effects and be stateful. For example, a + // get-the-next-element-from-the-collection action will need to + // remember the current element. + virtual Result Perform(const ArgumentTuple& args) = 0; + + private: + ActionInterface(const ActionInterface&) = delete; + ActionInterface& operator=(const ActionInterface&) = delete; +}; + +template +class Action; + +// An Action is a copyable and IMMUTABLE (except by assignment) +// object that represents an action to be taken when a mock function of type +// R(Args...) is called. The implementation of Action is just a +// std::shared_ptr to const ActionInterface. Don't inherit from Action! You +// can view an object implementing ActionInterface as a concrete action +// (including its current state), and an Action object as a handle to it. +template +class Action { + private: + using F = R(Args...); + + // Adapter class to allow constructing Action from a legacy ActionInterface. + // New code should create Actions from functors instead. + struct ActionAdapter { + // Adapter must be copyable to satisfy std::function requirements. + ::std::shared_ptr> impl_; + + template + typename internal::Function::Result operator()(InArgs&&... args) { + return impl_->Perform( + ::std::forward_as_tuple(::std::forward(args)...)); + } + }; + + template + using IsCompatibleFunctor = std::is_constructible, G>; + + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + // Constructs a null Action. Needed for storing Action objects in + // STL containers. + Action() = default; + + // Construct an Action from a specified callable. + // This cannot take std::function directly, because then Action would not be + // directly constructible from lambda (it would require two conversions). + template < + typename G, + typename = typename std::enable_if, std::is_constructible, + G>>::value>::type> + Action(G&& fun) { // NOLINT + Init(::std::forward(fun), IsCompatibleFunctor()); + } + + // Constructs an Action from its implementation. + explicit Action(ActionInterface* impl) + : fun_(ActionAdapter{::std::shared_ptr>(impl)}) {} + + // This constructor allows us to turn an Action object into an + // Action, as long as F's arguments can be implicitly converted + // to Func's and Func's return type can be implicitly converted to F's. + template + Action(const Action& action) // NOLINT + : fun_(action.fun_) {} + + // Returns true if and only if this is the DoDefault() action. + bool IsDoDefault() const { return fun_ == nullptr; } + + // Performs the action. Note that this method is const even though + // the corresponding method in ActionInterface is not. The reason + // is that a const Action means that it cannot be re-bound to + // another concrete action, not that the concrete action it binds to + // cannot change state. (Think of the difference between a const + // pointer and a pointer to const.) + Result Perform(ArgumentTuple args) const { + if (IsDoDefault()) { + internal::IllegalDoDefault(__FILE__, __LINE__); + } + return internal::Apply(fun_, ::std::move(args)); + } + + // An action can be used as a OnceAction, since it's obviously safe to call it + // once. + operator OnceAction() const { // NOLINT + // Return a OnceAction-compatible callable that calls Perform with the + // arguments it is provided. We could instead just return fun_, but then + // we'd need to handle the IsDoDefault() case separately. + struct OA { + Action action; + + R operator()(Args... args) && { + return action.Perform( + std::forward_as_tuple(std::forward(args)...)); + } + }; + + return OA{*this}; + } + + private: + template + friend class Action; + + template + void Init(G&& g, ::std::true_type) { + fun_ = ::std::forward(g); + } + + template + void Init(G&& g, ::std::false_type) { + fun_ = IgnoreArgs::type>{::std::forward(g)}; + } + + template + struct IgnoreArgs { + template + Result operator()(const InArgs&...) const { + return function_impl(); + } + + FunctionImpl function_impl; + }; + + // fun_ is an empty function if and only if this is the DoDefault() action. + ::std::function fun_; +}; + +// The PolymorphicAction class template makes it easy to implement a +// polymorphic action (i.e. an action that can be used in mock +// functions of than one type, e.g. Return()). +// +// To define a polymorphic action, a user first provides a COPYABLE +// implementation class that has a Perform() method template: +// +// class FooAction { +// public: +// template +// Result Perform(const ArgumentTuple& args) const { +// // Processes the arguments and returns a result, using +// // std::get(args) to get the N-th (0-based) argument in the tuple. +// } +// ... +// }; +// +// Then the user creates the polymorphic action using +// MakePolymorphicAction(object) where object has type FooAction. See +// the definition of Return(void) and SetArgumentPointee(value) for +// complete examples. +template +class PolymorphicAction { + public: + explicit PolymorphicAction(const Impl& impl) : impl_(impl) {} + + template + operator Action() const { + return Action(new MonomorphicImpl(impl_)); + } + + private: + template + class MonomorphicImpl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} + + Result Perform(const ArgumentTuple& args) override { + return impl_.template Perform(args); + } + + private: + Impl impl_; + }; + + Impl impl_; +}; + +// Creates an Action from its implementation and returns it. The +// created Action object owns the implementation. +template +Action MakeAction(ActionInterface* impl) { + return Action(impl); +} + +// Creates a polymorphic action from its implementation. This is +// easier to use than the PolymorphicAction constructor as it +// doesn't require you to explicitly write the template argument, e.g. +// +// MakePolymorphicAction(foo); +// vs +// PolymorphicAction(foo); +template +inline PolymorphicAction MakePolymorphicAction(const Impl& impl) { + return PolymorphicAction(impl); +} + +namespace internal { + +// Helper struct to specialize ReturnAction to execute a move instead of a copy +// on return. Useful for move-only types, but could be used on any type. +template +struct ByMoveWrapper { + explicit ByMoveWrapper(T value) : payload(std::move(value)) {} + T payload; +}; + +// The general implementation of Return(R). Specializations follow below. +template +class ReturnAction final { + public: + explicit ReturnAction(R value) : value_(std::move(value)) {} + + template >, // + negation>, // + std::is_convertible, // + std::is_move_constructible>::value>::type> + operator OnceAction() && { // NOLINT + return Impl(std::move(value_)); + } + + template >, // + negation>, // + std::is_convertible, // + std::is_copy_constructible>::value>::type> + operator Action() const { // NOLINT + return Impl(value_); + } + + private: + // Implements the Return(x) action for a mock function that returns type U. + template + class Impl final { + public: + // The constructor used when the return value is allowed to move from the + // input value (i.e. we are converting to OnceAction). + explicit Impl(R&& input_value) + : state_(new State(std::move(input_value))) {} + + // The constructor used when the return value is not allowed to move from + // the input value (i.e. we are converting to Action). + explicit Impl(const R& input_value) : state_(new State(input_value)) {} + + U operator()() && { return std::move(state_->value); } + U operator()() const& { return state_->value; } + + private: + // We put our state on the heap so that the compiler-generated copy/move + // constructors work correctly even when U is a reference-like type. This is + // necessary only because we eagerly create State::value (see the note on + // that symbol for details). If we instead had only the input value as a + // member then the default constructors would work fine. + // + // For example, when R is std::string and U is std::string_view, value is a + // reference to the string backed by input_value. The copy constructor would + // copy both, so that we wind up with a new input_value object (with the + // same contents) and a reference to the *old* input_value object rather + // than the new one. + struct State { + explicit State(const R& input_value_in) + : input_value(input_value_in), + // Make an implicit conversion to Result before initializing the U + // object we store, avoiding calling any explicit constructor of U + // from R. + // + // This simulates the language rules: a function with return type U + // that does `return R()` requires R to be implicitly convertible to + // U, and uses that path for the conversion, even U Result has an + // explicit constructor from R. + value(ImplicitCast_(internal::as_const(input_value))) {} + + // As above, but for the case where we're moving from the ReturnAction + // object because it's being used as a OnceAction. + explicit State(R&& input_value_in) + : input_value(std::move(input_value_in)), + // For the same reason as above we make an implicit conversion to U + // before initializing the value. + // + // Unlike above we provide the input value as an rvalue to the + // implicit conversion because this is a OnceAction: it's fine if it + // wants to consume the input value. + value(ImplicitCast_(std::move(input_value))) {} + + // A copy of the value originally provided by the user. We retain this in + // addition to the value of the mock function's result type below in case + // the latter is a reference-like type. See the std::string_view example + // in the documentation on Return. + R input_value; + + // The value we actually return, as the type returned by the mock function + // itself. + // + // We eagerly initialize this here, rather than lazily doing the implicit + // conversion automatically each time Perform is called, for historical + // reasons: in 2009-11, commit a070cbd91c (Google changelist 13540126) + // made the Action conversion operator eagerly convert the R value to + // U, but without keeping the R alive. This broke the use case discussed + // in the documentation for Return, making reference-like types such as + // std::string_view not safe to use as U where the input type R is a + // value-like type such as std::string. + // + // The example the commit gave was not very clear, nor was the issue + // thread (https://github.com/google/googlemock/issues/86), but it seems + // the worry was about reference-like input types R that flatten to a + // value-like type U when being implicitly converted. An example of this + // is std::vector::reference, which is often a proxy type with an + // reference to the underlying vector: + // + // // Helper method: have the mock function return bools according + // // to the supplied script. + // void SetActions(MockFunction& mock, + // const std::vector& script) { + // for (size_t i = 0; i < script.size(); ++i) { + // EXPECT_CALL(mock, Call(i)).WillOnce(Return(script[i])); + // } + // } + // + // TEST(Foo, Bar) { + // // Set actions using a temporary vector, whose operator[] + // // returns proxy objects that references that will be + // // dangling once the call to SetActions finishes and the + // // vector is destroyed. + // MockFunction mock; + // SetActions(mock, {false, true}); + // + // EXPECT_FALSE(mock.AsStdFunction()(0)); + // EXPECT_TRUE(mock.AsStdFunction()(1)); + // } + // + // This eager conversion helps with a simple case like this, but doesn't + // fully make these types work in general. For example the following still + // uses a dangling reference: + // + // TEST(Foo, Baz) { + // MockFunction()> mock; + // + // // Return the same vector twice, and then the empty vector + // // thereafter. + // auto action = Return(std::initializer_list{ + // "taco", "burrito", + // }); + // + // EXPECT_CALL(mock, Call) + // .WillOnce(action) + // .WillOnce(action) + // .WillRepeatedly(Return(std::vector{})); + // + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), IsEmpty()); + // } + // + U value; + }; + + const std::shared_ptr state_; + }; + + R value_; +}; + +// A specialization of ReturnAction when R is ByMoveWrapper for some T. +// +// This version applies the type system-defeating hack of moving from T even in +// the const call operator, checking at runtime that it isn't called more than +// once, since the user has declared their intent to do so by using ByMove. +template +class ReturnAction> final { + public: + explicit ReturnAction(ByMoveWrapper wrapper) + : state_(new State(std::move(wrapper.payload))) {} + + T operator()() const { + GTEST_CHECK_(!state_->called) + << "A ByMove() action must be performed at most once."; + + state_->called = true; + return std::move(state_->value); + } + + private: + // We store our state on the heap so that we are copyable as required by + // Action, despite the fact that we are stateful and T may not be copyable. + struct State { + explicit State(T&& value_in) : value(std::move(value_in)) {} + + T value; + bool called = false; + }; + + const std::shared_ptr state_; +}; + +// Implements the ReturnNull() action. +class ReturnNullAction { + public: + // Allows ReturnNull() to be used in any pointer-returning function. In C++11 + // this is enforced by returning nullptr, and in non-C++11 by asserting a + // pointer type on compile time. + template + static Result Perform(const ArgumentTuple&) { + return nullptr; + } +}; + +// Implements the Return() action. +class ReturnVoidAction { + public: + // Allows Return() to be used in any void-returning function. + template + static void Perform(const ArgumentTuple&) { + static_assert(std::is_void::value, "Result should be void."); + } +}; + +// Implements the polymorphic ReturnRef(x) action, which can be used +// in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefAction { + public: + // Constructs a ReturnRefAction object from the reference to be returned. + explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT + + // This template type conversion operator allows ReturnRef(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRef(x) when Return(x) + // should be used, and generates some helpful error message. + static_assert(std::is_reference::value, + "use Return instead of ReturnRef to return a value"); + return Action(new Impl(ref_)); + } + + private: + // Implements the ReturnRef(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(T& ref) : ref_(ref) {} // NOLINT + + Result Perform(const ArgumentTuple&) override { return ref_; } + + private: + T& ref_; + }; + + T& ref_; +}; + +// Implements the polymorphic ReturnRefOfCopy(x) action, which can be +// used in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefOfCopyAction { + public: + // Constructs a ReturnRefOfCopyAction object from the reference to + // be returned. + explicit ReturnRefOfCopyAction(const T& value) : value_(value) {} // NOLINT + + // This template type conversion operator allows ReturnRefOfCopy(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRefOfCopy(x) when Return(x) + // should be used, and generates some helpful error message. + static_assert(std::is_reference::value, + "use Return instead of ReturnRefOfCopy to return a value"); + return Action(new Impl(value_)); + } + + private: + // Implements the ReturnRefOfCopy(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const T& value) : value_(value) {} // NOLINT + + Result Perform(const ArgumentTuple&) override { return value_; } + + private: + T value_; + }; + + const T value_; +}; + +// Implements the polymorphic ReturnRoundRobin(v) action, which can be +// used in any function that returns the element_type of v. +template +class ReturnRoundRobinAction { + public: + explicit ReturnRoundRobinAction(std::vector values) { + GTEST_CHECK_(!values.empty()) + << "ReturnRoundRobin requires at least one element."; + state_->values = std::move(values); + } + + template + T operator()(Args&&...) const { + return state_->Next(); + } + + private: + struct State { + T Next() { + T ret_val = values[i++]; + if (i == values.size()) i = 0; + return ret_val; + } + + std::vector values; + size_t i = 0; + }; + std::shared_ptr state_ = std::make_shared(); +}; + +// Implements the polymorphic DoDefault() action. +class DoDefaultAction { + public: + // This template type conversion operator allows DoDefault() to be + // used in any function. + template + operator Action() const { + return Action(); + } // NOLINT +}; + +// Implements the Assign action to set a given pointer referent to a +// particular value. +template +class AssignAction { + public: + AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {} + + template + void Perform(const ArgumentTuple& /* args */) const { + *ptr_ = value_; + } + + private: + T1* const ptr_; + const T2 value_; +}; + +#ifndef GTEST_OS_WINDOWS_MOBILE + +// Implements the SetErrnoAndReturn action to simulate return from +// various system calls and libc functions. +template +class SetErrnoAndReturnAction { + public: + SetErrnoAndReturnAction(int errno_value, T result) + : errno_(errno_value), result_(result) {} + template + Result Perform(const ArgumentTuple& /* args */) const { + errno = errno_; + return result_; + } + + private: + const int errno_; + const T result_; +}; + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Implements the SetArgumentPointee(x) action for any function +// whose N-th argument (0-based) is a pointer to x's type. +template +struct SetArgumentPointeeAction { + A value; + + template + void operator()(const Args&... args) const { + *::std::get(std::tie(args...)) = value; + } +}; + +// Implements the Invoke(object_ptr, &Class::Method) action. +template +struct InvokeMethodAction { + Class* const obj_ptr; + const MethodPtr method_ptr; + + template + auto operator()(Args&&... args) const + -> decltype((obj_ptr->*method_ptr)(std::forward(args)...)) { + return (obj_ptr->*method_ptr)(std::forward(args)...); + } +}; + +// Implements the InvokeWithoutArgs(f) action. The template argument +// FunctionImpl is the implementation type of f, which can be either a +// function pointer or a functor. InvokeWithoutArgs(f) can be used as an +// Action as long as f's type is compatible with F. +template +struct InvokeWithoutArgsAction { + FunctionImpl function_impl; + + // Allows InvokeWithoutArgs(f) to be used as any action whose type is + // compatible with f. + template + auto operator()(const Args&...) -> decltype(function_impl()) { + return function_impl(); + } +}; + +// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action. +template +struct InvokeMethodWithoutArgsAction { + Class* const obj_ptr; + const MethodPtr method_ptr; + + using ReturnType = + decltype((std::declval()->*std::declval())()); + + template + ReturnType operator()(const Args&...) const { + return (obj_ptr->*method_ptr)(); + } +}; + +// Implements the IgnoreResult(action) action. +template +class IgnoreResultAction { + public: + explicit IgnoreResultAction(const A& action) : action_(action) {} + + template + operator Action() const { + // Assert statement belongs here because this is the best place to verify + // conditions on F. It produces the clearest error messages + // in most compilers. + // Impl really belongs in this scope as a local class but can't + // because MSVC produces duplicate symbols in different translation units + // in this case. Until MS fixes that bug we put Impl into the class scope + // and put the typedef both here (for use in assert statement) and + // in the Impl class. But both definitions must be the same. + typedef typename internal::Function::Result Result; + + // Asserts at compile time that F returns void. + static_assert(std::is_void::value, "Result type should be void."); + + return Action(new Impl(action_)); + } + + private: + template + class Impl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const A& action) : action_(action) {} + + void Perform(const ArgumentTuple& args) override { + // Performs the action and ignores its result. + action_.Perform(args); + } + + private: + // Type OriginalFunction is the same as F except that its return + // type is IgnoredValue. + typedef + typename internal::Function::MakeResultIgnoredValue OriginalFunction; + + const Action action_; + }; + + const A action_; +}; + +template +struct WithArgsAction { + InnerAction inner_action; + + // The signature of the function as seen by the inner action, given an out + // action with the given result and argument types. + template + using InnerSignature = + R(typename std::tuple_element>::type...); + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + struct OA { + OnceAction> inner_action; + + R operator()(Args&&... args) && { + return std::move(inner_action) + .Call(std::get( + std::forward_as_tuple(std::forward(args)...))...); + } + }; + + return OA{std::move(inner_action)}; + } + + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> + operator Action() const { // NOLINT + Action> converted(inner_action); + + return [converted](Args&&... args) -> R { + return converted.Perform(std::forward_as_tuple( + std::get(std::forward_as_tuple(std::forward(args)...))...)); + }; + } +}; + +template +class DoAllAction; + +// Base case: only a single action. +template +class DoAllAction { + public: + struct UserConstructorTag {}; + + template + explicit DoAllAction(UserConstructorTag, T&& action) + : final_action_(std::forward(action)) {} + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + // We support conversion to OnceAction whenever the sub-action does. + template >::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return std::move(final_action_); + } + + // We also support conversion to OnceAction whenever the sub-action supports + // conversion to Action (since any Action can also be a OnceAction). + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + negation< + std::is_convertible>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return Action(std::move(final_action_)); + } + + // We support conversion to Action whenever the sub-action does. + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>::value, + int>::type = 0> + operator Action() const { // NOLINT + return final_action_; + } + + private: + FinalAction final_action_; +}; + +// Recursive case: support N actions by calling the initial action and then +// calling through to the base class containing N-1 actions. +template +class DoAllAction + : private DoAllAction { + private: + using Base = DoAllAction; + + // The type of reference that should be provided to an initial action for a + // mocked function parameter of type T. + // + // There are two quirks here: + // + // * Unlike most forwarding functions, we pass scalars through by value. + // This isn't strictly necessary because an lvalue reference would work + // fine too and be consistent with other non-reference types, but it's + // perhaps less surprising. + // + // For example if the mocked function has signature void(int), then it + // might seem surprising for the user's initial action to need to be + // convertible to Action. This is perhaps less + // surprising for a non-scalar type where there may be a performance + // impact, or it might even be impossible, to pass by value. + // + // * More surprisingly, `const T&` is often not a const reference type. + // By the reference collapsing rules in C++17 [dcl.ref]/6, if T refers to + // U& or U&& for some non-scalar type U, then InitialActionArgType is + // U&. In other words, we may hand over a non-const reference. + // + // So for example, given some non-scalar type Obj we have the following + // mappings: + // + // T InitialActionArgType + // ------- ----------------------- + // Obj const Obj& + // Obj& Obj& + // Obj&& Obj& + // const Obj const Obj& + // const Obj& const Obj& + // const Obj&& const Obj& + // + // In other words, the initial actions get a mutable view of an non-scalar + // argument if and only if the mock function itself accepts a non-const + // reference type. They are never given an rvalue reference to an + // non-scalar type. + // + // This situation makes sense if you imagine use with a matcher that is + // designed to write through a reference. For example, if the caller wants + // to fill in a reference argument and then return a canned value: + // + // EXPECT_CALL(mock, Call) + // .WillOnce(DoAll(SetArgReferee<0>(17), Return(19))); + // + template + using InitialActionArgType = + typename std::conditional::value, T, const T&>::type; + + public: + struct UserConstructorTag {}; + + template + explicit DoAllAction(UserConstructorTag, T&& initial_action, + U&&... other_actions) + : Base({}, std::forward(other_actions)...), + initial_action_(std::forward(initial_action)) {} + + // We support conversion to OnceAction whenever both the initial action and + // the rest support conversion to OnceAction. + template < + typename R, typename... Args, + typename std::enable_if< + conjunction...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + OnceAction...)> initial_action; + OnceAction remaining_actions; + + R operator()(Args... args) && { + std::move(initial_action) + .Call(static_cast>(args)...); + + return std::move(remaining_actions).Call(std::forward(args)...); + } + }; + + return OA{ + std::move(initial_action_), + std::move(static_cast(*this)), + }; + } + + // We also support conversion to OnceAction whenever the initial action + // supports conversion to Action (since any Action can also be a OnceAction). + // + // The remaining sub-actions must also be compatible, but we don't need to + // special case them because the base class deals with them. + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + negation...)>>>, + std::is_convertible...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return DoAll( + Action...)>(std::move(initial_action_)), + std::move(static_cast(*this))); + } + + // We support conversion to Action whenever both the initial action and the + // rest support conversion to Action. + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + std::is_convertible...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator Action() const { // NOLINT + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + Action...)> initial_action; + Action remaining_actions; + + R operator()(Args... args) const { + initial_action.Perform(std::forward_as_tuple( + static_cast>(args)...)); + + return remaining_actions.Perform( + std::forward_as_tuple(std::forward(args)...)); + } + }; + + return OA{ + initial_action_, + static_cast(*this), + }; + } + + private: + InitialAction initial_action_; +}; + +template +struct ReturnNewAction { + T* operator()() const { + return internal::Apply( + [](const Params&... unpacked_params) { + return new T(unpacked_params...); + }, + params); + } + std::tuple params; +}; + +template +struct ReturnArgAction { + template ::type> + auto operator()(Args&&... args) const + -> decltype(std::get( + std::forward_as_tuple(std::forward(args)...))) { + return std::get(std::forward_as_tuple(std::forward(args)...)); + } +}; + +template +struct SaveArgAction { + Ptr pointer; + + template + void operator()(const Args&... args) const { + *pointer = std::get(std::tie(args...)); + } +}; + +template +struct SaveArgPointeeAction { + Ptr pointer; + + template + void operator()(const Args&... args) const { + *pointer = *std::get(std::tie(args...)); + } +}; + +template +struct SetArgRefereeAction { + T value; + + template + void operator()(Args&&... args) const { + using argk_type = + typename ::std::tuple_element>::type; + static_assert(std::is_lvalue_reference::value, + "Argument must be a reference type."); + std::get(std::tie(args...)) = value; + } +}; + +template +struct SetArrayArgumentAction { + I1 first; + I2 last; + + template + void operator()(const Args&... args) const { + auto value = std::get(std::tie(args...)); + for (auto it = first; it != last; ++it, (void)++value) { + *value = *it; + } + } +}; + +template +struct DeleteArgAction { + template + void operator()(const Args&... args) const { + delete std::get(std::tie(args...)); + } +}; + +template +struct ReturnPointeeAction { + Ptr pointer; + template + auto operator()(const Args&...) const -> decltype(*pointer) { + return *pointer; + } +}; + +#if GTEST_HAS_EXCEPTIONS +template +struct ThrowAction { + T exception; + // We use a conversion operator to adapt to any return type. + template + operator Action() const { // NOLINT + T copy = exception; + return [copy](Args...) -> R { throw copy; }; + } +}; +struct RethrowAction { + std::exception_ptr exception; + template + operator Action() const { // NOLINT + return [ex = exception](Args...) -> R { std::rethrow_exception(ex); }; + } +}; +#endif // GTEST_HAS_EXCEPTIONS + +} // namespace internal + +// An Unused object can be implicitly constructed from ANY value. +// This is handy when defining actions that ignore some or all of the +// mock function arguments. For example, given +// +// MOCK_METHOD3(Foo, double(const string& label, double x, double y)); +// MOCK_METHOD3(Bar, double(int index, double x, double y)); +// +// instead of +// +// double DistanceToOriginWithLabel(const string& label, double x, double y) { +// return sqrt(x*x + y*y); +// } +// double DistanceToOriginWithIndex(int index, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)) +// .WillOnce(Invoke(DistanceToOriginWithLabel)); +// EXPECT_CALL(mock, Bar(5, _, _)) +// .WillOnce(Invoke(DistanceToOriginWithIndex)); +// +// you could write +// +// // We can declare any uninteresting argument as Unused. +// double DistanceToOrigin(Unused, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin)); +// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin)); +typedef internal::IgnoredValue Unused; + +// Creates an action that does actions a1, a2, ..., sequentially in +// each invocation. All but the last action will have a readonly view of the +// arguments. +template +internal::DoAllAction::type...> DoAll( + Action&&... action) { + return internal::DoAllAction::type...>( + {}, std::forward(action)...); +} + +// WithArg(an_action) creates an action that passes the k-th +// (0-based) argument of the mock function to an_action and performs +// it. It adapts an action accepting one argument to one that accepts +// multiple arguments. For convenience, we also provide +// WithArgs(an_action) (defined below) as a synonym. +template +internal::WithArgsAction::type, k> WithArg( + InnerAction&& action) { + return {std::forward(action)}; +} + +// WithArgs(an_action) creates an action that passes +// the selected arguments of the mock function to an_action and +// performs it. It serves as an adaptor between actions with +// different argument lists. +template +internal::WithArgsAction::type, k, ks...> +WithArgs(InnerAction&& action) { + return {std::forward(action)}; +} + +// WithoutArgs(inner_action) can be used in a mock function with a +// non-empty argument list to perform inner_action, which takes no +// argument. In other words, it adapts an action accepting no +// argument to one that accepts (and ignores) arguments. +template +internal::WithArgsAction::type> WithoutArgs( + InnerAction&& action) { + return {std::forward(action)}; +} + +// Creates an action that returns a value. +// +// The returned type can be used with a mock function returning a non-void, +// non-reference type U as follows: +// +// * If R is convertible to U and U is move-constructible, then the action can +// be used with WillOnce. +// +// * If const R& is convertible to U and U is copy-constructible, then the +// action can be used with both WillOnce and WillRepeatedly. +// +// The mock expectation contains the R value from which the U return value is +// constructed (a move/copy of the argument to Return). This means that the R +// value will survive at least until the mock object's expectations are cleared +// or the mock object is destroyed, meaning that U can safely be a +// reference-like type such as std::string_view: +// +// // The mock function returns a view of a copy of the string fed to +// // Return. The view is valid even after the action is performed. +// MockFunction mock; +// EXPECT_CALL(mock, Call).WillOnce(Return(std::string("taco"))); +// const std::string_view result = mock.AsStdFunction()(); +// EXPECT_EQ("taco", result); +// +template +internal::ReturnAction Return(R value) { + return internal::ReturnAction(std::move(value)); +} + +// Creates an action that returns NULL. +inline PolymorphicAction ReturnNull() { + return MakePolymorphicAction(internal::ReturnNullAction()); +} + +// Creates an action that returns from a void function. +inline PolymorphicAction Return() { + return MakePolymorphicAction(internal::ReturnVoidAction()); +} + +// Creates an action that returns the reference to a variable. +template +inline internal::ReturnRefAction ReturnRef(R& x) { // NOLINT + return internal::ReturnRefAction(x); +} + +// Prevent using ReturnRef on reference to temporary. +template +internal::ReturnRefAction ReturnRef(R&&) = delete; + +// Creates an action that returns the reference to a copy of the +// argument. The copy is created when the action is constructed and +// lives as long as the action. +template +inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { + return internal::ReturnRefOfCopyAction(x); +} + +// DEPRECATED: use Return(x) directly with WillOnce. +// +// Modifies the parent action (a Return() action) to perform a move of the +// argument instead of a copy. +// Return(ByMove()) actions can only be executed once and will assert this +// invariant. +template +internal::ByMoveWrapper ByMove(R x) { + return internal::ByMoveWrapper(std::move(x)); +} + +// Creates an action that returns an element of `vals`. Calling this action will +// repeatedly return the next value from `vals` until it reaches the end and +// will restart from the beginning. +template +internal::ReturnRoundRobinAction ReturnRoundRobin(std::vector vals) { + return internal::ReturnRoundRobinAction(std::move(vals)); +} + +// Creates an action that returns an element of `vals`. Calling this action will +// repeatedly return the next value from `vals` until it reaches the end and +// will restart from the beginning. +template +internal::ReturnRoundRobinAction ReturnRoundRobin( + std::initializer_list vals) { + return internal::ReturnRoundRobinAction(std::vector(vals)); +} + +// Creates an action that does the default action for the give mock function. +inline internal::DoDefaultAction DoDefault() { + return internal::DoDefaultAction(); +} + +// Creates an action that sets the variable pointed by the N-th +// (0-based) function argument to 'value'. +template +internal::SetArgumentPointeeAction SetArgPointee(T value) { + return {std::move(value)}; +} + +// The following version is DEPRECATED. +template +internal::SetArgumentPointeeAction SetArgumentPointee(T value) { + return {std::move(value)}; +} + +// Creates an action that sets a pointer referent to a given value. +template +PolymorphicAction> Assign(T1* ptr, T2 val) { + return MakePolymorphicAction(internal::AssignAction(ptr, val)); +} + +#ifndef GTEST_OS_WINDOWS_MOBILE + +// Creates an action that sets errno and returns the appropriate error. +template +PolymorphicAction> SetErrnoAndReturn( + int errval, T result) { + return MakePolymorphicAction( + internal::SetErrnoAndReturnAction(errval, result)); +} + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Various overloads for Invoke(). + +// Legacy function. +// Actions can now be implicitly constructed from callables. No need to create +// wrapper objects. +// This function exists for backwards compatibility. +template +typename std::decay::type Invoke(FunctionImpl&& function_impl) { + return std::forward(function_impl); +} + +// Creates an action that invokes the given method on the given object +// with the mock function's arguments. +template +internal::InvokeMethodAction Invoke(Class* obj_ptr, + MethodPtr method_ptr) { + return {obj_ptr, method_ptr}; +} + +// Creates an action that invokes 'function_impl' with no argument. +template +internal::InvokeWithoutArgsAction::type> +InvokeWithoutArgs(FunctionImpl function_impl) { + return {std::move(function_impl)}; +} + +// Creates an action that invokes the given method on the given object +// with no argument. +template +internal::InvokeMethodWithoutArgsAction InvokeWithoutArgs( + Class* obj_ptr, MethodPtr method_ptr) { + return {obj_ptr, method_ptr}; +} + +// Creates an action that performs an_action and throws away its +// result. In other words, it changes the return type of an_action to +// void. an_action MUST NOT return void, or the code won't compile. +template +inline internal::IgnoreResultAction IgnoreResult(const A& an_action) { + return internal::IgnoreResultAction(an_action); +} + +// Creates a reference wrapper for the given L-value. If necessary, +// you can explicitly specify the type of the reference. For example, +// suppose 'derived' is an object of type Derived, ByRef(derived) +// would wrap a Derived&. If you want to wrap a const Base& instead, +// where Base is a base class of Derived, just write: +// +// ByRef(derived) +// +// N.B. ByRef is redundant with std::ref, std::cref and std::reference_wrapper. +// However, it may still be used for consistency with ByMove(). +template +inline ::std::reference_wrapper ByRef(T& l_value) { // NOLINT + return ::std::reference_wrapper(l_value); +} + +// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new +// instance of type T, constructed on the heap with constructor arguments +// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. +template +internal::ReturnNewAction::type...> ReturnNew( + Params&&... params) { + return {std::forward_as_tuple(std::forward(params)...)}; +} + +// Action ReturnArg() returns the k-th argument of the mock function. +template +internal::ReturnArgAction ReturnArg() { + return {}; +} + +// Action SaveArg(pointer) saves the k-th (0-based) argument of the +// mock function to *pointer. +template +internal::SaveArgAction SaveArg(Ptr pointer) { + return {pointer}; +} + +// Action SaveArgPointee(pointer) saves the value pointed to +// by the k-th (0-based) argument of the mock function to *pointer. +template +internal::SaveArgPointeeAction SaveArgPointee(Ptr pointer) { + return {pointer}; +} + +// Action SetArgReferee(value) assigns 'value' to the variable +// referenced by the k-th (0-based) argument of the mock function. +template +internal::SetArgRefereeAction::type> SetArgReferee( + T&& value) { + return {std::forward(value)}; +} + +// Action SetArrayArgument(first, last) copies the elements in +// source range [first, last) to the array pointed to by the k-th +// (0-based) argument, which can be either a pointer or an +// iterator. The action does not take ownership of the elements in the +// source range. +template +internal::SetArrayArgumentAction SetArrayArgument(I1 first, + I2 last) { + return {first, last}; +} + +// Action DeleteArg() deletes the k-th (0-based) argument of the mock +// function. +template +internal::DeleteArgAction DeleteArg() { + return {}; +} + +// This action returns the value pointed to by 'pointer'. +template +internal::ReturnPointeeAction ReturnPointee(Ptr pointer) { + return {pointer}; +} + +#if GTEST_HAS_EXCEPTIONS +// Action Throw(exception) can be used in a mock function of any type +// to throw the given exception. Any copyable value can be thrown, +// except for std::exception_ptr, which is likely a mistake if +// thrown directly. +template +typename std::enable_if< + !std::is_base_of::type>::value, + internal::ThrowAction::type>>::type +Throw(T&& exception) { + return {std::forward(exception)}; +} +// Action Rethrow(exception_ptr) can be used in a mock function of any type +// to rethrow any exception_ptr. Note that the same object is thrown each time. +inline internal::RethrowAction Rethrow(std::exception_ptr exception) { + return {std::move(exception)}; +} +#endif // GTEST_HAS_EXCEPTIONS + +namespace internal { + +// A macro from the ACTION* family (defined later in gmock-generated-actions.h) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// Builds an implementation of an Action<> for some particular signature, using +// a class defined by an ACTION* macro. +template +struct ActionImpl; + +template +struct ImplBase { + struct Holder { + // Allows each copy of the Action<> to get to the Impl. + explicit operator const Impl&() const { return *ptr; } + std::shared_ptr ptr; + }; + using type = typename std::conditional::value, + Impl, Holder>::type; +}; + +template +struct ActionImpl : ImplBase::type { + using Base = typename ImplBase::type; + using function_type = R(Args...); + using args_type = std::tuple; + + ActionImpl() = default; // Only defined if appropriate for Base. + explicit ActionImpl(std::shared_ptr impl) : Base{std::move(impl)} {} + + R operator()(Args&&... arg) const { + static constexpr size_t kMaxArgs = + sizeof...(Args) <= 10 ? sizeof...(Args) : 10; + return Apply(std::make_index_sequence{}, + std::make_index_sequence<10 - kMaxArgs>{}, + args_type{std::forward(arg)...}); + } + + template + R Apply(std::index_sequence, std::index_sequence, + const args_type& args) const { + // Impl need not be specific to the signature of action being implemented; + // only the implementing function body needs to have all of the specific + // types instantiated. Up to 10 of the args that are provided by the + // args_type get passed, followed by a dummy of unspecified type for the + // remainder up to 10 explicit args. + static constexpr ExcessiveArg kExcessArg{}; + return static_cast(*this) + .template gmock_PerformImpl< + /*function_type=*/function_type, /*return_type=*/R, + /*args_type=*/args_type, + /*argN_type=*/ + typename std::tuple_element::type...>( + /*args=*/args, std::get(args)..., + ((void)excess_id, kExcessArg)...); + } +}; + +// Stores a default-constructed Impl as part of the Action<>'s +// std::function<>. The Impl should be trivial to copy. +template +::testing::Action MakeAction() { + return ::testing::Action(ActionImpl()); +} + +// Stores just the one given instance of Impl. +template +::testing::Action MakeAction(std::shared_ptr impl) { + return ::testing::Action(ActionImpl(std::move(impl))); +} + +#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ + , GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ + GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \ + GMOCK_INTERNAL_ARG_UNUSED, , 10) + +#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_ \ + const args_type& args GMOCK_PP_REPEAT(GMOCK_INTERNAL_ARG, , 10) + +#define GMOCK_INTERNAL_TEMPLATE_ARG(i, data, el) , typename arg##i##_type +#define GMOCK_ACTION_TEMPLATE_ARGS_NAMES_ \ + GMOCK_PP_TAIL(GMOCK_PP_REPEAT(GMOCK_INTERNAL_TEMPLATE_ARG, , 10)) + +#define GMOCK_INTERNAL_TYPENAME_PARAM(i, data, param) , typename param##_type +#define GMOCK_ACTION_TYPENAME_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPENAME_PARAM, , params)) + +#define GMOCK_INTERNAL_TYPE_PARAM(i, data, param) , param##_type +#define GMOCK_ACTION_TYPE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_PARAM, , params)) + +#define GMOCK_INTERNAL_TYPE_GVALUE_PARAM(i, data, param) \ + , param##_type gmock_p##i +#define GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_GVALUE_PARAM, , params)) + +#define GMOCK_INTERNAL_GVALUE_PARAM(i, data, param) \ + , std::forward(gmock_p##i) +#define GMOCK_ACTION_GVALUE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GVALUE_PARAM, , params)) + +#define GMOCK_INTERNAL_INIT_PARAM(i, data, param) \ + , param(::std::forward(gmock_p##i)) +#define GMOCK_ACTION_INIT_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_INIT_PARAM, , params)) + +#define GMOCK_INTERNAL_FIELD_PARAM(i, data, param) param##_type param; +#define GMOCK_ACTION_FIELD_PARAMS_(params) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_FIELD_PARAM, , params) + +#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ + template \ + class full_name { \ + public: \ + explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : impl_(std::make_shared( \ + GMOCK_ACTION_GVALUE_PARAMS_(params))) {} \ + full_name(const full_name&) = default; \ + full_name(full_name&&) noexcept = default; \ + template \ + operator ::testing::Action() const { \ + return ::testing::internal::MakeAction(impl_); \ + } \ + \ + private: \ + class gmock_Impl { \ + public: \ + explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : GMOCK_ACTION_INIT_PARAMS_(params) {} \ + template \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_ACTION_FIELD_PARAMS_(params) \ + }; \ + std::shared_ptr impl_; \ + }; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ + return full_name( \ + GMOCK_ACTION_GVALUE_PARAMS_(params)); \ + } \ + template \ + template \ + return_type \ + full_name::gmock_Impl::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +} // namespace internal + +// Similar to GMOCK_INTERNAL_ACTION, but no bound parameters are stored. +#define ACTION(name) \ + class name##Action { \ + public: \ + explicit name##Action() noexcept {} \ + name##Action(const name##Action&) noexcept {} \ + template \ + operator ::testing::Action() const { \ + return ::testing::internal::MakeAction(); \ + } \ + \ + private: \ + class gmock_Impl { \ + public: \ + template \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + }; \ + }; \ + inline name##Action name() GTEST_MUST_USE_RESULT_; \ + inline name##Action name() { return name##Action(); } \ + template \ + return_type name##Action::gmock_Impl::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__)) + +#define ACTION_P2(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP2, (__VA_ARGS__)) + +#define ACTION_P3(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP3, (__VA_ARGS__)) + +#define ACTION_P4(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP4, (__VA_ARGS__)) + +#define ACTION_P5(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP5, (__VA_ARGS__)) + +#define ACTION_P6(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP6, (__VA_ARGS__)) + +#define ACTION_P7(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP7, (__VA_ARGS__)) + +#define ACTION_P8(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP8, (__VA_ARGS__)) + +#define ACTION_P9(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP9, (__VA_ARGS__)) + +#define ACTION_P10(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP10, (__VA_ARGS__)) + +} // namespace testing + +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4100 + +#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-cardinalities.h b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-cardinalities.h new file mode 100644 index 00000000..533e604f --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-cardinalities.h @@ -0,0 +1,159 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used cardinalities. More +// cardinalities can be defined by the user implementing the +// CardinalityInterface interface if necessary. + +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* + +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ + +#include + +#include +#include // NOLINT + +#include "gmock/internal/gmock-port.h" +#include "gtest/gtest.h" + +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + +namespace testing { + +// To implement a cardinality Foo, define: +// 1. a class FooCardinality that implements the +// CardinalityInterface interface, and +// 2. a factory function that creates a Cardinality object from a +// const FooCardinality*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Cardinality objects can now be copied like plain values. + +// The implementation of a cardinality. +class CardinalityInterface { + public: + virtual ~CardinalityInterface() = default; + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + virtual int ConservativeLowerBound() const { return 0; } + virtual int ConservativeUpperBound() const { return INT_MAX; } + + // Returns true if and only if call_count calls will satisfy this + // cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true if and only if call_count calls will saturate this + // cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; +}; + +// A Cardinality is a copyable and IMMUTABLE (except by assignment) +// object that specifies how many times a mock function is expected to +// be called. The implementation of Cardinality is just a std::shared_ptr +// to const CardinalityInterface. Don't inherit from Cardinality! +class GTEST_API_ Cardinality { + public: + // Constructs a null cardinality. Needed for storing Cardinality + // objects in STL containers. + Cardinality() = default; + + // Constructs a Cardinality from its implementation. + explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {} + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); } + int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); } + + // Returns true if and only if call_count calls will satisfy this + // cardinality. + bool IsSatisfiedByCallCount(int call_count) const { + return impl_->IsSatisfiedByCallCount(call_count); + } + + // Returns true if and only if call_count calls will saturate this + // cardinality. + bool IsSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count); + } + + // Returns true if and only if call_count calls will over-saturate this + // cardinality, i.e. exceed the maximum number of allowed calls. + bool IsOverSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count) && + !impl_->IsSatisfiedByCallCount(call_count); + } + + // Describes self to an ostream + void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + // Describes the given actual call count to an ostream. + static void DescribeActualCallCountTo(int actual_call_count, + ::std::ostream* os); + + private: + std::shared_ptr impl_; +}; + +// Creates a cardinality that allows at least n calls. +GTEST_API_ Cardinality AtLeast(int n); + +// Creates a cardinality that allows at most n calls. +GTEST_API_ Cardinality AtMost(int n); + +// Creates a cardinality that allows any number of calls. +GTEST_API_ Cardinality AnyNumber(); + +// Creates a cardinality that allows between min and max calls. +GTEST_API_ Cardinality Between(int min, int max); + +// Creates a cardinality that allows exactly n calls. +GTEST_API_ Cardinality Exactly(int n); + +// Creates a cardinality from its implementation. +inline Cardinality MakeCardinality(const CardinalityInterface* c) { + return Cardinality(c); +} + +} // namespace testing + +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + +#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-function-mocker.h b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-function-mocker.h new file mode 100644 index 00000000..d2cb13cd --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-function-mocker.h @@ -0,0 +1,519 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements MOCK_METHOD. + +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* + +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ + +#include +#include // IWYU pragma: keep +#include // IWYU pragma: keep + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-pp.h" + +namespace testing { +namespace internal { +template +using identity_t = T; + +template +struct ThisRefAdjuster { + template + using AdjustT = typename std::conditional< + std::is_const::type>::value, + typename std::conditional::value, + const T&, const T&&>::type, + typename std::conditional::value, T&, + T&&>::type>::type; + + template + static AdjustT Adjust(const MockType& mock) { + return static_cast>(const_cast(mock)); + } +}; + +constexpr bool PrefixOf(const char* a, const char* b) { + return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1)); +} + +template +constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(prefix, str); +} + +template +constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(suffix, str + M - N); +} + +template +constexpr bool Equals(const char (&a)[N], const char (&b)[M]) { + return N == M && internal::PrefixOf(a, b); +} + +template +constexpr bool ValidateSpec(const char (&spec)[N]) { + return internal::Equals("const", spec) || + internal::Equals("override", spec) || + internal::Equals("final", spec) || + internal::Equals("noexcept", spec) || + (internal::StartsWith("noexcept(", spec) && + internal::EndsWith(")", spec)) || + internal::Equals("ref(&)", spec) || + internal::Equals("ref(&&)", spec) || + (internal::StartsWith("Calltype(", spec) && + internal::EndsWith(")", spec)); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; +} // namespace testing + +#define MOCK_METHOD(...) \ + GMOCK_INTERNAL_WARNING_PUSH() \ + GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \ + GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) \ + GMOCK_INTERNAL_WARNING_POP() + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ + GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ + GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ + GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ + GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_REF_SPEC(_Spec), \ + (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_WRONG_ARITY(...) \ + static_assert( \ + false, \ + "MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \ + "_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \ + "enclosed in parentheses. If _Ret is a type with unprotected commas, " \ + "it must also be enclosed in parentheses.") + +#define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \ + static_assert( \ + GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \ + GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.") + +#define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \ + static_assert( \ + std::is_function<__VA_ARGS__>::value, \ + "Signature must be a function type, maybe return type contains " \ + "unprotected comma."); \ + static_assert( \ + ::testing::tuple_size::ArgumentTuple>::value == _N, \ + "This method does not take " GMOCK_PP_STRINGIZE( \ + _N) " arguments. Parenthesize all types with unprotected commas.") + +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec) + +#define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \ + _Override, _Final, _NoexceptSpec, \ + _CallType, _RefSpec, _Signature) \ + typename ::testing::internal::Function::Result \ + GMOCK_INTERNAL_EXPAND(_CallType) \ + _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ + GMOCK_PP_IF(_Constness, const, ) \ + _RefSpec _NoexceptSpec GMOCK_PP_IF(_Override, override, ) \ + GMOCK_PP_IF(_Final, final, ) { \ + GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .SetOwnerAndName(this, #_MethodName); \ + return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \ + } \ + ::testing::MockSpec gmock_##_MethodName( \ + GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \ + GMOCK_PP_IF(_Constness, const, ) _RefSpec { \ + GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \ + return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \ + } \ + ::testing::MockSpec gmock_##_MethodName( \ + const ::testing::internal::WithoutMatchers&, \ + GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \ + GMOCK_PP_REMOVE_PARENS(_Signature)>*) const _RefSpec _NoexceptSpec { \ + return ::testing::internal::ThisRefAdjuster::Adjust(*this) \ + .gmock_##_MethodName(GMOCK_PP_REPEAT( \ + GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ + } \ + mutable ::testing::FunctionMocker \ + GMOCK_MOCKER_(_N, _Constness, _MethodName) + +#define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ + +// Valid modifiers. +#define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ + GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) + +#define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \ + GMOCK_PP_HAS_COMMA( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple)) + +#define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \ + GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple)) + +#define GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT, ~, _Tuple) + +#define GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT(_i, _, _elem) \ + GMOCK_PP_IF( \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \ + _elem, ) + +#define GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE, ~, _Tuple) + +#define GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_IF( \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem)), \ + GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) + +#define GMOCK_INTERNAL_GET_REF_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_REF_SPEC_IF_REF, ~, _Tuple) + +#define GMOCK_INTERNAL_REF_SPEC_IF_REF(_i, _, _elem) \ + GMOCK_PP_IF(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)), \ + GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) + +#ifdef GMOCK_INTERNAL_STRICT_SPEC_ASSERT +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + ::testing::internal::ValidateSpec(GMOCK_PP_STRINGIZE(_elem)), \ + "Token \'" GMOCK_PP_STRINGIZE( \ + _elem) "\' cannot be recognized as a valid specification " \ + "modifier. Is a ',' missing?"); +#else +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem))) == 1, \ + GMOCK_PP_STRINGIZE( \ + _elem) " cannot be recognized as a valid specification modifier."); +#endif // GMOCK_INTERNAL_STRICT_SPEC_ASSERT + +// Modifiers implementation. +#define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_CONST_I_const , + +#define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override , + +#define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_FINAL_I_final , + +#define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept , + +#define GMOCK_INTERNAL_DETECT_REF(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_REF_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_REF_I_ref , + +#define GMOCK_INTERNAL_UNPACK_ref(x) x + +#define GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CALLTYPE_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_CALLTYPE_I_Calltype , + +#define GMOCK_INTERNAL_UNPACK_Calltype(...) __VA_ARGS__ + +// Note: The use of `identity_t` here allows _Ret to represent return types that +// would normally need to be specified in a different way. For example, a method +// returning a function pointer must be written as +// +// fn_ptr_return_t (*method(method_args_t...))(fn_ptr_args_t...) +// +// But we only support placing the return type at the beginning. To handle this, +// we wrap all calls in identity_t, so that a declaration will be expanded to +// +// identity_t method(method_args_t...) +// +// This allows us to work around the syntactic oddities of function/method +// types. +#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ + ::testing::internal::identity_t( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) + +#define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \ + GMOCK_PP_IDENTITY) \ + (_elem) + +#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \ + gmock_a##_i + +#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::std::forward(gmock_a##_i) + +#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_MATCHER_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \ + gmock_a##_i + +#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \ + GMOCK_PP_COMMA_IF(_i) \ + gmock_a##_i + +#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::testing::A() + +#define GMOCK_INTERNAL_ARG_O(_i, ...) \ + typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type + +#define GMOCK_INTERNAL_MATCHER_O(_i, ...) \ + const ::testing::Matcher::template Arg<_i>::type>& + +#define MOCK_METHOD0(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 0, __VA_ARGS__) +#define MOCK_METHOD1(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 1, __VA_ARGS__) +#define MOCK_METHOD2(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 2, __VA_ARGS__) +#define MOCK_METHOD3(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 3, __VA_ARGS__) +#define MOCK_METHOD4(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 4, __VA_ARGS__) +#define MOCK_METHOD5(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 5, __VA_ARGS__) +#define MOCK_METHOD6(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 6, __VA_ARGS__) +#define MOCK_METHOD7(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 7, __VA_ARGS__) +#define MOCK_METHOD8(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 8, __VA_ARGS__) +#define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__) +#define MOCK_METHOD10(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__) + +#define MOCK_CONST_METHOD0(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__) +#define MOCK_CONST_METHOD1(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 1, __VA_ARGS__) +#define MOCK_CONST_METHOD2(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 2, __VA_ARGS__) +#define MOCK_CONST_METHOD3(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 3, __VA_ARGS__) +#define MOCK_CONST_METHOD4(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 4, __VA_ARGS__) +#define MOCK_CONST_METHOD5(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 5, __VA_ARGS__) +#define MOCK_CONST_METHOD6(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 6, __VA_ARGS__) +#define MOCK_CONST_METHOD7(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 7, __VA_ARGS__) +#define MOCK_CONST_METHOD8(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 8, __VA_ARGS__) +#define MOCK_CONST_METHOD9(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 9, __VA_ARGS__) +#define MOCK_CONST_METHOD10(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 10, __VA_ARGS__) + +#define MOCK_METHOD0_T(m, ...) MOCK_METHOD0(m, __VA_ARGS__) +#define MOCK_METHOD1_T(m, ...) MOCK_METHOD1(m, __VA_ARGS__) +#define MOCK_METHOD2_T(m, ...) MOCK_METHOD2(m, __VA_ARGS__) +#define MOCK_METHOD3_T(m, ...) MOCK_METHOD3(m, __VA_ARGS__) +#define MOCK_METHOD4_T(m, ...) MOCK_METHOD4(m, __VA_ARGS__) +#define MOCK_METHOD5_T(m, ...) MOCK_METHOD5(m, __VA_ARGS__) +#define MOCK_METHOD6_T(m, ...) MOCK_METHOD6(m, __VA_ARGS__) +#define MOCK_METHOD7_T(m, ...) MOCK_METHOD7(m, __VA_ARGS__) +#define MOCK_METHOD8_T(m, ...) MOCK_METHOD8(m, __VA_ARGS__) +#define MOCK_METHOD9_T(m, ...) MOCK_METHOD9(m, __VA_ARGS__) +#define MOCK_METHOD10_T(m, ...) MOCK_METHOD10(m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T(m, ...) MOCK_CONST_METHOD0(m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T(m, ...) MOCK_CONST_METHOD1(m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T(m, ...) MOCK_CONST_METHOD2(m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T(m, ...) MOCK_CONST_METHOD3(m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T(m, ...) MOCK_CONST_METHOD4(m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T(m, ...) MOCK_CONST_METHOD5(m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T(m, ...) MOCK_CONST_METHOD6(m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T(m, ...) MOCK_CONST_METHOD7(m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T(m, ...) MOCK_CONST_METHOD8(m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T(m, ...) MOCK_CONST_METHOD9(m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T(m, ...) MOCK_CONST_METHOD10(m, __VA_ARGS__) + +#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 0, __VA_ARGS__) +#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 1, __VA_ARGS__) +#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 2, __VA_ARGS__) +#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 3, __VA_ARGS__) +#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 4, __VA_ARGS__) +#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 5, __VA_ARGS__) +#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 6, __VA_ARGS__) +#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 7, __VA_ARGS__) +#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 8, __VA_ARGS__) +#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 9, __VA_ARGS__) +#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 10, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 0, __VA_ARGS__) +#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 1, __VA_ARGS__) +#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 2, __VA_ARGS__) +#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 3, __VA_ARGS__) +#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 4, __VA_ARGS__) +#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 5, __VA_ARGS__) +#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 6, __VA_ARGS__) +#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 7, __VA_ARGS__) +#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 8, __VA_ARGS__) +#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 9, __VA_ARGS__) +#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 10, __VA_ARGS__) + +#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHODN(constness, ct, Method, args_num, ...) \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + args_num, ::testing::internal::identity_t<__VA_ARGS__>); \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + args_num, Method, GMOCK_PP_NARG0(constness), 0, 0, , ct, , \ + (::testing::internal::identity_t<__VA_ARGS__>)) + +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) + +#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ diff --git a/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-matchers.h b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-matchers.h new file mode 100644 index 00000000..3daf6173 --- /dev/null +++ b/test/ios/iOSUnitTesting/extern/googletest/googlemock/include/gmock/gmock-matchers.h @@ -0,0 +1,5638 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template +// FooMatcherPk +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md +// +// This file also implements some commonly used argument matchers. More +// matchers can be defined by the user implementing the +// MatcherInterface interface if necessary. +// +// See googletest/include/gtest/gtest-matchers.h for the definition of class +// Matcher, class MatcherInterface, and others. + +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* + +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // NOLINT +#include +#include +#include +#include +#include + +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" +#include "gmock/internal/gmock-pp.h" +#include "gtest/gtest.h" + +// MSVC warning C5046 is new as of VS2017 version 15.8. +#if defined(_MSC_VER) && _MSC_VER >= 1915 +#define GMOCK_MAYBE_5046_ 5046 +#else +#define GMOCK_MAYBE_5046_ +#endif + +GTEST_DISABLE_MSC_WARNINGS_PUSH_( + 4251 GMOCK_MAYBE_5046_ /* class A needs to have dll-interface to be used by + clients of class B */ + /* Symbol involving type with internal linkage not defined */) + +namespace testing { + +// To implement a matcher Foo for type T, define: +// 1. a class FooMatcherImpl that implements the +// MatcherInterface interface, and +// 2. a factory function that creates a Matcher object from a +// FooMatcherImpl*. +// +// The two-level delegation design makes it possible to allow a user +// to write "v" instead of "Eq(v)" where a Matcher is expected, which +// is impossible if we pass matchers by pointers. It also eases +// ownership management as Matcher objects can now be copied like +// plain values. + +// A match result listener that stores the explanation in a string. +class StringMatchResultListener : public MatchResultListener { + public: + StringMatchResultListener() : MatchResultListener(&ss_) {} + + // Returns the explanation accumulated so far. + std::string str() const { return ss_.str(); } + + // Clears the explanation accumulated so far. + void Clear() { ss_.str(""); } + + private: + ::std::stringstream ss_; + + StringMatchResultListener(const StringMatchResultListener&) = delete; + StringMatchResultListener& operator=(const StringMatchResultListener&) = + delete; +}; + +// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION +// and MUST NOT BE USED IN USER CODE!!! +namespace internal { + +// The MatcherCastImpl class template is a helper for implementing +// MatcherCast(). We need this helper in order to partially +// specialize the implementation of MatcherCast() (C++ allows +// class/struct templates to be partially specialized, but not +// function templates.). + +// This general version is used when MatcherCast()'s argument is a +// polymorphic matcher (i.e. something that can be converted to a +// Matcher but is not one yet; for example, Eq(value)) or a value (for +// example, "hello"). +template +class MatcherCastImpl { + public: + static Matcher Cast(const M& polymorphic_matcher_or_value) { + // M can be a polymorphic matcher, in which case we want to use + // its conversion operator to create Matcher. Or it can be a value + // that should be passed to the Matcher's constructor. + // + // We can't call Matcher(polymorphic_matcher_or_value) when M is a + // polymorphic matcher because it'll be ambiguous if T has an implicit + // constructor from M (this usually happens when T has an implicit + // constructor from any type). + // + // It won't work to unconditionally implicit_cast + // polymorphic_matcher_or_value to Matcher because it won't trigger + // a user-defined conversion from M to T if one exists (assuming M is + // a value). + return CastImpl(polymorphic_matcher_or_value, + std::is_convertible>{}, + std::is_convertible{}); + } + + private: + template + static Matcher CastImpl(const M& polymorphic_matcher_or_value, + std::true_type /* convertible_to_matcher */, + std::integral_constant) { + // M is implicitly convertible to Matcher, which means that either + // M is a polymorphic matcher or Matcher has an implicit constructor + // from M. In both cases using the implicit conversion will produce a + // matcher. + // + // Even if T has an implicit constructor from M, it won't be called because + // creating Matcher would require a chain of two user-defined conversions + // (first to create T from M and then to create Matcher from T). + return polymorphic_matcher_or_value; + } + + // M can't be implicitly converted to Matcher, so M isn't a polymorphic + // matcher. It's a value of a type implicitly convertible to T. Use direct + // initialization to create a matcher. + static Matcher CastImpl(const M& value, + std::false_type /* convertible_to_matcher */, + std::true_type /* convertible_to_T */) { + return Matcher(ImplicitCast_(value)); + } + + // M can't be implicitly converted to either Matcher or T. Attempt to use + // polymorphic matcher Eq(value) in this case. + // + // Note that we first attempt to perform an implicit cast on the value and + // only fall back to the polymorphic Eq() matcher afterwards because the + // latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end + // which might be undefined even when Rhs is implicitly convertible to Lhs + // (e.g. std::pair vs. std::pair). + // + // We don't define this method inline as we need the declaration of Eq(). + static Matcher CastImpl(const M& value, + std::false_type /* convertible_to_matcher */, + std::false_type /* convertible_to_T */); +}; + +// This more specialized version is used when MatcherCast()'s argument +// is already a Matcher. This only compiles when type T can be +// statically converted to type U. +template +class MatcherCastImpl> { + public: + static Matcher Cast(const Matcher& source_matcher) { + return Matcher(new Impl(source_matcher)); + } + + private: + class Impl : public MatcherInterface { + public: + explicit Impl(const Matcher& source_matcher) + : source_matcher_(source_matcher) {} + + // We delegate the matching logic to the source matcher. + bool MatchAndExplain(T x, MatchResultListener* listener) const override { + using FromType = typename std::remove_cv::type>::type>::type; + using ToType = typename std::remove_cv::type>::type>::type; + // Do not allow implicitly converting base*/& to derived*/&. + static_assert( + // Do not trigger if only one of them is a pointer. That implies a + // regular conversion and not a down_cast. + (std::is_pointer::type>::value != + std::is_pointer::type>::value) || + std::is_same::value || + !std::is_base_of::value, + "Can't implicitly convert from to "); + + // Do the cast to `U` explicitly if necessary. + // Otherwise, let implicit conversions do the trick. + using CastType = + typename std::conditional::value, + T&, U>::type; + + return source_matcher_.MatchAndExplain(static_cast(x), + listener); + } + + void DescribeTo(::std::ostream* os) const override { + source_matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + source_matcher_.DescribeNegationTo(os); + } + + private: + const Matcher source_matcher_; + }; +}; + +// This even more specialized version is used for efficiently casting +// a matcher to its own type. +template +class MatcherCastImpl> { + public: + static Matcher Cast(const Matcher& matcher) { return matcher; } +}; + +// Template specialization for parameterless Matcher. +template +class MatcherBaseImpl { + public: + MatcherBaseImpl() = default; + + template + operator ::testing::Matcher() const { // NOLINT(runtime/explicit) + return ::testing::Matcher(new + typename Derived::template gmock_Impl()); + } +}; + +// Template specialization for Matcher with parameters. +template