Skip to content

Commit

Permalink
Merge pull request #3312 from nscuro/backport-pr-3311
Browse files Browse the repository at this point in the history
Backport: Fix `ClassCastException` when updating an existing `ProjectMetadata#authors` field
  • Loading branch information
nscuro authored Dec 17, 2023
2 parents 4613a41 + 8cb9eff commit d55746a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ public void inform(final Event e) {

final var projectMetadata = new ProjectMetadata();
projectMetadata.setSupplier(ModelConverter.convert(cycloneDxBom.getMetadata().getSupplier()));
projectMetadata.setAuthors(ModelConverter.convertCdxContacts(cycloneDxBom.getMetadata().getAuthors()));
projectMetadata.setAuthors(cycloneDxBom.getMetadata().getAuthors() != null
? new ArrayList<>(ModelConverter.convertCdxContacts(cycloneDxBom.getMetadata().getAuthors()))
: null);
if (project.getMetadata() != null) {
qm.runInTransaction(() -> {
project.getMetadata().setSupplier(projectMetadata.getSupplier());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import alpine.notification.Subscription;
import net.jcip.annotations.NotThreadSafe;
import org.apache.commons.io.IOUtils;
import org.awaitility.core.ConditionTimeoutException;
import org.dependencytrack.PersistenceCapableTest;
import org.dependencytrack.event.BomUploadEvent;
import org.dependencytrack.event.NewVulnerableDependencyAnalysisEvent;
Expand Down Expand Up @@ -53,10 +54,13 @@
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedQueue;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.fail;
import static org.awaitility.Awaitility.await;
import static org.dependencytrack.assertion.Assertions.assertConditionWithTimeout;

@NotThreadSafe
Expand Down Expand Up @@ -285,7 +289,7 @@ public void informWithBomContainingLicenseExpressionTest() throws Exception {
""".getBytes(StandardCharsets.UTF_8);

new BomUploadProcessingTask().inform(new BomUploadEvent(project.getUuid(), bomBytes));
assertConditionWithTimeout(() -> NOTIFICATIONS.size() >= 2, Duration.ofSeconds(5));
awaitBomProcessedNotification();

assertThat(qm.getAllComponents(project)).satisfiesExactly(component -> {
assertThat(component.getLicense()).isNull();
Expand Down Expand Up @@ -329,7 +333,7 @@ public void informWithBomContainingLicenseExpressionWithSingleIdTest() throws Ex
""".getBytes(StandardCharsets.UTF_8);

new BomUploadProcessingTask().inform(new BomUploadEvent(project.getUuid(), bomBytes));
assertConditionWithTimeout(() -> NOTIFICATIONS.size() >= 2, Duration.ofSeconds(5));
awaitBomProcessedNotification();

assertThat(qm.getAllComponents(project)).satisfiesExactly(component -> {
assertThat(component.getResolvedLicense()).isNotNull();
Expand Down Expand Up @@ -369,7 +373,7 @@ public void informWithBomContainingInvalidLicenseExpressionTest() throws Excepti
""".getBytes(StandardCharsets.UTF_8);

new BomUploadProcessingTask().inform(new BomUploadEvent(project.getUuid(), bomBytes));
assertConditionWithTimeout(() -> NOTIFICATIONS.size() >= 2, Duration.ofSeconds(5));
awaitBomProcessedNotification();

assertThat(qm.getAllComponents(project)).satisfiesExactly(component -> {
assertThat(component.getLicense()).isNull();
Expand All @@ -378,4 +382,64 @@ public void informWithBomContainingInvalidLicenseExpressionTest() throws Excepti
});
}

@Test // https://github.com/DependencyTrack/dependency-track/issues/3309
public void informIssue3309Test() {
final var project = new Project();
project.setName("acme-app");
qm.persist(project);

final Runnable assertProjectAuthors = () -> {
qm.getPersistenceManager().evictAll();
assertThat(project.getMetadata()).isNotNull();
assertThat(project.getMetadata().getAuthors()).satisfiesExactly(author -> {
assertThat(author.getName()).isEqualTo("Author Name");
assertThat(author.getEmail()).isEqualTo("[email protected]");
});
};

final byte[] bomBytes = """
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"metadata": {
"authors": [
{
"name": "Author Name",
"email": "[email protected]"
}
]
}
}
""".getBytes();

new BomUploadProcessingTask().inform(new BomUploadEvent(project.getUuid(), bomBytes));
awaitBomProcessedNotification();
assertProjectAuthors.run();

NOTIFICATIONS.clear();

new BomUploadProcessingTask().inform(new BomUploadEvent(project.getUuid(), bomBytes));
awaitBomProcessedNotification();
assertProjectAuthors.run();
}

private void awaitBomProcessedNotification() {
try {
await("BOM Processed Notification")
.atMost(Duration.ofSeconds(3))
.untilAsserted(() -> assertThat(NOTIFICATIONS)
.anyMatch(n -> NotificationGroup.BOM_PROCESSED.name().equals(n.getGroup())));
} catch (ConditionTimeoutException e) {
final Optional<Notification> optionalNotification = NOTIFICATIONS.stream()
.filter(n -> NotificationGroup.BOM_PROCESSING_FAILED.name().equals(n.getGroup()))
.findAny();
if (optionalNotification.isEmpty()) {
throw e;
}

final var subject = (BomProcessingFailed) optionalNotification.get().getSubject();
fail("Expected BOM processing to succeed, but it failed due to: %s", subject.getCause());
}
}

}

0 comments on commit d55746a

Please sign in to comment.