Skip to content

Commit f142337

Browse files
authored
AJ-1234: Add WsmPactTest (#372)
This is the first of several test suites verifying interaction with WSM; this one focuses specifically on `createDataRepoSnapshotReference`.
1 parent 3cef8c3 commit f142337

File tree

1 file changed

+184
-0
lines changed
  • service/src/test/java/org/databiosphere/workspacedataservice/pact

1 file changed

+184
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package org.databiosphere.workspacedataservice.pact;
2+
3+
import static au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody;
4+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
7+
import au.com.dius.pact.consumer.MockServer;
8+
import au.com.dius.pact.consumer.dsl.DslPart;
9+
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
10+
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
11+
import au.com.dius.pact.consumer.junit5.PactTestFor;
12+
import au.com.dius.pact.core.model.PactSpecVersion;
13+
import au.com.dius.pact.core.model.RequestResponsePact;
14+
import au.com.dius.pact.core.model.annotations.Pact;
15+
import bio.terra.datarepo.model.SnapshotModel;
16+
import bio.terra.workspace.model.CloningInstructionsEnum;
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
import java.util.UUID;
20+
import org.databiosphere.workspacedataservice.workspacemanager.HttpWorkspaceManagerClientFactory;
21+
import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerClientFactory;
22+
import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerDao;
23+
import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerException;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Tag;
26+
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.extension.ExtendWith;
28+
import org.springframework.mock.web.MockHttpServletRequest;
29+
import org.springframework.web.context.request.RequestContextHolder;
30+
import org.springframework.web.context.request.ServletRequestAttributes;
31+
32+
@Tag("pact-test")
33+
@ExtendWith(PactConsumerTestExt.class)
34+
public class WsmPactTest {
35+
// copied from DslPart.UUID_REGEX, used to configure Pact to accept a wildcard UUID as the
36+
// workspaceId path param
37+
private static final String UUID_REGEX_PATTERN =
38+
"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
39+
40+
// the two UUIDs are hardcoded to prevent churn in pactfiles, and intended to be human memorable
41+
private static final UUID WORKSPACE_UUID =
42+
UUID.fromString("facade00-0000-4000-a000-000000000000");
43+
private static final UUID SNAPSHOT_UUID = UUID.fromString("decade00-0000-4000-a000-000000000000");
44+
private static final String SNAPSHOT_NAME = "hardcodedSnapshotName";
45+
private static final String SNAPSHOT_CREATOR_EMAIL = "[email protected]";
46+
47+
@BeforeEach
48+
void setUp() {
49+
// Without this setup, the HttpClient throws a "No thread-bound request found" error
50+
RequestContextHolder.setRequestAttributes(
51+
new ServletRequestAttributes(new MockHttpServletRequest()));
52+
}
53+
54+
private String snapshotPath(String workspaceIdPart) {
55+
return String.format(
56+
"/api/workspaces/v1/%s/resources/referenced/datarepo/snapshots", workspaceIdPart);
57+
}
58+
59+
@Pact(consumer = "wds", provider = "workspacemanager")
60+
RequestResponsePact linkSnapshotForPolicySuccess(PactDslWithProvider builder) {
61+
return builder
62+
.given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString()))
63+
.given("authenticated with the given email", Map.of("email", SNAPSHOT_CREATOR_EMAIL))
64+
.given("policies allowing snapshot reference creation")
65+
.uponReceiving("a request to create a snapshot reference")
66+
.matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString()))
67+
.method("POST")
68+
.headers(contentTypeJson())
69+
.body(createSnapshotReferenceBody(SNAPSHOT_NAME))
70+
.willRespondWith()
71+
.status(200) // ok
72+
.headers(contentTypeJson())
73+
.body(
74+
newJsonBody(
75+
body -> {
76+
// put expectations here if we ever start reading fields in the code under
77+
// test
78+
})
79+
.build())
80+
.toPact();
81+
}
82+
83+
private String conditions(String... conditions) {
84+
return String.join(" and ", conditions);
85+
}
86+
87+
@Pact(consumer = "wds", provider = "workspacemanager")
88+
RequestResponsePact linkSnapshotForPolicyConflict(PactDslWithProvider builder) {
89+
return builder
90+
.given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString()))
91+
.given("authenticated with the given email", Map.of("email", SNAPSHOT_CREATOR_EMAIL))
92+
.given("policies preventing snapshot reference creation")
93+
.uponReceiving("a request to create a snapshot reference")
94+
.matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString()))
95+
.method("POST")
96+
.headers(contentTypeJson())
97+
.body(createSnapshotReferenceBody(SNAPSHOT_NAME))
98+
.willRespondWith()
99+
.status(409) // conflict
100+
.headers(contentTypeJson())
101+
.body(
102+
newJsonBody(
103+
body ->
104+
body.stringMatcher(
105+
"message", "^(.*)policy conflict(.*)$", "unexpected policy conflict"))
106+
.build())
107+
.toPact();
108+
}
109+
110+
@Test
111+
@PactTestFor(
112+
pactMethod = "linkSnapshotForPolicySuccess",
113+
providerName = "workspacemanager",
114+
pactVersion = PactSpecVersion.V3)
115+
void testLinkSnapshotForPolicySuccess(MockServer mockServer) {
116+
var wsmDao = buildWsmDao(mockServer);
117+
var snapshotModel = buildSnapshotModel();
118+
119+
assertDoesNotThrow(() -> wsmDao.linkSnapshotForPolicy(snapshotModel));
120+
}
121+
122+
@Test
123+
@PactTestFor(
124+
pactMethod = "linkSnapshotForPolicyConflict",
125+
providerName = "workspacemanager",
126+
pactVersion = PactSpecVersion.V3)
127+
void testLinkSnapshotForPolicyConflict(MockServer mockServer) {
128+
var wsmDao = buildWsmDao(mockServer);
129+
var snapshotModel = buildSnapshotModel();
130+
131+
assertThrows(
132+
WorkspaceManagerException.class, () -> wsmDao.linkSnapshotForPolicy(snapshotModel));
133+
}
134+
135+
private SnapshotModel buildSnapshotModel() {
136+
return new SnapshotModel().id(SNAPSHOT_UUID).name(SNAPSHOT_NAME);
137+
}
138+
139+
private WorkspaceManagerDao buildWsmDao(MockServer mockServer) {
140+
WorkspaceManagerClientFactory clientFactory =
141+
new HttpWorkspaceManagerClientFactory(mockServer.getUrl());
142+
return new WorkspaceManagerDao(clientFactory, WORKSPACE_UUID.toString());
143+
}
144+
145+
private DslPart createSnapshotReferenceBody(String snapshotName) {
146+
// metadata.name is a composite of <snapshotName>_<timestamp>
147+
String nameFormatString = String.format("'%s'_yyyyMMddHHmmss", snapshotName);
148+
149+
return newJsonBody(
150+
body -> {
151+
body.object(
152+
"snapshot",
153+
snapshot -> {
154+
snapshot.stringValue("instanceName", "terra");
155+
snapshot.uuid("snapshot");
156+
});
157+
body.object(
158+
"metadata",
159+
metadata -> {
160+
metadata.stringValue(
161+
"cloningInstructions", CloningInstructionsEnum.REFERENCE.toString());
162+
metadata.datetime("name", nameFormatString);
163+
// expect exactly one property, declaring the snapshot as being for policy only
164+
metadata.minMaxArrayLike(
165+
"properties",
166+
/* minSize= */ 1,
167+
/* maxSize= */ 1,
168+
p -> {
169+
p.stringValue("key", "purpose");
170+
p.stringValue("value", "policy");
171+
});
172+
});
173+
})
174+
.build();
175+
}
176+
177+
private Map<String, String> contentTypeJson() {
178+
Map<String, String> headers = new HashMap<>();
179+
// pact will automatically assume an expected Content-Type of "application/json; charset=UTF-8"
180+
// unless we explicitly tell it otherwise
181+
headers.put("Content-Type", "application/json");
182+
return headers;
183+
}
184+
}

0 commit comments

Comments
 (0)