Skip to content

Commit 85c0a99

Browse files
committed
Add WdsContractVerificationTest
This pairs with DataBiosphere/terra-workspace-data-service#372 to establish a contract between WDS and WSM, initially focused on `ReferencedGcpResourceController`.
1 parent fe726d7 commit 85c0a99

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

service/gradle.lockfile

+4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ au.com.dius.pact.core:matchers:4.1.7=testCompileClasspath,testRuntimeClasspath
66
au.com.dius.pact.core:model:4.1.7=testCompileClasspath,testRuntimeClasspath
77
au.com.dius.pact.core:pactbroker:4.1.7=testCompileClasspath,testRuntimeClasspath
88
au.com.dius.pact.core:support:4.1.7=testCompileClasspath,testRuntimeClasspath
9+
au.com.dius.pact.provider:junit5:4.1.7=testCompileClasspath,testRuntimeClasspath
10+
au.com.dius.pact.provider:junit5spring:4.1.7=testCompileClasspath,testRuntimeClasspath
911
au.com.dius.pact:consumer:4.1.7=testCompileClasspath,testRuntimeClasspath
12+
au.com.dius.pact:provider:4.1.7=testCompileClasspath,testRuntimeClasspath
1013
bio.terra:billing-profile-manager-client:0.1.29-SNAPSHOT=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
1114
bio.terra:datarepo-client:1.41.0-SNAPSHOT=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
1215
bio.terra:stairway-gcp:0.0.76-SNAPSHOT=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -341,6 +344,7 @@ org.bouncycastle:bcutil-jdk18on:1.72=compileClasspath,productionRuntimeClasspath
341344
org.broadinstitute.dsde.workbench:sam-client_2.13:0.1-fd8ee25=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
342345
org.checkerframework:checker-compat-qual:2.5.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
343346
org.checkerframework:checker-qual:3.22.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
347+
org.codehaus.groovy:groovy:3.0.19=testRuntimeClasspath
344348
org.codehaus.mojo:animal-sniffer-annotations:1.21=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
345349
org.codehaus.plexus:plexus-utils:3.2.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
346350
org.codehaus.woodstox:stax2-api:4.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath

