From d6c0df546deaf6df621246f8e556157c8dd723ff Mon Sep 17 00:00:00 2001 From: Hiranya Jayathilaka Date: Mon, 14 Jun 2021 11:20:03 -0400 Subject: [PATCH 1/3] fix: Using Java 8 in release and nightly builds --- .github/workflows/ci.yml | 8 ++++++-- .github/workflows/nightly.yml | 8 ++++---- .github/workflows/release.yml | 8 ++++---- .../com/google/firebase/testing/IntegrationTestUtils.java | 7 ++++++- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58ecbfa35..e765291f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,13 +19,17 @@ jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + java-version: [7, 8, 11] + steps: - uses: actions/checkout@v1 - - name: Set up JDK 1.7 + - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 1.7 + java-version: ${{ matrix.java-version }} # Does the following: # 1. Runs the Checkstyle plugin (validate phase) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c9259a628..dd3110c46 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -33,10 +33,10 @@ jobs: with: ref: ${{ github.event.client_payload.ref || github.ref }} - - name: Set up JDK 1.7 + - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: - java-version: 1.7 + java-version: 1.8 - name: Compile, test and package run: ./.github/scripts/package_artifacts.sh @@ -63,7 +63,7 @@ jobs: subject: 'Nightly build ${{github.run_id}} of ${{github.repository}} failed!' html: > Nightly workflow ${{github.run_id}} failed on: ${{github.repository}} -

Navigate to the +

Navigate to the failed workflow. continue-on-error: true @@ -78,6 +78,6 @@ jobs: subject: 'Nightly build ${{github.run_id}} of ${{github.repository}} cancelled!' html: > Nightly workflow ${{github.run_id}} cancelled on: ${{github.repository}} -

Navigate to the +

