Skip to content

Commit

Permalink
Add fixedFindings to CodeTFChangesetEntry
Browse files Browse the repository at this point in the history
  • Loading branch information
drdavella committed Dec 9, 2024
1 parent 01f14f6 commit d324d56
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 7 deletions.
17 changes: 15 additions & 2 deletions src/main/java/io/codemodder/codetf/CodeTFChangesetEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

/** Describes an individual changeset entry. */
public final class CodeTFChangesetEntry {
Expand All @@ -18,25 +19,29 @@ public final class CodeTFChangesetEntry {
private final Strategy strategy;
private final boolean provisional;

private final List<FixedFinding> fixedFindings;

@JsonCreator
public CodeTFChangesetEntry(
@JsonProperty("path") final String path,
@JsonProperty("diff") final String diff,
@JsonProperty("changes") final List<CodeTFChange> changes,
@JsonProperty("ai") final CodeTFAiMetadata ai,
@JsonProperty("strategy") final Strategy strategy,
@JsonProperty("provisional") final boolean provisional) {
@JsonProperty("provisional") final boolean provisional,
@JsonProperty("fixedFindings") final List<FixedFinding> fixedFindings) {
this.path = CodeTFValidator.requireRelativePath(path);
this.diff = CodeTFValidator.requireNonBlank(diff);
this.changes = CodeTFValidator.toImmutableCopyOrEmptyOnNull(changes);
this.ai = ai;
this.strategy = strategy;
this.provisional = provisional;
this.fixedFindings = CodeTFValidator.toImmutableCopyOrEmptyOnNull(fixedFindings);
}

public CodeTFChangesetEntry(
final String path, final String diff, final List<CodeTFChange> changes) {
this(path, diff, changes, null, null, false);
this(path, diff, changes, null, null, false, null);
}

public String getPath() {
Expand Down Expand Up @@ -67,6 +72,14 @@ public boolean isProvisional() {
return provisional;
}

/** Fixed findings that are not associated with any particular change */
public List<FixedFinding> getFixedFindings() {
return Stream.concat(
fixedFindings.stream(),
changes.stream().map(CodeTFChange::getFixedFindings).flatMap(List::stream))
.toList();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/io/codemodder/codetf/CodeTFResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ public boolean usesAi() {
@JsonIgnore
public List<FixedFinding> getFixedFindings() {
return changeset.stream()
.map(CodeTFChangesetEntry::getChanges)
.flatMap(List::stream)
.map(CodeTFChange::getFixedFindings)
.map(CodeTFChangesetEntry::getFixedFindings)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Expand Down
91 changes: 89 additions & 2 deletions src/test/java/io/codemodder/codetf/CodeTFResultTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void it_creates_unfixed_findings() {
void it_has_changeset_with_ai() {
CodeTFAiMetadata ai = new CodeTFAiMetadata("ai", "best-model-ever", null);
CodeTFChangesetEntry entry =
new CodeTFChangesetEntry("src/foo", "diff", List.of(), ai, null, false);
new CodeTFChangesetEntry("src/foo", "diff", List.of(), ai, null, false, null);
assertTrue(entry.usesAi());

final var result =
Expand All @@ -161,7 +161,7 @@ void it_has_changeset_with_ai() {
void it_has_changeset_with_fix_quality_metadata() {
CodeTFAiMetadata ai = new CodeTFAiMetadata("ai", "best-model-ever", null);
CodeTFChangesetEntry entry =
new CodeTFChangesetEntry("src/foo", "diff", List.of(), ai, Strategy.HYBRID, true);
new CodeTFChangesetEntry("src/foo", "diff", List.of(), ai, Strategy.HYBRID, true, null);

assertEquals(entry.getStrategy(), Strategy.HYBRID);
assertTrue(entry.isProvisional());
Expand All @@ -173,4 +173,91 @@ void it_has_failure_state() {
assertEquals("reason", state.getReason());
assertEquals("exception", state.getException());
}

@Test
void it_has_changeset_with_change_with_fixed_finding() {
DetectorRule rule = new DetectorRule("rule", "Here's a rule", null);
FixedFinding finding = new FixedFinding("finding", rule);
CodeTFChange change =
new CodeTFChange(1, null, "whatever", CodeTFDiffSide.RIGHT, null, null, List.of(finding));
CodeTFChangesetEntry entry = new CodeTFChangesetEntry("src/foo", "diff", List.of(change));
assertEquals(1, entry.getFixedFindings().size());

final var result =
new CodeTFResult(
"codemodder:java/deserialization",
"Hardened object deserialization calls against attack",
"Lengthier description about deserialization risks, protections, etc...",
null,
null,
Set.of("/foo/failed.java"),
List.of(
new CodeTFReference(
"https://www.oracle.com/technetwork/java/seccodeguide-139067.html#8",
"Oracle's Secure Coding Guidelines for Java SE")),
null,
List.of(entry),
List.of());
assertEquals(1, result.getFixedFindings().size());
}

@Test
void it_has_changeset_with_fixed_finding() {
DetectorRule rule = new DetectorRule("rule", "Here's a rule", null);
FixedFinding finding = new FixedFinding("finding", rule);
CodeTFChange change =
new CodeTFChange(1, null, "whatever", CodeTFDiffSide.RIGHT, null, null, null);
CodeTFChangesetEntry entry =
new CodeTFChangesetEntry(
"src/foo", "diff", List.of(change), null, null, false, List.of(finding));
assertEquals(1, entry.getFixedFindings().size());

final var result =
new CodeTFResult(
"codemodder:java/deserialization",
"Hardened object deserialization calls against attack",
"Lengthier description about deserialization risks, protections, etc...",
null,
null,
Set.of("/foo/failed.java"),
List.of(
new CodeTFReference(
"https://www.oracle.com/technetwork/java/seccodeguide-139067.html#8",
"Oracle's Secure Coding Guidelines for Java SE")),
null,
List.of(entry),
List.of());
assertEquals(1, result.getFixedFindings().size());
}

@Test
void it_has_multiple_changes_with_findings_and_changeset_with_findings() {
DetectorRule rule = new DetectorRule("rule", "Here's a rule", null);
FixedFinding finding = new FixedFinding("finding", rule);
CodeTFChange change =
new CodeTFChange(1, null, "whatever", CodeTFDiffSide.RIGHT, null, null, List.of(finding));
CodeTFChange change2 =
new CodeTFChange(1, null, "whatever", CodeTFDiffSide.RIGHT, null, null, List.of(finding));
CodeTFChangesetEntry entry =
new CodeTFChangesetEntry(
"src/foo", "diff", List.of(change, change2), null, null, false, List.of(finding));
assertEquals(3, entry.getFixedFindings().size());

final var result =
new CodeTFResult(
"codemodder:java/deserialization",
"Hardened object deserialization calls against attack",
"Lengthier description about deserialization risks, protections, etc...",
null,
null,
Set.of("/foo/failed.java"),
List.of(
new CodeTFReference(
"https://www.oracle.com/technetwork/java/seccodeguide-139067.html#8",
"Oracle's Secure Coding Guidelines for Java SE")),
null,
List.of(entry, entry),
List.of());
assertEquals(6, result.getFixedFindings().size());
}
}

0 comments on commit d324d56

Please sign in to comment.