Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port regression test for parent field occasionally missing in /api/v1/project/{uuid} responses #4050

Merged
merged 1 commit into from
Aug 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.MediaType;
Expand Down Expand Up @@ -61,7 +62,9 @@

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -1245,4 +1248,76 @@ public void issue3883RegressionTest() {
""");
}

@Test // https://github.com/DependencyTrack/dependency-track/issues/4048
public void issue4048RegressionTest() {
final int projectsPerLevel = 10;
final int maxDepth = 5;

final Map<Integer, List<UUID>> projectUuidsByLevel = new HashMap<>();

// Create multiple parent-child hierarchies of projects.
for (int i = 0; i < maxDepth; i++) {
final List<UUID> parentUuids = projectUuidsByLevel.get(i - 1);

for (int j = 0; j < projectsPerLevel; j++) {
final UUID parentUuid = i > 0 ? parentUuids.get(j) : null;

final JsonObjectBuilder requestBodyBuilder = Json.createObjectBuilder()
.add("name", "project-%d-%d".formatted(i, j))
.add("version", "%d.%d".formatted(i, j));
if (parentUuid != null) {
requestBodyBuilder.add("parent", Json.createObjectBuilder()
.add("uuid", parentUuid.toString()));
}

final Response response = jersey.target(V1_PROJECT)
.request()
.header(X_API_KEY, apiKey)
.put(Entity.json(requestBodyBuilder.build().toString()));
assertThat(response.getStatus()).isEqualTo(201);
final JsonObject jsonResponse = parseJsonObject(response);

projectUuidsByLevel.compute(i, (ignored, uuids) -> {
final UUID uuid = UUID.fromString(jsonResponse.getString("uuid"));
if (uuids == null) {
return new ArrayList<>(List.of(uuid));
}

uuids.add(uuid);
return uuids;
});
}
}

// Pick out the UUIDs of projects that should have a parent (i.e. level 1 or above).
final List<UUID> childUuids = projectUuidsByLevel.entrySet().stream()
.filter(entry -> entry.getKey() > 0)
.map(Map.Entry::getValue)
.flatMap(List::stream)
.toList();

// Create a [uuid -> level] mapping for better assertion failure reporting.
final Map<UUID, Integer> levelByChildUuid = projectUuidsByLevel.entrySet().stream()
.filter(entry -> entry.getKey() > 0)
.flatMap(entry -> {
final Integer level = entry.getKey();
return entry.getValue().stream().map(uuid -> Map.entry(uuid, level));
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

// Request all child projects individually.
// Ensure that the parent field is populated for all of them.
for (final UUID uuid : childUuids) {
final Response response = jersey.target(V1_PROJECT + "/" + uuid)
.request()
.header(X_API_KEY, apiKey)
.get();
assertThat(response.getStatus()).isEqualTo(200);
final JsonObject json = parseJsonObject(response);
assertThat(json.getJsonObject("parent"))
.withFailMessage("Parent missing on level: " + levelByChildUuid.get(uuid))
.isNotEmpty();
}
}

}