Navigate to the cancelled workflow. continue-on-error: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 985ce94d6..b49a453fc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,10 +44,10 @@ jobs: with: ref: ${{ github.event.client_payload.ref || github.ref }} - - name: Set up JDK 1.7 + - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: - java-version: 1.7 + java-version: 1.8 - name: Compile, test and package run: ./.github/scripts/package_artifacts.sh @@ -82,10 +82,10 @@ jobs: - name: Checkout source for publish uses: actions/checkout@v2 - - name: Set up JDK 1.7 + - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: - java-version: 1.7 + java-version: 1.8 - name: Publish preflight check id: preflight diff --git a/src/test/java/com/google/firebase/testing/IntegrationTestUtils.java b/src/test/java/com/google/firebase/testing/IntegrationTestUtils.java index 3d0c55024..1c0a24c11 100644 --- a/src/test/java/com/google/firebase/testing/IntegrationTestUtils.java +++ b/src/test/java/com/google/firebase/testing/IntegrationTestUtils.java @@ -193,7 +193,12 @@ public static class ResponseInfo { private ResponseInfo(HttpResponse response) throws IOException { this.status = response.getStatusCode(); - this.payload = ByteStreams.toByteArray(response.getContent()); + InputStream in = response.getContent(); + if (in != null) { + this.payload = ByteStreams.toByteArray(in); + } else { + this.payload = new byte[0]; + } } public int getStatus() { From c12bf3577083e24ac0203ab77034a4d4f098a944 Mon Sep 17 00:00:00 2001 From: Hiranya Jayathilaka Date: Mon, 14 Jun 2021 12:17:14 -0400 Subject: [PATCH 2/3] fix: Removing env variable manipulation from tests --- pom.xml | 4 +- .../java/com/google/firebase/FirebaseApp.java | 7 +- .../google/firebase/auth/internal/Utils.java | 3 +- .../database/util/EmulatorHelper.java | 3 +- .../internal/FirebaseProcessEnvironment.java | 43 ++++++ .../com/google/firebase/FirebaseAppTest.java | 133 ++++++++++-------- ...EmulatorFirebaseTokenVerifierImplTest.java | 8 +- .../firebase/auth/FirebaseAuthTest.java | 10 +- .../firebase/auth/FirebaseTokenUtilsTest.java | 12 +- .../auth/FirebaseUserManagerTest.java | 7 +- .../FirebaseTenantClientTest.java | 8 +- .../database/FirebaseDatabaseTest.java | 22 ++- .../google/firebase/testing/TestUtils.java | 88 ------------ 13 files changed, 153 insertions(+), 195 deletions(-) create mode 100644 src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java diff --git a/pom.xml b/pom.xml index 675bcb049..009dc848c 100644 --- a/pom.xml +++ b/pom.xml @@ -467,8 +467,8 @@ org.mockito - mockito-core - 2.28.2 + mockito-inline + 3.11.0 test diff --git a/src/main/java/com/google/firebase/FirebaseApp.java b/src/main/java/com/google/firebase/FirebaseApp.java index d525d0673..27727c366 100644 --- a/src/main/java/com/google/firebase/FirebaseApp.java +++ b/src/main/java/com/google/firebase/FirebaseApp.java @@ -35,6 +35,7 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.firebase.internal.ApiClientUtils; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.internal.FirebaseScheduledExecutor; import com.google.firebase.internal.FirebaseService; import com.google.firebase.internal.ListenableFuture2ApiFuture; @@ -292,10 +293,10 @@ String getProjectId() { // Try to get project ID from the environment. if (Strings.isNullOrEmpty(projectId)) { - projectId = System.getenv("GOOGLE_CLOUD_PROJECT"); + projectId = FirebaseProcessEnvironment.getenv("GOOGLE_CLOUD_PROJECT"); } if (Strings.isNullOrEmpty(projectId)) { - projectId = System.getenv("GCLOUD_PROJECT"); + projectId = FirebaseProcessEnvironment.getenv("GCLOUD_PROJECT"); } return projectId; } @@ -563,7 +564,7 @@ enum State { } private static FirebaseOptions getOptionsFromEnvironment() throws IOException { - String defaultConfig = System.getenv(FIREBASE_CONFIG_ENV_VAR); + String defaultConfig = FirebaseProcessEnvironment.getenv(FIREBASE_CONFIG_ENV_VAR); if (Strings.isNullOrEmpty(defaultConfig)) { return FirebaseOptions.builder() .setCredentials(APPLICATION_DEFAULT_CREDENTIALS) diff --git a/src/main/java/com/google/firebase/auth/internal/Utils.java b/src/main/java/com/google/firebase/auth/internal/Utils.java index 487892df3..f4d082917 100644 --- a/src/main/java/com/google/firebase/auth/internal/Utils.java +++ b/src/main/java/com/google/firebase/auth/internal/Utils.java @@ -18,6 +18,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; +import com.google.firebase.internal.FirebaseProcessEnvironment; public class Utils { @VisibleForTesting @@ -28,7 +29,7 @@ public static boolean isEmulatorMode() { } public static String getEmulatorHost() { - return System.getenv(AUTH_EMULATOR_HOST); + return FirebaseProcessEnvironment.getenv(AUTH_EMULATOR_HOST); } } diff --git a/src/main/java/com/google/firebase/database/util/EmulatorHelper.java b/src/main/java/com/google/firebase/database/util/EmulatorHelper.java index c4ef2ff25..11c358fc6 100644 --- a/src/main/java/com/google/firebase/database/util/EmulatorHelper.java +++ b/src/main/java/com/google/firebase/database/util/EmulatorHelper.java @@ -22,6 +22,7 @@ import com.google.firebase.database.core.RepoInfo; import com.google.firebase.database.utilities.ParsedUrl; import com.google.firebase.database.utilities.Utilities; +import com.google.firebase.internal.FirebaseProcessEnvironment; public final class EmulatorHelper { @@ -33,7 +34,7 @@ private EmulatorHelper() { "FIREBASE_DATABASE_EMULATOR_HOST"; public static String getEmulatorHostFromEnv() { - return System.getenv(FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR); + return FirebaseProcessEnvironment.getenv(FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR); } @VisibleForTesting diff --git a/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java b/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java new file mode 100644 index 000000000..ab44a47f0 --- /dev/null +++ b/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 Google Inc. + * + * 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. + */ + +package com.google.firebase.internal; + +import com.google.common.base.Strings; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class FirebaseProcessEnvironment { + + private static final Map localCache = new ConcurrentHashMap<>(); + + public static String getenv(String name) { + String cachedValue = localCache.get(name); + if (!Strings.isNullOrEmpty(cachedValue)) { + return cachedValue; + } + + return System.getenv(name); + } + + public static void setenv(String name, String value) { + localCache.put(name, value); + } + + public static void clearCache() { + localCache.clear(); + } +} diff --git a/src/test/java/com/google/firebase/FirebaseAppTest.java b/src/test/java/com/google/firebase/FirebaseAppTest.java index 56e025d22..5f985d826 100644 --- a/src/test/java/com/google/firebase/FirebaseAppTest.java +++ b/src/test/java/com/google/firebase/FirebaseAppTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; @@ -38,9 +39,9 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.firebase.FirebaseApp.TokenRefresher; import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.internal.FirebaseService; import com.google.firebase.testing.FirebaseAppRule; import com.google.firebase.testing.ServiceAccount; @@ -62,9 +63,9 @@ import java.util.concurrent.TimeUnit; import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.mockito.MockedStatic; import org.mockito.Mockito; /** @@ -72,21 +73,19 @@ */ public class FirebaseAppTest { + private static final GoogleCredentials TEST_CREDENTIALS = TestUtils.getCertCredential( + ServiceAccount.EDITOR.asStream()); + private static final FirebaseOptions OPTIONS = FirebaseOptions.builder() - .setCredentials(TestUtils.getCertCredential(ServiceAccount.EDITOR.asStream())) + .setCredentials(TEST_CREDENTIALS) .build(); @Rule public FirebaseAppRule firebaseAppRule = new FirebaseAppRule(); - @BeforeClass - public static void setupClass() throws IOException { - TestUtils.getApplicationDefaultCredentials(); - } - @AfterClass public static void tearDownClass() { - TestUtils.unsetEnvironmentVariables(ImmutableSet.of(FirebaseApp.FIREBASE_CONFIG_ENV_VAR)); + FirebaseProcessEnvironment.clearCache(); } @Test(expected = NullPointerException.class) @@ -128,8 +127,7 @@ public void testGetProjectIdFromCredential() { public void testGetProjectIdFromEnvironment() { List variables = ImmutableList.of("GCLOUD_PROJECT", "GOOGLE_CLOUD_PROJECT"); for (String variable : variables) { - String gcloudProject = System.getenv(variable); - TestUtils.setEnvironmentVariables(ImmutableMap.of(variable, "project-id-1")); + FirebaseProcessEnvironment.setenv(variable, "project-id-1"); FirebaseOptions options = FirebaseOptions.builder() .setCredentials(new MockGoogleCredentials()) .build(); @@ -138,8 +136,7 @@ public void testGetProjectIdFromEnvironment() { String projectId = ImplFirebaseTrampolines.getProjectId(app); assertEquals("project-id-1", projectId); } finally { - TestUtils.setEnvironmentVariables(ImmutableMap.of( - variable, Strings.nullToEmpty(gcloudProject))); + FirebaseProcessEnvironment.clearCache(); } } } @@ -152,8 +149,8 @@ public void testProjectIdEnvironmentVariablePrecedence() { currentValues.put("GOOGLE_CLOUD_PROJECT", Strings.nullToEmpty( System.getenv("GOOGLE_CLOUD_PROJECT"))); - TestUtils.setEnvironmentVariables(ImmutableMap.of( - "GCLOUD_PROJECT", "project-id-1", "GOOGLE_CLOUD_PROJECT", "project-id-2")); + FirebaseProcessEnvironment.setenv("GCLOUD_PROJECT", "project-id-1"); + FirebaseProcessEnvironment.setenv("GOOGLE_CLOUD_PROJECT", "project-id-2"); FirebaseOptions options = FirebaseOptions.builder() .setCredentials(new MockGoogleCredentials()) .build(); @@ -162,7 +159,7 @@ public void testProjectIdEnvironmentVariablePrecedence() { String projectId = ImplFirebaseTrampolines.getProjectId(app); assertEquals("project-id-2", projectId); } finally { - TestUtils.setEnvironmentVariables(currentValues); + FirebaseProcessEnvironment.clearCache(); } } @@ -264,11 +261,7 @@ public void testGetNullApp() { @Test public void testToString() throws IOException { - FirebaseOptions options = - FirebaseOptions.builder() - .setCredentials(GoogleCredentials.fromStream(ServiceAccount.EDITOR.asStream())) - .build(); - FirebaseApp app = FirebaseApp.initializeApp(options, "app"); + FirebaseApp app = FirebaseApp.initializeApp(OPTIONS, "app"); String pattern = "FirebaseApp\\{name=app}"; assertTrue(app.toString().matches(pattern)); } @@ -503,23 +496,29 @@ public void testEmptyFirebaseConfigFile() { } @Test - public void testEmptyFirebaseConfigString() { + public void testEmptyFirebaseConfigString() throws IOException { setFirebaseConfigEnvironmentVariable(""); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertNull(firebaseApp.getOptions().getProjectId()); - assertNull(firebaseApp.getOptions().getStorageBucket()); - assertNull(firebaseApp.getOptions().getDatabaseUrl()); - assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertNull(firebaseApp.getOptions().getProjectId()); + assertNull(firebaseApp.getOptions().getStorageBucket()); + assertNull(firebaseApp.getOptions().getDatabaseUrl()); + assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + } } @Test - public void testEmptyFirebaseConfigJSONObject() { + public void testEmptyFirebaseConfigJSONObject() throws IOException { setFirebaseConfigEnvironmentVariable("{}"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertNull(firebaseApp.getOptions().getProjectId()); - assertNull(firebaseApp.getOptions().getStorageBucket()); - assertNull(firebaseApp.getOptions().getDatabaseUrl()); - assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertNull(firebaseApp.getOptions().getProjectId()); + assertNull(firebaseApp.getOptions().getStorageBucket()); + assertNull(firebaseApp.getOptions().getDatabaseUrl()); + assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + } } @Test(expected = IllegalArgumentException.class) @@ -541,21 +540,29 @@ public void testFirebaseConfigMissingFile() { } @Test - public void testFirebaseConfigFileWithSomeKeysMissing() { + public void testFirebaseConfigFileWithSomeKeysMissing() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config_partial.json"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); - assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); + } } @Test - public void testValidFirebaseConfigFile() { + public void testValidFirebaseConfigFile() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config.json"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); - assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); - assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); - assertEquals("testuser", firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); + assertEquals( + "https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); + assertEquals( + "testuser", firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + } } @Test @@ -569,7 +576,7 @@ public void testEnvironmentVariableIgnored() { } @Test - public void testValidFirebaseConfigString() { + public void testValidFirebaseConfigString() throws IOException { setFirebaseConfigEnvironmentVariable("{" + "\"databaseAuthVariableOverride\": {" + "\"uid\":" @@ -579,29 +586,38 @@ public void testValidFirebaseConfigString() { + "\"projectId\": \"hipster-chat-mock\"," + "\"storageBucket\": \"hipster-chat.appspot.mock\"" + "}"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); - assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); - assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); - assertEquals("testuser", - firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); + assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); + assertEquals("testuser", + firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + } } @Test - public void testFirebaseConfigFileIgnoresInvalidKey() { + public void testFirebaseConfigFileIgnoresInvalidKey() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config_invalid_key.json"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + } } @Test - public void testFirebaseConfigStringIgnoresInvalidKey() { + public void testFirebaseConfigStringIgnoresInvalidKey() throws IOException { setFirebaseConfigEnvironmentVariable("{" + "\"databaseUareL\": \"https://hipster-chat.firebaseio.mock\"," + "\"projectId\": \"hipster-chat-mock\"" + "}"); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(); - assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { + when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(); + assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + } } @Test @@ -618,9 +634,8 @@ private static void setFirebaseConfigEnvironmentVariable(String configJSON) { } else { configValue = new File("src/test/resources", configJSON).getAbsolutePath(); } - Map environmentVariables = - ImmutableMap.of(FirebaseApp.FIREBASE_CONFIG_ENV_VAR , configValue); - TestUtils.setEnvironmentVariables(environmentVariables); + + FirebaseProcessEnvironment.setenv(FirebaseApp.FIREBASE_CONFIG_ENV_VAR, configValue); } private static FirebaseOptions getMockCredentialOptions() { diff --git a/src/test/java/com/google/firebase/auth/EmulatorFirebaseTokenVerifierImplTest.java b/src/test/java/com/google/firebase/auth/EmulatorFirebaseTokenVerifierImplTest.java index 0cc12c6f9..55ca7bf6c 100644 --- a/src/test/java/com/google/firebase/auth/EmulatorFirebaseTokenVerifierImplTest.java +++ b/src/test/java/com/google/firebase/auth/EmulatorFirebaseTokenVerifierImplTest.java @@ -29,11 +29,9 @@ import com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.firebase.ErrorCode; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.testing.ServiceAccount; -import com.google.firebase.testing.TestUtils; import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Before; @@ -46,7 +44,7 @@ public class EmulatorFirebaseTokenVerifierImplTest { @Before public void setUp() throws Exception { // Set the Auth Emulator host prior to initialization - TestUtils.setEnvironmentVariables(ImmutableMap.of(AUTH_EMULATOR_HOST, "localhost:9099")); + FirebaseProcessEnvironment.setenv(AUTH_EMULATOR_HOST, "localhost:9099"); ServiceAccount serviceAccount = ServiceAccount.EDITOR; GooglePublicKeysManager publicKeysManager = newPublicKeysManager(serviceAccount.getCert()); this.tokenVerifier = newTestTokenVerifier(publicKeysManager); @@ -55,7 +53,7 @@ public void setUp() throws Exception { @After public void tearDown() { - TestUtils.unsetEnvironmentVariables(ImmutableSet.of(AUTH_EMULATOR_HOST)); + FirebaseProcessEnvironment.clearCache(); } @Test diff --git a/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java b/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java index d385e7e4e..8784193ac 100644 --- a/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java +++ b/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java @@ -31,12 +31,12 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.firebase.ErrorCode; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.TestOnlyImplFirebaseTrampolines; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.testing.ServiceAccount; import com.google.firebase.testing.TestResponseInterceptor; import com.google.firebase.testing.TestUtils; @@ -62,7 +62,7 @@ public class FirebaseAuthTest { @After public void cleanup() { // Cleanup for tests on Auth Emulator - TestUtils.unsetEnvironmentVariables(ImmutableSet.of("FIREBASE_AUTH_EMULATOR_HOST")); + FirebaseProcessEnvironment.clearCache(); TestOnlyImplFirebaseTrampolines.clearInstancesForTest(); } @@ -269,8 +269,7 @@ public void testVerifyIdTokenWithRevocationCheckFailure() { @Test public void testVerifyIdTokenWithEmulator() throws Exception { // Enable emulator mode - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); MockTokenVerifier tokenVerifier = MockTokenVerifier.fromResult( getFirebaseToken(VALID_SINCE + 1000)); FirebaseAuth auth = getAuthForIdTokenVerificationWithRevocationCheck(tokenVerifier); @@ -284,8 +283,7 @@ public void testVerifyIdTokenWithEmulator() throws Exception { @Test public void testVerifyIdTokenFailureWithEmulator() { // Enable emulator mode - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); MockTokenVerifier tokenVerifier = MockTokenVerifier.fromResult( getFirebaseToken(VALID_SINCE - 1000)); FirebaseAuth auth = getAuthForIdTokenVerificationWithRevocationCheck(tokenVerifier); diff --git a/src/test/java/com/google/firebase/auth/FirebaseTokenUtilsTest.java b/src/test/java/com/google/firebase/auth/FirebaseTokenUtilsTest.java index ccc1ad6a9..a274c0b11 100644 --- a/src/test/java/com/google/firebase/auth/FirebaseTokenUtilsTest.java +++ b/src/test/java/com/google/firebase/auth/FirebaseTokenUtilsTest.java @@ -27,13 +27,11 @@ import com.google.api.client.testing.http.FixedClock; import com.google.api.client.util.Clock; import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.TestOnlyImplFirebaseTrampolines; -import com.google.firebase.testing.TestUtils; +import com.google.firebase.internal.FirebaseProcessEnvironment; import org.junit.After; import org.junit.Rule; import org.junit.Test; @@ -51,7 +49,7 @@ public class FirebaseTokenUtilsTest { @After public void tearDown() { - TestUtils.unsetEnvironmentVariables(ImmutableSet.of("FIREBASE_AUTH_EMULATOR_HOST")); + FirebaseProcessEnvironment.clearCache(); TestOnlyImplFirebaseTrampolines.clearInstancesForTest(); } @@ -79,8 +77,7 @@ public void testCreateIdTokenVerifier() { @Test public void testCreateIdTokenVerifierForEmulator() { - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); FirebaseApp app = FirebaseApp.initializeApp(FirebaseOptions.builder() .setCredentials(MOCK_CREDENTIALS) .setProjectId(TEST_PROJECT_ID) @@ -130,8 +127,7 @@ public void testSessionCookieVerifier() { @Test public void testSessionCookieVerifierForEmulator() { - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); FirebaseApp app = FirebaseApp.initializeApp(FirebaseOptions.builder() .setCredentials(MOCK_CREDENTIALS) .setProjectId(TEST_PROJECT_ID) diff --git a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java index 83b98068d..cd43c0147 100644 --- a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java +++ b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java @@ -38,7 +38,6 @@ import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.firebase.ErrorCode; import com.google.firebase.FirebaseApp; @@ -48,6 +47,7 @@ import com.google.firebase.auth.multitenancy.TenantAwareFirebaseAuth; import com.google.firebase.auth.multitenancy.TenantManager; import com.google.firebase.internal.ApiClientUtils; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.internal.SdkUtils; import com.google.firebase.testing.MultiRequestMockHttpTransport; import com.google.firebase.testing.TestResponseInterceptor; @@ -108,7 +108,7 @@ public class FirebaseUserManagerTest { @After public void tearDown() { - TestUtils.unsetEnvironmentVariables(ImmutableSet.of("FIREBASE_AUTH_EMULATOR_HOST")); + FirebaseProcessEnvironment.clearCache(); TestOnlyImplFirebaseTrampolines.clearInstancesForTest(); } @@ -2853,8 +2853,7 @@ public void testTenantAwareDeleteSamlProviderConfig() throws Exception { @Test public void testCreateOidcProviderFromEmulatorAuth() throws Exception { - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); TestResponseInterceptor interceptor = initializeAppForUserManagement(OIDC_RESPONSE); OidcProviderConfig.CreateRequest createRequest = new OidcProviderConfig.CreateRequest() diff --git a/src/test/java/com/google/firebase/auth/multitenancy/FirebaseTenantClientTest.java b/src/test/java/com/google/firebase/auth/multitenancy/FirebaseTenantClientTest.java index b94038925..3e57dc3a1 100644 --- a/src/test/java/com/google/firebase/auth/multitenancy/FirebaseTenantClientTest.java +++ b/src/test/java/com/google/firebase/auth/multitenancy/FirebaseTenantClientTest.java @@ -34,8 +34,6 @@ import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.firebase.ErrorCode; import com.google.firebase.FirebaseApp; @@ -46,6 +44,7 @@ import com.google.firebase.auth.FirebaseAuthException; import com.google.firebase.auth.MockGoogleCredentials; import com.google.firebase.internal.ApiClientUtils; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.internal.SdkUtils; import com.google.firebase.testing.MultiRequestMockHttpTransport; import com.google.firebase.testing.TestResponseInterceptor; @@ -78,7 +77,7 @@ public class FirebaseTenantClientTest { @After public void tearDown() throws ReflectiveOperationException { - TestUtils.unsetEnvironmentVariables(ImmutableSet.of("FIREBASE_AUTH_EMULATOR_HOST")); + FirebaseProcessEnvironment.clearCache(); TestOnlyImplFirebaseTrampolines.clearInstancesForTest(); } @@ -323,8 +322,7 @@ public void testDeleteTenantWithNotFoundError() { @Test public void testGetTenantFromAuthEmulator() throws Exception { - TestUtils.setEnvironmentVariables( - ImmutableMap.of("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR)); + FirebaseProcessEnvironment.setenv("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR); TestResponseInterceptor interceptor = initializeAppForTenantManagement( TestUtils.loadResource("tenant.json")); diff --git a/src/test/java/com/google/firebase/database/FirebaseDatabaseTest.java b/src/test/java/com/google/firebase/database/FirebaseDatabaseTest.java index 2bdc6185e..3dc23746d 100644 --- a/src/test/java/com/google/firebase/database/FirebaseDatabaseTest.java +++ b/src/test/java/com/google/firebase/database/FirebaseDatabaseTest.java @@ -23,15 +23,13 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; -import com.google.auth.oauth2.GoogleCredentials; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.TestOnlyImplFirebaseTrampolines; import com.google.firebase.database.util.EmulatorHelper; +import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.testing.ServiceAccount; import com.google.firebase.testing.TestUtils; import java.io.IOException; @@ -220,9 +218,9 @@ public void testDbUrlIsEmulatorUrlWhenSettingOptionsManually() throws IOExceptio for (CustomTestCase tc : testCases) { try { FirebaseApp app = FirebaseApp.initializeApp(firebaseOptionsWithoutDatabaseUrl); - TestUtils.setEnvironmentVariables( - ImmutableMap.of(EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR, - Strings.nullToEmpty(tc.envVariableUrl))); + FirebaseProcessEnvironment.setenv( + EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR, + Strings.nullToEmpty(tc.envVariableUrl)); FirebaseDatabase instance = FirebaseDatabase.getInstance(app, tc.rootDbUrl); assertEquals(tc.expectedEmulatorRootUrl, instance.getReference().repo.getRepoInfo().toString()); @@ -230,8 +228,7 @@ public void testDbUrlIsEmulatorUrlWhenSettingOptionsManually() throws IOExceptio // clean up after app.delete(); } finally { - TestUtils.unsetEnvironmentVariables( - ImmutableSet.of(EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR)); + FirebaseProcessEnvironment.clearCache(); } } } @@ -257,9 +254,9 @@ public void testDbUrlIsEmulatorUrlForDbRefWithPath() throws IOException { for (CustomTestCase tc : testCases) { try { FirebaseApp app = FirebaseApp.initializeApp(firebaseOptionsWithoutDatabaseUrl); - TestUtils.setEnvironmentVariables( - ImmutableMap.of(EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR, - Strings.nullToEmpty(tc.envVariableUrl))); + FirebaseProcessEnvironment.setenv( + EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR, + Strings.nullToEmpty(tc.envVariableUrl)); FirebaseDatabase instance = FirebaseDatabase.getInstance(app, tc.rootDbUrl); DatabaseReference dbRef = instance.getReferenceFromUrl(tc.pathUrl); assertEquals(tc.expectedEmulatorRootUrl, dbRef.repo.getRepoInfo().toString()); @@ -269,8 +266,7 @@ public void testDbUrlIsEmulatorUrlForDbRefWithPath() throws IOException { app.delete(); } finally { - TestUtils.unsetEnvironmentVariables( - ImmutableSet.of(EmulatorHelper.FIREBASE_RTDB_EMULATOR_HOST_ENV_VAR)); + FirebaseProcessEnvironment.clearCache(); } } } diff --git a/src/test/java/com/google/firebase/testing/TestUtils.java b/src/test/java/com/google/firebase/testing/TestUtils.java index e44ca2be8..59f6b7195 100644 --- a/src/test/java/com/google/firebase/testing/TestUtils.java +++ b/src/test/java/com/google/firebase/testing/TestUtils.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.api.client.googleapis.testing.auth.oauth2.MockTokenServerTransport; import com.google.api.client.http.EmptyContent; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpRequest; @@ -28,32 +27,20 @@ import com.google.api.client.json.webtoken.JsonWebSignature; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.testing.http.MockLowLevelHttpRequest; -import com.google.auth.http.HttpTransportFactory; import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; import com.google.common.io.CharStreams; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.security.PublicKey; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; /** Test Utils for use by all tests (both unit and integration tests). */ public class TestUtils { public static final long TEST_TIMEOUT_MILLIS = 7 * 1000; - private static final String TEST_ADC_ACCESS_TOKEN = "test-adc-access-token"; private static final GenericUrl TEST_URL = new GenericUrl("https://firebase.google.com"); - private static GoogleCredentials defaultCredentials; - public static boolean verifySignature(JsonWebSignature token, List keys) throws Exception { for (PublicKey key : keys) { @@ -64,52 +51,6 @@ public static boolean verifySignature(JsonWebSignature token, List ke return false; } - public static void setEnvironmentVariables(Map vars) { - // Setting the environment variables after the JVM has started requires a bit of a hack: - // we reach into the package-private java.lang.ProcessEnvironment class, which incidentally - // is platform-specific, and replace the map held in a static final field there, - // using yet more reflection. - // - // This is copied from {#see com.google.apphosting.runtime.NullSandboxPlugin} - Map allVars = new HashMap<>(System.getenv()); - allVars.putAll(vars); - try { - Class pe = Class.forName("java.lang.ProcessEnvironment", true, null); - Field f = pe.getDeclaredField("theUnmodifiableEnvironment"); - f.setAccessible(true); - Field m = Field.class.getDeclaredField("modifiers"); - m.setAccessible(true); - m.setInt(f, m.getInt(f) & ~Modifier.FINAL); - f.set(null, Collections.unmodifiableMap(allVars)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("failed to set the environment variables", e); - } - } - - public static void unsetEnvironmentVariables(Set vars) { - // Unsetting the environment variables after the JVM has started requires a bit of a hack: - // we reach into the package-private java.lang.ProcessEnvironment class, which incidentally - // is platform-specific, and replace the map held in a static final field there, - // using yet more reflection. - // - // This is copied from {#see com.google.apphosting.runtime.NullSandboxPlugin} - Map allVars = new HashMap<>(System.getenv()); - for (String var : vars) { - allVars.remove(var); - } - try { - Class pe = Class.forName("java.lang.ProcessEnvironment", true, null); - Field f = pe.getDeclaredField("theUnmodifiableEnvironment"); - f.setAccessible(true); - Field m = Field.class.getDeclaredField("modifiers"); - m.setAccessible(true); - m.setInt(f, m.getInt(f) & ~Modifier.FINAL); - f.set(null, Collections.unmodifiableMap(allVars)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("failed to unset the environment variables", e); - } - } - public static String loadResource(String path) { InputStream stream = TestUtils.class.getClassLoader().getResourceAsStream(path); checkNotNull(stream, "Failed to load resource: %s", path); @@ -128,35 +69,6 @@ public static GoogleCredentials getCertCredential(InputStream stream) { } } - /** - * Ensures initialization of Google Application Default Credentials. Any test that depends on - * ADC should consider this as a fixture, and invoke it before hand. Since ADC are initialized - * once per JVM, this makes sure that all dependent tests get the same ADC instance, and - * can reliably reason about the tokens minted using it. - */ - public static synchronized GoogleCredentials getApplicationDefaultCredentials() - throws IOException { - if (defaultCredentials != null) { - return defaultCredentials; - } - final MockTokenServerTransport transport = new MockTokenServerTransport( - "https://accounts.google.com/o/oauth2/token"); - transport.addServiceAccount(ServiceAccount.EDITOR.getEmail(), TEST_ADC_ACCESS_TOKEN); - File serviceAccount = new File("src/test/resources/service_accounts", "editor.json"); - Map environmentVariables = - ImmutableMap.builder() - .put("GOOGLE_APPLICATION_CREDENTIALS", serviceAccount.getAbsolutePath()) - .build(); - setEnvironmentVariables(environmentVariables); - defaultCredentials = GoogleCredentials.getApplicationDefault(new HttpTransportFactory() { - @Override - public HttpTransport create() { - return transport; - } - }); - return defaultCredentials; - } - public static HttpRequest createRequest() throws IOException { return createRequest(new MockLowLevelHttpRequest()); } From d1ef5d1ce90309566fc64a56df32d358fac9f3b1 Mon Sep 17 00:00:00 2001 From: Hiranya Jayathilaka Date: Mon, 14 Jun 2021 13:34:30 -0400 Subject: [PATCH 3/3] Downgraded to mockito 2; Using wrapper classes to mock ADC --- pom.xml | 4 +- .../com/google/firebase/FirebaseOptions.java | 4 +- ...ApplicationDefaultCredentialsProvider.java | 46 +++++++++++++++++++ .../internal/FirebaseProcessEnvironment.java | 3 ++ .../com/google/firebase/FirebaseAppTest.java | 45 +++++++++++------- 5 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/google/firebase/internal/ApplicationDefaultCredentialsProvider.java diff --git a/pom.xml b/pom.xml index 009dc848c..675bcb049 100644 --- a/pom.xml +++ b/pom.xml @@ -467,8 +467,8 @@ org.mockito - mockito-inline - 3.11.0 + mockito-core + 2.28.2 test diff --git a/src/main/java/com/google/firebase/FirebaseOptions.java b/src/main/java/com/google/firebase/FirebaseOptions.java index f13f022db..836f701e9 100644 --- a/src/main/java/com/google/firebase/FirebaseOptions.java +++ b/src/main/java/com/google/firebase/FirebaseOptions.java @@ -29,6 +29,7 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.firebase.internal.ApiClientUtils; +import com.google.firebase.internal.ApplicationDefaultCredentialsProvider; import com.google.firebase.internal.FirebaseThreadManagers; import com.google.firebase.internal.NonNull; import com.google.firebase.internal.Nullable; @@ -64,7 +65,8 @@ public final class FirebaseOptions { @Override public GoogleCredentials get() { try { - return GoogleCredentials.getApplicationDefault().createScoped(FIREBASE_SCOPES); + return ApplicationDefaultCredentialsProvider.getApplicationDefault() + .createScoped(FIREBASE_SCOPES); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/src/main/java/com/google/firebase/internal/ApplicationDefaultCredentialsProvider.java b/src/main/java/com/google/firebase/internal/ApplicationDefaultCredentialsProvider.java new file mode 100644 index 000000000..93672bbe9 --- /dev/null +++ b/src/main/java/com/google/firebase/internal/ApplicationDefaultCredentialsProvider.java @@ -0,0 +1,46 @@ +/* + * Copyright 2021 Google Inc. + * + * 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. + */ + +package com.google.firebase.internal; + +import com.google.auth.oauth2.GoogleCredentials; +import java.io.IOException; + +/** + * Provides a hook to override application default credentials (ADC) lookup for tests. ADC has + * a dependency on environment variables, and Java famously doesn't support environment variable + * manipulation at runtime. With this class, the test cases that require ADC has a way to register + * their own mock credentials as ADC. + * + *

Once we are able to upgrade to Mockito 3.x (requires Java 8+), we can drop this class + * altogether, and use Mockito tools to mock the behavior of the GoogleCredentials static methods. + */ +public class ApplicationDefaultCredentialsProvider { + + private static GoogleCredentials cachedCredentials; + + public static GoogleCredentials getApplicationDefault() throws IOException { + if (cachedCredentials != null) { + return cachedCredentials; + } + + return GoogleCredentials.getApplicationDefault(); + } + + public static void setApplicationDefault(GoogleCredentials credentials) { + cachedCredentials = credentials; + } +} diff --git a/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java b/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java index ab44a47f0..a9c3022d4 100644 --- a/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java +++ b/src/main/java/com/google/firebase/internal/FirebaseProcessEnvironment.java @@ -20,6 +20,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +/** + * A utility for overriding environment variables during tests. + */ public class FirebaseProcessEnvironment { private static final Map localCache = new ConcurrentHashMap<>(); diff --git a/src/test/java/com/google/firebase/FirebaseAppTest.java b/src/test/java/com/google/firebase/FirebaseAppTest.java index 5f985d826..a35aefe15 100644 --- a/src/test/java/com/google/firebase/FirebaseAppTest.java +++ b/src/test/java/com/google/firebase/FirebaseAppTest.java @@ -28,7 +28,6 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; @@ -41,6 +40,7 @@ import com.google.common.collect.ImmutableMap; import com.google.firebase.FirebaseApp.TokenRefresher; import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.internal.ApplicationDefaultCredentialsProvider; import com.google.firebase.internal.FirebaseProcessEnvironment; import com.google.firebase.internal.FirebaseService; import com.google.firebase.testing.FirebaseAppRule; @@ -65,7 +65,6 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.mockito.MockedStatic; import org.mockito.Mockito; /** @@ -498,26 +497,30 @@ public void testEmptyFirebaseConfigFile() { @Test public void testEmptyFirebaseConfigString() throws IOException { setFirebaseConfigEnvironmentVariable(""); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertNull(firebaseApp.getOptions().getProjectId()); assertNull(firebaseApp.getOptions().getStorageBucket()); assertNull(firebaseApp.getOptions().getDatabaseUrl()); assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @Test public void testEmptyFirebaseConfigJSONObject() throws IOException { setFirebaseConfigEnvironmentVariable("{}"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertNull(firebaseApp.getOptions().getProjectId()); assertNull(firebaseApp.getOptions().getStorageBucket()); assertNull(firebaseApp.getOptions().getDatabaseUrl()); assertTrue(firebaseApp.getOptions().getDatabaseAuthVariableOverride().isEmpty()); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @@ -542,19 +545,21 @@ public void testFirebaseConfigMissingFile() { @Test public void testFirebaseConfigFileWithSomeKeysMissing() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config_partial.json"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @Test public void testValidFirebaseConfigFile() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config.json"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); @@ -562,6 +567,8 @@ public void testValidFirebaseConfigFile() throws IOException { "https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); assertEquals( "testuser", firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @@ -586,24 +593,28 @@ public void testValidFirebaseConfigString() throws IOException { + "\"projectId\": \"hipster-chat-mock\"," + "\"storageBucket\": \"hipster-chat.appspot.mock\"" + "}"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); assertEquals("hipster-chat.appspot.mock", firebaseApp.getOptions().getStorageBucket()); assertEquals("https://hipster-chat.firebaseio.mock", firebaseApp.getOptions().getDatabaseUrl()); assertEquals("testuser", firebaseApp.getOptions().getDatabaseAuthVariableOverride().get("uid")); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @Test public void testFirebaseConfigFileIgnoresInvalidKey() throws IOException { setFirebaseConfigEnvironmentVariable("firebase_config_invalid_key.json"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } } @@ -613,10 +624,12 @@ public void testFirebaseConfigStringIgnoresInvalidKey() throws IOException { + "\"databaseUareL\": \"https://hipster-chat.firebaseio.mock\"," + "\"projectId\": \"hipster-chat-mock\"" + "}"); - try (MockedStatic scoped = Mockito.mockStatic(GoogleCredentials.class)) { - when(GoogleCredentials.getApplicationDefault()).thenReturn(TEST_CREDENTIALS); + ApplicationDefaultCredentialsProvider.setApplicationDefault(TEST_CREDENTIALS); + try { FirebaseApp firebaseApp = FirebaseApp.initializeApp(); assertEquals("hipster-chat-mock", firebaseApp.getOptions().getProjectId()); + } finally { + ApplicationDefaultCredentialsProvider.setApplicationDefault(null); } }