From c9836f49a95f00eff42f064eefe403a2a952b0e1 Mon Sep 17 00:00:00 2001 From: pmbittner Date: Thu, 18 Aug 2022 16:53:39 +0200 Subject: [PATCH 1/9] serialization of formulas for use in cpp annotations --- .../io/kernelhaven/ArtefactCSVExporter.java | 6 +++--- .../vevos/simulation/util/fide/FormulaUtils.java | 13 ++++++++++++- .../simulation/util/fide/bugfix/FixTrueFalse.java | 7 +++++++ .../pc/variantlines/VariantAnnotation.java | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/variantsync/vevos/simulation/io/kernelhaven/ArtefactCSVExporter.java b/src/main/java/org/variantsync/vevos/simulation/io/kernelhaven/ArtefactCSVExporter.java index d7806e0..e0f1f11 100644 --- a/src/main/java/org/variantsync/vevos/simulation/io/kernelhaven/ArtefactCSVExporter.java +++ b/src/main/java/org/variantsync/vevos/simulation/io/kernelhaven/ArtefactCSVExporter.java @@ -59,9 +59,9 @@ public CSV export() { private String[] toRow(final LineBasedAnnotation annotation) { final String[] row = makeRow(); row[0] = currentFile.getFile().toString(); - row[1] = FormulaUtils.toString(currentFile.getPresenceCondition(), NodeWriter.javaSymbols); - row[2] = FormulaUtils.toString(annotation.getFeatureMapping(), NodeWriter.javaSymbols); - row[3] = FormulaUtils.toString(annotation.getPresenceCondition(), NodeWriter.javaSymbols); + row[1] = FormulaUtils.toFormulaString(currentFile.getPresenceCondition(), NodeWriter.javaSymbols); + row[2] = FormulaUtils.toFormulaString(annotation.getFeatureMapping(), NodeWriter.javaSymbols); + row[3] = FormulaUtils.toFormulaString(annotation.getPresenceCondition(), NodeWriter.javaSymbols); row[4] = "" + annotation.getLineFrom(); // -1 because Kernelhaven stores annotations as [#if, #endif) intervals, so we have to point one line before the annotation end (#endif). row[5] = "" + (annotation.getLineTo() - (annotation.isMacro() ? 1 : 0)); diff --git a/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java b/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java index 6ea5b21..2fc35d9 100644 --- a/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java +++ b/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java @@ -103,10 +103,21 @@ public static Node replaceAllInplace(final Node root, final Predicate who, } } - public static String toString(Node formula, final String[] symbols) { + /** + * Serializes the given formula to a string usable in C preprocessor conditions. + * True and false will be converted to 1 and 0, respectively. + * Variables will be wrapped in a defined expression. + * @see FixTrueFalse#TrueAs1 + * @see FixTrueFalse#FalseAs0 + */ + public static String toCPPString(Node formula, final String[] symbols) { formula = replaceAll(formula, FixTrueFalse::isTrue, n -> FixTrueFalse.TrueAs1); formula = replaceAllInplace(formula, FixTrueFalse::isFalse, n -> FixTrueFalse.FalseAs0); + formula = replaceAllInplace(formula, FixTrueFalse::isVariable, n -> new Literal("defined(" + n.toString() + ")")); + return toFormulaString(formula, symbols); + } + public static String toFormulaString(Node formula, final String[] symbols) { final NodeWriter writer = new NodeWriter(formula); writer.setNotation(NodeWriter.Notation.INFIX); writer.setEnquoteWhitespace(false); diff --git a/src/main/java/org/variantsync/vevos/simulation/util/fide/bugfix/FixTrueFalse.java b/src/main/java/org/variantsync/vevos/simulation/util/fide/bugfix/FixTrueFalse.java index 87afab3..6dcb1ab 100644 --- a/src/main/java/org/variantsync/vevos/simulation/util/fide/bugfix/FixTrueFalse.java +++ b/src/main/java/org/variantsync/vevos/simulation/util/fide/bugfix/FixTrueFalse.java @@ -50,6 +50,13 @@ public static boolean isFalse(final Node n) { return n instanceof Literal l && isFalseLiteral(l); } + /** + * @return True iff the given formula is a literal that neither {@link #isTrue} nor {@link #isFalse}. + */ + public static boolean isVariable(final Node n) { + return n instanceof Literal l && !isTrueLiteral(l) && !isFalseLiteral(l); + } + /** * @return True iff the given name represents the atomic value true w.r.t. the constant TrueNames. */ diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java index 9a693d2..402b272 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java @@ -17,7 +17,7 @@ public List project(final VariantGenerationOptions projectionOptions, fi final List result = new ArrayList<>(); if (projectionOptions.withMacros()) { - result.add("#if " + FormulaUtils.toString(condition, NodeWriter.javaSymbols)); + result.add("#if " + FormulaUtils.toCPPString(condition, NodeWriter.javaSymbols)); } for (final VariantLineChunk child : lines) { From e0a46ec808b0154d51af616038c5e96773d7117c Mon Sep 17 00:00:00 2001 From: pmbittner Date: Thu, 18 Aug 2022 18:22:33 +0200 Subject: [PATCH 2/9] bugfix: in wrapping negated literals in defined statements --- .../simulation/util/fide/FormulaUtils.java | 26 ++++++++++++++++--- .../pc/variantlines/VariantAnnotation.java | 3 +-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java b/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java index 2fc35d9..a85923e 100644 --- a/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java +++ b/src/main/java/org/variantsync/vevos/simulation/util/fide/FormulaUtils.java @@ -103,6 +103,21 @@ public static Node replaceAllInplace(final Node root, final Predicate who, } } + /** + * Wraps a literal name in a defined statement. + * x -> defined(x) + * !x -> !defined(x) + */ + private static Node ifdef(final Literal l) { + final Function toDefinedLiteral = s -> new Literal("defined(" + s + ")"); + + if (l.positive) { + return toDefinedLiteral.apply(l); + } else { + return new Not(toDefinedLiteral.apply(new Literal(l.var, true))); + } + } + /** * Serializes the given formula to a string usable in C preprocessor conditions. * True and false will be converted to 1 and 0, respectively. @@ -110,14 +125,17 @@ public static Node replaceAllInplace(final Node root, final Predicate who, * @see FixTrueFalse#TrueAs1 * @see FixTrueFalse#FalseAs0 */ - public static String toCPPString(Node formula, final String[] symbols) { + public static String toCPPString(Node formula) { formula = replaceAll(formula, FixTrueFalse::isTrue, n -> FixTrueFalse.TrueAs1); formula = replaceAllInplace(formula, FixTrueFalse::isFalse, n -> FixTrueFalse.FalseAs0); - formula = replaceAllInplace(formula, FixTrueFalse::isVariable, n -> new Literal("defined(" + n.toString() + ")")); - return toFormulaString(formula, symbols); + formula = replaceAllInplace(formula, FixTrueFalse::isVariable, + // we know that n is a literal because FixTureFalse::isVariable returned true + n -> ifdef((Literal) n) + ); + return toFormulaString(formula, NodeWriter.javaSymbols); } - public static String toFormulaString(Node formula, final String[] symbols) { + public static String toFormulaString(final Node formula, final String[] symbols) { final NodeWriter writer = new NodeWriter(formula); writer.setNotation(NodeWriter.Notation.INFIX); writer.setEnquoteWhitespace(false); diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java index 402b272..c255fb5 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java @@ -1,7 +1,6 @@ package org.variantsync.vevos.simulation.variability.pc.variantlines; import org.prop4j.Node; -import org.prop4j.NodeWriter; import org.variantsync.vevos.simulation.util.fide.FormulaUtils; import org.variantsync.vevos.simulation.variability.pc.options.VariantGenerationOptions; @@ -17,7 +16,7 @@ public List project(final VariantGenerationOptions projectionOptions, fi final List result = new ArrayList<>(); if (projectionOptions.withMacros()) { - result.add("#if " + FormulaUtils.toCPPString(condition, NodeWriter.javaSymbols)); + result.add("#if " + FormulaUtils.toCPPString(condition)); } for (final VariantLineChunk child : lines) { From c6366858e8e3238111e1df76a99b25b01ce11fe2 Mon Sep 17 00:00:00 2001 From: pmbittner Date: Thu, 18 Aug 2022 18:34:33 +0200 Subject: [PATCH 3/9] bugfix: do not generate redundant true annotations --- .../pc/variantlines/VariantAnnotation.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java index c255fb5..3a1bddb 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/pc/variantlines/VariantAnnotation.java @@ -2,6 +2,7 @@ import org.prop4j.Node; import org.variantsync.vevos.simulation.util.fide.FormulaUtils; +import org.variantsync.vevos.simulation.util.fide.bugfix.FixTrueFalse; import org.variantsync.vevos.simulation.variability.pc.options.VariantGenerationOptions; import java.util.ArrayList; @@ -15,7 +16,9 @@ public record VariantAnnotation( public List project(final VariantGenerationOptions projectionOptions, final List splFileLines) { final List result = new ArrayList<>(); - if (projectionOptions.withMacros()) { + final boolean genMacro = projectionOptions.withMacros() && !isTrue(); + + if (genMacro) { result.add("#if " + FormulaUtils.toCPPString(condition)); } @@ -23,10 +26,14 @@ public List project(final VariantGenerationOptions projectionOptions, fi result.addAll(child.project(projectionOptions, splFileLines)); } - if (projectionOptions.withMacros()) { + if (genMacro) { result.add("#endif"); } return result; } + + public boolean isTrue() { + return FixTrueFalse.isTrue(condition); + } } From e472307958a846d6615f621f620db890d3b5bfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Wed, 24 Aug 2022 12:59:05 +0200 Subject: [PATCH 4/9] fix: removed invalid '-character from BusyBox ENABLE macro normalization --- .../vevos/simulation/repository/BusyboxRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/variantsync/vevos/simulation/repository/BusyboxRepository.java b/src/main/java/org/variantsync/vevos/simulation/repository/BusyboxRepository.java index e9f558e..911734f 100644 --- a/src/main/java/org/variantsync/vevos/simulation/repository/BusyboxRepository.java +++ b/src/main/java/org/variantsync/vevos/simulation/repository/BusyboxRepository.java @@ -275,13 +275,13 @@ private static boolean doNotNormalizeDefUndef(@NonNull final String line) { temp = notNull(temp.replace("ENABLE_", "defined CONFIG_")); } if (temp.contains("&& ENABLE_")) { - temp = notNull(temp.replace("ENABLE_", "'defined CONFIG_")); + temp = notNull(temp.replace("ENABLE_", "defined CONFIG_")); } if (temp.contains("|| !ENABLE_")) { temp = notNull(temp.replace("!ENABLE_", "!defined CONFIG_")); } if (temp.contains("&& !ENABLE_")) { - temp = notNull(temp.replace("!ENABLE_", "'!defined CONFIG_")); + temp = notNull(temp.replace("!ENABLE_", "!defined CONFIG_")); } return temp; From 22481c98bf5789d29559d3a2424345d8d322945c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Thu, 1 Sep 2022 16:55:52 +0200 Subject: [PATCH 5/9] test: added test for the example specified in the docs of LongestNonOverlappingSequences --- .../simulation/variability/SPLCommit.java | 2 +- .../LongestNonOverlappingSequencesTest.java | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/SPLCommit.java b/src/main/java/org/variantsync/vevos/simulation/variability/SPLCommit.java index 9f34ef1..1cff95e 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/SPLCommit.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/SPLCommit.java @@ -138,7 +138,7 @@ public Optional parents() { return Optional.ofNullable(parents); } - public void setParents(final SPLCommit[] parents) { + public void setParents(final SPLCommit... parents) { this.parents = parents; } diff --git a/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java new file mode 100644 index 0000000..df93245 --- /dev/null +++ b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java @@ -0,0 +1,72 @@ +package org.variantsync.vevos.simulation.variability.sequenceextraction; + +import org.junit.Test; +import org.variantsync.functjonal.list.NonEmptyList; +import org.variantsync.vevos.simulation.variability.SPLCommit; + +import java.util.Arrays; +import java.util.List; + +public class LongestNonOverlappingSequencesTest { + + @Test + public void exampleExtraction() { + // For example, if the commits comprise three partially overlapping sequences ([A-B-C-D-E], [X-Y-Z], [A-B-F-G]), + // the function will return the sequences ([A-B-C-D-E], [X-Y-Z], [F-G]). + final SPLCommit a = new SPLCommit("A"); + final SPLCommit b = new SPLCommit("B"); + final SPLCommit c = new SPLCommit("C"); + final SPLCommit d = new SPLCommit("D"); + final SPLCommit e = new SPLCommit("E"); + final SPLCommit f = new SPLCommit("F"); + final SPLCommit g = new SPLCommit("G"); + final SPLCommit x = new SPLCommit("X"); + final SPLCommit y = new SPLCommit("Y"); + final SPLCommit z = new SPLCommit("Z"); + // A has no parent + a.setParents(); + // A-B + b.setParents(a); + // B-C + c.setParents(b); + // C-D + d.setParents(c); + // D-E + e.setParents(d); + // B-F + f.setParents(b); + // F-G + g.setParents(f); + // X has no parent + x.setParents(); + // X-Y + y.setParents(x); + // Y-Z + z.setParents(y); + + List exampleCommits = Arrays.asList(a, b, c, d, e, f, g, x, y, z); + NonEmptyList expectedOne = new NonEmptyList<>(Arrays.asList(a,b,c,d,e)); + NonEmptyList expectedTwo = new NonEmptyList<>(Arrays.asList(x, y, z)); + NonEmptyList expectedThree = new NonEmptyList<>(Arrays.asList(f, g)); + + LongestNonOverlappingSequences algorithm = new LongestNonOverlappingSequences(); + List> result = algorithm.extract(exampleCommits); + + assert result.size() == 3; + assert sequencesAreEqual(result.get(0), expectedOne); + assert sequencesAreEqual(result.get(1), expectedTwo); + assert sequencesAreEqual(result.get(2), expectedThree); + } + + public boolean sequencesAreEqual(final NonEmptyList a, final NonEmptyList b) { + if (a.size() != b.size()) { + return false; + } + for (int i = 0; i < a.size(); i++) { + if (!a.get(i).id().equals(b.get(i).id())) { + return false; + } + } + return true; + } +} From c329c198d4cb3d7fc54a17ffe6c905503515b84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Thu, 1 Sep 2022 17:19:00 +0200 Subject: [PATCH 6/9] fix(#8): the longest commit sequences are now retrieved non-recursively to prevent stack overflow --- .../LongestNonOverlappingSequences.java | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java b/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java index 2d2bee5..960ce2f 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java @@ -83,29 +83,52 @@ public List> extract(final Collection commits } } + // Sort the sequences once more, after filtering them + commitSequences.sort((o1, o2) -> Integer.compare(o2.size(), o1.size())); return commitSequences; } - // Recursively build sequences private static Set> retrieveSequencesForStart(final Map> parentChildMap, final SPLCommit start) { - if (!parentChildMap.containsKey(start)) { - // Create a new sequence that contains the start commit - final Set> sequenceSet = new HashSet<>(); + // Set for holding all retrieved sequences + Set> sequenceSet = new HashSet<>(); + { + // We start with the 'start' commit final LinkedList sequence = new LinkedList<>(); sequence.add(start); sequenceSet.add(sequence); - return sequenceSet; - } else { - // Collect the sequences of the children and prepend the commit to each of them as parent - final Set> sequences = new HashSet<>(); - for (final SPLCommit child : parentChildMap.get(start)) { - final Set> childSequences = retrieveSequencesForStart(parentChildMap, child); - for (final LinkedList childSequence : childSequences) { - childSequence.addFirst(start); - sequences.add(childSequence); + } + + // We continue to build sequences, going from parent to descendents, until the ends of all possible sequences have been reached + boolean incomplete = true; + while(incomplete) { + Set> updatedSet = new HashSet<>(); + // Set to false at the start of the iteration, it is set to true if at least one sequence has been extended + incomplete = false; + // For all found sequences, check whether their last commit has more children that can be added to the sequence + // if multiple children exist, new sequences are created + for (LinkedList sequence : sequenceSet) { + final SPLCommit parent = sequence.getLast(); + if (parentChildMap.containsKey(parent)) { + final Set children = parentChildMap.get(parent); + for (SPLCommit child : children) { + // There is at least one child, we are not done yet + incomplete = true; + // Create a new sequence from the old sequence for each child + final LinkedList anotherSequence = new LinkedList<>(sequence); + anotherSequence.add(child); + // Add the new sequence to the new set + updatedSet.add(anotherSequence); + } + } else { + // There are no children, simply add the old sequence to the updated set + updatedSet.add(sequence); } } - return sequences; + // Update the sequence set + sequenceSet = updatedSet; } + + return sequenceSet; } } + From 145b5c3450de00c7edee2b52695c9a5d9bcf9a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Thu, 1 Sep 2022 18:13:03 +0200 Subject: [PATCH 7/9] test(#8): added test that confirms that no StackOverflowError is caused by large histories I also confirmed that the test fails when the recursive implementation is used --- .../LongestNonOverlappingSequencesTest.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java index df93245..e26b943 100644 --- a/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java +++ b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java @@ -5,7 +5,9 @@ import org.variantsync.vevos.simulation.variability.SPLCommit; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class LongestNonOverlappingSequencesTest { @@ -58,7 +60,27 @@ public void exampleExtraction() { assert sequencesAreEqual(result.get(2), expectedThree); } - public boolean sequencesAreEqual(final NonEmptyList a, final NonEmptyList b) { + @Test + public void stackOverflowPrevented() { + int size = 10_000; + Set commits = new HashSet<>(); + SPLCommit previousCommit = new SPLCommit("0"); + previousCommit.setParents(); + commits.add(previousCommit); + for (int i = 1; i < size; i++) { + SPLCommit commit = new SPLCommit(String.valueOf(i)); + commit.setParents(previousCommit); + commits.add(commit); + previousCommit = commit; + } + + LongestNonOverlappingSequences algo = new LongestNonOverlappingSequences(); + var result = algo.extract(commits); + assert result.size() == 1; + assert result.get(0).size() == size; + } + + private boolean sequencesAreEqual(final NonEmptyList a, final NonEmptyList b) { if (a.size() != b.size()) { return false; } From 7a3b14e7ce416461bbfd15cf171416c9e1f3b89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Thu, 1 Sep 2022 19:46:13 +0200 Subject: [PATCH 8/9] misc: minor improvements --- .../LongestNonOverlappingSequencesTest.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java index e26b943..4609ceb 100644 --- a/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java +++ b/src/test/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequencesTest.java @@ -1,5 +1,6 @@ package org.variantsync.vevos.simulation.variability.sequenceextraction; +import org.junit.Assert; import org.junit.Test; import org.variantsync.functjonal.list.NonEmptyList; import org.variantsync.vevos.simulation.variability.SPLCommit; @@ -54,13 +55,15 @@ public void exampleExtraction() { LongestNonOverlappingSequences algorithm = new LongestNonOverlappingSequences(); List> result = algorithm.extract(exampleCommits); - assert result.size() == 3; - assert sequencesAreEqual(result.get(0), expectedOne); - assert sequencesAreEqual(result.get(1), expectedTwo); - assert sequencesAreEqual(result.get(2), expectedThree); + Assert.assertEquals(result.size(), 3); + Assert.assertTrue(sequencesAreEqual(result.get(0), expectedOne)); + Assert.assertTrue(sequencesAreEqual(result.get(1), expectedTwo)); + Assert.assertTrue(sequencesAreEqual(result.get(2), expectedThree)); } @Test + // This test caused a StackoverflowError for the previous implementation of LongestNonOverlappingSequences at + // confirms that the Error is no longer thrown. public void stackOverflowPrevented() { int size = 10_000; Set commits = new HashSet<>(); @@ -76,8 +79,9 @@ public void stackOverflowPrevented() { LongestNonOverlappingSequences algo = new LongestNonOverlappingSequences(); var result = algo.extract(commits); - assert result.size() == 1; - assert result.get(0).size() == size; + // Some sanity checks (i.e., is the sequence extracted correctly?) + Assert.assertEquals(1, result.size()); + Assert.assertEquals(result.get(0).size(), size); } private boolean sequencesAreEqual(final NonEmptyList a, final NonEmptyList b) { From 54346d6dd01c891caac8b5c45a1ace6bba610987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Schulthei=C3=9F?= Date: Fri, 2 Sep 2022 10:05:42 +0200 Subject: [PATCH 9/9] docs(https://github.com/VariantSync/VEVOS_Simulation/pull/13): added comments from GitHub regarding the creation of a new set in each iteration --- .../LongestNonOverlappingSequences.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java b/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java index 960ce2f..0051c4c 100644 --- a/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java +++ b/src/main/java/org/variantsync/vevos/simulation/variability/sequenceextraction/LongestNonOverlappingSequences.java @@ -101,7 +101,19 @@ private static Set> retrieveSequencesForStart(final Map> updatedSet = new HashSet<>(); + // Set to false at the start of the iteration, it is set to true if at least one sequence has been extended incomplete = false; // For all found sequences, check whether their last commit has more children that can be added to the sequence