service/gradle/dependencies.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ dependencies {
116116

117117
// pact
118118
testImplementation 'au.com.dius.pact.consumer:junit5:4.1.7'
119+
testImplementation 'au.com.dius.pact.provider:junit5:4.1.7'
120+
testImplementation 'au.com.dius.pact.provider:junit5spring:4.1.7'
119121

120122
annotationProcessor group: "com.google.auto.value", name: "auto-value", version: "1.7.4"
121123
annotationProcessor group: "org.springframework.boot", name: "spring-boot-configuration-processor", version: "2.6.6"

service/gradle/testing.gradle

+10
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,13 @@ task pactTests(type: Test) {
212212
environment.put('pact.provider.version', "$project.version")
213213
}
214214

215+
// verify the provider side of pacts WSM has with other services
216+
task verifyPacts(type: Test) {
217+
useJUnitPlatform {
218+
includeTags "pact-verification"
219+
}
220+
systemProperty 'pactbroker.host', System.getenv('PACTBROKER_HOST')
221+
systemProperty 'pact.provider.version', System.getenv('PACT_PROVIDER_COMMIT')
222+
systemProperty 'pact.provider.branch', System.getenv('PACT_PROVIDER_BRANCH')
223+
systemProperty 'pact.verifier.publishResults', System.getenv('PACT_PUBLISH_RESULTS')
224+
}

service/src/test/java/bio/terra/workspace/common/BaseAzureUnitTest.java

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import bio.terra.workspace.service.resource.controlled.ControlledResourceMetadataManager;
1111
import bio.terra.workspace.service.resource.controlled.ControlledResourceService;
1212
import bio.terra.workspace.service.resource.controlled.cloud.azure.AzureStorageAccessService;
13+
import bio.terra.workspace.service.resource.referenced.ReferencedResourceService;
1314
import bio.terra.workspace.service.spendprofile.SpendProfileId;
1415
import bio.terra.workspace.service.workspace.WorkspaceService;
1516
import com.azure.core.management.Region;
@@ -31,6 +32,7 @@ public class BaseAzureUnitTest extends BaseUnitTestMocks {
3132
@MockBean private WorkspaceService mockWorkspaceService;
3233
@MockBean private ControlledResourceMetadataManager mockControlledResourceMetadataManager;
3334
@MockBean private ControlledResourceService mockControlledResourceService;
35+
@MockBean private ReferencedResourceService mockReferencedResourceService;
3436

3537
public AzureStorageAccessService mockAzureStorageAccessService() {
3638
return mockAzureStorageAccessService;
@@ -56,6 +58,10 @@ public ControlledResourceService getMockControlledResourceService() {
5658
return mockControlledResourceService;
5759
}
5860

61+
public ReferencedResourceService mockReferencedResourceService() {
62+
return mockReferencedResourceService;
63+
}
64+
5965
public void setupMockLandingZoneRegion(Region region) {
6066
when(mockWorkspaceService().getWorkspace(any()))
6167
.thenReturn(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package bio.terra.workspace.pact;
2+
3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.ArgumentMatchers.anyString;
5+
import static org.mockito.ArgumentMatchers.eq;
6+
import static org.mockito.Mockito.when;
7+
8+
import au.com.dius.pact.provider.junit5.PactVerificationContext;
9+
import au.com.dius.pact.provider.junitsupport.Provider;
10+
import au.com.dius.pact.provider.junitsupport.State;
11+
import au.com.dius.pact.provider.junitsupport.loader.PactBroker;
12+
import au.com.dius.pact.provider.spring.junit5.MockMvcTestTarget;
13+
import au.com.dius.pact.provider.spring.junit5.PactVerificationSpringProvider;
14+
import bio.terra.landingzone.db.LandingZoneDao;
15+
import bio.terra.landingzone.job.LandingZoneJobService;
16+
import bio.terra.policy.model.TpsPaoConflict;
17+
import bio.terra.policy.model.TpsPaoDescription;
18+
import bio.terra.policy.model.TpsPaoUpdateResult;
19+
import bio.terra.policy.model.TpsUpdateMode;
20+
import bio.terra.workspace.common.BaseAzureUnitTest;
21+
import bio.terra.workspace.service.iam.AuthenticatedUserRequest;
22+
import bio.terra.workspace.service.job.JobService;
23+
import bio.terra.workspace.service.resource.referenced.model.ReferencedResource;
24+
import bio.terra.workspace.service.workspace.model.Workspace;
25+
import bio.terra.workspace.service.workspace.model.WorkspaceStage;
26+
import java.util.Map;
27+
import java.util.UUID;
28+
import org.broadinstitute.dsde.workbench.client.sam.model.UserStatusInfo;
29+
import org.junit.jupiter.api.BeforeEach;
30+
import org.junit.jupiter.api.Tag;
31+
import org.junit.jupiter.api.TestTemplate;
32+
import org.junit.jupiter.api.extension.ExtendWith;
33+
import org.springframework.beans.factory.annotation.Autowired;
34+
import org.springframework.boot.test.mock.mockito.MockBean;
35+
import org.springframework.test.web.servlet.MockMvc;
36+
import org.springframework.transaction.TransactionManager;
37+
38+
@Tag("pact-verification")
39+
@Provider("terra-workspace-manager")
40+
@PactBroker()
41+
public class WdsContractVerificationTest extends BaseAzureUnitTest {
42+
@Autowired private MockMvc mockMvc;
43+
44+
// this block of @MockBeans sprouted up as a result of playing whackamole with failed dependency
45+
// injection errors, mostly due to NPEs through by `DataSourceInitializer`
46+
@MockBean
47+
private LandingZoneDao
48+
mockLandingZoneDao; // required for dependency chain up to azureConnectedTestUtils
49+
50+
@MockBean(name = "tlzTransactionManager")
51+
private TransactionManager
52+
mockTlzTransactionManager; // this bean fails on missing datasource otherwise
53+
54+
@MockBean private JobService mockJobService; // for JobService.initialize call on startup
55+
56+
@MockBean
57+
private LandingZoneJobService mockLandingZoneJobService; // for LandingZone.main call on startup
58+
59+
@TestTemplate
60+
@ExtendWith(PactVerificationSpringProvider.class)
61+
void pactVerificationTestTemplate(PactVerificationContext context) {
62+
context.verifyInteraction();
63+
}
64+
65+
@BeforeEach
66+
void setPactVerificationContext(PactVerificationContext context) {
67+
context.setTarget(new MockMvcTestTarget(mockMvc));
68+
}
69+
70+
@State({"authenticated with the given email"})
71+
public void authenticatedAsAccount(Map<?, ?> parameters) throws InterruptedException {
72+
var authenticatedEmail = parameters.get("email").toString();
73+
74+
// for recording the creator of the snapshot reference...
75+
when(mockSamService()
76+
.getUserEmailFromSamAndRethrowOnInterrupt(any(AuthenticatedUserRequest.class)))
77+
.thenReturn(authenticatedEmail);
78+
79+
// for activity logging...
80+
when(mockSamService().getUserStatusInfo(any(AuthenticatedUserRequest.class)))
81+
.thenReturn(new UserStatusInfo().userEmail(authenticatedEmail).userSubjectId("subjectid"));
82+
}
83+
84+
@State({"a workspace with the given id exists"})
85+
public void workspaceIdExists(Map<?, ?> parameters) {
86+
var workspaceUuid = UUID.fromString(parameters.get("id").toString());
87+
when(mockWorkspaceService()
88+
.validateWorkspaceAndAction(
89+
any(AuthenticatedUserRequest.class), eq(workspaceUuid), /* action= */ anyString()))
90+
.thenReturn(
91+
Workspace.builder()
92+
.workspaceId(workspaceUuid)
93+
.workspaceStage(WorkspaceStage.RAWLS_WORKSPACE)
94+
.userFacingId("workspaceid")
95+
.createdByEmail("[email protected]")
96+
.build());
97+
}
98+
99+
@State({"policies allowing snapshot reference creation"})
100+
public void allowSnapshotReferenceCreation() throws InterruptedException {
101+
when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(true);
102+
var policyUpdateSuccessful = new TpsPaoUpdateResult().updateApplied(true);
103+
when(mockWorkspaceService()
104+
.linkPolicies(
105+
/* workspaceUuid= */ any(UUID.class),
106+
any(TpsPaoDescription.class),
107+
any(TpsUpdateMode.class),
108+
any(AuthenticatedUserRequest.class)))
109+
.thenReturn(policyUpdateSuccessful);
110+
111+
when(mockReferencedResourceService()
112+
.createReferenceResource(
113+
any(ReferencedResource.class), any(AuthenticatedUserRequest.class)))
114+
// just echo back the resource that the controller attempted to create to simulate success
115+
.thenAnswer(invocation -> invocation.getArgument(0));
116+
}
117+
118+
@State({"policies preventing snapshot reference creation"})
119+
public void preventSnapshotReferenceCreation() throws InterruptedException {
120+
when(mockFeatureConfiguration().isTpsEnabled()).thenReturn(true);
121+
var policiesConflicting =
122+
new TpsPaoUpdateResult()
123+
.updateApplied(false)
124+
.addConflictsItem(new TpsPaoConflict().name("some conflict"));
125+
when(mockWorkspaceService()
126+
.linkPolicies(
127+
/* workspaceUuid= */ any(UUID.class),
128+
any(TpsPaoDescription.class),
129+
any(TpsUpdateMode.class),
130+
any(AuthenticatedUserRequest.class)))
131+
.thenReturn(policiesConflicting);
132+
}
133+
}

0 commit comments

Comments
 (0)