diff --git a/src/main/scala/io/stepfunc/dnp3c/conformance/Revision.scala b/src/main/scala/io/stepfunc/dnp3c/conformance/Revision.scala index 87a6a71..00e1184 100644 --- a/src/main/scala/io/stepfunc/dnp3c/conformance/Revision.scala +++ b/src/main/scala/io/stepfunc/dnp3c/conformance/Revision.scala @@ -81,7 +81,8 @@ final class Revision private[conformance] ( /** * Check that the configuration is one this revision can test: it gives a subset level the revision tests, and it has - * what the revision needs configured, whatever procedures run, and what the procedures selected need. + * what the revision needs configured, whatever procedures run, and what each procedure selected needs, if it will run: + * it's implemented, applies at that level and is enabled. * * @param selected the procedures a run will run; all of them unless given * @return the subset level @@ -90,7 +91,8 @@ final class Revision private[conformance] ( def validate(options: OptionSource, selected: Iterable[TestProcedure] = flatMapProcedures(Some(_))): Int = { val level = subsetLevel(options) // what the procedures that will run need, each problem once - val procedures = selected.filter(p => !p.incomplete && p.disabledBy(options).isEmpty) + val procedures = + selected.filter(p => !p.incomplete && levelsOf(p).contains(level) && p.disabledBy(options).isEmpty) val problems = (configurationProblems(options) ++ procedures.flatMap(_.definition.configurationProblems(options))).distinct if (problems.nonEmpty) throw new ConfigurationException("configuration", problems) diff --git a/src/test/scala/io/stepfunc/dnp3c/conformance/CleanupTest.scala b/src/test/scala/io/stepfunc/dnp3c/conformance/CleanupTest.scala index 72d4b98..2733a70 100644 --- a/src/test/scala/io/stepfunc/dnp3c/conformance/CleanupTest.scala +++ b/src/test/scala/io/stepfunc/dnp3c/conformance/CleanupTest.scala @@ -169,4 +169,21 @@ class CleanupTest extends AnyFunSuite with Matchers { problems(Map(), needing(required = false), needing(required = false)) should equal(List(problem)) problems(Map(Inputs.binary.points.id -> "false"), needing(required = true)) should equal(Nil) } + + test("a run doesn't check the configuration problems of a procedure that doesn't apply at its level") { + val problem = ConfigProblem("some.option", "", "needed") + val levelTwo = TestProcedure( + "a", + "a", + new ProcedureDefinition { + override protected def steps(options: OptionSource): Iterable[LabeledStep] = Nil + override def configurationProblems(options: OptionSource): List[ConfigProblem] = List(problem) + }, + levels = Some(Set(2)) + ) + val revision = new Revision("t", "t", "2000-01-01", List(1, 2), List(section("s", "s")(levelTwo))) + def at(level: Int) = Options.from(Map(OutstationOptions.subsetLevel.id -> level.toString)) + revision.validate(at(1)) should equal(1) + intercept[ConfigurationException](revision.validate(at(2))).problems should equal(List(problem)) + } }