diff --git a/admob/integration_test/AndroidManifest.xml b/admob/integration_test/AndroidManifest.xml
new file mode 100644
index 0000000000..0996b3d0df
--- /dev/null
+++ b/admob/integration_test/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/admob/integration_test/CMakeLists.txt b/admob/integration_test/CMakeLists.txt
new file mode 100644
index 0000000000..fdc3fbcd58
--- /dev/null
+++ b/admob/integration_test/CMakeLists.txt
@@ -0,0 +1,224 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Cmake file for a single C++ integration test build.
+
+cmake_minimum_required(VERSION 2.8)
+
+# User settings for Firebase integration tests.
+# Path to Firebase SDK.
+# Try to read the path to the Firebase C++ SDK from an environment variable.
+if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}")
+else()
+ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../cpp_sdk_version.json")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
+ else()
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk")
+ endif()
+endif()
+if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR})
+endif()
+if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR})
+ message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information")
+endif()
+
+# Copy all prerequisite files for integration tests to run.
+if(NOT ANDROID)
+ if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py)
+ # If this is running from inside the SDK directory, run the setup script.
+ execute_process(COMMAND "python" "${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py" "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
+endif()
+
+# Windows runtime mode, either MD or MT depending on whether you are using
+# /MD or /MT. For more information see:
+# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+set(MSVC_RUNTIME_MODE MD)
+
+project(firebase_testapp)
+
+# Integration test source files.
+set(FIREBASE_APP_FRAMEWORK_SRCS
+ src/app_framework.cc
+ src/app_framework.h
+)
+
+set(FIREBASE_TEST_FRAMEWORK_SRCS
+ src/firebase_test_framework.h
+ src/firebase_test_framework.cc
+)
+
+set(FIREBASE_INTEGRATION_TEST_SRCS
+ src/integration_test.cc
+)
+
+# The include directory for the testapp.
+include_directories(src)
+
+# Integration test uses some features that require C++ 11, such as lambdas.
+set (CMAKE_CXX_STANDARD 11)
+
+# Download and unpack googletest (and googlemock) at configure time
+set(GOOGLETEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/external/googletest)
+# Note: Once googletest is downloaded once, it won't be updated or
+# downloaded again unless you delete the "external/googletest"
+# directory.
+if (NOT EXISTS ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ configure_file(googletest.cmake
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/CMakeLists.txt COPYONLY)
+ execute_process(COMMAND ${CMAKE_COMMAND} .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+ endif()
+endif()
+
+if(ANDROID)
+ # Build an Android application.
+
+ # Source files used for the Android build.
+ set(FIREBASE_APP_FRAMEWORK_ANDROID_SRCS
+ src/android/android_app_framework.cc
+ )
+
+ # Source files used for the Android build.
+ set(FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS
+ src/android/android_firebase_test_framework.cc
+ )
+
+ # Build native_app_glue as a static lib
+ add_library(native_app_glue STATIC
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+
+ # Export ANativeActivity_onCreate(),
+ # Refer to: https://github.com/android-ndk/ndk/issues/381.
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
+
+ add_library(gtest STATIC
+ ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ target_include_directories(gtest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include)
+ add_library(gmock STATIC
+ ${GOOGLETEST_ROOT}/src/googlemock/src/gmock-all.cc)
+ target_include_directories(gmock
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googlemock
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include
+ PUBLIC ${GOOGLETEST_ROOT}/src/googlemock/include)
+
+ # Define the target as a shared library, as that is what gradle expects.
+ set(integration_test_target_name "android_integration_test_main")
+ add_library(${integration_test_target_name} SHARED
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_ANDROID_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS}
+ )
+
+ target_include_directories(${integration_test_target_name} PRIVATE
+ ${ANDROID_NDK}/sources/android/native_app_glue)
+
+ set(ADDITIONAL_LIBS log android atomic native_app_glue)
+else()
+ # Build a desktop application.
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+
+ # Prevent overriding the parent project's compiler/linker
+ # settings on Windows
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This defines
+ # the gtest and gtest_main targets.
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/googletest/src
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/build
+ EXCLUDE_FROM_ALL)
+
+ # The gtest/gtest_main targets carry header search path
+ # dependencies automatically when using CMake 2.8.11 or
+ # later. Otherwise we have to add them here ourselves.
+ if (CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories("${gtest_SOURCE_DIR}/include")
+ include_directories("${gmock_SOURCE_DIR}/include")
+ endif()
+
+ # Windows runtime mode, either MD or MT depending on whether you are using
+ # /MD or /MT. For more information see:
+ # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+ set(MSVC_RUNTIME_MODE MD)
+
+ # Platform abstraction layer for the desktop integration test.
+ set(FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS
+ src/desktop/desktop_app_framework.cc
+ )
+
+ set(integration_test_target_name "integration_test")
+ add_executable(${integration_test_target_name}
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ )
+
+ if(APPLE)
+ set(ADDITIONAL_LIBS
+ gssapi_krb5
+ pthread
+ "-framework CoreFoundation"
+ "-framework Foundation"
+ "-framework GSS"
+ "-framework Security"
+ )
+ elseif(MSVC)
+ set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32)
+ else()
+ set(ADDITIONAL_LIBS pthread)
+ endif()
+
+ # If a config file is present, copy it into the binary location so that it's
+ # possible to create the default Firebase app.
+ set(FOUND_JSON_FILE FALSE)
+ foreach(config "google-services-desktop.json" "google-services.json")
+ if (EXISTS ${config})
+ add_custom_command(
+ TARGET ${integration_test_target_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${config} $)
+ set(FOUND_JSON_FILE TRUE)
+ break()
+ endif()
+ endforeach()
+ if(NOT FOUND_JSON_FILE)
+ message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.")
+ endif()
+endif()
+
+# Add the Firebase libraries to the target using the function from the SDK.
+add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
+# Note that firebase_app needs to be last in the list.
+set(firebase_libs firebase_admob firebase_app)
+set(gtest_libs gtest gmock)
+target_link_libraries(${integration_test_target_name} ${firebase_libs}
+ ${gtest_libs} ${ADDITIONAL_LIBS})
diff --git a/admob/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json b/admob/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..d8db8d65fd
--- /dev/null
+++ b/admob/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/admob/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json b/admob/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..6f870a4629
--- /dev/null
+++ b/admob/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,51 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/admob/integration_test/Info.plist b/admob/integration_test/Info.plist
new file mode 100644
index 0000000000..a3e8956703
--- /dev/null
+++ b/admob/integration_test/Info.plist
@@ -0,0 +1,37 @@
+
+
+
+
+ GADApplicationIdentifier
+ ca-app-pub-3940256099942544~1458002511
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ com.google.ios.admob.testapp
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ CFBundleURLTypes
+
+
+ CFBundleURLSchemes
+
+ firebase-game-loop
+
+
+
+
+
diff --git a/admob/integration_test/LaunchScreen.storyboard b/admob/integration_test/LaunchScreen.storyboard
new file mode 100644
index 0000000000..673e0f7e68
--- /dev/null
+++ b/admob/integration_test/LaunchScreen.storyboard
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/admob/integration_test/LibraryManifest.xml b/admob/integration_test/LibraryManifest.xml
new file mode 100644
index 0000000000..e1d761e160
--- /dev/null
+++ b/admob/integration_test/LibraryManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/admob/integration_test/Podfile b/admob/integration_test/Podfile
new file mode 100644
index 0000000000..23b23b5411
--- /dev/null
+++ b/admob/integration_test/Podfile
@@ -0,0 +1,15 @@
+
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+# Firebase AdMob test application.
+
+target 'integration_test' do
+ pod 'Firebase/AdMob', '6.24.0'
+end
+
+post_install do |installer|
+ # If this is running from inside the SDK directory, run the setup script.
+ system("if [[ -r ../../setup_integration_tests.py ]]; then python ../../setup_integration_tests.py .; fi")
+ system("/usr/bin/python ./download_googletest.py")
+end
+
diff --git a/admob/integration_test/build.gradle b/admob/integration_test/build.gradle
new file mode 100644
index 0000000000..1b40229275
--- /dev/null
+++ b/admob/integration_test/build.gradle
@@ -0,0 +1,76 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.google.gms:google-services:4.0.1'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src/android/java']
+ res.srcDirs = ['res']
+ }
+ }
+
+ defaultConfig {
+ applicationId 'com.google.android.admob.testapp'
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ externalNativeBuild.cmake {
+ arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir"
+ }
+ }
+ externalNativeBuild.cmake {
+ path 'CMakeLists.txt'
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFile getDefaultProguardFile('proguard-android.txt')
+ proguardFile file('proguard.pro')
+ }
+ }
+}
+
+apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
+firebaseCpp.dependencies {
+ admob
+}
+
+apply plugin: 'com.google.gms.google-services'
+
+task copyIntegrationTestFiles(type:Exec) {
+ // If this is running form inside the SDK directory, run the setup script.
+ if (project.file('../../setup_integration_tests.py').exists()) {
+ commandLine 'python', '../../setup_integration_tests.py', project.projectDir.toString()
+ }
+ else {
+ commandLine 'echo', ''
+ }
+}
+
+build.dependsOn(copyIntegrationTestFiles)
\ No newline at end of file
diff --git a/admob/integration_test/googletest.cmake b/admob/integration_test/googletest.cmake
new file mode 100644
index 0000000000..2ecbb08679
--- /dev/null
+++ b/admob/integration_test/googletest.cmake
@@ -0,0 +1,34 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Download GoogleTest from GitHub as an external project.
+
+# This CMake file is taken from:
+# https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG master
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/admob/integration_test/gradle/wrapper/gradle-wrapper.jar b/admob/integration_test/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
Binary files /dev/null and b/admob/integration_test/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/admob/integration_test/gradle/wrapper/gradle-wrapper.properties b/admob/integration_test/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..35732b09a0
--- /dev/null
+++ b/admob/integration_test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 27 14:03:45 PST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/admob/integration_test/gradlew b/admob/integration_test/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/admob/integration_test/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/admob/integration_test/gradlew.bat b/admob/integration_test/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/admob/integration_test/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/admob/integration_test/integration_test.xcodeproj/project.pbxproj b/admob/integration_test/integration_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..57e3561511
--- /dev/null
+++ b/admob/integration_test/integration_test.xcodeproj/project.pbxproj
@@ -0,0 +1,409 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; };
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; };
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; };
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; };
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D61C5F8C22BABA9B00A79141 /* Images.xcassets */; };
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D61C5F9222BABAD100A79141 /* integration_test.cc */; };
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D62CCBBF22F367140099BE9F /* gmock-all.cc */; };
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; };
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D67D355622BABD2100292C1D /* gtest-all.cc */; };
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E722CB322900C2651A /* ios_app_framework.mm */; };
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */; };
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EC22CB323300C2651A /* firebase_test_framework.cc */; };
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EF22CB32A000C2651A /* app_framework.cc */; };
+ FF88C17A940D28F103913070 /* libPods-integration_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E4B91AFE2AFA744509A9C25 /* libPods-integration_test.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1878FBCB416E0920F536416B /* Pods-integration_test.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-integration_test.release.xcconfig"; path = "Target Support Files/Pods-integration_test/Pods-integration_test.release.xcconfig"; sourceTree = ""; };
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 529226D21C85F68000C89379 /* integration_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ 8E4B91AFE2AFA744509A9C25 /* libPods-integration_test.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-integration_test.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ BFA4C698DDB19F60D12FED3A /* Pods-integration_test.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-integration_test.debug.xcconfig"; path = "Target Support Files/Pods-integration_test/Pods-integration_test.debug.xcconfig"; sourceTree = ""; };
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ D61C5F8D22BABA9C00A79141 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D61C5F9222BABAD100A79141 /* integration_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test.cc; path = src/integration_test.cc; sourceTree = ""; };
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "external/googletest/src/googlemock/src/gmock-all.cc"; sourceTree = ""; };
+ D62CCBC122F367320099BE9F /* gmock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gmock.h; path = external/googletest/src/googlemock/include/gmock/gmock.h; sourceTree = ""; };
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ D67D355622BABD2100292C1D /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "external/googletest/src/googletest/src/gtest-all.cc"; sourceTree = ""; };
+ D67D355722BABD2100292C1D /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtest.h; path = external/googletest/src/googletest/include/gtest/gtest.h; sourceTree = ""; };
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_app_framework.mm; path = src/ios/ios_app_framework.mm; sourceTree = ""; };
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_firebase_test_framework.mm; path = src/ios/ios_firebase_test_framework.mm; sourceTree = ""; };
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = firebase_test_framework.h; path = src/firebase_test_framework.h; sourceTree = ""; };
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = firebase_test_framework.cc; path = src/firebase_test_framework.cc; sourceTree = ""; };
+ D6C179ED22CB323300C2651A /* app_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = app_framework.h; path = src/app_framework.h; sourceTree = ""; };
+ D6C179EF22CB32A000C2651A /* app_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = app_framework.cc; path = src/app_framework.cc; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 529226CF1C85F68000C89379 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */,
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */,
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */,
+ FF88C17A940D28F103913070 /* libPods-integration_test.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 529226C91C85F68000C89379 = {
+ isa = PBXGroup;
+ children = (
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */,
+ D61C5F8D22BABA9C00A79141 /* Info.plist */,
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */,
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */,
+ 5292271D1C85FB5500C89379 /* src */,
+ 529226D41C85F68000C89379 /* Frameworks */,
+ 529226D31C85F68000C89379 /* Products */,
+ 78E4FA177005E3E6FE395AE2 /* Pods */,
+ );
+ sourceTree = "";
+ };
+ 529226D31C85F68000C89379 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D21C85F68000C89379 /* integration_test.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 529226D41C85F68000C89379 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D51C85F68000C89379 /* Foundation.framework */,
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */,
+ 529226D91C85F68000C89379 /* UIKit.framework */,
+ 529226EE1C85F68000C89379 /* XCTest.framework */,
+ 8E4B91AFE2AFA744509A9C25 /* libPods-integration_test.a */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 5292271D1C85FB5500C89379 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D62CCBC122F367320099BE9F /* gmock.h */,
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */,
+ D67D355622BABD2100292C1D /* gtest-all.cc */,
+ D67D355722BABD2100292C1D /* gtest.h */,
+ D6C179EF22CB32A000C2651A /* app_framework.cc */,
+ D6C179ED22CB323300C2651A /* app_framework.h */,
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */,
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */,
+ D61C5F9222BABAD100A79141 /* integration_test.cc */,
+ 5292271E1C85FB5B00C89379 /* ios */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ 5292271E1C85FB5B00C89379 /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */,
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */,
+ );
+ name = ios;
+ sourceTree = "";
+ };
+ 78E4FA177005E3E6FE395AE2 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ BFA4C698DDB19F60D12FED3A /* Pods-integration_test.debug.xcconfig */,
+ 1878FBCB416E0920F536416B /* Pods-integration_test.release.xcconfig */,
+ );
+ name = Pods;
+ path = Pods;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 529226D11C85F68000C89379 /* integration_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */;
+ buildPhases = (
+ 7DBB351D9F7518B4E087635C /* [CP] Check Pods Manifest.lock */,
+ 529226CE1C85F68000C89379 /* Sources */,
+ 529226CF1C85F68000C89379 /* Frameworks */,
+ 529226D01C85F68000C89379 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = integration_test;
+ productName = testapp;
+ productReference = 529226D21C85F68000C89379 /* integration_test.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 529226CA1C85F68000C89379 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0640;
+ ORGANIZATIONNAME = Google;
+ TargetAttributes = {
+ 529226D11C85F68000C89379 = {
+ CreatedOnToolsVersion = 6.4;
+ DevelopmentTeam = EQHXZ8M8AV;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 529226C91C85F68000C89379;
+ productRefGroup = 529226D31C85F68000C89379 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 529226D11C85F68000C89379 /* integration_test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 529226D01C85F68000C89379 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */,
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */,
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 7DBB351D9F7518B4E087635C /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-integration_test-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 529226CE1C85F68000C89379 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */,
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */,
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */,
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */,
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */,
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */,
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 529226F71C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.4;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 529226F81C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ 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 = 8.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 529226FA1C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = BFA4C698DDB19F60D12FED3A /* Pods-integration_test.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 529226FB1C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 1878FBCB416E0920F536416B /* Pods-integration_test.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226F71C85F68000C89379 /* Debug */,
+ 529226F81C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226FA1C85F68000C89379 /* Debug */,
+ 529226FB1C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 529226CA1C85F68000C89379 /* Project object */;
+}
diff --git a/admob/integration_test/proguard.pro b/admob/integration_test/proguard.pro
new file mode 100644
index 0000000000..2d04b8a9a5
--- /dev/null
+++ b/admob/integration_test/proguard.pro
@@ -0,0 +1,2 @@
+-ignorewarnings
+-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { * ; }
diff --git a/admob/integration_test/res/layout/main.xml b/admob/integration_test/res/layout/main.xml
new file mode 100644
index 0000000000..d3ffb63082
--- /dev/null
+++ b/admob/integration_test/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/admob/integration_test/res/values/strings.xml b/admob/integration_test/res/values/strings.xml
new file mode 100644
index 0000000000..f38ec9de9d
--- /dev/null
+++ b/admob/integration_test/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Firebase AdMob Integration Test
+
diff --git a/admob/integration_test/settings.gradle b/admob/integration_test/settings.gradle
new file mode 100644
index 0000000000..e30c259ab6
--- /dev/null
+++ b/admob/integration_test/settings.gradle
@@ -0,0 +1,39 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
+if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
+ if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ if ((new File('../../cpp_sdk_version.json')).exists()) {
+ firebase_cpp_sdk_dir = new File('../..').absolutePath
+ }
+ else if ((new File('firebase_cpp_sdk')).exists()) {
+ firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
+ } else {
+ throw new StopActionException(
+ 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' +
+ 'environment variable must be set to reference the Firebase C++ ' +
+ 'SDK install directory. This is used to configure static library ' +
+ 'and C/C++ include paths for the SDK.')
+ }
+ }
+}
+if (!(new File(firebase_cpp_sdk_dir)).exists()) {
+ throw new StopActionException(
+ sprintf('Firebase C++ SDK directory %s does not exist',
+ firebase_cpp_sdk_dir))
+}
+gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
+includeBuild "$firebase_cpp_sdk_dir"
\ No newline at end of file
diff --git a/admob/integration_test/src/integration_test.cc b/admob/integration_test/src/integration_test.cc
new file mode 100644
index 0000000000..b97fbba2ef
--- /dev/null
+++ b/admob/integration_test/src/integration_test.cc
@@ -0,0 +1,552 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "app_framework.h" // NOLINT
+#include "firebase/admob.h"
+#include "firebase/app.h"
+#include "firebase/util.h"
+#include "firebase_test_framework.h" // NOLINT
+
+#if defined(ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+// includes for phone-only tests.
+#include
+#include
+#endif // defined(ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+
+// The TO_STRING macro is useful for command line defined strings as the quotes
+// get stripped.
+#define TO_STRING_EXPAND(X) #X
+#define TO_STRING(X) TO_STRING_EXPAND(X)
+
+// Path to the Firebase config file to load.
+#ifdef FIREBASE_CONFIG
+#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG)
+#else
+#define FIREBASE_CONFIG_STRING ""
+#endif // FIREBASE_CONFIG
+
+namespace firebase_testapp_automated {
+
+// The AdMob app IDs for the test app.
+#if defined(__ANDROID__)
+// If you change the AdMob app ID for your Android app, make sure to change it
+// in AndroidManifest.xml as well.
+const char* kAdMobAppID = "ca-app-pub-3940256099942544~3347511713";
+#else
+// If you change the AdMob app ID for your iOS app, make sure to change the
+// value for "GADApplicationIdentifier" in your Info.plist as well.
+const char* kAdMobAppID = "ca-app-pub-3940256099942544~1458002511";
+#endif
+
+// These ad units IDs have been created specifically for testing, and will
+// always return test ads.
+#if defined(__ANDROID__)
+const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
+const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/1033173712";
+const char* kRewardedVideoAdUnit = "ca-app-pub-3940256099942544/5224354917";
+#else
+const char* kBannerAdUnit = "ca-app-pub-3940256099942544/2934735716";
+const char* kInterstitialAdUnit = "ca-app-pub-3940256099942544/4411468910";
+const char* kRewardedVideoAdUnit = "ca-app-pub-3940256099942544/1712485313";
+#endif
+
+using app_framework::LogDebug;
+using app_framework::ProcessEvents;
+
+using firebase_test_framework::FirebaseTest;
+
+class FirebaseAdMobTest : public FirebaseTest {
+ public:
+ FirebaseAdMobTest();
+ ~FirebaseAdMobTest() override;
+
+ static void SetUpTestSuite();
+ static void TearDownTestSuite();
+
+ void SetUp() override;
+ void TearDown() override;
+
+ protected:
+ firebase::admob::AdRequest GetAdRequest();
+
+ static firebase::App* shared_app_;
+};
+
+firebase::App* FirebaseAdMobTest::shared_app_ = nullptr;
+
+void FirebaseAdMobTest::SetUpTestSuite() {
+ LogDebug("Initialize Firebase App.");
+
+ FindFirebaseConfig(FIREBASE_CONFIG_STRING);
+
+#if defined(__ANDROID__)
+ shared_app_ = ::firebase::App::Create(app_framework::GetJniEnv(),
+ app_framework::GetActivity());
+#else
+ shared_app_ = ::firebase::App::Create();
+#endif // defined(__ANDROID__)
+
+ LogDebug("Initializing AdMob.");
+
+ ::firebase::ModuleInitializer initializer;
+ initializer.Initialize(
+ shared_app_, nullptr, [](::firebase::App* app, void* /* userdata */) {
+ LogDebug("Try to initialize AdMob");
+ return ::firebase::admob::Initialize(*app, kAdMobAppID);
+ });
+
+ WaitForCompletion(initializer.InitializeLastResult(), "Initialize");
+
+ ASSERT_EQ(initializer.InitializeLastResult().error(), 0)
+ << initializer.InitializeLastResult().error_message();
+
+ LogDebug("Successfully initialized AdMob.");
+}
+
+void FirebaseAdMobTest::TearDownTestSuite() {
+ LogDebug("Shutdown AdMob.");
+ firebase::admob::Terminate();
+ LogDebug("Shutdown Firebase App.");
+ delete shared_app_;
+ shared_app_ = nullptr;
+}
+
+FirebaseAdMobTest::FirebaseAdMobTest() {}
+
+FirebaseAdMobTest::~FirebaseAdMobTest() {}
+
+void FirebaseAdMobTest::SetUp() { FirebaseTest::SetUp(); }
+
+void FirebaseAdMobTest::TearDown() { FirebaseTest::TearDown(); }
+
+firebase::admob::AdRequest FirebaseAdMobTest::GetAdRequest() {
+ // Sample keywords to use in making the request.
+ static const char* kKeywords[] = {"AdMob", "C++", "Fun"};
+
+ // Sample birthday value to use in making the request.
+ static const int kBirthdayDay = 10;
+ static const int kBirthdayMonth = 11;
+ static const int kBirthdayYear = 1976;
+
+ // Sample test device IDs to use in making the request.
+ static const char* kTestDeviceIDs[] = {"2077ef9a63d2b398840261c8221a0c9b",
+ "098fe087d987c9a878965454a65654d7"};
+
+ firebase::admob::AdRequest request;
+ // If the app is aware of the user's gender, it can be added to the targeting
+ // information. Otherwise, "unknown" should be used.
+ request.gender = firebase::admob::kGenderUnknown;
+
+ // This value allows publishers to specify whether they would like the request
+ // to be treated as child-directed for purposes of the Children’s Online
+ // Privacy Protection Act (COPPA).
+ // See http://business.ftc.gov/privacy-and-security/childrens-privacy.
+ request.tagged_for_child_directed_treatment =
+ firebase::admob::kChildDirectedTreatmentStateTagged;
+
+ // The user's birthday, if known. Note that months are indexed from one.
+ request.birthday_day = kBirthdayDay;
+ request.birthday_month = kBirthdayMonth;
+ request.birthday_year = kBirthdayYear;
+
+ // Additional keywords to be used in targeting.
+ request.keyword_count = sizeof(kKeywords) / sizeof(kKeywords[0]);
+ request.keywords = kKeywords;
+
+ // "Extra" key value pairs can be added to the request as well. Typically
+ // these are used when testing new features.
+ static const firebase::admob::KeyValuePair kRequestExtras[] = {
+ {"the_name_of_an_extra", "the_value_for_that_extra"}};
+ request.extras_count = sizeof(kRequestExtras) / sizeof(kRequestExtras[0]);
+ request.extras = kRequestExtras;
+
+ // This example uses ad units that are specially configured to return test ads
+ // for every request. When using your own ad unit IDs, however, it's important
+ // to register the device IDs associated with any devices that will be used to
+ // test the app. This ensures that regardless of the ad unit ID, those
+ // devices will always receive test ads in compliance with AdMob policy.
+ //
+ // Device IDs can be obtained by checking the logcat or the Xcode log while
+ // debugging. They appear as a long string of hex characters.
+ request.test_device_id_count =
+ sizeof(kTestDeviceIDs) / sizeof(kTestDeviceIDs[0]);
+ request.test_device_ids = kTestDeviceIDs;
+ return request;
+}
+
+// Test cases below.
+
+TEST_F(FirebaseAdMobTest, TestGetAdRequest) { GetAdRequest(); }
+
+// A simple listener to help test changes to a BannerView.
+class TestBannerViewListener : public firebase::admob::BannerView::Listener {
+ public:
+ void OnPresentationStateChanged(
+ firebase::admob::BannerView* banner_view,
+ firebase::admob::BannerView::PresentationState state) override {
+ presentation_states_.push_back(state);
+ }
+ void OnBoundingBoxChanged(firebase::admob::BannerView* banner_view,
+ firebase::admob::BoundingBox box) override {
+ bounding_box_changes_.push_back(box);
+ }
+ std::vector
+ presentation_states_;
+ std::vector bounding_box_changes_;
+};
+
+TEST_F(FirebaseAdMobTest, TestBannerView) {
+ // AdMob cannot be tested on Firebase Test Lab, so disable tests on FTL.
+ TEST_REQUIRES_USER_INTERACTION;
+
+ static const int kBannerWidth = 320;
+ static const int kBannerHeight = 50;
+
+ firebase::admob::AdSize banner_ad_size;
+ banner_ad_size.ad_size_type = firebase::admob::kAdSizeStandard;
+ banner_ad_size.width = kBannerWidth;
+ banner_ad_size.height = kBannerHeight;
+
+ firebase::admob::BannerView* banner = new firebase::admob::BannerView();
+ WaitForCompletion(banner->Initialize(app_framework::GetWindowContext(),
+ kBannerAdUnit, banner_ad_size),
+ "Initialize");
+
+ // Set the listener.
+ TestBannerViewListener banner_listener;
+ banner->SetListener(&banner_listener);
+
+ // Load the banner ad.
+ firebase::admob::AdRequest request = GetAdRequest();
+ WaitForCompletion(banner->LoadAd(request), "LoadAd");
+
+ std::vector
+ expected_presentation_states;
+ int expected_num_bounding_box_changes = 0;
+
+ // Make the BannerView visible.
+ WaitForCompletion(banner->Show(), "Show 0");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ // Move to each of the six pre-defined positions.
+
+ WaitForCompletion(banner->MoveTo(firebase::admob::BannerView::kPositionTop),
+ "MoveTo(Top)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(
+ banner->MoveTo(firebase::admob::BannerView::kPositionTopLeft),
+ "MoveTo(TopLeft)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(
+ banner->MoveTo(firebase::admob::BannerView::kPositionTopRight),
+ "MoveTo(TopRight)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(
+ banner->MoveTo(firebase::admob::BannerView::kPositionBottom),
+ "Moveto(Bottom)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(
+ banner->MoveTo(firebase::admob::BannerView::kPositionBottomLeft),
+ "MoveTo(BottomLeft)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(
+ banner->MoveTo(firebase::admob::BannerView::kPositionBottomRight),
+ "MoveTo(BottomRight)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ // Move to some coordinates.
+ WaitForCompletion(banner->MoveTo(100, 300), "MoveTo(x0, y0)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(banner->MoveTo(100, 400), "MoveTo(x1, y1)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ // Try hiding and showing the BannerView.
+ WaitForCompletion(banner->Hide(), "Hide 1");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateHidden);
+
+ WaitForCompletion(banner->Show(), "Show 1");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ // Move again after hiding/showing.
+ WaitForCompletion(banner->MoveTo(100, 300), "MoveTo(x2, y2)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(banner->MoveTo(100, 400), "Moveto(x3, y3)");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateVisibleWithAd);
+ expected_num_bounding_box_changes++;
+
+ WaitForCompletion(banner->Hide(), "Hide 2");
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateHidden);
+
+ delete banner;
+ expected_presentation_states.push_back(
+ firebase::admob::BannerView::kPresentationStateHidden);
+ expected_num_bounding_box_changes++;
+
+#if defined(__ANDROID__) || TARGET_OS_IPHONE
+ // Ensure that we got all the presentation state changes.
+ EXPECT_EQ(banner_listener.presentation_states_, expected_presentation_states);
+
+ // For the bounding box, check that we got the number of bounding box events
+ // we expect, since we don't know the exact bounding box coordinates to
+ // expect.
+ EXPECT_EQ(banner_listener.bounding_box_changes_.size(),
+ expected_num_bounding_box_changes);
+
+ // As an extra check, all bounding boxes except the last should have the same
+ // size aspect ratio that we requested. For example if you requested a 320x50
+ // banner, you can get one with the size 960x150. Use EXPECT_NEAR because the
+ // calculation can have a small bit of error.
+ double kAspectRatioAllowedError = 0.02; // Allow about 2% of error.
+ double expected_aspect_ratio =
+ static_cast(kBannerWidth) / static_cast(kBannerHeight);
+ for (int i = 0; i < banner_listener.bounding_box_changes_.size() - 1; ++i) {
+ double actual_aspect_ratio =
+ static_cast(banner_listener.bounding_box_changes_[i].width) /
+ static_cast(banner_listener.bounding_box_changes_[i].height);
+ EXPECT_NEAR(actual_aspect_ratio, expected_aspect_ratio,
+ kAspectRatioAllowedError)
+ << "Banner size " << banner_listener.bounding_box_changes_[i].width
+ << "x" << banner_listener.bounding_box_changes_[i].height
+ << " does not have the same aspect ratio as requested size "
+ << kBannerWidth << "x" << kBannerHeight << ".";
+ }
+
+ // And finally, the last bounding box change, when the banner is deleted,
+ // should be (0,0,0,0).
+ EXPECT_TRUE(banner_listener.bounding_box_changes_.back().x == 0 &&
+ banner_listener.bounding_box_changes_.back().y == 0 &&
+ banner_listener.bounding_box_changes_.back().width == 0 &&
+ banner_listener.bounding_box_changes_.back().height == 0);
+#endif
+}
+
+// A simple listener to help test changes to a InterstitialAd.
+class TestInterstitialAdListener
+ : public firebase::admob::InterstitialAd::Listener {
+ public:
+ void OnPresentationStateChanged(
+ firebase::admob::InterstitialAd* interstitial_ad,
+ firebase::admob::InterstitialAd::PresentationState state) override {
+ presentation_states_.push_back(state);
+ }
+ std::vector
+ presentation_states_;
+};
+
+TEST_F(FirebaseAdMobTest, TestInterstitialAd) {
+ TEST_REQUIRES_USER_INTERACTION;
+
+ firebase::admob::InterstitialAd* interstitial =
+ new firebase::admob::InterstitialAd();
+ WaitForCompletion(interstitial->Initialize(app_framework::GetWindowContext(),
+ kInterstitialAdUnit),
+ "Initialize");
+ TestInterstitialAdListener interstitial_listener;
+ interstitial->SetListener(&interstitial_listener);
+
+ firebase::admob::AdRequest request = GetAdRequest();
+ // When the InterstitialAd is initialized, load an ad.
+ WaitForCompletion(interstitial->LoadAd(request), "LoadAd");
+ std::vector
+ expected_presentation_states;
+
+ WaitForCompletion(interstitial->Show(), "Show");
+ expected_presentation_states.push_back(
+ firebase::admob::InterstitialAd::PresentationState::
+ kPresentationStateCoveringUI);
+ // Wait for the user to close the interstitial ad.
+ while (interstitial->presentation_state() !=
+ firebase::admob::InterstitialAd::PresentationState::
+ kPresentationStateHidden) {
+ app_framework::ProcessEvents(1000);
+ }
+ expected_presentation_states.push_back(
+ firebase::admob::InterstitialAd::PresentationState::
+ kPresentationStateHidden);
+#if defined(__ANDROID__) || TARGET_OS_IPHONE
+ EXPECT_EQ(interstitial_listener.presentation_states_,
+ expected_presentation_states);
+#endif
+ delete interstitial;
+}
+
+// A simple listener to help test changes to rewarded video state.
+class TestRewardedVideoListener
+ : public firebase::admob::rewarded_video::Listener {
+ public:
+ TestRewardedVideoListener() { got_reward_ = false; }
+ void OnRewarded(firebase::admob::rewarded_video::RewardItem reward) override {
+ got_reward_ = true;
+ reward_type_ = reward.reward_type;
+ reward_amount_ = reward.amount;
+ }
+ void OnPresentationStateChanged(
+ firebase::admob::rewarded_video::PresentationState state) override {
+ presentation_states_.push_back(state);
+ }
+ bool got_reward_;
+ std::string reward_type_;
+ float reward_amount_;
+ std::vector
+ presentation_states_;
+};
+
+TEST_F(FirebaseAdMobTest, TestRewardedVideoAd) {
+ TEST_REQUIRES_USER_INTERACTION;
+
+ namespace rewarded_video = firebase::admob::rewarded_video;
+ WaitForCompletion(rewarded_video::Initialize(), "Initialize");
+
+ TestRewardedVideoListener rewarded_listener;
+ rewarded_video::SetListener(&rewarded_listener);
+
+ firebase::admob::AdRequest request = GetAdRequest();
+ WaitForCompletion(rewarded_video::LoadAd(kRewardedVideoAdUnit, request),
+ "LoadAd");
+
+ std::vector expected_presentation_states;
+
+ WaitForCompletion(rewarded_video::Show(app_framework::GetWindowContext()),
+ "Show");
+
+ expected_presentation_states.push_back(
+ rewarded_video::PresentationState::kPresentationStateCoveringUI);
+ expected_presentation_states.push_back(
+ rewarded_video::PresentationState::kPresentationStateVideoHasStarted);
+
+ // Wait a moment, then pause, then resume.
+ ProcessEvents(1000);
+ WaitForCompletion(rewarded_video::Pause(), "Pause");
+ ProcessEvents(1000);
+ WaitForCompletion(rewarded_video::Resume(), "Resume");
+
+#if defined(__ANDROID__) || TARGET_OS_IPHONE
+ // Wait for video to complete.
+ while (
+ rewarded_listener.presentation_states_.back() !=
+ rewarded_video::PresentationState::kPresentationStateVideoHasCompleted) {
+ ProcessEvents(1000);
+ }
+ expected_presentation_states.push_back(
+ rewarded_video::PresentationState::kPresentationStateVideoHasCompleted);
+
+ EXPECT_TRUE(rewarded_listener.got_reward_);
+ EXPECT_NE(rewarded_listener.reward_type_, "");
+ EXPECT_NE(rewarded_listener.reward_amount_, 0);
+ LogDebug("Got reward: %.02f %s", rewarded_listener.reward_amount_,
+ rewarded_listener.reward_type_.c_str());
+
+ EXPECT_EQ(rewarded_listener.presentation_states_,
+ expected_presentation_states);
+#endif
+ rewarded_video::Destroy();
+}
+
+#if defined(ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+// Test runs & compiles for phones only.
+
+struct ThreadArgs {
+ firebase::admob::BannerView* banner;
+ sem_t* semaphore;
+};
+
+static void* DeleteBannerViewOnSignal(void* args) {
+ ThreadArgs* thread_args = static_cast(args);
+ sem_wait(thread_args->semaphore);
+ delete thread_args->banner;
+ return nullptr;
+}
+
+TEST_F(FirebaseAdMobTest, TestBannerViewMultithreadDeletion) {
+ SKIP_TEST_ON_DESKTOP;
+
+ static const int kBannerWidth = 320;
+ static const int kBannerHeight = 50;
+
+ firebase::admob::AdSize banner_ad_size;
+ banner_ad_size.ad_size_type = firebase::admob::kAdSizeStandard;
+ banner_ad_size.width = kBannerWidth;
+ banner_ad_size.height = kBannerHeight;
+
+ for (int i = 0; i < 5; ++i) {
+ firebase::admob::BannerView* banner = new firebase::admob::BannerView();
+ WaitForCompletion(banner->Initialize(app_framework::GetWindowContext(),
+ kBannerAdUnit, banner_ad_size),
+ "Initialize");
+ sem_t semaphore;
+ sem_init(&semaphore, 0, 1);
+
+ ThreadArgs args = {banner, &semaphore};
+
+ pthread_t t1;
+ int err = pthread_create(&t1, nullptr, &DeleteBannerViewOnSignal, &args);
+ EXPECT_EQ(err, 0);
+
+ banner->Destroy();
+ sem_post(&semaphore);
+
+ // Blocks until DeleteBannerViewOnSignal function is done.
+ void* result = nullptr;
+ err = pthread_join(t1, &result);
+
+ EXPECT_EQ(err, 0);
+ EXPECT_EQ(result, nullptr);
+
+ sem_destroy(&semaphore);
+ }
+}
+#endif // #if defined(ANDROID) || (defined(TARGET_OS_IPHONE) &&
+ // TARGET_OS_IPHONE)
+
+} // namespace firebase_testapp_automated
diff --git a/analytics/integration_test/AndroidManifest.xml b/analytics/integration_test/AndroidManifest.xml
new file mode 100644
index 0000000000..9acf51d9d2
--- /dev/null
+++ b/analytics/integration_test/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/analytics/integration_test/CMakeLists.txt b/analytics/integration_test/CMakeLists.txt
new file mode 100644
index 0000000000..7d2609824d
--- /dev/null
+++ b/analytics/integration_test/CMakeLists.txt
@@ -0,0 +1,224 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Cmake file for a single C++ integration test build.
+
+cmake_minimum_required(VERSION 2.8)
+
+# User settings for Firebase integration tests.
+# Path to Firebase SDK.
+# Try to read the path to the Firebase C++ SDK from an environment variable.
+if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}")
+else()
+ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../cpp_sdk_version.json")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
+ else()
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk")
+ endif()
+endif()
+if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR})
+endif()
+if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR})
+ message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information")
+endif()
+
+# Copy all prerequisite files for integration tests to run.
+if(NOT ANDROID)
+ if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py)
+ # If this is running from inside the SDK directory, run the setup script.
+ execute_process(COMMAND "python" "${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py" "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
+endif()
+
+# Windows runtime mode, either MD or MT depending on whether you are using
+# /MD or /MT. For more information see:
+# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+set(MSVC_RUNTIME_MODE MD)
+
+project(firebase_testapp)
+
+# Integration test source files.
+set(FIREBASE_APP_FRAMEWORK_SRCS
+ src/app_framework.cc
+ src/app_framework.h
+)
+
+set(FIREBASE_TEST_FRAMEWORK_SRCS
+ src/firebase_test_framework.h
+ src/firebase_test_framework.cc
+)
+
+set(FIREBASE_INTEGRATION_TEST_SRCS
+ src/integration_test.cc
+)
+
+# The include directory for the testapp.
+include_directories(src)
+
+# Integration test uses some features that require C++ 11, such as lambdas.
+set (CMAKE_CXX_STANDARD 11)
+
+# Download and unpack googletest (and googlemock) at configure time
+set(GOOGLETEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/external/googletest)
+# Note: Once googletest is downloaded once, it won't be updated or
+# downloaded again unless you delete the "external/googletest"
+# directory.
+if (NOT EXISTS ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ configure_file(googletest.cmake
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/CMakeLists.txt COPYONLY)
+ execute_process(COMMAND ${CMAKE_COMMAND} .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+ endif()
+endif()
+
+if(ANDROID)
+ # Build an Android application.
+
+ # Source files used for the Android build.
+ set(FIREBASE_APP_FRAMEWORK_ANDROID_SRCS
+ src/android/android_app_framework.cc
+ )
+
+ # Source files used for the Android build.
+ set(FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS
+ src/android/android_firebase_test_framework.cc
+ )
+
+ # Build native_app_glue as a static lib
+ add_library(native_app_glue STATIC
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+
+ # Export ANativeActivity_onCreate(),
+ # Refer to: https://github.com/android-ndk/ndk/issues/381.
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
+
+ add_library(gtest STATIC
+ ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ target_include_directories(gtest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include)
+ add_library(gmock STATIC
+ ${GOOGLETEST_ROOT}/src/googlemock/src/gmock-all.cc)
+ target_include_directories(gmock
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googlemock
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include
+ PUBLIC ${GOOGLETEST_ROOT}/src/googlemock/include)
+
+ # Define the target as a shared library, as that is what gradle expects.
+ set(integration_test_target_name "android_integration_test_main")
+ add_library(${integration_test_target_name} SHARED
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_ANDROID_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS}
+ )
+
+ target_include_directories(${integration_test_target_name} PRIVATE
+ ${ANDROID_NDK}/sources/android/native_app_glue)
+
+ set(ADDITIONAL_LIBS log android atomic native_app_glue)
+else()
+ # Build a desktop application.
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+
+ # Prevent overriding the parent project's compiler/linker
+ # settings on Windows
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This defines
+ # the gtest and gtest_main targets.
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/googletest/src
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/build
+ EXCLUDE_FROM_ALL)
+
+ # The gtest/gtest_main targets carry header search path
+ # dependencies automatically when using CMake 2.8.11 or
+ # later. Otherwise we have to add them here ourselves.
+ if (CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories("${gtest_SOURCE_DIR}/include")
+ include_directories("${gmock_SOURCE_DIR}/include")
+ endif()
+
+ # Windows runtime mode, either MD or MT depending on whether you are using
+ # /MD or /MT. For more information see:
+ # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+ set(MSVC_RUNTIME_MODE MD)
+
+ # Platform abstraction layer for the desktop integration test.
+ set(FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS
+ src/desktop/desktop_app_framework.cc
+ )
+
+ set(integration_test_target_name "integration_test")
+ add_executable(${integration_test_target_name}
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ )
+
+ if(APPLE)
+ set(ADDITIONAL_LIBS
+ gssapi_krb5
+ pthread
+ "-framework CoreFoundation"
+ "-framework Foundation"
+ "-framework GSS"
+ "-framework Security"
+ )
+ elseif(MSVC)
+ set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32)
+ else()
+ set(ADDITIONAL_LIBS pthread)
+ endif()
+
+ # If a config file is present, copy it into the binary location so that it's
+ # possible to create the default Firebase app.
+ set(FOUND_JSON_FILE FALSE)
+ foreach(config "google-services-desktop.json" "google-services.json")
+ if (EXISTS ${config})
+ add_custom_command(
+ TARGET ${integration_test_target_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${config} $)
+ set(FOUND_JSON_FILE TRUE)
+ break()
+ endif()
+ endforeach()
+ if(NOT FOUND_JSON_FILE)
+ message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.")
+ endif()
+endif()
+
+# Add the Firebase libraries to the target using the function from the SDK.
+add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
+# Note that firebase_app needs to be last in the list.
+set(firebase_libs firebase_analytics firebase_app)
+set(gtest_libs gtest gmock)
+target_link_libraries(${integration_test_target_name} ${firebase_libs}
+ ${gtest_libs} ${ADDITIONAL_LIBS})
diff --git a/analytics/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json b/analytics/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..d8db8d65fd
--- /dev/null
+++ b/analytics/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/analytics/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json b/analytics/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..6f870a4629
--- /dev/null
+++ b/analytics/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,51 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/analytics/integration_test/Info.plist b/analytics/integration_test/Info.plist
new file mode 100644
index 0000000000..3e13e24ba6
--- /dev/null
+++ b/analytics/integration_test/Info.plist
@@ -0,0 +1,42 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ com.google.ios.analytics.testapp
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ google
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.255980362477-3a1nf8c4nl0c7hlnlnmc98hbtg2mnbue
+ firebase-game-loop
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/analytics/integration_test/LaunchScreen.storyboard b/analytics/integration_test/LaunchScreen.storyboard
new file mode 100644
index 0000000000..673e0f7e68
--- /dev/null
+++ b/analytics/integration_test/LaunchScreen.storyboard
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/analytics/integration_test/LibraryManifest.xml b/analytics/integration_test/LibraryManifest.xml
new file mode 100644
index 0000000000..5e886a778c
--- /dev/null
+++ b/analytics/integration_test/LibraryManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/analytics/integration_test/Podfile b/analytics/integration_test/Podfile
new file mode 100644
index 0000000000..5ab82b3642
--- /dev/null
+++ b/analytics/integration_test/Podfile
@@ -0,0 +1,15 @@
+
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+# Firebase Analytics test application.
+
+target 'integration_test' do
+ pod 'Firebase/Analytics', '6.24.0'
+end
+
+post_install do |installer|
+ # If this is running from inside the SDK directory, run the setup script.
+ system("if [[ -r ../../setup_integration_tests.py ]]; then python ../../setup_integration_tests.py .; fi")
+ system("/usr/bin/python ./download_googletest.py")
+end
+
diff --git a/analytics/integration_test/build.gradle b/analytics/integration_test/build.gradle
new file mode 100644
index 0000000000..a1d574b5e4
--- /dev/null
+++ b/analytics/integration_test/build.gradle
@@ -0,0 +1,76 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.google.gms:google-services:4.0.1'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src/android/java']
+ res.srcDirs = ['res']
+ }
+ }
+
+ defaultConfig {
+ applicationId 'com.google.android.analytics.testapp'
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ externalNativeBuild.cmake {
+ arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir"
+ }
+ }
+ externalNativeBuild.cmake {
+ path 'CMakeLists.txt'
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFile getDefaultProguardFile('proguard-android.txt')
+ proguardFile file('proguard.pro')
+ }
+ }
+}
+
+apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
+firebaseCpp.dependencies {
+ analytics
+}
+
+apply plugin: 'com.google.gms.google-services'
+
+task copyIntegrationTestFiles(type:Exec) {
+ // If this is running form inside the SDK directory, run the setup script.
+ if (project.file('../../setup_integration_tests.py').exists()) {
+ commandLine 'python', '../../setup_integration_tests.py', project.projectDir.toString()
+ }
+ else {
+ commandLine 'echo', ''
+ }
+}
+
+build.dependsOn(copyIntegrationTestFiles)
\ No newline at end of file
diff --git a/analytics/integration_test/googletest.cmake b/analytics/integration_test/googletest.cmake
new file mode 100644
index 0000000000..2ecbb08679
--- /dev/null
+++ b/analytics/integration_test/googletest.cmake
@@ -0,0 +1,34 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Download GoogleTest from GitHub as an external project.
+
+# This CMake file is taken from:
+# https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG master
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/analytics/integration_test/gradle/wrapper/gradle-wrapper.jar b/analytics/integration_test/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
Binary files /dev/null and b/analytics/integration_test/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/analytics/integration_test/gradle/wrapper/gradle-wrapper.properties b/analytics/integration_test/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..35732b09a0
--- /dev/null
+++ b/analytics/integration_test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 27 14:03:45 PST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/analytics/integration_test/gradlew b/analytics/integration_test/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/analytics/integration_test/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/analytics/integration_test/gradlew.bat b/analytics/integration_test/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/analytics/integration_test/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/analytics/integration_test/integration_test.xcodeproj/project.pbxproj b/analytics/integration_test/integration_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..d1d6b852d1
--- /dev/null
+++ b/analytics/integration_test/integration_test.xcodeproj/project.pbxproj
@@ -0,0 +1,364 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; };
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; };
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; };
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; };
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D61C5F8C22BABA9B00A79141 /* Images.xcassets */; };
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D61C5F9222BABAD100A79141 /* integration_test.cc */; };
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D62CCBBF22F367140099BE9F /* gmock-all.cc */; };
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; };
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D67D355622BABD2100292C1D /* gtest-all.cc */; };
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E722CB322900C2651A /* ios_app_framework.mm */; };
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */; };
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EC22CB323300C2651A /* firebase_test_framework.cc */; };
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EF22CB32A000C2651A /* app_framework.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 529226D21C85F68000C89379 /* integration_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ D61C5F8D22BABA9C00A79141 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D61C5F9222BABAD100A79141 /* integration_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test.cc; path = src/integration_test.cc; sourceTree = ""; };
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "external/googletest/src/googlemock/src/gmock-all.cc"; sourceTree = ""; };
+ D62CCBC122F367320099BE9F /* gmock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gmock.h; path = external/googletest/src/googlemock/include/gmock/gmock.h; sourceTree = ""; };
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ D67D355622BABD2100292C1D /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "external/googletest/src/googletest/src/gtest-all.cc"; sourceTree = ""; };
+ D67D355722BABD2100292C1D /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtest.h; path = external/googletest/src/googletest/include/gtest/gtest.h; sourceTree = ""; };
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_app_framework.mm; path = src/ios/ios_app_framework.mm; sourceTree = ""; };
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_firebase_test_framework.mm; path = src/ios/ios_firebase_test_framework.mm; sourceTree = ""; };
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = firebase_test_framework.h; path = src/firebase_test_framework.h; sourceTree = ""; };
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = firebase_test_framework.cc; path = src/firebase_test_framework.cc; sourceTree = ""; };
+ D6C179ED22CB323300C2651A /* app_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = app_framework.h; path = src/app_framework.h; sourceTree = ""; };
+ D6C179EF22CB32A000C2651A /* app_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = app_framework.cc; path = src/app_framework.cc; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 529226CF1C85F68000C89379 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */,
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */,
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 529226C91C85F68000C89379 = {
+ isa = PBXGroup;
+ children = (
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */,
+ D61C5F8D22BABA9C00A79141 /* Info.plist */,
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */,
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */,
+ 5292271D1C85FB5500C89379 /* src */,
+ 529226D41C85F68000C89379 /* Frameworks */,
+ 529226D31C85F68000C89379 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 529226D31C85F68000C89379 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D21C85F68000C89379 /* integration_test.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 529226D41C85F68000C89379 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D51C85F68000C89379 /* Foundation.framework */,
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */,
+ 529226D91C85F68000C89379 /* UIKit.framework */,
+ 529226EE1C85F68000C89379 /* XCTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 5292271D1C85FB5500C89379 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D62CCBC122F367320099BE9F /* gmock.h */,
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */,
+ D67D355622BABD2100292C1D /* gtest-all.cc */,
+ D67D355722BABD2100292C1D /* gtest.h */,
+ D6C179EF22CB32A000C2651A /* app_framework.cc */,
+ D6C179ED22CB323300C2651A /* app_framework.h */,
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */,
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */,
+ D61C5F9222BABAD100A79141 /* integration_test.cc */,
+ 5292271E1C85FB5B00C89379 /* ios */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ 5292271E1C85FB5B00C89379 /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */,
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */,
+ );
+ name = ios;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 529226D11C85F68000C89379 /* integration_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */;
+ buildPhases = (
+ 529226CE1C85F68000C89379 /* Sources */,
+ 529226CF1C85F68000C89379 /* Frameworks */,
+ 529226D01C85F68000C89379 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = integration_test;
+ productName = testapp;
+ productReference = 529226D21C85F68000C89379 /* integration_test.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 529226CA1C85F68000C89379 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0640;
+ ORGANIZATIONNAME = Google;
+ TargetAttributes = {
+ 529226D11C85F68000C89379 = {
+ CreatedOnToolsVersion = 6.4;
+ DevelopmentTeam = EQHXZ8M8AV;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 529226C91C85F68000C89379;
+ productRefGroup = 529226D31C85F68000C89379 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 529226D11C85F68000C89379 /* integration_test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 529226D01C85F68000C89379 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */,
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */,
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 529226CE1C85F68000C89379 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */,
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */,
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */,
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */,
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */,
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */,
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 529226F71C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.4;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 529226F81C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ 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 = 8.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 529226FA1C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 529226FB1C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226F71C85F68000C89379 /* Debug */,
+ 529226F81C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226FA1C85F68000C89379 /* Debug */,
+ 529226FB1C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 529226CA1C85F68000C89379 /* Project object */;
+}
diff --git a/analytics/integration_test/proguard.pro b/analytics/integration_test/proguard.pro
new file mode 100644
index 0000000000..2d04b8a9a5
--- /dev/null
+++ b/analytics/integration_test/proguard.pro
@@ -0,0 +1,2 @@
+-ignorewarnings
+-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { * ; }
diff --git a/analytics/integration_test/readme.md b/analytics/integration_test/readme.md
new file mode 100644
index 0000000000..18599e5952
--- /dev/null
+++ b/analytics/integration_test/readme.md
@@ -0,0 +1,184 @@
+Firebase Analytics Quickstart
+==============================
+
+The Firebase Analytics Sample demonstrates logging a range of different events
+using the Firebase Analytics C++ SDK. The application has no user interface and
+simply logs actions it's performing to the console.
+
+Introduction
+------------
+
+- [Read more about Firebase Analytics](https://firebase.google.com/docs/analytics/)
+
+Building and Running the sample
+-------------------------------
+
+### iOS
+ - Link your iOS app to the Firebase libraries.
+ - Get CocoaPods version 1 or later by running,
+ ```
+ sudo gem install cocoapods --pre
+ ```
+ - From the sample directory, install the CocoaPods listed in the Podfile
+ by running,
+ ```
+ pod install
+ ```
+ - Open the generated Xcode workspace (which now has the CocoaPods),
+ ```
+ open sample.xcworkspace
+ ```
+ - For further details please refer to the
+ [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup).
+ - Register your iOS app with Firebase.
+ - Create a new app on the [Firebase console](https://firebase.google.com/console/), and attach
+ your iOS app to it.
+ - You can use "com.google.ios.analytics.testapp" as the iOS Bundle ID
+ while you're testing. You can omit App Store ID while testing.
+ - Add the GoogleService-Info.plist that you downloaded from Firebase
+ console to the sample directory. This file identifies your iOS app
+ to the Firebase backend.
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Add the following frameworks from the Firebase C++ SDK to the project:
+ - frameworks/ios/universal/firebase.framework
+ - frameworks/ios/universal/firebase\_analytics.framework
+ - You will need to either,
+ 1. Check "Copy items if needed" when adding the frameworks, or
+ 2. Add the framework path in "Framework Search Paths"
+ - e.g. If you downloaded the Firebase C++ SDK to
+ `/Users/me/firebase_cpp_sdk`,
+ then you would add the path
+ `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`.
+ - To add the path, in XCode, select your project in the project
+ navigator, then select your target in the main window.
+ Select the "Build Settings" tab, and click "All" to see all
+ the build settings. Scroll down to "Search Paths", and add
+ your path to "Framework Search Paths".
+ - In XCode, build & run the sample on an iOS device or simulator.
+ - The sample has no user interface. The output of the app can be viewed
+ via the console. In Xcode, select
+ "View --> Debug Area --> Activate Console" from the menu.
+ - After 5 hours, data should be visible in the Firebase Console under the
+ "Analytics" tab accessible from
+ [https://firebase.google.com/console/](https://firebase.google.com/console/).
+
+### Android
+ - Register your Android app with Firebase.
+ - Create a new app on the [Firebase console](https://firebase.google.com/console/), and attach
+ your Android app to it.
+ - You can use "com.google.android.analytics.testapp" as the Package Name
+ while you're testing.
+ - To [generate a SHA1](https://developers.google.com/android/guides/client-auth)
+ run this command on Mac and Linux,
+ ```
+ keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
+ ```
+ or this command on Windows,
+ ```
+ keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore
+ ```
+ - If keytool reports that you do not have a debug.keystore, you can
+ [create one with](http://developer.android.com/tools/publishing/app-signing.html#signing-manually),
+ ```
+ keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"
+ ```
+ - Add the `google-services.json` file that you downloaded from Firebase
+ console to the sample directory. This file identifies your
+ Android app to the Firebase backend.
+ - For further details please refer to the
+ [general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup).
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Configure the location of the Firebase C++ SDK by setting the
+ firebase\_cpp\_sdk.dir Gradle property to the SDK install directory.
+ For example, in the project directory:
+ ```
+ echo "systemProp.firebase\_cpp\_sdk.dir=/User/$USER/firebase\_cpp\_sdk" >> gradle.properties
+ ```
+ - Ensure the Android SDK and NDK locations are set in Android Studio.
+ - From the Android Studio launch menu, go to `File/Project Structure...` or
+ `Configure/Project Defaults/Project Structure...`
+ (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac)
+ and download the SDK and NDK if the locations are not yet set.
+ - Open *build.gradle* in Android Studio.
+ - From the Android Studio launch menu, "Open an existing Android Studio
+ project", and select `build.gradle`.
+ - Install the SDK Platforms that Android Studio reports missing.
+ - Build the sample and run it on an Android device or emulator.
+ - The sample has no user interface. The output of the app can be viewed
+ in the logcat output of Android studio or by running "adb logcat" from
+ the command line.
+ - After 5 hours, data should be visible in the Firebase Console under the
+ "Analytics" tab accessible from
+ [https://firebase.google.com/console/](https://firebase.google.com/console/).
+
+### Desktop
+ - Register your app with Firebase.
+ - Create a new app on the [Firebase console](https://firebase.google.com/console/),
+ following the above instructions for Android or iOS.
+ - If you have an Android project, add the `google-services.json` file that
+ you downloaded from the Firebase console to the sample directory.
+ - If you have an iOS project, and don't wish to use an Android project,
+ you can use the Python script `generate_xml_from_google_services_json.py --plist`,
+ located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist`
+ file into a `google-services-desktop.json` file, which can then be
+ placed in the root directory of the sample.
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Configure the sample with the location of the Firebase C++ SDK.
+ This can be done a couple different ways (in highest to lowest priority):
+ - When invoking cmake, pass in the location with
+ -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk.
+ - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use.
+ - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path
+ to the appropriate location.
+ - From the sample directory, generate the build files by running,
+ ```
+ cmake .
+ ```
+ If you want to use XCode, you can use -G"Xcode" to generate the project.
+ Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more
+ information, see
+ [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
+ - Build the sample, by either opening the generated project file based on
+ the platform, or running,
+ ```
+ cmake --build .
+ ```
+ - Execute the sample by running,
+ ```
+ ./sample
+ ```
+ Note that the executable might be under another directory, such as Debug.
+ - The sample has no user interface, but the output can be viewed via the
+ console. Note that Analytics uses a stubbed implementation on desktop,
+ so functionality is not expected.
+
+Support
+-------
+
+[https://firebase.google.com/support/](https://firebase.google.com/support/)
+
+License
+-------
+
+Copyright 2016 Google, Inc.
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements. See the NOTICE file distributed with this work for
+additional information regarding copyright ownership. The ASF licenses this
+file to you under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
diff --git a/analytics/integration_test/res/layout/main.xml b/analytics/integration_test/res/layout/main.xml
new file mode 100644
index 0000000000..d3ffb63082
--- /dev/null
+++ b/analytics/integration_test/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/analytics/integration_test/res/values/strings.xml b/analytics/integration_test/res/values/strings.xml
new file mode 100644
index 0000000000..3375587120
--- /dev/null
+++ b/analytics/integration_test/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Firebase Analytics Integration Test
+
diff --git a/analytics/integration_test/settings.gradle b/analytics/integration_test/settings.gradle
new file mode 100644
index 0000000000..e30c259ab6
--- /dev/null
+++ b/analytics/integration_test/settings.gradle
@@ -0,0 +1,39 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
+if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
+ if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ if ((new File('../../cpp_sdk_version.json')).exists()) {
+ firebase_cpp_sdk_dir = new File('../..').absolutePath
+ }
+ else if ((new File('firebase_cpp_sdk')).exists()) {
+ firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
+ } else {
+ throw new StopActionException(
+ 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' +
+ 'environment variable must be set to reference the Firebase C++ ' +
+ 'SDK install directory. This is used to configure static library ' +
+ 'and C/C++ include paths for the SDK.')
+ }
+ }
+}
+if (!(new File(firebase_cpp_sdk_dir)).exists()) {
+ throw new StopActionException(
+ sprintf('Firebase C++ SDK directory %s does not exist',
+ firebase_cpp_sdk_dir))
+}
+gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
+includeBuild "$firebase_cpp_sdk_dir"
\ No newline at end of file
diff --git a/analytics/integration_test/src/integration_test.cc b/analytics/integration_test/src/integration_test.cc
new file mode 100644
index 0000000000..f629bdee07
--- /dev/null
+++ b/analytics/integration_test/src/integration_test.cc
@@ -0,0 +1,155 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "app_framework.h" // NOLINT
+#include "firebase/analytics.h"
+#include "firebase/analytics/event_names.h"
+#include "firebase/analytics/parameter_names.h"
+#include "firebase/analytics/user_property_names.h"
+#include "firebase/app.h"
+#include "firebase/util.h"
+#include "firebase_test_framework.h" // NOLINT
+
+// The TO_STRING macro is useful for command line defined strings as the quotes
+// get stripped.
+#define TO_STRING_EXPAND(X) #X
+#define TO_STRING(X) TO_STRING_EXPAND(X)
+
+// Path to the Firebase config file to load.
+#ifdef FIREBASE_CONFIG
+#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG)
+#else
+#define FIREBASE_CONFIG_STRING ""
+#endif // FIREBASE_CONFIG
+
+namespace firebase_testapp_automated {
+
+using firebase_test_framework::FirebaseTest;
+
+class FirebaseAnalyticsTest : public FirebaseTest {
+ public:
+ static void SetUpTestSuite();
+ static void TearDownTestSuite();
+
+ static firebase::App* shared_app_;
+};
+
+firebase::App* FirebaseAnalyticsTest::shared_app_;
+
+void FirebaseAnalyticsTest::SetUpTestSuite() {
+#if defined(__ANDROID__)
+ shared_app_ = firebase::App::Create(app_framework::GetJniEnv(),
+ app_framework::GetActivity());
+#else
+ shared_app_ = firebase::App::Create();
+#endif // defined(__ANDROID__)
+
+ firebase::analytics::Initialize(*shared_app_);
+}
+
+void FirebaseAnalyticsTest::TearDownTestSuite() {
+ firebase::analytics::Terminate();
+ delete shared_app_;
+ shared_app_ = nullptr;
+}
+
+TEST_F(FirebaseAnalyticsTest, TestSetCollectionEnabled) {
+ // Can't confirm that these do anything but just run them all to ensure the
+ // app doesn't crash.
+ firebase::analytics::SetAnalyticsCollectionEnabled(true);
+ firebase::analytics::SetAnalyticsCollectionEnabled(false);
+ firebase::analytics::SetAnalyticsCollectionEnabled(true);
+}
+
+TEST_F(FirebaseAnalyticsTest, TestSetSessionTimeoutDuraction) {
+ firebase::analytics::SetSessionTimeoutDuration(1000 * 60 * 5);
+ firebase::analytics::SetSessionTimeoutDuration(1000 * 60 * 15);
+ firebase::analytics::SetSessionTimeoutDuration(1000 * 60 * 30);
+}
+
+TEST_F(FirebaseAnalyticsTest, TestGetAnalyticsInstanceID) {
+ firebase::Future future =
+ firebase::analytics::GetAnalyticsInstanceId();
+ WaitForCompletion(future, "GetAnalyticsInstanceId");
+ EXPECT_FALSE(future.result()->empty());
+}
+
+TEST_F(FirebaseAnalyticsTest, TestSetProperties) {
+ // Set the user's sign up method.
+ firebase::analytics::SetUserProperty(
+ firebase::analytics::kUserPropertySignUpMethod, "Google");
+ // Set the user ID.
+ firebase::analytics::SetUserId("my_integration_test_user");
+
+ firebase::analytics::SetCurrentScreen(
+ "Firebase Analytics C++ integration test", "integration_test");
+}
+
+TEST_F(FirebaseAnalyticsTest, TestLogEvents) {
+ // Log an event with no parameters.
+ firebase::analytics::LogEvent(firebase::analytics::kEventLogin);
+
+ // Log an event with a floating point parameter.
+ firebase::analytics::LogEvent("progress", "percent", 0.4f);
+
+ // Log an event with an integer parameter.
+ firebase::analytics::LogEvent(firebase::analytics::kEventPostScore,
+ firebase::analytics::kParameterScore, 42);
+
+ // Log an event with a string parameter.
+ firebase::analytics::LogEvent(firebase::analytics::kEventJoinGroup,
+ firebase::analytics::kParameterGroupID,
+ "spoon_welders");
+}
+
+TEST_F(FirebaseAnalyticsTest, TestLogEventWithMultipleParameters) {
+ const firebase::analytics::Parameter kLevelUpParameters[] = {
+ firebase::analytics::Parameter(firebase::analytics::kParameterLevel, 5),
+ firebase::analytics::Parameter(firebase::analytics::kParameterCharacter,
+ "mrspoon"),
+ firebase::analytics::Parameter("hit_accuracy", 3.14f),
+ };
+ firebase::analytics::LogEvent(
+ firebase::analytics::kEventLevelUp, kLevelUpParameters,
+ sizeof(kLevelUpParameters) / sizeof(kLevelUpParameters[0]));
+}
+
+#if !(TARGET_OS_IPHONE)
+// Test is flakey on iPhone due to a known issue in iOS. See b/143656277.
+TEST_F(FirebaseAnalyticsTest, TestResettingGivesNewInstanceId) {
+ firebase::Future future =
+ firebase::analytics::GetAnalyticsInstanceId();
+ WaitForCompletion(future, "GetAnalyticsInstanceId");
+ EXPECT_FALSE(future.result()->empty());
+ std::string instance_id = *future.result();
+
+ firebase::analytics::ResetAnalyticsData();
+
+ future = firebase::analytics::GetAnalyticsInstanceId();
+ WaitForCompletion(future, "GetAnalyticsInstanceId after ResetAnalyticsData");
+ std::string new_instance_id = *future.result();
+ EXPECT_FALSE(future.result()->empty());
+ EXPECT_NE(instance_id, new_instance_id);
+}
+#endif // !(TARGET_OS_IPHONE)
+
+} // namespace firebase_testapp_automated
diff --git a/app/integration_test/AndroidManifest.xml b/app/integration_test/AndroidManifest.xml
new file mode 100644
index 0000000000..ffd3c1f9d0
--- /dev/null
+++ b/app/integration_test/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/integration_test/CMakeLists.txt b/app/integration_test/CMakeLists.txt
new file mode 100644
index 0000000000..f27111df56
--- /dev/null
+++ b/app/integration_test/CMakeLists.txt
@@ -0,0 +1,224 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Cmake file for a single C++ integration test build.
+
+cmake_minimum_required(VERSION 2.8)
+
+# User settings for Firebase integration tests.
+# Path to Firebase SDK.
+# Try to read the path to the Firebase C++ SDK from an environment variable.
+if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}")
+else()
+ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../cpp_sdk_version.json")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
+ else()
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk")
+ endif()
+endif()
+if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR})
+endif()
+if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR})
+ message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information")
+endif()
+
+# Copy all prerequisite files for integration tests to run.
+if(NOT ANDROID)
+ if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py)
+ # If this is running from inside the SDK directory, run the setup script.
+ execute_process(COMMAND "python" "${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py" "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
+endif()
+
+# Windows runtime mode, either MD or MT depending on whether you are using
+# /MD or /MT. For more information see:
+# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+set(MSVC_RUNTIME_MODE MD)
+
+project(firebase_testapp)
+
+# Integration test source files.
+set(FIREBASE_APP_FRAMEWORK_SRCS
+ src/app_framework.cc
+ src/app_framework.h
+)
+
+set(FIREBASE_TEST_FRAMEWORK_SRCS
+ src/firebase_test_framework.h
+ src/firebase_test_framework.cc
+)
+
+set(FIREBASE_INTEGRATION_TEST_SRCS
+ src/integration_test.cc
+)
+
+# The include directory for the testapp.
+include_directories(src)
+
+# Integration test uses some features that require C++ 11, such as lambdas.
+set (CMAKE_CXX_STANDARD 11)
+
+# Download and unpack googletest (and googlemock) at configure time
+set(GOOGLETEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/external/googletest)
+# Note: Once googletest is downloaded once, it won't be updated or
+# downloaded again unless you delete the "external/googletest"
+# directory.
+if (NOT EXISTS ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ configure_file(googletest.cmake
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/CMakeLists.txt COPYONLY)
+ execute_process(COMMAND ${CMAKE_COMMAND} .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+ endif()
+endif()
+
+if(ANDROID)
+ # Build an Android application.
+
+ # Source files used for the Android build.
+ set(FIREBASE_APP_FRAMEWORK_ANDROID_SRCS
+ src/android/android_app_framework.cc
+ )
+
+ # Source files used for the Android build.
+ set(FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS
+ src/android/android_firebase_test_framework.cc
+ )
+
+ # Build native_app_glue as a static lib
+ add_library(native_app_glue STATIC
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+
+ # Export ANativeActivity_onCreate(),
+ # Refer to: https://github.com/android-ndk/ndk/issues/381.
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
+
+ add_library(gtest STATIC
+ ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ target_include_directories(gtest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include)
+ add_library(gmock STATIC
+ ${GOOGLETEST_ROOT}/src/googlemock/src/gmock-all.cc)
+ target_include_directories(gmock
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googlemock
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include
+ PUBLIC ${GOOGLETEST_ROOT}/src/googlemock/include)
+
+ # Define the target as a shared library, as that is what gradle expects.
+ set(integration_test_target_name "android_integration_test_main")
+ add_library(${integration_test_target_name} SHARED
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_ANDROID_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS}
+ )
+
+ target_include_directories(${integration_test_target_name} PRIVATE
+ ${ANDROID_NDK}/sources/android/native_app_glue)
+
+ set(ADDITIONAL_LIBS log android atomic native_app_glue)
+else()
+ # Build a desktop application.
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+
+ # Prevent overriding the parent project's compiler/linker
+ # settings on Windows
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This defines
+ # the gtest and gtest_main targets.
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/googletest/src
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/build
+ EXCLUDE_FROM_ALL)
+
+ # The gtest/gtest_main targets carry header search path
+ # dependencies automatically when using CMake 2.8.11 or
+ # later. Otherwise we have to add them here ourselves.
+ if (CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories("${gtest_SOURCE_DIR}/include")
+ include_directories("${gmock_SOURCE_DIR}/include")
+ endif()
+
+ # Windows runtime mode, either MD or MT depending on whether you are using
+ # /MD or /MT. For more information see:
+ # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+ set(MSVC_RUNTIME_MODE MD)
+
+ # Platform abstraction layer for the desktop integration test.
+ set(FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS
+ src/desktop/desktop_app_framework.cc
+ )
+
+ set(integration_test_target_name "integration_test")
+ add_executable(${integration_test_target_name}
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ )
+
+ if(APPLE)
+ set(ADDITIONAL_LIBS
+ gssapi_krb5
+ pthread
+ "-framework CoreFoundation"
+ "-framework Foundation"
+ "-framework GSS"
+ "-framework Security"
+ )
+ elseif(MSVC)
+ set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32)
+ else()
+ set(ADDITIONAL_LIBS pthread)
+ endif()
+
+ # If a config file is present, copy it into the binary location so that it's
+ # possible to create the default Firebase app.
+ set(FOUND_JSON_FILE FALSE)
+ foreach(config "google-services-desktop.json" "google-services.json")
+ if (EXISTS ${config})
+ add_custom_command(
+ TARGET ${integration_test_target_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${config} $)
+ set(FOUND_JSON_FILE TRUE)
+ break()
+ endif()
+ endforeach()
+ if(NOT FOUND_JSON_FILE)
+ message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.")
+ endif()
+endif()
+
+# Add the Firebase libraries to the target using the function from the SDK.
+add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
+# Note that firebase_app needs to be last in the list.
+set(firebase_libs firebase_app)
+set(gtest_libs gtest gmock)
+target_link_libraries(${integration_test_target_name} ${firebase_libs}
+ ${gtest_libs} ${ADDITIONAL_LIBS})
diff --git a/app/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json b/app/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..d8db8d65fd
--- /dev/null
+++ b/app/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/app/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json b/app/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..6f870a4629
--- /dev/null
+++ b/app/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,51 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/app/integration_test/Info.plist b/app/integration_test/Info.plist
new file mode 100644
index 0000000000..d938a81f9b
--- /dev/null
+++ b/app/integration_test/Info.plist
@@ -0,0 +1,41 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ com.google.ios.analytics.testapp
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ google
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.255980362477-3a1nf8c4nl0c7hlnlnmc98hbtg2mnbue
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/app/integration_test/LaunchScreen.storyboard b/app/integration_test/LaunchScreen.storyboard
new file mode 100644
index 0000000000..673e0f7e68
--- /dev/null
+++ b/app/integration_test/LaunchScreen.storyboard
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/app/integration_test/LibraryManifest.xml b/app/integration_test/LibraryManifest.xml
new file mode 100644
index 0000000000..855b13b5dc
--- /dev/null
+++ b/app/integration_test/LibraryManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/integration_test/Podfile b/app/integration_test/Podfile
new file mode 100644
index 0000000000..2f9fa57fa2
--- /dev/null
+++ b/app/integration_test/Podfile
@@ -0,0 +1,15 @@
+
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+# Firebase App test application.
+
+target 'integration_test' do
+ pod 'Firebase/Analytics', '6.24.0'
+end
+
+post_install do |installer|
+ # If this is running from inside the SDK directory, run the setup script.
+ system("if [[ -r ../../setup_integration_tests.py ]]; then python ../../setup_integration_tests.py .; fi")
+ system("/usr/bin/python ./download_googletest.py")
+end
+
diff --git a/app/integration_test/build.gradle b/app/integration_test/build.gradle
new file mode 100644
index 0000000000..95ab16fd6c
--- /dev/null
+++ b/app/integration_test/build.gradle
@@ -0,0 +1,76 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.google.gms:google-services:4.0.1'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src/android/java']
+ res.srcDirs = ['res']
+ }
+ }
+
+ defaultConfig {
+ applicationId 'com.google.android.analytics.testapp'
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ externalNativeBuild.cmake {
+ arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir"
+ }
+ }
+ externalNativeBuild.cmake {
+ path 'CMakeLists.txt'
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFile getDefaultProguardFile('proguard-android.txt')
+ proguardFile file('proguard.pro')
+ }
+ }
+}
+
+apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
+firebaseCpp.dependencies {
+ app
+}
+
+apply plugin: 'com.google.gms.google-services'
+
+task copyIntegrationTestFiles(type:Exec) {
+ // If this is running form inside the SDK directory, run the setup script.
+ if (project.file('../../setup_integration_tests.py').exists()) {
+ commandLine 'python', '../../setup_integration_tests.py', project.projectDir.toString()
+ }
+ else {
+ commandLine 'echo', ''
+ }
+}
+
+build.dependsOn(copyIntegrationTestFiles)
\ No newline at end of file
diff --git a/app/integration_test/googletest.cmake b/app/integration_test/googletest.cmake
new file mode 100644
index 0000000000..2ecbb08679
--- /dev/null
+++ b/app/integration_test/googletest.cmake
@@ -0,0 +1,34 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Download GoogleTest from GitHub as an external project.
+
+# This CMake file is taken from:
+# https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG master
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/app/integration_test/gradle/wrapper/gradle-wrapper.jar b/app/integration_test/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
Binary files /dev/null and b/app/integration_test/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/app/integration_test/gradle/wrapper/gradle-wrapper.properties b/app/integration_test/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..35732b09a0
--- /dev/null
+++ b/app/integration_test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 27 14:03:45 PST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/app/integration_test/gradlew b/app/integration_test/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/app/integration_test/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/app/integration_test/gradlew.bat b/app/integration_test/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/app/integration_test/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/app/integration_test/integration_test.xcodeproj/project.pbxproj b/app/integration_test/integration_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..d1d6b852d1
--- /dev/null
+++ b/app/integration_test/integration_test.xcodeproj/project.pbxproj
@@ -0,0 +1,364 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; };
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; };
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; };
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; };
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D61C5F8C22BABA9B00A79141 /* Images.xcassets */; };
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D61C5F9222BABAD100A79141 /* integration_test.cc */; };
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D62CCBBF22F367140099BE9F /* gmock-all.cc */; };
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; };
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D67D355622BABD2100292C1D /* gtest-all.cc */; };
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E722CB322900C2651A /* ios_app_framework.mm */; };
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */; };
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EC22CB323300C2651A /* firebase_test_framework.cc */; };
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EF22CB32A000C2651A /* app_framework.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 529226D21C85F68000C89379 /* integration_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ D61C5F8D22BABA9C00A79141 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D61C5F9222BABAD100A79141 /* integration_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test.cc; path = src/integration_test.cc; sourceTree = ""; };
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "external/googletest/src/googlemock/src/gmock-all.cc"; sourceTree = ""; };
+ D62CCBC122F367320099BE9F /* gmock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gmock.h; path = external/googletest/src/googlemock/include/gmock/gmock.h; sourceTree = ""; };
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ D67D355622BABD2100292C1D /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "external/googletest/src/googletest/src/gtest-all.cc"; sourceTree = ""; };
+ D67D355722BABD2100292C1D /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtest.h; path = external/googletest/src/googletest/include/gtest/gtest.h; sourceTree = ""; };
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_app_framework.mm; path = src/ios/ios_app_framework.mm; sourceTree = ""; };
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_firebase_test_framework.mm; path = src/ios/ios_firebase_test_framework.mm; sourceTree = ""; };
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = firebase_test_framework.h; path = src/firebase_test_framework.h; sourceTree = ""; };
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = firebase_test_framework.cc; path = src/firebase_test_framework.cc; sourceTree = ""; };
+ D6C179ED22CB323300C2651A /* app_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = app_framework.h; path = src/app_framework.h; sourceTree = ""; };
+ D6C179EF22CB32A000C2651A /* app_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = app_framework.cc; path = src/app_framework.cc; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 529226CF1C85F68000C89379 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */,
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */,
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 529226C91C85F68000C89379 = {
+ isa = PBXGroup;
+ children = (
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */,
+ D61C5F8D22BABA9C00A79141 /* Info.plist */,
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */,
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */,
+ 5292271D1C85FB5500C89379 /* src */,
+ 529226D41C85F68000C89379 /* Frameworks */,
+ 529226D31C85F68000C89379 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 529226D31C85F68000C89379 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D21C85F68000C89379 /* integration_test.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 529226D41C85F68000C89379 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D51C85F68000C89379 /* Foundation.framework */,
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */,
+ 529226D91C85F68000C89379 /* UIKit.framework */,
+ 529226EE1C85F68000C89379 /* XCTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 5292271D1C85FB5500C89379 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D62CCBC122F367320099BE9F /* gmock.h */,
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */,
+ D67D355622BABD2100292C1D /* gtest-all.cc */,
+ D67D355722BABD2100292C1D /* gtest.h */,
+ D6C179EF22CB32A000C2651A /* app_framework.cc */,
+ D6C179ED22CB323300C2651A /* app_framework.h */,
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */,
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */,
+ D61C5F9222BABAD100A79141 /* integration_test.cc */,
+ 5292271E1C85FB5B00C89379 /* ios */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ 5292271E1C85FB5B00C89379 /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */,
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */,
+ );
+ name = ios;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 529226D11C85F68000C89379 /* integration_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */;
+ buildPhases = (
+ 529226CE1C85F68000C89379 /* Sources */,
+ 529226CF1C85F68000C89379 /* Frameworks */,
+ 529226D01C85F68000C89379 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = integration_test;
+ productName = testapp;
+ productReference = 529226D21C85F68000C89379 /* integration_test.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 529226CA1C85F68000C89379 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0640;
+ ORGANIZATIONNAME = Google;
+ TargetAttributes = {
+ 529226D11C85F68000C89379 = {
+ CreatedOnToolsVersion = 6.4;
+ DevelopmentTeam = EQHXZ8M8AV;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 529226C91C85F68000C89379;
+ productRefGroup = 529226D31C85F68000C89379 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 529226D11C85F68000C89379 /* integration_test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 529226D01C85F68000C89379 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */,
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */,
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 529226CE1C85F68000C89379 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */,
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */,
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */,
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */,
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */,
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */,
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 529226F71C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.4;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 529226F81C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ 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 = 8.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 529226FA1C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 529226FB1C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226F71C85F68000C89379 /* Debug */,
+ 529226F81C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226FA1C85F68000C89379 /* Debug */,
+ 529226FB1C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 529226CA1C85F68000C89379 /* Project object */;
+}
diff --git a/app/integration_test/proguard.pro b/app/integration_test/proguard.pro
new file mode 100644
index 0000000000..2d04b8a9a5
--- /dev/null
+++ b/app/integration_test/proguard.pro
@@ -0,0 +1,2 @@
+-ignorewarnings
+-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { * ; }
diff --git a/app/integration_test/res/layout/main.xml b/app/integration_test/res/layout/main.xml
new file mode 100644
index 0000000000..d3ffb63082
--- /dev/null
+++ b/app/integration_test/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/integration_test/res/values/strings.xml b/app/integration_test/res/values/strings.xml
new file mode 100644
index 0000000000..15ff2a0621
--- /dev/null
+++ b/app/integration_test/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Firebase App Integration Test
+
diff --git a/app/integration_test/settings.gradle b/app/integration_test/settings.gradle
new file mode 100644
index 0000000000..e30c259ab6
--- /dev/null
+++ b/app/integration_test/settings.gradle
@@ -0,0 +1,39 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
+if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
+ if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ if ((new File('../../cpp_sdk_version.json')).exists()) {
+ firebase_cpp_sdk_dir = new File('../..').absolutePath
+ }
+ else if ((new File('firebase_cpp_sdk')).exists()) {
+ firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
+ } else {
+ throw new StopActionException(
+ 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' +
+ 'environment variable must be set to reference the Firebase C++ ' +
+ 'SDK install directory. This is used to configure static library ' +
+ 'and C/C++ include paths for the SDK.')
+ }
+ }
+}
+if (!(new File(firebase_cpp_sdk_dir)).exists()) {
+ throw new StopActionException(
+ sprintf('Firebase C++ SDK directory %s does not exist',
+ firebase_cpp_sdk_dir))
+}
+gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
+includeBuild "$firebase_cpp_sdk_dir"
\ No newline at end of file
diff --git a/app/integration_test/src/integration_test.cc b/app/integration_test/src/integration_test.cc
new file mode 100644
index 0000000000..c22acb8bec
--- /dev/null
+++ b/app/integration_test/src/integration_test.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "app_framework.h" // NOLINT
+#include "firebase_test_framework.h" // NOLINT
+
+// The TO_STRING macro is useful for command line defined strings as the quotes
+// get stripped.
+#define TO_STRING_EXPAND(X) #X
+#define TO_STRING(X) TO_STRING_EXPAND(X)
+
+// Path to the Firebase config file to load.
+#ifdef FIREBASE_CONFIG
+#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG)
+#else
+#define FIREBASE_CONFIG_STRING ""
+#endif // FIREBASE_CONFIG
+
+namespace firebase_testapp_automated {
+
+using firebase_test_framework::FirebaseTest;
+
+class FirebaseAppTest : public FirebaseTest {
+ public:
+ FirebaseAppTest();
+};
+
+FirebaseAppTest::FirebaseAppTest() {
+ FindFirebaseConfig(FIREBASE_CONFIG_STRING);
+}
+
+// For simplicity of test code, handle the Android-specific arguments here.
+#if defined(__ANDROID__)
+#define APP_CREATE_PARAMS \
+ app_framework::GetJniEnv(), app_framework::GetActivity()
+#else
+#define APP_CREATE_PARAMS
+#endif // defined(__ANDROID__)
+
+TEST_F(FirebaseAppTest, TestDefaultAppWithDefaultOptions) {
+ firebase::App* default_app;
+ default_app = firebase::App::Create(APP_CREATE_PARAMS);
+ EXPECT_NE(default_app, nullptr);
+
+ delete default_app;
+ default_app = nullptr;
+}
+
+} // namespace firebase_testapp_automated
diff --git a/auth/integration_test/AndroidManifest.xml b/auth/integration_test/AndroidManifest.xml
new file mode 100644
index 0000000000..c1c8a0c0ce
--- /dev/null
+++ b/auth/integration_test/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/auth/integration_test/CMakeLists.txt b/auth/integration_test/CMakeLists.txt
new file mode 100644
index 0000000000..12c9db3699
--- /dev/null
+++ b/auth/integration_test/CMakeLists.txt
@@ -0,0 +1,224 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Cmake file for a single C++ integration test build.
+
+cmake_minimum_required(VERSION 2.8)
+
+# User settings for Firebase integration tests.
+# Path to Firebase SDK.
+# Try to read the path to the Firebase C++ SDK from an environment variable.
+if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}")
+else()
+ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../cpp_sdk_version.json")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
+ else()
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk")
+ endif()
+endif()
+if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR})
+endif()
+if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR})
+ message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information")
+endif()
+
+# Copy all prerequisite files for integration tests to run.
+if(NOT ANDROID)
+ if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py)
+ # If this is running from inside the SDK directory, run the setup script.
+ execute_process(COMMAND "python" "${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py" "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
+endif()
+
+# Windows runtime mode, either MD or MT depending on whether you are using
+# /MD or /MT. For more information see:
+# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+set(MSVC_RUNTIME_MODE MD)
+
+project(firebase_testapp)
+
+# Integration test source files.
+set(FIREBASE_APP_FRAMEWORK_SRCS
+ src/app_framework.cc
+ src/app_framework.h
+)
+
+set(FIREBASE_TEST_FRAMEWORK_SRCS
+ src/firebase_test_framework.h
+ src/firebase_test_framework.cc
+)
+
+set(FIREBASE_INTEGRATION_TEST_SRCS
+ src/integration_test.cc
+)
+
+# The include directory for the testapp.
+include_directories(src)
+
+# Integration test uses some features that require C++ 11, such as lambdas.
+set (CMAKE_CXX_STANDARD 11)
+
+# Download and unpack googletest (and googlemock) at configure time
+set(GOOGLETEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/external/googletest)
+# Note: Once googletest is downloaded once, it won't be updated or
+# downloaded again unless you delete the "external/googletest"
+# directory.
+if (NOT EXISTS ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ configure_file(googletest.cmake
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/CMakeLists.txt COPYONLY)
+ execute_process(COMMAND ${CMAKE_COMMAND} .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+ endif()
+endif()
+
+if(ANDROID)
+ # Build an Android application.
+
+ # Source files used for the Android build.
+ set(FIREBASE_APP_FRAMEWORK_ANDROID_SRCS
+ src/android/android_app_framework.cc
+ )
+
+ # Source files used for the Android build.
+ set(FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS
+ src/android/android_firebase_test_framework.cc
+ )
+
+ # Build native_app_glue as a static lib
+ add_library(native_app_glue STATIC
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+
+ # Export ANativeActivity_onCreate(),
+ # Refer to: https://github.com/android-ndk/ndk/issues/381.
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
+
+ add_library(gtest STATIC
+ ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ target_include_directories(gtest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include)
+ add_library(gmock STATIC
+ ${GOOGLETEST_ROOT}/src/googlemock/src/gmock-all.cc)
+ target_include_directories(gmock
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googlemock
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include
+ PUBLIC ${GOOGLETEST_ROOT}/src/googlemock/include)
+
+ # Define the target as a shared library, as that is what gradle expects.
+ set(integration_test_target_name "android_integration_test_main")
+ add_library(${integration_test_target_name} SHARED
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_ANDROID_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS}
+ )
+
+ target_include_directories(${integration_test_target_name} PRIVATE
+ ${ANDROID_NDK}/sources/android/native_app_glue)
+
+ set(ADDITIONAL_LIBS log android atomic native_app_glue)
+else()
+ # Build a desktop application.
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+
+ # Prevent overriding the parent project's compiler/linker
+ # settings on Windows
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This defines
+ # the gtest and gtest_main targets.
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/googletest/src
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/build
+ EXCLUDE_FROM_ALL)
+
+ # The gtest/gtest_main targets carry header search path
+ # dependencies automatically when using CMake 2.8.11 or
+ # later. Otherwise we have to add them here ourselves.
+ if (CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories("${gtest_SOURCE_DIR}/include")
+ include_directories("${gmock_SOURCE_DIR}/include")
+ endif()
+
+ # Windows runtime mode, either MD or MT depending on whether you are using
+ # /MD or /MT. For more information see:
+ # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+ set(MSVC_RUNTIME_MODE MD)
+
+ # Platform abstraction layer for the desktop integration test.
+ set(FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS
+ src/desktop/desktop_app_framework.cc
+ )
+
+ set(integration_test_target_name "integration_test")
+ add_executable(${integration_test_target_name}
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ )
+
+ if(APPLE)
+ set(ADDITIONAL_LIBS
+ gssapi_krb5
+ pthread
+ "-framework CoreFoundation"
+ "-framework Foundation"
+ "-framework GSS"
+ "-framework Security"
+ )
+ elseif(MSVC)
+ set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32)
+ else()
+ set(ADDITIONAL_LIBS pthread)
+ endif()
+
+ # If a config file is present, copy it into the binary location so that it's
+ # possible to create the default Firebase app.
+ set(FOUND_JSON_FILE FALSE)
+ foreach(config "google-services-desktop.json" "google-services.json")
+ if (EXISTS ${config})
+ add_custom_command(
+ TARGET ${integration_test_target_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${config} $)
+ set(FOUND_JSON_FILE TRUE)
+ break()
+ endif()
+ endforeach()
+ if(NOT FOUND_JSON_FILE)
+ message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.")
+ endif()
+endif()
+
+# Add the Firebase libraries to the target using the function from the SDK.
+add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
+# Note that firebase_app needs to be last in the list.
+set(firebase_libs firebase_auth firebase_app)
+set(gtest_libs gtest gmock)
+target_link_libraries(${integration_test_target_name} ${firebase_libs}
+ ${gtest_libs} ${ADDITIONAL_LIBS})
diff --git a/auth/integration_test/Firebase_Cpp_Auth_Test_App_Dev.mobileprovision b/auth/integration_test/Firebase_Cpp_Auth_Test_App_Dev.mobileprovision
new file mode 100644
index 0000000000..979b0856e6
Binary files /dev/null and b/auth/integration_test/Firebase_Cpp_Auth_Test_App_Dev.mobileprovision differ
diff --git a/auth/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json b/auth/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..d8db8d65fd
--- /dev/null
+++ b/auth/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/auth/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json b/auth/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..6f870a4629
--- /dev/null
+++ b/auth/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,51 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/auth/integration_test/Info.plist b/auth/integration_test/Info.plist
new file mode 100644
index 0000000000..d4e02ca97a
--- /dev/null
+++ b/auth/integration_test/Info.plist
@@ -0,0 +1,54 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ com.google.FirebaseCppAuthTestApp.dev
+ CFBundleURLSchemes
+
+ com.google.FirebaseCppAuthTestApp.dev
+
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ google
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.53101460582-aosfj1hlbc89719t6qfian100u6hehh8
+ firebase-game-loop
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIBackgroundModes
+
+ fetch
+
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/auth/integration_test/LaunchScreen.storyboard b/auth/integration_test/LaunchScreen.storyboard
new file mode 100644
index 0000000000..673e0f7e68
--- /dev/null
+++ b/auth/integration_test/LaunchScreen.storyboard
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/auth/integration_test/LibraryManifest.xml b/auth/integration_test/LibraryManifest.xml
new file mode 100644
index 0000000000..b6faca73f6
--- /dev/null
+++ b/auth/integration_test/LibraryManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/auth/integration_test/Podfile b/auth/integration_test/Podfile
new file mode 100644
index 0000000000..42a0f26285
--- /dev/null
+++ b/auth/integration_test/Podfile
@@ -0,0 +1,15 @@
+
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+# Firebase Auth test application.
+
+target 'integration_test' do
+ pod 'Firebase/Auth', '6.24.0'
+end
+
+post_install do |installer|
+ # If this is running from inside the SDK directory, run the setup script.
+ system("if [[ -r ../../setup_integration_tests.py ]]; then python ../../setup_integration_tests.py .; fi")
+ system("/usr/bin/python ./download_googletest.py")
+end
+
diff --git a/auth/integration_test/build.gradle b/auth/integration_test/build.gradle
new file mode 100644
index 0000000000..abdf5361a8
--- /dev/null
+++ b/auth/integration_test/build.gradle
@@ -0,0 +1,76 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.google.gms:google-services:4.0.1'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src/android/java']
+ res.srcDirs = ['res']
+ }
+ }
+
+ defaultConfig {
+ applicationId 'com.google.android.auth.testapp'
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ externalNativeBuild.cmake {
+ arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir"
+ }
+ }
+ externalNativeBuild.cmake {
+ path 'CMakeLists.txt'
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFile getDefaultProguardFile('proguard-android.txt')
+ proguardFile file('proguard.pro')
+ }
+ }
+}
+
+apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
+firebaseCpp.dependencies {
+ auth
+}
+
+apply plugin: 'com.google.gms.google-services'
+
+task copyIntegrationTestFiles(type:Exec) {
+ // If this is running form inside the SDK directory, run the setup script.
+ if (project.file('../../setup_integration_tests.py').exists()) {
+ commandLine 'python', '../../setup_integration_tests.py', project.projectDir.toString()
+ }
+ else {
+ commandLine 'echo', ''
+ }
+}
+
+build.dependsOn(copyIntegrationTestFiles)
\ No newline at end of file
diff --git a/auth/integration_test/googletest.cmake b/auth/integration_test/googletest.cmake
new file mode 100644
index 0000000000..2ecbb08679
--- /dev/null
+++ b/auth/integration_test/googletest.cmake
@@ -0,0 +1,34 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Download GoogleTest from GitHub as an external project.
+
+# This CMake file is taken from:
+# https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG master
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/auth/integration_test/gradle/wrapper/gradle-wrapper.jar b/auth/integration_test/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
Binary files /dev/null and b/auth/integration_test/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/auth/integration_test/gradle/wrapper/gradle-wrapper.properties b/auth/integration_test/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..35732b09a0
--- /dev/null
+++ b/auth/integration_test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 27 14:03:45 PST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/auth/integration_test/gradlew b/auth/integration_test/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/auth/integration_test/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/auth/integration_test/gradlew.bat b/auth/integration_test/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/auth/integration_test/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/auth/integration_test/integration_test.entitlements b/auth/integration_test/integration_test.entitlements
new file mode 100644
index 0000000000..9199daef18
--- /dev/null
+++ b/auth/integration_test/integration_test.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ application-identifier
+ $(AppIdentifierPrefix)$(CFBundleIdentifier)
+ aps-environment
+ development
+
+
diff --git a/auth/integration_test/integration_test.xcodeproj/project.pbxproj b/auth/integration_test/integration_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..a3901f2c6a
--- /dev/null
+++ b/auth/integration_test/integration_test.xcodeproj/project.pbxproj
@@ -0,0 +1,376 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; };
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; };
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; };
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; };
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D61C5F8C22BABA9B00A79141 /* Images.xcassets */; };
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D61C5F9222BABAD100A79141 /* integration_test.cc */; };
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D62CCBBF22F367140099BE9F /* gmock-all.cc */; };
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; };
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D67D355622BABD2100292C1D /* gtest-all.cc */; };
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E722CB322900C2651A /* ios_app_framework.mm */; };
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */; };
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EC22CB323300C2651A /* firebase_test_framework.cc */; };
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EF22CB32A000C2651A /* app_framework.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 529226D21C85F68000C89379 /* integration_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ D61C5F8D22BABA9C00A79141 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D61C5F9222BABAD100A79141 /* integration_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test.cc; path = src/integration_test.cc; sourceTree = ""; };
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ D67D355622BABD2100292C1D /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "external/googletest/src/googletest/src/gtest-all.cc"; sourceTree = ""; };
+ D67D355722BABD2100292C1D /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtest.h; path = external/googletest/src/googletest/include/gtest/gtest.h; sourceTree = ""; };
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "external/googletest/src/googlemock/src/gmock-all.cc"; sourceTree = ""; };
+ D62CCBC122F367320099BE9F /* gmock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gmock.h; path = external/googletest/src/googlemock/include/gmock/gmock.h; sourceTree = ""; };
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_app_framework.mm; path = src/ios/ios_app_framework.mm; sourceTree = ""; };
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_firebase_test_framework.mm; path = src/ios/ios_firebase_test_framework.mm; sourceTree = ""; };
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = firebase_test_framework.h; path = src/firebase_test_framework.h; sourceTree = ""; };
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = firebase_test_framework.cc; path = src/firebase_test_framework.cc; sourceTree = ""; };
+ D6C179ED22CB323300C2651A /* app_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = app_framework.h; path = src/app_framework.h; sourceTree = ""; };
+ D6C179EF22CB32A000C2651A /* app_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = app_framework.cc; path = src/app_framework.cc; sourceTree = ""; };
+ D6E7D43C22D51D9900EDBD35 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 529226CF1C85F68000C89379 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */,
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */,
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 529226C91C85F68000C89379 = {
+ isa = PBXGroup;
+ children = (
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */,
+ D61C5F8D22BABA9C00A79141 /* Info.plist */,
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */,
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */,
+ 5292271D1C85FB5500C89379 /* src */,
+ 529226D41C85F68000C89379 /* Frameworks */,
+ 529226D31C85F68000C89379 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 529226D31C85F68000C89379 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D21C85F68000C89379 /* integration_test.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 529226D41C85F68000C89379 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ D6E7D43C22D51D9900EDBD35 /* UserNotifications.framework */,
+ 529226D51C85F68000C89379 /* Foundation.framework */,
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */,
+ 529226D91C85F68000C89379 /* UIKit.framework */,
+ 529226EE1C85F68000C89379 /* XCTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 5292271D1C85FB5500C89379 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D62CCBC122F367320099BE9F /* gmock.h */,
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */,
+ D67D355622BABD2100292C1D /* gtest-all.cc */,
+ D67D355722BABD2100292C1D /* gtest.h */,
+ D6C179EF22CB32A000C2651A /* app_framework.cc */,
+ D6C179ED22CB323300C2651A /* app_framework.h */,
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */,
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */,
+ D61C5F9222BABAD100A79141 /* integration_test.cc */,
+ 5292271E1C85FB5B00C89379 /* ios */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ 5292271E1C85FB5B00C89379 /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */,
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */,
+ );
+ name = ios;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 529226D11C85F68000C89379 /* integration_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */;
+ buildPhases = (
+ 529226CE1C85F68000C89379 /* Sources */,
+ 529226CF1C85F68000C89379 /* Frameworks */,
+ 529226D01C85F68000C89379 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = integration_test;
+ productName = testapp;
+ productReference = 529226D21C85F68000C89379 /* integration_test.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 529226CA1C85F68000C89379 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0640;
+ ORGANIZATIONNAME = Google;
+ TargetAttributes = {
+ 529226D11C85F68000C89379 = {
+ CreatedOnToolsVersion = 6.4;
+ DevelopmentTeam = EQHXZ8M8AV;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.BackgroundModes = {
+ enabled = 1;
+ };
+ com.apple.Push = {
+ enabled = 1;
+ };
+ };
+ };
+ };
+ };
+ buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 529226C91C85F68000C89379;
+ productRefGroup = 529226D31C85F68000C89379 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 529226D11C85F68000C89379 /* integration_test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 529226D01C85F68000C89379 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */,
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */,
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 529226CE1C85F68000C89379 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */,
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */,
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */,
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */,
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */,
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */,
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 529226F71C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.4;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 529226F81C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ 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 = 8.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 529226FA1C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseCppAuthTestApp.dev;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 529226FB1C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseCppAuthTestApp.dev;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226F71C85F68000C89379 /* Debug */,
+ 529226F81C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226FA1C85F68000C89379 /* Debug */,
+ 529226FB1C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 529226CA1C85F68000C89379 /* Project object */;
+}
diff --git a/auth/integration_test/proguard.pro b/auth/integration_test/proguard.pro
new file mode 100644
index 0000000000..2d04b8a9a5
--- /dev/null
+++ b/auth/integration_test/proguard.pro
@@ -0,0 +1,2 @@
+-ignorewarnings
+-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { * ; }
diff --git a/auth/integration_test/res/layout/main.xml b/auth/integration_test/res/layout/main.xml
new file mode 100644
index 0000000000..d3ffb63082
--- /dev/null
+++ b/auth/integration_test/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/auth/integration_test/res/values/strings.xml b/auth/integration_test/res/values/strings.xml
new file mode 100644
index 0000000000..cfd0d03516
--- /dev/null
+++ b/auth/integration_test/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Firebase Auth Integration Test
+
diff --git a/auth/integration_test/settings.gradle b/auth/integration_test/settings.gradle
new file mode 100644
index 0000000000..e30c259ab6
--- /dev/null
+++ b/auth/integration_test/settings.gradle
@@ -0,0 +1,39 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
+if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
+ if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ if ((new File('../../cpp_sdk_version.json')).exists()) {
+ firebase_cpp_sdk_dir = new File('../..').absolutePath
+ }
+ else if ((new File('firebase_cpp_sdk')).exists()) {
+ firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
+ } else {
+ throw new StopActionException(
+ 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' +
+ 'environment variable must be set to reference the Firebase C++ ' +
+ 'SDK install directory. This is used to configure static library ' +
+ 'and C/C++ include paths for the SDK.')
+ }
+ }
+}
+if (!(new File(firebase_cpp_sdk_dir)).exists()) {
+ throw new StopActionException(
+ sprintf('Firebase C++ SDK directory %s does not exist',
+ firebase_cpp_sdk_dir))
+}
+gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
+includeBuild "$firebase_cpp_sdk_dir"
\ No newline at end of file
diff --git a/auth/integration_test/src/integration_test.cc b/auth/integration_test/src/integration_test.cc
new file mode 100644
index 0000000000..fbfa5c496e
--- /dev/null
+++ b/auth/integration_test/src/integration_test.cc
@@ -0,0 +1,1118 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "app_framework.h" // NOLINT
+#include "firebase/app.h"
+#include "firebase/auth.h"
+#include "firebase/auth/credential.h"
+#include "firebase/auth/user.h"
+#include "firebase/util.h"
+#include "firebase/variant.h"
+#include "firebase_test_framework.h" // NOLINT
+
+// The TO_STRING macro is useful for command line defined strings as the quotes
+// get stripped.
+#define TO_STRING_EXPAND(X) #X
+#define TO_STRING(X) TO_STRING_EXPAND(X)
+
+// Path to the Firebase config file to load.
+#ifdef FIREBASE_CONFIG
+#define FIREBASE_CONFIG_STRING TO_STRING(FIREBASE_CONFIG)
+#else
+#define FIREBASE_CONFIG_STRING ""
+#endif // FIREBASE_CONFIG
+
+namespace firebase_testapp_automated {
+
+// Set kCustomTestEmail and kCustomTestPassword if you want to test email and
+// password login using a custom account you've already set up on your Firebase
+// project.
+static const char kCustomTestEmail[] = "put_custom_test_account_here@gmail.com";
+static const char kCustomTestPassword[] = "";
+
+static const int kWaitIntervalMs = 300; // NOLINT
+static const int kPhoneAuthCodeSendWaitMs = 600000; // NOLINT
+static const int kPhoneAuthCompletionWaitMs = 8000; // NOLINT
+static const int kPhoneAuthTimeoutMs = 0; // NOLINT
+
+// Set these in Firebase Console for your app.
+static const char kPhoneAuthTestPhoneNumber[] = "+12345556789"; // NOLINT
+static const char kPhoneAuthTestVerificationCode[] = "123456"; // NOLINT
+
+static const char kTestPassword[] = "testEmailPassword123";
+static const char kTestEmailBad[] = "bad.test.email@example.com";
+static const char kTestPasswordBad[] = "badTestPassword";
+static const char kTestIdTokenBad[] = "bad id token for testing";
+static const char kTestAccessTokenBad[] = "bad access token for testing";
+static const char kTestPasswordUpdated[] = "testpasswordupdated";
+static const char kTestIdProviderIdBad[] = "bad provider id for testing";
+static const char kTestServerAuthCodeBad[] = "bad server auth code"; // NOLINT
+
+using app_framework::LogDebug;
+using app_framework::LogError; // NOLINT
+using app_framework::LogInfo;
+using app_framework::ProcessEvents;
+
+using firebase_test_framework::FirebaseTest;
+
+class FirebaseAuthTest : public FirebaseTest {
+ public:
+ FirebaseAuthTest();
+ ~FirebaseAuthTest() override;
+
+ void SetUp() override;
+ void TearDown() override;
+
+ protected:
+ // Initialize Firebase App and Firebase Auth.
+ void Initialize();
+ // Shut down Firebase App and Firebase Auth.
+ void Terminate();
+
+ // Sign out of any user we were signed into. This is automatically called
+ // before and after every test.
+ void SignOut();
+
+ // Delete the current user if it's currently signed in.
+ void DeleteUser();
+
+ // Passthrough method to the base class's WaitForCompletion.
+ bool WaitForCompletion(firebase::Future future, const char* fn,
+ int expected_error = firebase::auth::kAuthErrorNone) {
+ return FirebaseTest::WaitForCompletion(future, fn, expected_error);
+ }
+
+ // Passthrough method to the base class's WaitForCompletion.
+ bool WaitForCompletion(firebase::Future future, const char* fn,
+ int expected_error = firebase::auth::kAuthErrorNone) {
+ return FirebaseTest::WaitForCompletion(future, fn, expected_error);
+ }
+
+ // Custom WaitForCompletion that checks if User matches afterwards.
+ bool WaitForCompletion(firebase::Future future,
+ const char* fn,
+ int expected_error = firebase::auth::kAuthErrorNone);
+ // Custom WaitForCompletion that checks if User matches afterwards.
+ bool WaitForCompletion(firebase::Future future,
+ const char* fn,
+ int expected_error = firebase::auth::kAuthErrorNone);
+
+ // Custom WaitForCompletion that checks if User and Provider ID matches
+ // afterwards.
+ bool WaitForCompletion(firebase::Future future,
+ const char* fn, const std::string& provider_id);
+
+ bool initialized_;
+ firebase::auth::Auth* auth_;
+};
+
+FirebaseAuthTest::FirebaseAuthTest() : initialized_(false), auth_(nullptr) {
+ FindFirebaseConfig(FIREBASE_CONFIG_STRING);
+}
+
+FirebaseAuthTest::~FirebaseAuthTest() {
+ // Must be cleaned up on exit.
+ assert(app_ == nullptr);
+ assert(auth_ == nullptr);
+}
+
+void FirebaseAuthTest::SetUp() {
+ FirebaseTest::SetUp();
+ Initialize();
+ SignOut();
+}
+
+void FirebaseAuthTest::TearDown() {
+ SignOut();
+ Terminate();
+ FirebaseTest::TearDown();
+}
+
+void FirebaseAuthTest::Initialize() {
+ if (initialized_) return;
+
+ InitializeApp();
+
+ LogDebug("Initializing Firebase Auth.");
+
+ ::firebase::ModuleInitializer initializer;
+ initializer.Initialize(app_, &auth_, [](::firebase::App* app, void* target) {
+ LogDebug("Try to initialize Firebase Auth");
+ firebase::InitResult result;
+ firebase::auth::Auth** auth_ptr =
+ reinterpret_cast(target);
+ *auth_ptr = firebase::auth::Auth::GetAuth(app, &result);
+ return result;
+ });
+
+ FirebaseTest::WaitForCompletion(initializer.InitializeLastResult(),
+ "Initialize");
+
+ ASSERT_EQ(initializer.InitializeLastResult().error(), 0)
+ << initializer.InitializeLastResult().error_message();
+
+ LogDebug("Successfully initialized Firebase Auth.");
+
+ initialized_ = true;
+}
+
+void FirebaseAuthTest::Terminate() {
+ if (!initialized_) return;
+
+ if (auth_) {
+ LogDebug("Shutdown the Auth library.");
+ delete auth_;
+ auth_ = nullptr;
+ }
+
+ TerminateApp();
+
+ initialized_ = false;
+
+ ProcessEvents(100);
+}
+
+bool FirebaseAuthTest::WaitForCompletion(
+ firebase::Future future, const char* fn,
+ int expected_error) {
+ bool succeeded = FirebaseTest::WaitForCompletion(future, fn, expected_error);
+
+ if (succeeded) {
+ if (expected_error == ::firebase::auth::kAuthErrorNone) {
+ const firebase::auth::User* future_result_user =
+ future.result() ? *future.result() : nullptr;
+ const firebase::auth::User* auth_user = auth_->current_user();
+ EXPECT_EQ(future_result_user, auth_user)
+ << "User returned by Future doesn't match User in Auth";
+ return (future_result_user == auth_user);
+ }
+ }
+ return succeeded;
+}
+
+bool FirebaseAuthTest::WaitForCompletion(
+ firebase::Future future, const char* fn,
+ int expected_error) {
+ bool succeeded = FirebaseTest::WaitForCompletion(future, fn, expected_error);
+
+ if (succeeded) {
+ if (expected_error == ::firebase::auth::kAuthErrorNone) {
+ const firebase::auth::User* future_result_user =
+ (future.result() && future.result()->user) ? future.result()->user
+ : nullptr;
+ const firebase::auth::User* auth_user = auth_->current_user();
+ EXPECT_EQ(future_result_user, auth_user)
+ << "User returned by Future doesn't match User in Auth";
+ return (future_result_user == auth_user);
+ }
+ }
+ return succeeded;
+}
+
+bool FirebaseAuthTest::WaitForCompletion(
+ firebase::Future future, const char* fn,
+ const std::string& provider_id) {
+ bool succeeded = FirebaseTest::WaitForCompletion(future, fn);
+ if (succeeded) {
+ const firebase::auth::SignInResult* result_ptr = future.result();
+ EXPECT_NE(result_ptr->user, nullptr);
+ EXPECT_EQ(result_ptr->info.provider_id, provider_id);
+ }
+ return succeeded;
+}
+
+void FirebaseAuthTest::SignOut() {
+ if (auth_ == nullptr) {
+ // Auth is not set up.
+ return;
+ }
+ if (auth_->current_user() == nullptr) {
+ // Already signed out.
+ return;
+ }
+ auth_->SignOut();
+ // Wait for the sign-out to finish.
+ while (auth_->current_user() != nullptr) {
+ if (ProcessEvents(100)) break;
+ }
+ ProcessEvents(100);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+}
+
+void FirebaseAuthTest::DeleteUser() {
+ if (auth_ != nullptr && auth_->current_user() != nullptr) {
+ FirebaseTest::WaitForCompletion(auth_->current_user()->Delete(),
+ "Delete User");
+ ProcessEvents(100);
+ }
+}
+
+TEST_F(FirebaseAuthTest, TestInitialization) {
+ // Initialized in SetUp and terminated in TearDown.
+ EXPECT_NE(app_, nullptr);
+ EXPECT_NE(auth_, nullptr);
+}
+
+TEST_F(FirebaseAuthTest, TestAnonymousSignin) {
+ // Test notification on SignIn().
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ EXPECT_TRUE(auth_->current_user()->is_anonymous());
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestCredentialCopy) {
+ // --- Credential copy tests -------------------------------------------------
+ {
+ firebase::auth::Credential email_cred =
+ firebase::auth::EmailAuthProvider::GetCredential(kCustomTestEmail,
+ kTestPassword);
+ firebase::auth::Credential facebook_cred =
+ firebase::auth::FacebookAuthProvider::GetCredential(
+ kTestAccessTokenBad);
+
+ std::string email_provider = email_cred.provider();
+ std::string facebook_provider = facebook_cred.provider();
+
+ // Test copy constructor.
+ firebase::auth::Credential cred_copy(email_cred);
+ EXPECT_EQ(cred_copy.provider(), email_provider);
+ // Test assignment operator.
+ cred_copy = facebook_cred;
+ EXPECT_EQ(cred_copy.provider(), facebook_provider);
+ }
+}
+
+class TestAuthStateListener : public firebase::auth::AuthStateListener {
+ public:
+ virtual void OnAuthStateChanged(firebase::auth::Auth* auth) { // NOLINT
+ // Log the provider ID.
+ std::string provider =
+ auth->current_user() ? auth->current_user()->provider_id() : "";
+ LogDebug("OnAuthStateChanged called, provider=%s", provider.c_str());
+ if (auth_states_.empty() || auth_states_.back() != provider) {
+ // Only log unique events.
+ auth_states_.push_back(provider);
+ }
+ }
+ const std::vector& auth_states() { return auth_states_; }
+
+ private:
+ std::vector auth_states_;
+};
+
+class TestIdTokenListener : public firebase::auth::IdTokenListener {
+ public:
+ virtual void OnIdTokenChanged(firebase::auth::Auth* auth) { // NOLINT
+ // Log the auth token (if available).
+ std::string token = "";
+ if (auth->current_user()) {
+ firebase::Future token_future =
+ auth->current_user()->GetToken(false);
+ if (token_future.status() == firebase::kFutureStatusComplete) {
+ if (token_future.error() == 0) {
+ token = *token_future.result();
+ }
+ } else {
+ token = "[in progress]";
+ }
+ }
+ LogDebug("OnIdTokenChanged called, token=%s", token.c_str());
+ if (token_states_.empty() || !token.empty() ||
+ token_states_.back() != token) {
+ // Only log unique empty events.
+ token_states_.push_back(token);
+ }
+ }
+
+ const std::vector& token_states() { return token_states_; }
+
+ private:
+ std::vector token_states_;
+};
+
+using testing::AnyOf;
+using testing::ElementsAre;
+using testing::Not;
+using testing::StrCaseEq;
+
+TEST_F(FirebaseAuthTest, TestTokensAndAuthStateListeners) {
+ TestAuthStateListener listener;
+ TestIdTokenListener token_listener;
+ auth_->AddAuthStateListener(&listener);
+ auth_->AddIdTokenListener(&token_listener);
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ // Get an initial token.
+ firebase::Future token_future =
+ auth_->current_user()->GetToken(false);
+ WaitForCompletion(token_future, "GetToken(false)");
+ std::string first_token = *token_future.result();
+ // Force a token refresh.
+ ProcessEvents(1000);
+ token_future = auth_->current_user()->GetToken(true);
+ WaitForCompletion(token_future, "GetToken(true)");
+ EXPECT_NE(*token_future.result(), "");
+ std::string second_token = *token_future.result();
+ EXPECT_NE(first_token, second_token);
+
+ DeleteUser();
+ SignOut();
+ auth_->RemoveAuthStateListener(&listener);
+ auth_->RemoveIdTokenListener(&token_listener);
+ // Providers should be blank, then Firebase, then blank.
+ EXPECT_THAT(listener.auth_states(),
+ ElementsAre("", StrCaseEq("Firebase"), ""));
+ // We should have blank, then two (or sometimes three) tokens, then blank.
+ EXPECT_THAT(token_listener.token_states(),
+ AnyOf(ElementsAre("", Not(""), Not(""), ""),
+ ElementsAre("", Not(""), Not(""), Not(""), "")));
+}
+
+static std::string GenerateEmailAddress() {
+ std::string email =
+ "random_user_" +
+ std::to_string(app_framework::GetCurrentTimeInMicroseconds()) +
+ "@gmail.com";
+ LogDebug("Generated email address: %s", email.c_str());
+ return email;
+}
+
+TEST_F(FirebaseAuthTest, TestEmailAndPasswordSignin) {
+ std::string email = GenerateEmailAddress();
+ // Register a random email and password. This signs us in as that user.
+ std::string password = kTestPassword;
+ firebase::Future create_user =
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), password.c_str());
+ WaitForCompletion(create_user, "CreateUserWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ // Sign out and log in using SignInWithCredential(EmailCredential).
+ SignOut();
+ {
+ firebase::auth::Credential email_credential =
+ firebase::auth::EmailAuthProvider::GetCredential(email.c_str(),
+ password.c_str());
+ WaitForCompletion(auth_->SignInWithCredential(email_credential),
+ "SignInWithCredential");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ }
+ // Sign out and log in using
+ // SignInAndRetrieveDataWithCredential(EmailCredential).
+ SignOut();
+ {
+ firebase::auth::Credential email_credential =
+ firebase::auth::EmailAuthProvider::GetCredential(email.c_str(),
+ password.c_str());
+ WaitForCompletion(
+ auth_->SignInAndRetrieveDataWithCredential(email_credential),
+ "SignAndRetrieveDataInWithCredential");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ }
+ SignOut();
+ // Sign in with SignInWithEmailAndPassword values.
+ firebase::Future sign_in_user =
+ auth_->SignInWithEmailAndPassword(email.c_str(), password.c_str());
+ WaitForCompletion(sign_in_user, "SignInWithEmailAndPassword");
+ ASSERT_NE(auth_->current_user(), nullptr);
+
+ // Then delete the account.
+ firebase::Future delete_user = auth_->current_user()->Delete();
+ WaitForCompletion(delete_user, "Delete");
+ firebase::Future invalid_sign_in_user =
+ auth_->SignInWithEmailAndPassword(email.c_str(), password.c_str());
+ WaitForCompletion(invalid_sign_in_user,
+ "SignInWithEmailAndPassword (invalid user)",
+ firebase::auth::kAuthErrorUserNotFound);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+}
+
+TEST_F(FirebaseAuthTest, TestUpdateUserProfile) {
+ std::string email = GenerateEmailAddress();
+ firebase::Future create_user =
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword);
+ WaitForCompletion(create_user, "CreateUserWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ // Set some user profile properties.
+ firebase::auth::User* user = *create_user.result();
+ const char kDisplayName[] = "Hello World";
+ const char kPhotoUrl[] = "http://example.com/image.jpg";
+ firebase::auth::User::UserProfile user_profile;
+ user_profile.display_name = kDisplayName;
+ user_profile.photo_url = kPhotoUrl;
+ firebase::Future update_profile = user->UpdateUserProfile(user_profile);
+ WaitForCompletion(update_profile, "UpdateUserProfile");
+ EXPECT_EQ(user->display_name(), kDisplayName);
+ EXPECT_EQ(user->photo_url(), kPhotoUrl);
+ SignOut();
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPassword),
+ "SignInWithEmailAndPassword");
+ EXPECT_EQ(user->display_name(), kDisplayName);
+ EXPECT_EQ(user->photo_url(), kPhotoUrl);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestUpdateEmailAndPassword) {
+ std::string email = GenerateEmailAddress();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ firebase::auth::User* user = auth_->current_user();
+
+ // Update the user's email and password.
+ const std::string new_email = "new_" + email;
+ WaitForCompletion(user->UpdateEmail(new_email.c_str()), "UpdateEmail");
+ WaitForCompletion(user->UpdatePassword(kTestPasswordUpdated),
+ "UpdatePassword");
+
+ firebase::auth::Credential new_email_cred =
+ firebase::auth::EmailAuthProvider::GetCredential(new_email.c_str(),
+ kTestPasswordUpdated);
+ WaitForCompletion(user->Reauthenticate(new_email_cred), "Reauthenticate");
+ EXPECT_NE(auth_->current_user(), nullptr);
+
+ WaitForCompletion(user->SendEmailVerification(), "SendEmailVerification");
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestLinkAnonymousUserWithEmailCredential) {
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ firebase::auth::User* user = auth_->current_user();
+ std::string email = GenerateEmailAddress();
+ firebase::auth::Credential credential =
+ firebase::auth::EmailAuthProvider::GetCredential(email.c_str(),
+ kTestPassword);
+ WaitForCompletion(user->LinkAndRetrieveDataWithCredential(credential),
+ "LinkAndRetrieveDataWithCredential");
+ WaitForCompletion(user->Unlink(credential.provider().c_str()), "Unlink");
+ SignOut();
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ std::string email1 = GenerateEmailAddress();
+ firebase::auth::Credential credential1 =
+ firebase::auth::EmailAuthProvider::GetCredential(email1.c_str(),
+ kTestPassword);
+ WaitForCompletion(user->LinkWithCredential(credential1),
+ "LinkWithCredential 1");
+ std::string email2 = GenerateEmailAddress();
+ firebase::auth::Credential credential2 =
+ firebase::auth::EmailAuthProvider::GetCredential(email2.c_str(),
+ kTestPassword);
+ WaitForCompletion(user->LinkWithCredential(credential2),
+ "LinkWithCredential 2",
+ firebase::auth::kAuthErrorProviderAlreadyLinked);
+ WaitForCompletion(user->Unlink(credential.provider().c_str()), "Unlink 2");
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestLinkAnonymousUserWithBadCredential) {
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ firebase::auth::User* pre_link_user = auth_->current_user();
+ firebase::auth::Credential twitter_cred =
+ firebase::auth::TwitterAuthProvider::GetCredential(kTestIdTokenBad,
+ kTestAccessTokenBad);
+ WaitForCompletion(pre_link_user->LinkWithCredential(twitter_cred),
+ "LinkWithCredential",
+ firebase::auth::kAuthErrorInvalidCredential);
+ // Ensure that user stays the same.
+ EXPECT_EQ(auth_->current_user(), pre_link_user);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSignInWithBadEmailFails) {
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(kTestEmailBad, kTestPassword),
+ "SignInWithEmailAndPassword", firebase::auth::kAuthErrorUserNotFound);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+}
+
+TEST_F(FirebaseAuthTest, TestSignInWithBadPasswordFails) {
+ std::string email = GenerateEmailAddress();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ SignOut();
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPasswordBad),
+ "SignInWithEmailAndPassword", firebase::auth::kAuthErrorWrongPassword);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+ SignOut();
+ // Sign back in and delete the user.
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPassword),
+ "SignInWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestCreateUserWithExistingEmailFails) {
+ std::string email = GenerateEmailAddress();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword 1");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ SignOut();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword 2",
+ firebase::auth::kAuthErrorEmailAlreadyInUse);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+ SignOut();
+ // Try again with a different password.
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPasswordBad),
+ "CreateUserWithEmailAndPassword 3",
+ firebase::auth::kAuthErrorEmailAlreadyInUse);
+ EXPECT_EQ(auth_->current_user(), nullptr);
+ SignOut();
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPassword),
+ "SignInWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSignInWithBadCredentials) {
+ // Get an anonymous user first.
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ // Hold on to the existing user, to make sure it is unchanged by bad signins.
+ firebase::auth::User* existing_user = auth_->current_user();
+ // Test signing in with a variety of bad credentials.
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::FacebookAuthProvider::GetCredential(
+ kTestAccessTokenBad)),
+ "SignInWithCredential (Facebook)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ // Ensure that failing to sign in with a credential doesn't modify the user.
+ EXPECT_EQ(auth_->current_user(), existing_user);
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::TwitterAuthProvider::GetCredential(
+ kTestIdTokenBad, kTestAccessTokenBad)),
+ "SignInWithCredential (Twitter)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::GitHubAuthProvider::GetCredential(
+ kTestAccessTokenBad)),
+ "SignInWithCredential (GitHub)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::GoogleAuthProvider::GetCredential(
+ kTestIdTokenBad, kTestAccessTokenBad)),
+ "SignInWithCredential (Google 1)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::GoogleAuthProvider::GetCredential(
+ kTestIdTokenBad, nullptr)),
+ "SignInWithCredential (Google 2)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+ WaitForCompletion(
+ auth_->SignInWithCredential(firebase::auth::OAuthProvider::GetCredential(
+ kTestIdProviderIdBad, kTestIdTokenBad, kTestAccessTokenBad)),
+ "SignInWithCredential (OAuth)", firebase::auth::kAuthErrorFailure);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+
+#if defined(__ANDROID__)
+ // Test Play Games sign-in on Android only.
+ WaitForCompletion(auth_->SignInWithCredential(
+ firebase::auth::PlayGamesAuthProvider::GetCredential(
+ kTestServerAuthCodeBad)),
+ "SignInWithCredential (Play Games)",
+ firebase::auth::kAuthErrorInvalidCredential);
+ EXPECT_EQ(auth_->current_user(), existing_user);
+#endif // defined(__ANDROID__)
+ DeleteUser();
+}
+
+#if TARGET_OS_IPHONE
+TEST_F(FirebaseAuthTest, TestGameCenterSignIn) {
+ // Test Game Center sign-in on iPhone only.
+ if (!firebase::auth::GameCenterAuthProvider::IsPlayerAuthenticated()) {
+ LogInfo("Not signed into Game Center, skipping test.");
+ GTEST_SKIP();
+ return;
+ }
+ LogDebug("Signed in, testing Game Center authentication.");
+ firebase::Future credential_future =
+ firebase::auth::GameCenterAuthProvider::GetCredential();
+ FirebaseTest::WaitForCompletion(credential_future,
+ "GameCenterAuthProvider::GetCredential()");
+
+ EXPECT_NE(credential_future.result(), nullptr);
+ if (credential_future.result()) {
+ WaitForCompletion(auth_->SignInWithCredential(*credential_future.result()),
+ "SignInWithCredential (Game Center)");
+ }
+ DeleteUser();
+}
+#endif // TARGET_OS_IPHONE
+
+TEST_F(FirebaseAuthTest, TestSendPasswordResetEmail) {
+ // Test Auth::SendPasswordResetEmail().
+ std::string email = GenerateEmailAddress();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ SignOut();
+ // Send to correct email.
+ WaitForCompletion(auth_->SendPasswordResetEmail(email.c_str()),
+ "SendPasswordResetEmail (good)");
+ // Send to incorrect email.
+ WaitForCompletion(auth_->SendPasswordResetEmail(kTestEmailBad),
+ "SendPasswordResetEmail (bad)",
+ firebase::auth::kAuthErrorUserNotFound);
+ // Delete user now that we are done with it.
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPassword),
+ "SignInWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestWithCustomEmailAndPassword) {
+ if (strlen(kCustomTestEmail) == 0 || strlen(kCustomTestPassword) == 0) {
+ LogInfo(
+ "Skipping %s. To enable this test, set "
+ "kCustomTestEmail and kCustomTestPassword in integration_test.cc.",
+ test_info_->name());
+ GTEST_SKIP();
+ return;
+ }
+ firebase::Future sign_in_user =
+ auth_->SignInWithEmailAndPassword(kCustomTestEmail, kCustomTestPassword);
+ WaitForCompletion(sign_in_user, "SignInWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+}
+
+TEST_F(FirebaseAuthTest, TestAuthPersistenceWithAnonymousSignin) {
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ EXPECT_TRUE(auth_->current_user()->is_anonymous());
+ Terminate();
+ ProcessEvents(2000);
+ Initialize();
+ EXPECT_NE(auth_, nullptr);
+ ASSERT_NE(auth_->current_user(), nullptr);
+ EXPECT_TRUE(auth_->current_user()->is_anonymous());
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestAuthPersistenceWithEmailSignin) {
+ std::string email = GenerateEmailAddress();
+ WaitForCompletion(
+ auth_->CreateUserWithEmailAndPassword(email.c_str(), kTestPassword),
+ "CreateUserWithEmailAndPassword");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ EXPECT_FALSE(auth_->current_user()->is_anonymous());
+ std::string prev_provider_id = auth_->current_user()->provider_id();
+ // Save the old provider ID list so we can make sure it's the same once it's
+ // loaded again.
+ std::vector prev_provider_data_ids;
+ for (int i = 0; i < auth_->current_user()->provider_data().size(); i++) {
+ prev_provider_data_ids.push_back(
+ auth_->current_user()->provider_data()[i]->provider_id());
+ }
+ Terminate();
+ ProcessEvents(2000);
+ Initialize();
+ EXPECT_NE(auth_, nullptr);
+ ASSERT_NE(auth_->current_user(), nullptr);
+ EXPECT_FALSE(auth_->current_user()->is_anonymous());
+ // Make sure the provider IDs are the same as they were before.
+ EXPECT_EQ(auth_->current_user()->provider_id(), prev_provider_id);
+ std::vector loaded_provider_data_ids;
+ for (int i = 0; i < auth_->current_user()->provider_data().size(); i++) {
+ loaded_provider_data_ids.push_back(
+ auth_->current_user()->provider_data()[i]->provider_id());
+ }
+ EXPECT_EQ(loaded_provider_data_ids, prev_provider_data_ids);
+
+ // Cleanup, ensure we are signed in as the user so we can delete it.
+ WaitForCompletion(
+ auth_->SignInWithEmailAndPassword(email.c_str(), kTestPassword),
+ "SignInWithEmailAndPassword");
+ EXPECT_NE(auth_->current_user(), nullptr);
+ DeleteUser();
+}
+
+class PhoneListener : public firebase::auth::PhoneAuthProvider::Listener {
+ public:
+ PhoneListener()
+ : on_verification_complete_count_(0),
+ on_verification_failed_count_(0),
+ on_code_sent_count_(0),
+ on_code_auto_retrieval_time_out_count_(0) {}
+
+ void OnVerificationCompleted(firebase::auth::Credential credential) override {
+ LogDebug("PhoneListener: successful automatic verification.");
+ on_verification_complete_count_++;
+ credential_ = credential;
+ }
+
+ void OnVerificationFailed(const std::string& error) override {
+ LogError("PhoneListener verification failed with error, %s", error.c_str());
+ on_verification_failed_count_++;
+ }
+
+ void OnCodeSent(const std::string& verification_id,
+ const firebase::auth::PhoneAuthProvider::ForceResendingToken&
+ force_resending_token) override {
+ LogDebug("PhoneListener: code sent. verification_id=%s",
+ verification_id.c_str());
+ verification_id_ = verification_id;
+ force_resending_token_ = force_resending_token;
+ on_code_sent_count_++;
+ }
+
+ void OnCodeAutoRetrievalTimeOut(const std::string& verification_id) override {
+ LogDebug("PhoneListener: auto retrieval timeout. verification_id=%s",
+ verification_id.c_str());
+ verification_id_ = verification_id;
+ on_code_auto_retrieval_time_out_count_++;
+ }
+
+ const std::string& verification_id() const { return verification_id_; }
+ const firebase::auth::PhoneAuthProvider::ForceResendingToken&
+ force_resending_token() const {
+ return force_resending_token_;
+ }
+ int on_verification_complete_count() const {
+ return on_verification_complete_count_;
+ }
+ int on_verification_failed_count() const {
+ return on_verification_failed_count_;
+ }
+ int on_code_sent_count() const { return on_code_sent_count_; }
+ int on_code_auto_retrieval_time_out_count() const {
+ return on_code_auto_retrieval_time_out_count_;
+ }
+
+ // Helper functions for workflow.
+ bool waiting_to_send_code() {
+ return on_verification_complete_count() == 0 &&
+ on_verification_failed_count() == 0 && on_code_sent_count() == 0;
+ }
+
+ bool waiting_for_verification_id() {
+ return on_verification_complete_count() == 0 &&
+ on_verification_failed_count() == 0 &&
+ on_code_auto_retrieval_time_out_count() == 0;
+ }
+
+ firebase::auth::Credential credential() { return credential_; }
+
+ private:
+ std::string verification_id_;
+ firebase::auth::PhoneAuthProvider::ForceResendingToken force_resending_token_;
+ firebase::auth::Credential credential_;
+ int on_verification_complete_count_;
+ int on_verification_failed_count_;
+ int on_code_sent_count_;
+ int on_code_auto_retrieval_time_out_count_;
+};
+
+TEST_F(FirebaseAuthTest, TestPhoneAuth) {
+ SKIP_TEST_ON_DESKTOP;
+
+#if TARGET_OS_IPHONE
+ // Note: This test requires interactivity on iOS, as it displays a CAPTCHA.
+ TEST_REQUIRES_USER_INTERACTION;
+#endif // TARGET_OS_IPHONE
+ {
+ firebase::auth::PhoneAuthProvider& phone_provider =
+ firebase::auth::PhoneAuthProvider::GetInstance(auth_);
+ LogDebug("Creating listener.");
+ PhoneListener listener;
+ LogDebug("Calling VerifyPhoneNumber.");
+ phone_provider.VerifyPhoneNumber(kPhoneAuthTestPhoneNumber,
+ kPhoneAuthTimeoutMs, nullptr, &listener);
+ // Wait for OnCodeSent() callback.
+ int wait_ms = 0;
+ LogDebug("Waiting for code send.");
+ while (listener.waiting_to_send_code()) {
+ if (wait_ms > kPhoneAuthCodeSendWaitMs) break;
+ ProcessEvents(kWaitIntervalMs);
+ wait_ms += kWaitIntervalMs;
+ }
+ EXPECT_EQ(listener.on_verification_failed_count(), 0);
+ LogDebug("Waiting for verification ID.");
+ // Wait for the listener to have a verification ID.
+ wait_ms = 0;
+ while (listener.waiting_for_verification_id()) {
+ if (wait_ms > kPhoneAuthCompletionWaitMs) break;
+ ProcessEvents(kWaitIntervalMs);
+ wait_ms += kWaitIntervalMs;
+ }
+ if (listener.on_verification_complete_count() > 0) {
+ LogDebug("Signing in with automatic verification code.");
+ WaitForCompletion(auth_->SignInWithCredential(listener.credential()),
+ "SignInWithCredential(PhoneCredential) automatic");
+ } else if (listener.on_verification_failed_count() > 0) {
+ FAIL() << "Automatic verification failed.";
+ } else {
+ // Did not automatically verify, submit verification code manually.
+ EXPECT_GT(listener.on_code_auto_retrieval_time_out_count(), 0);
+ EXPECT_NE(listener.verification_id(), "");
+ LogDebug("Signing in with verification code.");
+ const firebase::auth::Credential phone_credential =
+ phone_provider.GetCredential(listener.verification_id().c_str(),
+ kPhoneAuthTestVerificationCode);
+
+ WaitForCompletion(auth_->SignInWithCredential(phone_credential),
+ "SignInWithCredential(PhoneCredential)");
+ }
+ }
+ ProcessEvents(1000);
+ DeleteUser();
+}
+
+#if defined(ENABLE_OAUTH_TESTS)
+// SignInWithProvider
+TEST_F(FirebaseAuthTest, TestSuccessfulSignInFederatedProviderNoScopes) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest,
+ TestSuccessfulSignInFederatedProviderNoScopesNoCustomParameters) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSuccessfulSignInFederatedProvider) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id,
+ /*scopes=*/{"https://www.googleapis.com/auth/fitness.activity.read"},
+ /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSignInFederatedProviderBadProviderIdFails) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ /*provider=*/"MadeUpProvider",
+ /*scopes=*/{"https://www.googleapis.com/auth/fitness.activity.read"},
+ /*custom_parameters=*/{{"req_id", "5321"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "SignInWithProvider",
+ firebase::auth::kAuthErrorInvalidProviderId);
+}
+
+// ReauthenticateWithProvider
+TEST_F(FirebaseAuthTest, TestSuccessfulReauthenticateWithProvider) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id,
+ /*scopes=*/{"https://www.googleapis.com/auth/fitness.activity.read"},
+ /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ if (WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id)) {
+ WaitForCompletion(
+ sign_in_future.result()->user->ReauthenticateWithProvider(&provider),
+ "ReauthenticateWithProvider", provider_id);
+ }
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSuccessfulReauthenticateWithProviderNoScopes) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ if (WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id)) {
+ WaitForCompletion(
+ sign_in_future.result()->user->ReauthenticateWithProvider(&provider),
+ "ReauthenticateWithProvider", provider_id);
+ }
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest,
+ TestSuccessfulReauthenticateWithProviderNoScopesNoCustomParameters) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ if (WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id)) {
+ WaitForCompletion(
+ sign_in_future.result()->user->ReauthenticateWithProvider(&provider),
+ "ReauthenticateWithProvider", provider_id);
+ }
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestReauthenticateWithProviderBadProviderIdFails) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(provider_id);
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->SignInWithProvider(&provider);
+ if (WaitForCompletion(sign_in_future, "SignInWithProvider", provider_id)) {
+ provider_data.provider_id = "MadeUpProvider";
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future reauth_future =
+ auth_->current_user()->ReauthenticateWithProvider(&provider);
+ WaitForCompletion(reauth_future, "ReauthenticateWithProvider",
+ firebase::auth::kAuthErrorInvalidProviderId);
+ }
+ DeleteUser();
+}
+
+// LinkWithProvider
+TEST_F(FirebaseAuthTest, TestSuccessfulLinkFederatedProviderNoScopes) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->current_user()->LinkWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "LinkWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest,
+ TestSuccessfulLinkFederatedProviderNoScopesNoCustomParameters) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id, /*scopes=*/{}, /*custom_parameters=*/{});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->current_user()->LinkWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "LinkWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestSuccessfulLinkFederatedProvider) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ const std::string provider_id =
+ firebase::auth::GoogleAuthProvider::kProviderId;
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ provider_id,
+ /*scopes=*/{"https://www.googleapis.com/auth/fitness.activity.read"},
+ /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->current_user()->LinkWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "LinkWithProvider", provider_id);
+ DeleteUser();
+}
+
+TEST_F(FirebaseAuthTest, TestLinkFederatedProviderBadProviderIdFails) {
+ SKIP_TEST_ON_DESKTOP;
+ TEST_REQUIRES_USER_INTERACTION;
+
+ WaitForCompletion(auth_->SignInAnonymously(), "SignInAnonymously");
+ ASSERT_NE(auth_->current_user(), nullptr);
+ firebase::auth::FederatedOAuthProviderData provider_data(
+ /*provider=*/"MadeUpProvider",
+ /*scopes=*/{"https://www.googleapis.com/auth/fitness.activity.read"},
+ /*custom_parameters=*/{{"req_id", "1234"}});
+ firebase::auth::FederatedOAuthProvider provider(provider_data);
+ firebase::Future sign_in_future =
+ auth_->current_user()->LinkWithProvider(&provider);
+ WaitForCompletion(sign_in_future, "LinkWithProvider",
+ firebase::auth::kAuthErrorInvalidProviderId);
+ DeleteUser();
+}
+
+#endif // defined(ENABLE_OAUTH_TESTS)
+
+} // namespace firebase_testapp_automated
diff --git a/database/integration_test/AndroidManifest.xml b/database/integration_test/AndroidManifest.xml
new file mode 100644
index 0000000000..4a470ed5fd
--- /dev/null
+++ b/database/integration_test/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/database/integration_test/CMakeLists.txt b/database/integration_test/CMakeLists.txt
new file mode 100644
index 0000000000..29638cae20
--- /dev/null
+++ b/database/integration_test/CMakeLists.txt
@@ -0,0 +1,224 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Cmake file for a single C++ integration test build.
+
+cmake_minimum_required(VERSION 2.8)
+
+# User settings for Firebase integration tests.
+# Path to Firebase SDK.
+# Try to read the path to the Firebase C++ SDK from an environment variable.
+if (NOT "$ENV{FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "$ENV{FIREBASE_CPP_SDK_DIR}")
+else()
+ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../cpp_sdk_version.json")
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
+ else()
+ set(DEFAULT_FIREBASE_CPP_SDK_DIR "firebase_cpp_sdk")
+ endif()
+endif()
+if ("${FIREBASE_CPP_SDK_DIR}" STREQUAL "")
+ set(FIREBASE_CPP_SDK_DIR ${DEFAULT_FIREBASE_CPP_SDK_DIR})
+endif()
+if(NOT EXISTS ${FIREBASE_CPP_SDK_DIR})
+ message(FATAL_ERROR "The Firebase C++ SDK directory does not exist: ${FIREBASE_CPP_SDK_DIR}. See the readme.md for more information")
+endif()
+
+# Copy all prerequisite files for integration tests to run.
+if(NOT ANDROID)
+ if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py)
+ # If this is running from inside the SDK directory, run the setup script.
+ execute_process(COMMAND "python" "${CMAKE_CURRENT_LIST_DIR}/../../setup_integration_tests.py" "${CMAKE_CURRENT_LIST_DIR}")
+ endif()
+endif()
+
+# Windows runtime mode, either MD or MT depending on whether you are using
+# /MD or /MT. For more information see:
+# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+set(MSVC_RUNTIME_MODE MD)
+
+project(firebase_testapp)
+
+# Integration test source files.
+set(FIREBASE_APP_FRAMEWORK_SRCS
+ src/app_framework.cc
+ src/app_framework.h
+)
+
+set(FIREBASE_TEST_FRAMEWORK_SRCS
+ src/firebase_test_framework.h
+ src/firebase_test_framework.cc
+)
+
+set(FIREBASE_INTEGRATION_TEST_SRCS
+ src/integration_test.cc
+)
+
+# The include directory for the testapp.
+include_directories(src)
+
+# Integration test uses some features that require C++ 11, such as lambdas.
+set (CMAKE_CXX_STANDARD 11)
+
+# Download and unpack googletest (and googlemock) at configure time
+set(GOOGLETEST_ROOT ${CMAKE_CURRENT_LIST_DIR}/external/googletest)
+# Note: Once googletest is downloaded once, it won't be updated or
+# downloaded again unless you delete the "external/googletest"
+# directory.
+if (NOT EXISTS ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ configure_file(googletest.cmake
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/CMakeLists.txt COPYONLY)
+ execute_process(COMMAND ${CMAKE_COMMAND} .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/googletest )
+ if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+ endif()
+endif()
+
+if(ANDROID)
+ # Build an Android application.
+
+ # Source files used for the Android build.
+ set(FIREBASE_APP_FRAMEWORK_ANDROID_SRCS
+ src/android/android_app_framework.cc
+ )
+
+ # Source files used for the Android build.
+ set(FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS
+ src/android/android_firebase_test_framework.cc
+ )
+
+ # Build native_app_glue as a static lib
+ add_library(native_app_glue STATIC
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+
+ # Export ANativeActivity_onCreate(),
+ # Refer to: https://github.com/android-ndk/ndk/issues/381.
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
+
+ add_library(gtest STATIC
+ ${GOOGLETEST_ROOT}/src/googletest/src/gtest-all.cc)
+ target_include_directories(gtest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include)
+ add_library(gmock STATIC
+ ${GOOGLETEST_ROOT}/src/googlemock/src/gmock-all.cc)
+ target_include_directories(gmock
+ PRIVATE ${GOOGLETEST_ROOT}/src/googletest
+ PRIVATE ${GOOGLETEST_ROOT}/src/googlemock
+ PUBLIC ${GOOGLETEST_ROOT}/src/googletest/include
+ PUBLIC ${GOOGLETEST_ROOT}/src/googlemock/include)
+
+ # Define the target as a shared library, as that is what gradle expects.
+ set(integration_test_target_name "android_integration_test_main")
+ add_library(${integration_test_target_name} SHARED
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_ANDROID_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_ANDROID_SRCS}
+ )
+
+ target_include_directories(${integration_test_target_name} PRIVATE
+ ${ANDROID_NDK}/sources/android/native_app_glue)
+
+ set(ADDITIONAL_LIBS log android atomic native_app_glue)
+else()
+ # Build a desktop application.
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+
+ # Prevent overriding the parent project's compiler/linker
+ # settings on Windows
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This defines
+ # the gtest and gtest_main targets.
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/googletest/src
+ ${CMAKE_CURRENT_LIST_DIR}/external/googletest/build
+ EXCLUDE_FROM_ALL)
+
+ # The gtest/gtest_main targets carry header search path
+ # dependencies automatically when using CMake 2.8.11 or
+ # later. Otherwise we have to add them here ourselves.
+ if (CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories("${gtest_SOURCE_DIR}/include")
+ include_directories("${gmock_SOURCE_DIR}/include")
+ endif()
+
+ # Windows runtime mode, either MD or MT depending on whether you are using
+ # /MD or /MT. For more information see:
+ # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+ set(MSVC_RUNTIME_MODE MD)
+
+ # Platform abstraction layer for the desktop integration test.
+ set(FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS
+ src/desktop/desktop_app_framework.cc
+ )
+
+ set(integration_test_target_name "integration_test")
+ add_executable(${integration_test_target_name}
+ ${FIREBASE_APP_FRAMEWORK_SRCS}
+ ${FIREBASE_APP_FRAMEWORK_DESKTOP_SRCS}
+ ${FIREBASE_TEST_FRAMEWORK_SRCS}
+ ${FIREBASE_INTEGRATION_TEST_SRCS}
+ )
+
+ if(APPLE)
+ set(ADDITIONAL_LIBS
+ gssapi_krb5
+ pthread
+ "-framework CoreFoundation"
+ "-framework Foundation"
+ "-framework GSS"
+ "-framework Security"
+ )
+ elseif(MSVC)
+ set(ADDITIONAL_LIBS advapi32 ws2_32 crypt32 iphlpapi psapi userenv shell32)
+ else()
+ set(ADDITIONAL_LIBS pthread)
+ endif()
+
+ # If a config file is present, copy it into the binary location so that it's
+ # possible to create the default Firebase app.
+ set(FOUND_JSON_FILE FALSE)
+ foreach(config "google-services-desktop.json" "google-services.json")
+ if (EXISTS ${config})
+ add_custom_command(
+ TARGET ${integration_test_target_name} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${config} $)
+ set(FOUND_JSON_FILE TRUE)
+ break()
+ endif()
+ endforeach()
+ if(NOT FOUND_JSON_FILE)
+ message(WARNING "Failed to find either google-services-desktop.json or google-services.json. See the readme.md for more information.")
+ endif()
+endif()
+
+# Add the Firebase libraries to the target using the function from the SDK.
+add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
+# Note that firebase_app needs to be last in the list.
+set(firebase_libs firebase_database firebase_auth firebase_app)
+set(gtest_libs gtest gmock)
+target_link_libraries(${integration_test_target_name} ${firebase_libs}
+ ${gtest_libs} ${ADDITIONAL_LIBS})
diff --git a/database/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json b/database/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..d8db8d65fd
--- /dev/null
+++ b/database/integration_test/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/database/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json b/database/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..6f870a4629
--- /dev/null
+++ b/database/integration_test/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,51 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/database/integration_test/Info.plist b/database/integration_test/Info.plist
new file mode 100644
index 0000000000..a21836a7b2
--- /dev/null
+++ b/database/integration_test/Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ com.google.firebase.cpp.database.testapp
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ google
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.255980362477-3a1nf8c4nl0c7hlnlnmc98hbtg2mnbue
+ firebase-game-loop
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/database/integration_test/LaunchScreen.storyboard b/database/integration_test/LaunchScreen.storyboard
new file mode 100644
index 0000000000..673e0f7e68
--- /dev/null
+++ b/database/integration_test/LaunchScreen.storyboard
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/database/integration_test/LibraryManifest.xml b/database/integration_test/LibraryManifest.xml
new file mode 100644
index 0000000000..edd412c1b8
--- /dev/null
+++ b/database/integration_test/LibraryManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/database/integration_test/Podfile b/database/integration_test/Podfile
new file mode 100644
index 0000000000..1094de283a
--- /dev/null
+++ b/database/integration_test/Podfile
@@ -0,0 +1,16 @@
+
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+# Firebase Realtime Database test application.
+
+target 'integration_test' do
+ pod 'Firebase/Database', '6.24.0'
+ pod 'Firebase/Auth', '6.24.0'
+end
+
+post_install do |installer|
+ # If this is running from inside the SDK directory, run the setup script.
+ system("if [[ -r ../../setup_integration_tests.py ]]; then python ../../setup_integration_tests.py .; fi")
+ system("/usr/bin/python ./download_googletest.py")
+end
+
diff --git a/database/integration_test/build.gradle b/database/integration_test/build.gradle
new file mode 100644
index 0000000000..f7f6059178
--- /dev/null
+++ b/database/integration_test/build.gradle
@@ -0,0 +1,77 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.google.gms:google-services:4.0.1'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ maven { url 'https://maven.google.com' }
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src/android/java']
+ res.srcDirs = ['res']
+ }
+ }
+
+ defaultConfig {
+ applicationId 'com.google.firebase.cpp.database.testapp'
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ externalNativeBuild.cmake {
+ arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir"
+ }
+ }
+ externalNativeBuild.cmake {
+ path 'CMakeLists.txt'
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFile getDefaultProguardFile('proguard-android.txt')
+ proguardFile file('proguard.pro')
+ }
+ }
+}
+
+apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
+firebaseCpp.dependencies {
+ auth
+ database
+}
+
+apply plugin: 'com.google.gms.google-services'
+
+task copyIntegrationTestFiles(type:Exec) {
+ // If this is running form inside the SDK directory, run the setup script.
+ if (project.file('../../setup_integration_tests.py').exists()) {
+ commandLine 'python', '../../setup_integration_tests.py', project.projectDir.toString()
+ }
+ else {
+ commandLine 'echo', ''
+ }
+}
+
+build.dependsOn(copyIntegrationTestFiles)
\ No newline at end of file
diff --git a/database/integration_test/googletest.cmake b/database/integration_test/googletest.cmake
new file mode 100644
index 0000000000..2ecbb08679
--- /dev/null
+++ b/database/integration_test/googletest.cmake
@@ -0,0 +1,34 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Download GoogleTest from GitHub as an external project.
+
+# This CMake file is taken from:
+# https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG master
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/database/integration_test/gradle/wrapper/gradle-wrapper.jar b/database/integration_test/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
Binary files /dev/null and b/database/integration_test/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/database/integration_test/gradle/wrapper/gradle-wrapper.properties b/database/integration_test/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..35732b09a0
--- /dev/null
+++ b/database/integration_test/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Nov 27 14:03:45 PST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/database/integration_test/gradlew b/database/integration_test/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/database/integration_test/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/database/integration_test/gradlew.bat b/database/integration_test/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/database/integration_test/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/database/integration_test/integration_test.xcodeproj/project.pbxproj b/database/integration_test/integration_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..d1d6b852d1
--- /dev/null
+++ b/database/integration_test/integration_test.xcodeproj/project.pbxproj
@@ -0,0 +1,364 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */; };
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D51C85F68000C89379 /* Foundation.framework */; };
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D71C85F68000C89379 /* CoreGraphics.framework */; };
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 529226D91C85F68000C89379 /* UIKit.framework */; };
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D61C5F8C22BABA9B00A79141 /* Images.xcassets */; };
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D61C5F9222BABAD100A79141 /* integration_test.cc */; };
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D62CCBBF22F367140099BE9F /* gmock-all.cc */; };
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */; };
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D67D355622BABD2100292C1D /* gtest-all.cc */; };
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E722CB322900C2651A /* ios_app_framework.mm */; };
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */ = {isa = PBXBuildFile; fileRef = D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */; };
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EC22CB323300C2651A /* firebase_test_framework.cc */; };
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6C179EF22CB32A000C2651A /* app_framework.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 529226D21C85F68000C89379 /* integration_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 529226D51C85F68000C89379 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 529226D91C85F68000C89379 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 529226EE1C85F68000C89379 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ D61C5F8D22BABA9C00A79141 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D61C5F9222BABAD100A79141 /* integration_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test.cc; path = src/integration_test.cc; sourceTree = ""; };
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "external/googletest/src/googlemock/src/gmock-all.cc"; sourceTree = ""; };
+ D62CCBC122F367320099BE9F /* gmock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gmock.h; path = external/googletest/src/googlemock/include/gmock/gmock.h; sourceTree = ""; };
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ D67D355622BABD2100292C1D /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "external/googletest/src/googletest/src/gtest-all.cc"; sourceTree = ""; };
+ D67D355722BABD2100292C1D /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtest.h; path = external/googletest/src/googletest/include/gtest/gtest.h; sourceTree = ""; };
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_app_framework.mm; path = src/ios/ios_app_framework.mm; sourceTree = ""; };
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_firebase_test_framework.mm; path = src/ios/ios_firebase_test_framework.mm; sourceTree = ""; };
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = firebase_test_framework.h; path = src/firebase_test_framework.h; sourceTree = ""; };
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = firebase_test_framework.cc; path = src/firebase_test_framework.cc; sourceTree = ""; };
+ D6C179ED22CB323300C2651A /* app_framework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = app_framework.h; path = src/app_framework.h; sourceTree = ""; };
+ D6C179EF22CB32A000C2651A /* app_framework.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = app_framework.cc; path = src/app_framework.cc; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 529226CF1C85F68000C89379 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 529226D81C85F68000C89379 /* CoreGraphics.framework in Frameworks */,
+ 529226DA1C85F68000C89379 /* UIKit.framework in Frameworks */,
+ 529226D61C85F68000C89379 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 529226C91C85F68000C89379 = {
+ isa = PBXGroup;
+ children = (
+ D61C5F8C22BABA9B00A79141 /* Images.xcassets */,
+ D61C5F8D22BABA9C00A79141 /* Info.plist */,
+ D66B16861CE46E8900E5638A /* LaunchScreen.storyboard */,
+ 520BC0381C869159008CFBC3 /* GoogleService-Info.plist */,
+ 5292271D1C85FB5500C89379 /* src */,
+ 529226D41C85F68000C89379 /* Frameworks */,
+ 529226D31C85F68000C89379 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 529226D31C85F68000C89379 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D21C85F68000C89379 /* integration_test.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 529226D41C85F68000C89379 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 529226D51C85F68000C89379 /* Foundation.framework */,
+ 529226D71C85F68000C89379 /* CoreGraphics.framework */,
+ 529226D91C85F68000C89379 /* UIKit.framework */,
+ 529226EE1C85F68000C89379 /* XCTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 5292271D1C85FB5500C89379 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D62CCBC122F367320099BE9F /* gmock.h */,
+ D62CCBBF22F367140099BE9F /* gmock-all.cc */,
+ D67D355622BABD2100292C1D /* gtest-all.cc */,
+ D67D355722BABD2100292C1D /* gtest.h */,
+ D6C179EF22CB32A000C2651A /* app_framework.cc */,
+ D6C179ED22CB323300C2651A /* app_framework.h */,
+ D6C179EC22CB323300C2651A /* firebase_test_framework.cc */,
+ D6C179EB22CB323300C2651A /* firebase_test_framework.h */,
+ D61C5F9222BABAD100A79141 /* integration_test.cc */,
+ 5292271E1C85FB5B00C89379 /* ios */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ 5292271E1C85FB5B00C89379 /* ios */ = {
+ isa = PBXGroup;
+ children = (
+ D6C179E722CB322900C2651A /* ios_app_framework.mm */,
+ D6C179E822CB322900C2651A /* ios_firebase_test_framework.mm */,
+ );
+ name = ios;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 529226D11C85F68000C89379 /* integration_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */;
+ buildPhases = (
+ 529226CE1C85F68000C89379 /* Sources */,
+ 529226CF1C85F68000C89379 /* Frameworks */,
+ 529226D01C85F68000C89379 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = integration_test;
+ productName = testapp;
+ productReference = 529226D21C85F68000C89379 /* integration_test.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 529226CA1C85F68000C89379 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0640;
+ ORGANIZATIONNAME = Google;
+ TargetAttributes = {
+ 529226D11C85F68000C89379 = {
+ CreatedOnToolsVersion = 6.4;
+ DevelopmentTeam = EQHXZ8M8AV;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 529226C91C85F68000C89379;
+ productRefGroup = 529226D31C85F68000C89379 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 529226D11C85F68000C89379 /* integration_test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 529226D01C85F68000C89379 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D61C5F8E22BABA9C00A79141 /* Images.xcassets in Resources */,
+ D66B16871CE46E8900E5638A /* LaunchScreen.storyboard in Resources */,
+ 520BC0391C869159008CFBC3 /* GoogleService-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 529226CE1C85F68000C89379 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D67D355822BABD2200292C1D /* gtest-all.cc in Sources */,
+ D62CCBC022F367140099BE9F /* gmock-all.cc in Sources */,
+ D6C179EA22CB322900C2651A /* ios_firebase_test_framework.mm in Sources */,
+ D61C5F9622BABAD200A79141 /* integration_test.cc in Sources */,
+ D6C179E922CB322900C2651A /* ios_app_framework.mm in Sources */,
+ D6C179F022CB32A000C2651A /* app_framework.cc in Sources */,
+ D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 529226F71C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.4;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 529226F81C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ 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 = 8.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 529226FA1C85F68000C89379 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 529226FB1C85F68000C89379 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+ "\"$(SRCROOT)/src\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock/include\"",
+ "\"$(SRCROOT)/external/googletest/src/googletest\"",
+ "\"$(SRCROOT)/external/googletest/src/googlemock\"",
+ );
+ INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 529226CD1C85F68000C89379 /* Build configuration list for PBXProject "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226F71C85F68000C89379 /* Debug */,
+ 529226F81C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 529226F91C85F68000C89379 /* Build configuration list for PBXNativeTarget "integration_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 529226FA1C85F68000C89379 /* Debug */,
+ 529226FB1C85F68000C89379 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 529226CA1C85F68000C89379 /* Project object */;
+}
diff --git a/database/integration_test/proguard.pro b/database/integration_test/proguard.pro
new file mode 100644
index 0000000000..2d04b8a9a5
--- /dev/null
+++ b/database/integration_test/proguard.pro
@@ -0,0 +1,2 @@
+-ignorewarnings
+-keep,includedescriptorclasses public class com.google.firebase.example.LoggingUtils { * ; }
diff --git a/database/integration_test/readme.md b/database/integration_test/readme.md
new file mode 100644
index 0000000000..6b9efa6fcd
--- /dev/null
+++ b/database/integration_test/readme.md
@@ -0,0 +1,215 @@
+Cloud Storage for Firebase Quickstart
+========================
+
+The Cloud Storage for Firebase Integration Test (integration test) demonstrates
+Cloud Storage operations with the Firebase C++ SDK for Cloud Storage.
+The application has no user interface and simply logs actions it's performing
+to the console.
+
+The integration test uses the GoogleTest testing framework to perform a variety
+of tests on a live Firebase project. Tests include:
+ - Creating a firebase::App in a platform-specific way. The App holds
+ platform-specific context that's used by other Firebase APIs, and is a
+ central point for communication between the Cloud Storage C++ and
+ Firebase Auth C++ libraries.
+ - Getting a pointer to firebase::Auth, and signs in anonymously. This allows the
+ integration test to access a Cloud Storage instance with authentication rules
+ enabled, which is the default setting in Firebase Console.
+ - Gets a StorageReference to a test-specific storage node, uses
+ StorageReference::Child() to create a child with a unique key based on the
+ current time in microseconds to work in, and gets a reference to that child,
+ which the integration test will use for the remainder of its actions.
+ - Uploads some sample files and reads them back to ensure the storage can be
+ read from and written to.
+ - Checks the Metadata of the uploaded and downloaded files to ensure they
+ return the expected values for things like size and date modified.
+ - Disconnects and then reconnects and verifies it still has access to the
+ files uploaded.
+ - Shuts down the Cloud Storage, Firebase Auth, and Firebase App systems,
+ ensuring the systems can be shut down in any order.
+
+Introduction
+------------
+
+- [Read more about Cloud Storage for Firebase](https://firebase.google.com/docs/storage/)
+
+Building and Running the integration test
+-----------------------------------------
+
+### iOS
+ - Link your iOS app to the Firebase libraries.
+ - Get CocoaPods version 1 or later by running,
+ ```
+ sudo gem install cocoapods --pre
+ ```
+ - From the integration_tests/storage directory, install the CocoaPods listed
+ in the Podfile by running,
+ ```
+ pod install
+ ```
+ - Open the generated Xcode workspace (which now has the CocoaPods),
+ ```
+ open integration_test.xcworkspace
+ ```
+ - For further details please refer to the
+ [general instructions for setting up an iOS app with Firebase](https://firebase.google.com/docs/ios/setup).
+ - Register your iOS app with Firebase.
+ - Create a new app on the [Firebase console](https://firebase.google.com/console/), and attach
+ your iOS app to it.
+ - You can use "com.google.firebase.cpp.storage.testapp" as the iOS Bundle
+ ID while you're testing. You can omit App Store ID while testing.
+ - Add the GoogleService-Info.plist that you downloaded from Firebase console
+ to the integration_test/storage directory. This file identifies your iOS
+ app to the Firebase backend.
+ - In the Firebase console for your app, select "Auth", then enable
+ "Anonymous". This will allow the integration test to use anonymous sign-in to
+ authenticate with Cloud Storage, which requires a signed-in user by
+ default (an anonymous user will suffice).
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Add the following frameworks from the Firebase C++ SDK to the project:
+ - frameworks/ios/universal/firebase.framework
+ - frameworks/ios/universal/firebase_auth.framework
+ - frameworks/ios/universal/firebase_storage.framework
+ - You will need to either,
+ 1. Check "Copy items if needed" when adding the frameworks, or
+ 2. Add the framework path in "Framework Search Paths"
+ - e.g. If you downloaded the Firebase C++ SDK to
+ `/Users/me/firebase_cpp_sdk`,
+ then you would add the path
+ `/Users/me/firebase_cpp_sdk/frameworks/ios/universal`.
+ - To add the path, in XCode, select your project in the project
+ navigator, then select your target in the main window.
+ Select the "Build Settings" tab, and click "All" to see all
+ the build settings. Scroll down to "Search Paths", and add
+ your path to "Framework Search Paths".
+ - In XCode, build & run the sample on an iOS device or simulator.
+ - The integration test has no interativity. The output of the app can be
+ viewed via the console or on the device's display. In Xcode, select "View
+ --> Debug Area --> Activate Console" from the menu to view the console.
+
+### Android
+ - Register your Android app with Firebase.
+ - Create a new app on
+ the [Firebase console](https://firebase.google.com/console/), and attach
+ your Android app to it.
+ - You can use "com.google.firebase.cpp.storage.testapp" as the Package
+ Name while you're testing.
+ - To
+ [generate a SHA1](https://developers.google.com/android/guides/client-auth)
+ run this command on Mac and Linux,
+ ```
+ keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
+ ```
+ or this command on Windows,
+ ```
+ keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore
+ ```
+ - If keytool reports that you do not have a debug.keystore, you can
+ [create one with](http://developer.android.com/tools/publishing/app-signing.html#signing-manually),
+ ```
+ keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"
+ ```
+ - Add the `google-services.json` file that you downloaded from Firebase
+ console to the integration_test/storage directory. This file identifies
+ your Android app to the Firebase backend.
+ - In the Firebase console for your app, select "Auth", then enable
+ "Anonymous". This will allow the integration test to use anonymous sign-in
+ to authenticate with Cloud Storage, which requires a signed-in user by
+ default (an anonymous user will suffice).
+ - For further details please refer to the
+ [general instructions for setting up an Android app with Firebase](https://firebase.google.com/docs/android/setup).
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Configure the location of the Firebase C++ SDK by setting the
+ firebase\_cpp\_sdk.dir Gradle property to the SDK install directory.
+ For example, in the project directory:
+ ```
+ echo "systemProp.firebase\_cpp\_sdk.dir=/User/$USER/firebase\_cpp\_sdk" >> gradle.properties
+ ```
+ - Ensure the Android SDK and NDK locations are set in Android Studio.
+ - From the Android Studio launch menu, go to `File/Project Structure...` or
+ `Configure/Project Defaults/Project Structure...`
+ (Shortcut: Control + Alt + Shift + S on windows, Command + ";" on a mac)
+ and download the SDK and NDK if the locations are not yet set.
+ - Open *build.gradle* in Android Studio.
+ - From the Android Studio launch menu, "Open an existing Android Studio
+ project", and select `build.gradle`.
+ - Install the SDK Platforms that Android Studio reports missing.
+ - Build the integration test and run it on an Android device or emulator.
+ - Once you've installed the SDKs in Android Studio, you can build the
+ integration test in Android Studio, or from the command-line by running
+ `./gradlew build`.
+ - The integration test has no interactive interface. The output of the app can
+ be viewed on the device's display, or in the logcat output of Android studio
+ or by running "adb logcat *:W android_main firebase" from the command line.
+
+### Desktop
+ - Register your app with Firebase.
+ - Create a new app on the [Firebase console](https://firebase.google.com/console/),
+ following the above instructions for Android or iOS.
+ - If you have an Android project, add the `google-services.json` file that
+ you downloaded from the Firebase console to the integration_test/storage
+ directory.
+ - If you have an iOS project, and don't wish to use an Android project,
+ you can use the Python script `generate_xml_from_google_services_json.py --plist`,
+ located in the Firebase C++ SDK, to convert your `GoogleService-Info.plist`
+ file into a `google-services-desktop.json` file, which can then be
+ placed in the integration_test/storage directory .
+ - Download the Firebase C++ SDK linked from
+ [https://firebase.google.com/docs/cpp/setup](https://firebase.google.com/docs/cpp/setup)
+ and unzip it to a directory of your choice.
+ - Configure the integration test with the location of the Firebase C++ SDK.
+ This can be done a couple different ways (in highest to lowest priority):
+ - When invoking cmake, pass in the location with
+ -DFIREBASE_CPP_SDK_DIR=/path/to/firebase_cpp_sdk.
+ - Set an environment variable for FIREBASE_CPP_SDK_DIR to the path to use.
+ - Edit the CMakeLists.txt file, changing the FIREBASE_CPP_SDK_DIR path
+ to the appropriate location.
+ - From the integration_test/storage directory, generate the build files by running,
+ ```
+ cmake .
+ ```
+ If you want to use XCode, you can use -G"Xcode" to generate the project.
+ Similarly, to use Visual Studio, -G"Visual Studio 15 2017". For more
+ information, see
+ [CMake generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
+ - Build the integration test, by either opening the generated project file
+ based on the platform, or running,
+ ```
+ cmake --build .
+ ```
+ - Execute the integration test by running,
+ ```
+ ./integration_test
+ ```
+ Note that the executable might be under another directory, such as Debug.
+ - The integration test has no user interface, but the output can be viewed via
+ the console.
+
+Support
+-------
+
+[https://firebase.google.com/support/](https://firebase.google.com/support/)
+
+License
+-------
+
+Copyright 2016 Google, Inc.
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor
+license agreements. See the NOTICE file distributed with this work for
+additional information regarding copyright ownership. The ASF licenses this
+file to you under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
diff --git a/database/integration_test/res/layout/main.xml b/database/integration_test/res/layout/main.xml
new file mode 100644
index 0000000000..d3ffb63082
--- /dev/null
+++ b/database/integration_test/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/database/integration_test/res/values/strings.xml b/database/integration_test/res/values/strings.xml
new file mode 100644
index 0000000000..e848e9c7ba
--- /dev/null
+++ b/database/integration_test/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Firebase Database Integration Test
+
diff --git a/database/integration_test/settings.gradle b/database/integration_test/settings.gradle
new file mode 100644
index 0000000000..e30c259ab6
--- /dev/null
+++ b/database/integration_test/settings.gradle
@@ -0,0 +1,39 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
+if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
+ if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
+ if ((new File('../../cpp_sdk_version.json')).exists()) {
+ firebase_cpp_sdk_dir = new File('../..').absolutePath
+ }
+ else if ((new File('firebase_cpp_sdk')).exists()) {
+ firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
+ } else {
+ throw new StopActionException(
+ 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' +
+ 'environment variable must be set to reference the Firebase C++ ' +
+ 'SDK install directory. This is used to configure static library ' +
+ 'and C/C++ include paths for the SDK.')
+ }
+ }
+}
+if (!(new File(firebase_cpp_sdk_dir)).exists()) {
+ throw new StopActionException(
+ sprintf('Firebase C++ SDK directory %s does not exist',
+ firebase_cpp_sdk_dir))
+}
+gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
+includeBuild "$firebase_cpp_sdk_dir"
\ No newline at end of file
diff --git a/database/integration_test/src/integration_test.cc b/database/integration_test/src/integration_test.cc
new file mode 100644
index 0000000000..4d97c92003
--- /dev/null
+++ b/database/integration_test/src/integration_test.cc
@@ -0,0 +1,1204 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include