Skip to content

Commit a7fabef

Browse files
authored
test(async-profiler): split GraphQL integration tests into separate file (#1689)
1 parent a622d7c commit a7fabef

2 files changed

Lines changed: 243 additions & 170 deletions

File tree

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/*
2+
* Copyright The Cryostat Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package itest.agent;
17+
18+
import static io.restassured.RestAssured.given;
19+
import static org.hamcrest.MatcherAssert.assertThat;
20+
import static org.hamcrest.Matchers.*;
21+
22+
import java.time.Duration;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.concurrent.TimeoutException;
26+
27+
import io.cryostat.resources.AgentApplicationResource;
28+
29+
import io.quarkus.test.common.QuarkusTestResource;
30+
import io.quarkus.test.junit.QuarkusIntegrationTest;
31+
import io.restassured.http.ContentType;
32+
import io.restassured.response.Response;
33+
import io.vertx.core.json.JsonObject;
34+
import itest.resources.S3StorageITResource;
35+
import org.hamcrest.MatcherAssert;
36+
import org.hamcrest.Matchers;
37+
import org.junit.jupiter.api.AfterEach;
38+
import org.junit.jupiter.api.Test;
39+
40+
@QuarkusIntegrationTest
41+
@QuarkusTestResource(value = AgentApplicationResource.class, restrictToAnnotatedClass = true)
42+
@QuarkusTestResource(value = S3StorageITResource.class, restrictToAnnotatedClass = true)
43+
public class AgentAsyncProfilerGraphQLIT extends AgentTestBase {
44+
45+
@AfterEach
46+
void cleanupAsyncProfiles() {
47+
if (target == null) {
48+
return;
49+
}
50+
51+
List<Map<String, Object>> profiles =
52+
given().log()
53+
.all()
54+
.pathParams("targetId", target.id())
55+
.when()
56+
.get("/api/beta/targets/{targetId}/async-profiler")
57+
.then()
58+
.extract()
59+
.body()
60+
.jsonPath()
61+
.getList("$");
62+
63+
for (Map<String, Object> profile : profiles) {
64+
String profileId = (String) profile.get("id");
65+
given().log()
66+
.all()
67+
.pathParams("targetId", target.id(), "profileId", profileId)
68+
.when()
69+
.delete("/api/beta/targets/{targetId}/async-profiler/{profileId}")
70+
.then()
71+
.log()
72+
.all();
73+
}
74+
}
75+
76+
@Test
77+
void testGraphQL() {
78+
long targetId = target.id();
79+
80+
// Create a Profile
81+
Map<String, Object> requestBody = Map.of("events", List.of("alloc"), "duration", 5);
82+
83+
given().log()
84+
.all()
85+
.pathParams("targetId", targetId)
86+
.contentType(ContentType.JSON)
87+
.body(requestBody)
88+
.when()
89+
.post("/api/beta/targets/{targetId}/async-profiler")
90+
.then()
91+
.log()
92+
.all()
93+
.and()
94+
.assertThat()
95+
.statusCode(200)
96+
.contentType(ContentType.TEXT)
97+
.body(Matchers.notNullValue())
98+
.and()
99+
.extract()
100+
.body()
101+
.asString();
102+
JsonObject query = new JsonObject();
103+
query.put(
104+
"query",
105+
"query TargetAsyncProfiles {targetNodes(filter: { id: "
106+
+ targetId
107+
+ " }) {target {agent id connectUrl alias jvmId asyncProfiles { data {"
108+
+ " duration id startTime size } aggregate { count } } } } }");
109+
Response resp =
110+
given().basePath("/")
111+
.contentType(ContentType.JSON)
112+
.body(query.encode())
113+
.log()
114+
.all()
115+
.when()
116+
.post("/api/v4/graphql")
117+
.then()
118+
.log()
119+
.all()
120+
.and()
121+
.assertThat()
122+
.statusCode(200)
123+
.extract()
124+
.response();
125+
126+
JsonObject retrievedResponse = new JsonObject(resp.asString());
127+
assertThat(retrievedResponse, notNullValue());
128+
assertThat(retrievedResponse.getMap().size(), not(0));
129+
}
130+
131+
@Test
132+
void testCreateMutation() throws InterruptedException, TimeoutException {
133+
long targetId = target.id();
134+
135+
JsonObject query = new JsonObject();
136+
query.put(
137+
"query",
138+
"mutation {createAsyncProfile(nodes:{id:"
139+
+ targetId
140+
+ "},id: \"profile\",startTime: 1,events: [\"alloc\"],duration: 5)}");
141+
142+
Response response =
143+
given().basePath("/")
144+
.contentType(ContentType.JSON)
145+
.body(query.encode())
146+
.log()
147+
.all()
148+
.when()
149+
.post("/api/v4/graphql")
150+
.then()
151+
.log()
152+
.all()
153+
.and()
154+
.assertThat()
155+
.statusCode(allOf(greaterThanOrEqualTo(200), lessThan(300)))
156+
.extract()
157+
.response();
158+
159+
webSocketClient.expectNotification("AsyncProfilerCreated", Duration.ofSeconds(10));
160+
161+
assertThat(response.getStatusCode(), equalTo(200));
162+
assertThat(response.getBody(), notNullValue());
163+
}
164+
165+
@Test
166+
void testDeleteMutation() throws Exception {
167+
long targetId = target.id();
168+
169+
// Create a Profile
170+
Map<String, Object> requestBody = Map.of("events", List.of("alloc"), "duration", 5);
171+
172+
String profileId =
173+
given().log()
174+
.all()
175+
.pathParams("targetId", targetId)
176+
.contentType(ContentType.JSON)
177+
.body(requestBody)
178+
.when()
179+
.post("/api/beta/targets/{targetId}/async-profiler")
180+
.then()
181+
.log()
182+
.all()
183+
.and()
184+
.assertThat()
185+
.statusCode(200)
186+
.contentType(ContentType.TEXT)
187+
.body(Matchers.notNullValue())
188+
.and()
189+
.extract()
190+
.body()
191+
.asString();
192+
193+
webSocketClient.expectNotification("AsyncProfilerCreated", Duration.ofSeconds(10));
194+
// Wait for the profile to stop
195+
JsonObject stoppedNotification =
196+
webSocketClient.expectNotification(
197+
"AsyncProfilerStopped",
198+
Duration.ofMinutes(2),
199+
o -> profileId.equals(o.getJsonObject("message").getString("id")));
200+
201+
MatcherAssert.assertThat(
202+
stoppedNotification.getJsonObject("message").getString("id"),
203+
Matchers.equalTo(profileId));
204+
205+
JsonObject deleteQuery = new JsonObject();
206+
deleteQuery.put(
207+
"query",
208+
String.format(
209+
"mutation { deleteAsyncProfiles (nodes: { id:"
210+
+ targetId
211+
+ "}) { id size duration startTime }}",
212+
profileId));
213+
214+
Response deleteResponse =
215+
given().contentType(ContentType.JSON)
216+
.body(deleteQuery.encode())
217+
.when()
218+
.post("/api/v4/graphql")
219+
.then()
220+
.log()
221+
.all()
222+
.statusCode(allOf(greaterThanOrEqualTo(200), lessThan(300)))
223+
.extract()
224+
.response();
225+
226+
assertThat(deleteResponse.getStatusCode(), equalTo(200));
227+
228+
// Verify the profile was deleted
229+
given().log()
230+
.all()
231+
.pathParams("targetId", targetId)
232+
.when()
233+
.get("/api/beta/targets/{targetId}/async-profiler")
234+
.then()
235+
.log()
236+
.all()
237+
.and()
238+
.assertThat()
239+
.contentType(ContentType.JSON)
240+
.statusCode(200)
241+
.body("$.size()", Matchers.equalTo(0));
242+
}
243+
}

0 commit comments

Comments
 (0)