From 028469621d0dc7af6e1899ded1039d35f5c6e0c7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jun 2022 09:34:41 +0000 Subject: [PATCH] chore(deps): update dependency featureide to v3.8.3 (#6) * chore(deps): update dependency featureide to v3.8.3 * feat: migrate to featureide v3.8.3 (#13) * feat: new version * test: unify tests * feat: more migration code Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Kriese --- .vscode/settings.json | 2 +- java/build.gradle | 16 ++- java/src/test/java/AlternateModelTests.java | 101 ++++++++++++++ java/src/test/java/Tests.java | 110 ++++++++++++--- java/src/test/java/Utils.java | 8 +- .../de.ovgu.featureide.fm.test/Prop4jTests.cs | 22 ++- .../PropagatorTests.cs | 130 ++++++++++++++++++ .../de.ovgu.featureide.fm.test/SolverTests.cs | 68 +++++++++ test/de.ovgu.featureide.fm.test/Tests.cs | 115 +++++++++++----- test/de.ovgu.featureide.fm.test/Utils.cs | 11 +- tools/utils/config.ps1 | 2 +- 11 files changed, 511 insertions(+), 74 deletions(-) create mode 100644 java/src/test/java/AlternateModelTests.java create mode 100644 test/de.ovgu.featureide.fm.test/PropagatorTests.cs create mode 100644 test/de.ovgu.featureide.fm.test/SolverTests.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index 050505c..04cd618 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "java.configuration.updateBuildConfiguration": "interactive" + "java.configuration.updateBuildConfiguration": "automatic" } diff --git a/java/build.gradle b/java/build.gradle index e2de5c6..978bcd3 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -1,21 +1,25 @@ plugins { - id 'java-library' + id 'java-library' } repositories { - mavenCentral() + mavenCentral() } java { - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } } version = '0.0.1' test { - useJUnitPlatform() + useJUnitPlatform() + // testLogging { + // showStandardStreams = true + // events = ['standard_out'] + // } } dependencies { diff --git a/java/src/test/java/AlternateModelTests.java b/java/src/test/java/AlternateModelTests.java new file mode 100644 index 0000000..4e7e3e9 --- /dev/null +++ b/java/src/test/java/AlternateModelTests.java @@ -0,0 +1,101 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.prop4j.Implies; +import org.prop4j.Literal; +import org.prop4j.Not; +import org.prop4j.Or; + +import de.ovgu.featureide.fm.core.analysis.cnf.formula.FeatureModelFormula; +import de.ovgu.featureide.fm.core.base.IFeatureModel; +import de.ovgu.featureide.fm.core.base.IFeatureStructure; +import de.ovgu.featureide.fm.core.configuration.Configuration; +import de.ovgu.featureide.fm.core.configuration.ConfigurationAnalyzer; +import de.ovgu.featureide.fm.core.configuration.Selection; + +class AlternateModelTests { + + private IFeatureModel model; + private IFeatureStructure root; + + @BeforeEach + void BeforeEach() { + model = Utils.CreateModel(); + root = Utils.addFeature(model, "Root", true); + root.setMandatory(true); + model.getStructure().setRoot(root); + } + + @Test + void simple() { + root.addChild(Utils.addFeature(model, "CORE1")); + root.addChild(Utils.addFeature(model, "CORE2")); + root.changeToAlternative(); + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); + + System.out.println(formula.getCNFNode().toString()); + + assertTrue(configAnalyzer.canBeValid(), "canbeValid"); + assertFalse(configAnalyzer.isValid(), "isValid"); + } + + @Test + void canBeValid() { + root.addChild(Utils.addFeature(model, "CORE1")); + root.addChild(Utils.addFeature(model, "CORE2")); + + Utils.add(model, new Or( + new Literal("CORE1"), + new Literal("CORE2"))); + Utils.add(model, new Implies( + new Literal("CORE1"), + new Not( + new Literal("CORE2")))); + Utils.add(model, new Implies( + new Literal("CORE2"), + new Not( + new Literal("CORE1")))); + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); + + System.out.println(formula.getCNFNode().toString()); + + assertTrue(configAnalyzer.canBeValid(), "canbeValid"); + assertFalse(configAnalyzer.isValid(), "isValid"); + } + + @Test + void shouldBeValid() { + root.addChild(Utils.addFeature(model, "CORE")); + + Utils.add(model, new Or(new Literal("CORE"))); + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); + + System.out.println(formula.getCNFNode().toString()); + + assertTrue(configAnalyzer.canBeValid(), "canBeValid"); + assertTrue(configAnalyzer.isValid(), "isValid"); + + var sfCore = config.getSelectableFeature("CORE"); + assertNotNull(sfCore); + assertEquals(Selection.SELECTED, sfCore.getAutomatic(), "isAutoSelected"); + } +} diff --git a/java/src/test/java/Tests.java b/java/src/test/java/Tests.java index fb9acff..b9a885a 100644 --- a/java/src/test/java/Tests.java +++ b/java/src/test/java/Tests.java @@ -5,13 +5,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.prop4j.And; import org.prop4j.Implies; import org.prop4j.Literal; import org.prop4j.Not; +import org.prop4j.Or; +import de.ovgu.featureide.fm.core.analysis.cnf.formula.FeatureModelFormula; import de.ovgu.featureide.fm.core.base.IFeatureModel; import de.ovgu.featureide.fm.core.base.IFeatureStructure; import de.ovgu.featureide.fm.core.configuration.Configuration; +import de.ovgu.featureide.fm.core.configuration.ConfigurationAnalyzer; import de.ovgu.featureide.fm.core.configuration.Selection; class Tests { @@ -28,16 +32,17 @@ void BeforeEach() { model.getStructure().setRoot(root); cores = Utils.addFeature(model, "CoreModules", true); - cores.changeToAlternative(); + // change to alternate + cores.setAlternative(); cores.setMandatory(true); root.addChild(cores); mods = Utils.addFeature(model, "Modules", true); - mods.changeToOr(); + mods.setOr(); root.addChild(mods); devs = Utils.addFeature(model, "Devices", true); - devs.changeToOr(); + mods.setOr(); root.addChild(devs); } @@ -46,26 +51,34 @@ void canBeValid() { cores.addChild(Utils.addFeature(model, "CORE1")); cores.addChild(Utils.addFeature(model, "CORE2")); - var config = new Configuration(model, false); - config.setPropagate(true); - config.update(true, null); + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); - assertTrue(config.canBeValid(), "canbeValid"); - assertFalse(config.isValid(), "isValid"); + configAnalyzer.update(true); + + System.out.println(formula.getCNFNode().toString()); + + assertTrue(configAnalyzer.canBeValid(), "canbeValid"); + assertFalse(configAnalyzer.isValid(), "isValid"); } @Test void shouldBeValid() { cores.addChild(Utils.addFeature(model, "CORE")); - var config = new Configuration(model, false); - config.setPropagate(true); - config.update(true, null); + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); - assertTrue(config.canBeValid(), "canBeValid"); - assertTrue(config.isValid(), "isValid"); + System.out.println(formula.getCNFNode().toString()); - var sfCore = config.getSelectablefeature("CORE"); + assertTrue(configAnalyzer.canBeValid(), "canBeValid"); + assertTrue(configAnalyzer.isValid(), "isValid"); + + var sfCore = config.getSelectableFeature("CORE"); assertNotNull(sfCore); assertEquals(Selection.SELECTED, sfCore.getAutomatic(), "isAutoSelected"); } @@ -73,6 +86,47 @@ void shouldBeValid() { @Test void complex() { cores.addChild(Utils.addFeature(model, "CORE")); + cores.getFirstChild().setMandatory(true); + + mods.addChild(Utils.addFeature(model, "M1")); + mods.addChild(Utils.addFeature(model, "M2")); + mods.addChild(Utils.addFeature(model, "M3")); + mods.addChild(Utils.addFeature(model, "M4")); + + devs.addChild(Utils.addFeature(model, "D1")); + devs.addChild(Utils.addFeature(model, "D2")); + devs.addChild(Utils.addFeature(model, "D3")); + devs.addChild(Utils.addFeature(model, "D4")); + + Utils.add(model, new Implies( + new Literal("M2"), + new Not( + new Literal("M3")))); + + Utils.add(model, new Implies( + new Literal("D1"), + new Not( + new Literal("M3")))); + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); + + System.out.println(formula.getCNFNode().toString()); + + assertTrue(configAnalyzer.canBeValid(), "canBeValid"); + assertTrue(configAnalyzer.isValid(), "isValid"); + + var sfCore = config.getSelectableFeature("CORE"); + assertNotNull(sfCore); + assertEquals(Selection.SELECTED, sfCore.getAutomatic(), "isAutoSelected"); + } + + @Test + void complex2() { + cores.addChild(Utils.addFeature(model, "CORE")); mods.addChild(Utils.addFeature(model, "M1")); mods.addChild(Utils.addFeature(model, "M2")); @@ -84,6 +138,14 @@ void complex() { devs.addChild(Utils.addFeature(model, "D3")); devs.addChild(Utils.addFeature(model, "D4")); + Utils.add(model, new Implies( + new Literal("CORE"), + new Or( + new And(new Literal("M4"), new Literal("M2")), + new And(new Literal("M4"), new Literal("M3")) + ) + )); + Utils.add(model, new Implies( new Literal("M2"), new Not( @@ -94,16 +156,24 @@ void complex() { new Not( new Literal("M3")))); - var config = new Configuration(model, false); - config.setPropagate(true); - config.update(true, null); + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + + configAnalyzer.update(true); - assertTrue(config.canBeValid(), "canBeValid"); - assertTrue(config.isValid(), "isValid"); + System.out.println(formula.getCNFNode().toString()); - var sfCore = config.getSelectablefeature("CORE"); + assertTrue(configAnalyzer.canBeValid(), "canBeValid"); + assertFalse(configAnalyzer.isValid(), "isValid"); + + var sfCore = config.getSelectableFeature("CORE"); assertNotNull(sfCore); assertEquals(Selection.SELECTED, sfCore.getAutomatic(), "isAutoSelected"); + + var sfM4 = config.getSelectableFeature("M4"); + assertNotNull(sfM4); + assertEquals(Selection.SELECTED, sfM4.getAutomatic(), "isAutoSelected"); } } diff --git a/java/src/test/java/Utils.java b/java/src/test/java/Utils.java index 60b2af8..589dd18 100644 --- a/java/src/test/java/Utils.java +++ b/java/src/test/java/Utils.java @@ -3,14 +3,20 @@ import de.ovgu.featureide.fm.core.base.IConstraint; import de.ovgu.featureide.fm.core.base.IFeatureModel; import de.ovgu.featureide.fm.core.base.IFeatureStructure; +import de.ovgu.featureide.fm.core.base.impl.ConfigurationFactoryManager; +import de.ovgu.featureide.fm.core.base.impl.DefaultConfigurationFactory; import de.ovgu.featureide.fm.core.base.impl.DefaultFeatureModelFactory; public class Utils { private static DefaultFeatureModelFactory FACTORY = new DefaultFeatureModelFactory(); + static { + ConfigurationFactoryManager.getInstance().addExtension(DefaultConfigurationFactory.getInstance()); + } + public static IFeatureModel CreateModel() { - return FACTORY.createFeatureModel(); + return FACTORY.create(); } public static IFeatureStructure addFeature(IFeatureModel self, String feature) { diff --git a/test/de.ovgu.featureide.fm.test/Prop4jTests.cs b/test/de.ovgu.featureide.fm.test/Prop4jTests.cs index 8dcac8b..d5709b5 100644 --- a/test/de.ovgu.featureide.fm.test/Prop4jTests.cs +++ b/test/de.ovgu.featureide.fm.test/Prop4jTests.cs @@ -1,14 +1,16 @@ using org.prop4j; +using org.prop4j.explain.solvers; namespace de.ovgu.featureide.fm.test { internal class Prop4jTests { - private readonly long Timeout = (long)TimeSpan.FromSeconds(5).TotalMilliseconds; + private org.prop4j.explain.solvers.SatSolver solver; [SetUp] public void Setup() { + solver = SatSolverFactory.getDefault().getSatSolver(); } [Test] @@ -16,7 +18,11 @@ public void Simple() { var formula = new And(); - var solver = new SatSolver(formula, Timeout); + + + Expect(solver.isSatisfiable()).To.Be.True(); + + solver.addFormula(formula); Expect(solver.isSatisfiable()).To.Be.True(); } @@ -24,13 +30,15 @@ public void Simple() [Test] public void CanBeValid() { - var formula = new And( - new Implies(new Literal("CORE1"), new Not(new Literal("CORE2"))), - new Implies(new Literal("CORE2"), new Not(new Literal("CORE1"))) - ); - var solver = new SatSolver(formula, Timeout); + solver.addFormula(new Implies(new Literal("CORE1"), new Not(new Literal("CORE2")))); + solver.addFormula(new Implies(new Literal("CORE2"), new Not(new Literal("CORE1")))); Expect(solver.isSatisfiable()).To.Be.True(); + + + var map = solver.getAssumptions(); + var m = solver.getModel(); + Console.WriteLine("assumptions: " + map.keySet().Cast().ToArray()); } } } diff --git a/test/de.ovgu.featureide.fm.test/PropagatorTests.cs b/test/de.ovgu.featureide.fm.test/PropagatorTests.cs new file mode 100644 index 0000000..f8a4a0b --- /dev/null +++ b/test/de.ovgu.featureide.fm.test/PropagatorTests.cs @@ -0,0 +1,130 @@ +using de.ovgu.featureide.fm.core.analysis.cnf; +using de.ovgu.featureide.fm.core.analysis.cnf.analysis; +using de.ovgu.featureide.fm.core.analysis.cnf.formula; +using de.ovgu.featureide.fm.core.analysis.cnf.solver; +using de.ovgu.featureide.fm.core.@base; +using de.ovgu.featureide.fm.core.configuration; +using de.ovgu.featureide.fm.core.job; +using java.util; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace de.ovgu.featureide.fm.test +{ + internal class PropagatorTests + { + private IFeatureModel model; + private IFeatureStructure cores; + private IFeatureStructure mods; + private IFeatureStructure devs; + private FeatureModelFormula formula; + + [SetUp] + public void Setup() + { + model = Utils.CreateModel(); + var root = model.AddFeature("Root", true); + root.setMandatory(true); + model.getStructure().setRoot(root); + + cores = model.AddFeature("CoreModules", true); + cores.changeToAlternative(); + cores.setMandatory(true); + root.addChild(cores); + + mods = model.AddFeature("Modules", true); + mods.changeToOr(); + root.addChild(mods); + + devs = model.AddFeature("Devices", true); + devs.changeToOr(); + root.addChild(devs); + + + formula = new FeatureModelFormula(model); + } + + [Test] + public void ShouldBeValid() + { + cores.addChild(model.AddFeature("CORE1")); + + var config = new Configuration(formula); + var rootNode = formula.getCNF(); + var analysis = new CoreDeadAnalysis(rootNode); + + var manualLiterals = new ArrayList(); + var manualLiteralSet = new HashSet(manualLiterals); + + var intLiterals = new int[manualLiterals.size()]; + for (int i = 0; i < intLiterals.Length; i++) + { + intLiterals[i] = (int)manualLiterals.get(i); + } + + Expect(intLiterals).To.Be.Empty(); + + analysis.setAssumptions(new LiteralSet(intLiterals)); + var impliedFeatures = LongRunningWrapper.runMethod(analysis) as LiteralSet; + + Expect(impliedFeatures).To.Not.Be.Null(); + Expect(impliedFeatures.size()).To.Equal(2); + + var result = new HashSet(rootNode.getVariables().size()); + + foreach (var i in impliedFeatures.getLiterals()) + { + SelectableFeature feature = config.getSelectableFeature(rootNode.getVariables().getName(i)); + if (feature != null) + { + Console.WriteLine(feature.getName() + ": " + i); + config.setAutomatic(feature, i > 0 ? Selection.SELECTED : Selection.UNSELECTED); + result.add(feature); + manualLiteralSet.add(feature.getManual() == Selection.SELECTED ? i : -i); + } + } + + + Expect(manualLiteralSet.size()).To.Equal(2); + Expect(result.size()).To.Equal(2); + + var updateFeatures = new ArrayList(); + foreach ( SelectableFeature feature in config.getFeatures().Cast()) + { + if (!manualLiteralSet + .contains(rootNode.getVariables().getVariable(feature.getFeature().getName(), feature.getManual() == Selection.SELECTED))) + { + updateFeatures.add(feature); + result.add(feature); + } + } + + Expect(result.size()).To.Equal(5); + + var solver = new AdvancedSatSolver(formula.getCNF()); + + foreach ( int feature in intLiterals) + { + solver.assignmentPush(feature); + } + + Expect(solver.getAssignmentSize()).To.Equal(0); + } + + + + [Test] + public void CanBeValid() + { + cores.addChild(model.AddFeature("CORE1")); + cores.addChild(model.AddFeature("CORE2")); + + var solver = new AdvancedSatSolver(formula.getCNF()); + + Expect(solver.hasSolution()).To.Equal(ISimpleSatSolver.SatResult.TRUE); + } + } +} diff --git a/test/de.ovgu.featureide.fm.test/SolverTests.cs b/test/de.ovgu.featureide.fm.test/SolverTests.cs new file mode 100644 index 0000000..7af993e --- /dev/null +++ b/test/de.ovgu.featureide.fm.test/SolverTests.cs @@ -0,0 +1,68 @@ +using de.ovgu.featureide.fm.core.analysis.cnf.formula; +using de.ovgu.featureide.fm.core.analysis.cnf.solver; +using de.ovgu.featureide.fm.core.@base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace de.ovgu.featureide.fm.test +{ + internal class SolverTests + { + private IFeatureModel model; + private IFeatureStructure cores; + private IFeatureStructure mods; + private IFeatureStructure devs; + private FeatureModelFormula formula; + + [SetUp] + public void Setup() + { + model = Utils.CreateModel(); + var root = model.AddFeature("Root", true); + root.setMandatory(true); + model.getStructure().setRoot(root); + + cores = model.AddFeature("CoreModules", true); + cores.changeToAlternative(); + cores.setMandatory(true); + root.addChild(cores); + + mods = model.AddFeature("Modules", true); + mods.changeToOr(); + root.addChild(mods); + + devs = model.AddFeature("Devices", true); + devs.changeToOr(); + root.addChild(devs); + + + formula = new FeatureModelFormula(model); + } + + [Test] + public void ShouldBeValid() + { + cores.addChild(model.AddFeature("CORE1")); + + var solver = new AdvancedSatSolver(formula.getCNF()); + + Expect(solver.hasSolution()).To.Equal(ISimpleSatSolver.SatResult.TRUE); + } + + + + [Test] + public void CanBeValid() + { + cores.addChild(model.AddFeature("CORE1")); + cores.addChild(model.AddFeature("CORE2")); + + var solver = new AdvancedSatSolver(formula.getCNF()); + + Expect(solver.hasSolution()).To.Equal(ISimpleSatSolver.SatResult.TRUE); + } + } +} diff --git a/test/de.ovgu.featureide.fm.test/Tests.cs b/test/de.ovgu.featureide.fm.test/Tests.cs index 9e7f18a..cfeaee8 100644 --- a/test/de.ovgu.featureide.fm.test/Tests.cs +++ b/test/de.ovgu.featureide.fm.test/Tests.cs @@ -1,3 +1,4 @@ +using de.ovgu.featureide.fm.core.analysis.cnf.formula; using de.ovgu.featureide.fm.core.@base; using de.ovgu.featureide.fm.core.configuration; using org.prop4j; @@ -20,16 +21,16 @@ public void Setup() model.getStructure().setRoot(root); cores = model.AddFeature("CoreModules", true); - cores.changeToAlternative(); + cores.setAlternative(); cores.setMandatory(true); root.addChild(cores); mods = model.AddFeature("Modules", true); - mods.changeToOr(); + mods.setOr(); root.addChild(mods); devs = model.AddFeature("Devices", true); - devs.changeToOr(); + devs.setOr(); root.addChild(devs); } @@ -41,39 +42,39 @@ public void CanBeValid() cores.addChild(core1); cores.addChild(core2); - var config = new Configuration(model, false); - var sCore1 = config.getSelectablefeature( "CORE1"); - var sCore2 = config.getSelectablefeature("CORE2"); + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); - config.setPropagate(true); - config.update(true, null); + var sCore1 = config.getSelectableFeature("CORE1"); + var sCore2 = config.getSelectableFeature("CORE2"); - Expect(sCore1?.getAutomatic()).To.Equal(Selection.UNDEFINED); - Expect(sCore1?.getSelection()).To.Equal(Selection.UNDEFINED); - Expect(sCore2?.getAutomatic()).To.Equal(Selection.UNDEFINED); - Expect(sCore2?.getSelection()).To.Equal(Selection.UNDEFINED); + configAnalyzer.update(true); - Expect(config.canBeValid()).To.Be.True("Should have a solution"); - Expect(config.isValid()).To.Be.False("Shouldn't be valid"); + Expect(configAnalyzer.canBeValid()).To.Be.True("canBeValid"); + Expect(configAnalyzer.isValid()).To.Be.False("isValid"); + + Expect(sCore1?.getAutomatic()?.name()).To.Equal(Selection.UNDEFINED.name(), "isAutoSelected"); + Expect(sCore2?.getAutomatic()?.name()).To.Equal(Selection.UNDEFINED.name(), "isAutoSelected"); } [Test] public void ShouldBeValid() { - var core1 = model.AddFeature("CORE1"); - cores.addChild(core1); - var config = new Configuration(model, false); + cores.addChild(model.AddFeature("CORE")); + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); - var sCore = config.getSelectablefeature("CORE1"); + var sCore = config.getSelectableFeature("CORE"); - config.setPropagate(true); - config.update(true, null); + configAnalyzer.update(true); - Expect(sCore?.getAutomatic()).To.Equal(Selection.SELECTED); - Expect(sCore?.getSelection()).To.Equal(Selection.SELECTED); + Expect(configAnalyzer.canBeValid()).To.Be.True("canBeValid"); + Expect(configAnalyzer.isValid()).To.Be.True("isValid"); - Expect(config.canBeValid()).To.Be.True("Should have a solution"); - Expect(config.isValid()).To.Be.True("Should be valid"); + Expect(sCore?.getAutomatic()?.name()).To.Equal(Selection.SELECTED.name(), "isAutoSelected"); } [Test] @@ -91,6 +92,50 @@ public void Complex() devs.addChild(model.AddFeature("D3")); devs.addChild(model.AddFeature("D4")); + model.Add(new Implies( + new Literal("M2"), + new Not( + new Literal("M3") + ) + )); + + model.Add(new Implies( + new Literal("D1"), + new Not( + new Literal("M3") + ) + )); + + + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + var sCore = config.getSelectableFeature("CORE"); + + configAnalyzer.update(true); + + Expect(configAnalyzer.canBeValid()).To.Be.True("canBeValid"); + Expect(configAnalyzer.isValid()).To.Be.True("isValid"); + Expect(sCore?.getAutomatic()?.name()).To.Equal(Selection.SELECTED.name(), "isAutoSelected"); + } + + + + [Test] + public void Complex2() + { + cores.addChild(model.AddFeature("CORE")); + + mods.addChild(model.AddFeature("M1")); + mods.addChild(model.AddFeature("M2")); + mods.addChild(model.AddFeature("M3")); + mods.addChild(model.AddFeature("M4")); + + devs.addChild(model.AddFeature("D1")); + devs.addChild(model.AddFeature("D2")); + devs.addChild(model.AddFeature("D3")); + devs.addChild(model.AddFeature("D4")); + model.Add(new Implies( new Literal("CORE"), new Or( @@ -113,19 +158,19 @@ public void Complex() ) )); - var config = new Configuration(model, false); - var sCore = config.getSelectablefeature("CORE"); - var sm4 = config.getSelectablefeature("M4"); - config.setPropagate(true); - config.update(true, null); + var formula = new FeatureModelFormula(model); + var config = new Configuration(formula); + var configAnalyzer = new ConfigurationAnalyzer(formula, config); + var sCore = config.getSelectableFeature("CORE"); + var sm4 = config.getSelectableFeature("M4"); + + configAnalyzer.update(true); - Expect(sCore?.getAutomatic()).To.Equal(Selection.SELECTED); - Expect(sCore?.getSelection()).To.Equal(Selection.SELECTED); - Expect(sm4?.getAutomatic()).To.Equal(Selection.SELECTED); - Expect(sm4?.getSelection()).To.Equal(Selection.SELECTED); + Expect(configAnalyzer.canBeValid()).To.Be.True("canBeValid"); + Expect(configAnalyzer.isValid()).To.Be.False("isValid"); - Expect(config.canBeValid()).To.Be.True("Should have a solution"); - Expect(config.isValid()).To.Be.False("Shouldn't be valid"); + Expect(sCore?.getAutomatic()?.name()).To.Equal(Selection.SELECTED.name(), "isAutoSelected"); + Expect(sm4?.getAutomatic()?.name()).To.Equal(Selection.SELECTED.name(), "isAutoSelected"); } } diff --git a/test/de.ovgu.featureide.fm.test/Utils.cs b/test/de.ovgu.featureide.fm.test/Utils.cs index 2f28829..96112c5 100644 --- a/test/de.ovgu.featureide.fm.test/Utils.cs +++ b/test/de.ovgu.featureide.fm.test/Utils.cs @@ -1,9 +1,9 @@ -using org.prop4j; using de.ovgu.featureide.fm.core.@base; using de.ovgu.featureide.fm.core.@base.impl; using de.ovgu.featureide.fm.core.configuration; -using java.lang; using de.ovgu.featureide.fm.core.job; +using java.lang; +using org.prop4j; namespace de.ovgu.featureide.fm.test { @@ -11,6 +11,11 @@ internal static class Utils { private static readonly DefaultFeatureModelFactory FACTORY = new(); + static Utils() + { + ConfigurationFactoryManager.getInstance().addExtension(DefaultConfigurationFactory.getInstance()); + } + public static IFeatureStructure AddFeature(this IFeatureModel @this, string feature, bool @abstract = false) { var f = FACTORY.createFeature(@this, feature); @@ -27,7 +32,7 @@ public static IFeatureStructure AddFeature(this IFeatureModel @this, string feat return res; } - public static IFeatureModel CreateModel() => FACTORY.createFeatureModel(); + public static IFeatureModel CreateModel() => FACTORY.create(); public static IEnumerable GetFeatures(this Configuration @this) => @this.getFeatures().Cast(); public static IEnumerable Cast(this Iterable @this) diff --git a/tools/utils/config.ps1 b/tools/utils/config.ps1 index ed7ad61..24941a9 100644 --- a/tools/utils/config.ps1 +++ b/tools/utils/config.ps1 @@ -9,7 +9,7 @@ $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' $IKVM_VERSION = "8.2.0-prerelease.911" # renovate: datasource=github-releases depName=featureide packageName=FeatureIDE/FeatureIDE -$FEATUREIDE_VERSION = "3.3.0" +$FEATUREIDE_VERSION = "v3.8.3" # newer version is broken #disabled renovate: datasource=maven depName=sat4j packageName=org.ow2.sat4j:org.ow2.sat4j.pom