Skip to content

Commit

Permalink
fix(3.x): GcpFirestoreEmulatorAutoConfiguration constructs invalid do…
Browse files Browse the repository at this point in the history
…cument parent (#2429)

Backport of (#2348).

Fixes: #2290.
Fixes: #2330.
  • Loading branch information
meltsufin authored Dec 12, 2023
1 parent d956978 commit 30f7b7a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public FirestoreOptions firestoreOptions() {
private Credentials emulatorCredentials() {
final Map<String, List<String>> headerMap = new HashMap<>();
headerMap.put("Authorization", Collections.singletonList("Bearer owner"));
headerMap.put("google-cloud-resource-prefix", Collections.singletonList(rootPath));
headerMap.put("google-cloud-resource-prefix", Collections.singletonList(
rootPath.substring(0, rootPath.lastIndexOf("/documents"))));

return new Credentials() {
@Override
Expand Down Expand Up @@ -120,7 +121,7 @@ public FirestoreTemplate firestoreTemplate(
FirestoreClassMapper classMapper,
FirestoreMappingContext firestoreMappingContext) {
return new FirestoreTemplate(
firestoreStub, rootPath + "/documents", classMapper, firestoreMappingContext);
firestoreStub, rootPath, classMapper, firestoreMappingContext);
}

@Bean
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,95 @@
package com.google.cloud.spring.autoconfigure.firestore;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.auth.Credentials;
import com.google.cloud.NoCredentials;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.FirestoreOptions;
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
import com.google.cloud.spring.core.GcpProjectIdProvider;
import com.google.cloud.spring.data.firestore.FirestoreTemplate;
import java.util.List;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.test.util.ReflectionTestUtils;

/** Tests for the Firestore emulator config. */
/**
* Tests for Firestore Emulator autoconfiguration.
*/
class GcpFirestoreEmulatorAutoConfigurationTests {

GcpProjectIdProvider projectId = () -> "projectId";

private final ApplicationContextRunner contextRunner =
ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
GcpFirestoreEmulatorAutoConfiguration.class, GcpFirestoreAutoConfiguration.class))
.withBean("projectId", GcpProjectIdProvider.class, () -> projectId);
GcpFirestoreEmulatorAutoConfiguration.class,
GcpContextAutoConfiguration.class,
GcpFirestoreAutoConfiguration.class,
FirestoreTransactionManagerAutoConfiguration.class));

@Test
void testEmulatorEnabledConfig() {
void testAutoConfigurationEnabled() {
contextRunner
.withPropertyValues(
"spring.cloud.gcp.firestore.project-id=",
"spring.cloud.gcp.firestore.emulator.enabled=true",
"spring.cloud.gcp.firestore.host-port=localhost:9000")
.run(
context -> {
FirestoreOptions firestoreOptions = context.getBean(FirestoreOptions.class);
String endpoint =
((InstantiatingGrpcChannelProvider)
firestoreOptions.getTransportChannelProvider())
.getEndpoint();
assertThat(endpoint).isEqualTo("localhost:9000");

assertThat(firestoreOptions.getProjectId()).isEqualTo("unused");
});
}

@Test
void testAutoConfigurationDisabled() {
contextRunner
.withBean(CredentialsProvider.class, () -> NoCredentials::getInstance)
.withBean(GcpProjectIdProvider.class, () -> () -> "my-project")
.run(
context -> {
FirestoreOptions firestoreOptions = context.getBean(FirestoreOptions.class);
String endpoint =
((InstantiatingGrpcChannelProvider) firestoreOptions.getTransportChannelProvider())
.getEndpoint();
assertThat(endpoint).isEqualTo("firestore.googleapis.com:443");
});
}

CredentialsProvider mockedCredentialsProvider = () -> mock(NoCredentials.class);
@Test
void testThatIfProjectIdIsGivenItWillBeUsed() {
contextRunner
.withPropertyValues(
"spring.cloud.gcp.firestore.project-id=demo",
"spring.cloud.gcp.firestore.emulator.enabled=true",
"spring.cloud.gcp.firestore.host-port=localhost:9000")
.run(
context -> {
FirestoreOptions firestoreOptions = context.getBean(FirestoreOptions.class);
assertThat(firestoreOptions.getProjectId()).isEqualTo("demo");
});
}

@Test
void testEmulatorEnabledConfig() {
this.contextRunner
.withPropertyValues(
"spring.cloud.gcp.firestore.projectId=test-project",
"spring.cloud.gcp.firestore.emulator.enabled=true",
"spring.cloud.gcp.firestore.host-port=localhost:8080")
.withBean(
"mockedCredentialsProvider", CredentialsProvider.class, () -> mockedCredentialsProvider)
.run(
context -> {
CredentialsProvider defaultCredentialsProvider =
context.getBean(CredentialsProvider.class);
assertThat(defaultCredentialsProvider).isSameAs(mockedCredentialsProvider);

GcpFirestoreAutoConfiguration firestoreAutoConfiguration =
context.getBean(GcpFirestoreAutoConfiguration.class);
assertThat(firestoreAutoConfiguration.getCredentialsProvider())
.isInstanceOf(NoCredentialsProvider.class);

FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions();
assertThat(datastoreOptions.getProjectId()).isEqualTo("test-project");

Expand All @@ -77,23 +117,16 @@ void testEmulatorEnabledConfig() {

@Test
void testDefaultConfig() {
CredentialsProvider mockedCredentialsProvider = () -> mock(Credentials.class);

this.contextRunner
.withPropertyValues("spring.cloud.gcp.firestore.projectId=test-project")
.withBean(
"mockedCredentialsProvider", CredentialsProvider.class, () -> mockedCredentialsProvider)
.withBean(CredentialsProvider.class, () -> NoCredentials::getInstance)
.withBean(GcpProjectIdProvider.class, () -> () -> "my-project")
.run(
context -> {
GcpFirestoreProperties gcpFirestoreProperties =
context.getBean(GcpFirestoreProperties.class);
assertThat(gcpFirestoreProperties.getEmulator().isEnabled()).isFalse();

GcpFirestoreAutoConfiguration firestoreAutoConfiguration =
context.getBean(GcpFirestoreAutoConfiguration.class);
assertThat(firestoreAutoConfiguration.getCredentialsProvider())
.isEqualTo(mockedCredentialsProvider);

FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions();
assertThat(datastoreOptions.getProjectId()).isEqualTo("test-project");

Expand All @@ -102,4 +135,36 @@ void testDefaultConfig() {
assertThat(channelProvider.getEndpoint()).isEqualTo("firestore.googleapis.com:443");
});
}

@Test
void testFirestoreTemplateParent() {
contextRunner
.withPropertyValues(
"spring.cloud.gcp.firestore.project-id=demo",
"spring.cloud.gcp.firestore.emulator.enabled=true",
"spring.cloud.gcp.firestore.database-id=testdb")
.run(
context -> {
FirestoreTemplate template = context.getBean(FirestoreTemplate.class);
assertThat(ReflectionTestUtils.getField(template, "parent")).isEqualTo(
"projects/demo/databases/testdb/documents");
});
}

@Test
void testDefaultCredentials() {
contextRunner
.withPropertyValues(
"spring.cloud.gcp.firestore.project-id=demo",
"spring.cloud.gcp.firestore.emulator.enabled=true",
"spring.cloud.gcp.firestore.database-id=testdb")
.run(
context -> {
FirestoreOptions firestoreOptions = context.getBean(FirestoreOptions.class);
Credentials credentials = firestoreOptions.getCredentials();
List<String> header = credentials.getRequestMetadata()
.get("google-cloud-resource-prefix");
assertThat(header).isEqualTo(Lists.list("projects/demo/databases/testdb"));
});
}
}

0 comments on commit 30f7b7a

Please sign in to comment.