Commit 4240f27e authored by Martti Käärik's avatar Martti Käärik
Browse files

Constraint severity test

parent d7a5f486
Loading
Loading
Loading
Loading
+98 −0
Changes for plugins/org.etsi.mts.tdl.tx.tests/src/org/etsi/mts/tdl/tx/tests/ConstraintSeverityTest.java: 98 added lines, 0 removed lines.
Original line number Diff line number Diff line
package org.etsi.mts.tdl.tx.tests;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.validation.Issue;
import org.etsi.mts.tdl.Package;
import org.etsi.mts.tdl.tx.tests.constraints.ConstraintInventory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * Severities of constraint violations come from {@code model/constraint-severities.properties}, which the
 * constraint exporter writes into the compiled invariants as the {@code severity} part of the tuple-valued
 * invariant; the deployed Complete OCL documents of the interpreter carry them by hand. Unlisted invariants
 * keep the OCL runtime's default, a warning. Both constraint implementations.
 */
public class ConstraintSeverityTest extends TDLtxAbstractTest {

	private static final String SEVERITIES = "constraint-severities.properties";

	@Override
	public void verifySingleModel(File file) {
	}

	@Test
	public void everyConfiguredSeverityNamesAnExistingInvariant() throws Exception {
		ConstraintInventory inventory = ConstraintInventory.read();
		List<String> lines = Files.readAllLines(new File(ConstraintInventory.modelFolder(), SEVERITIES).toPath(), StandardCharsets.UTF_8);
		int entries = 0;
		for (String line : lines) {
			line = line.replaceAll("#.*$", "").trim();
			if (line.isEmpty()) {
				continue;
			}
			String id = line.substring(0, line.indexOf('=')).trim();
			Assertions.assertNotNull(inventory.get(id), SEVERITIES + " names no invariant of the .ocl documents: " + id);
			entries++;
		}
		Assertions.assertTrue(entries > 0, "no entries in " + SEVERITIES);
	}

	@Test
	public void configuredInvariantIsReportedAsError() throws Exception {
		Fixtures.loadStandardLibrary(parseHelper, rs);
		Package pkg = parseHelper.parse(String.join("\n",
				"Package Severities {",
				"    Import all from TDL",
				"    Type Nut",
				"    Type Bolt",
				"    Bolt oneBolt",
				"    Structure Fastening ( Nut nutSlot )",
				"    Fastening wrongSlot ( nutSlot = oneBolt )",
				"}"), rs);
		List<Issue> issues = issuesStartingWith(pkg, "The 'DataType' of the 'DataUse' of 'memberSpec' shall conform");
		Assertions.assertEquals(1, issues.size(), "MemberAssignment::MatchingMemberDataType once: " + issues);
		Assertions.assertEquals(Severity.ERROR, issues.get(0).getSeverity(), "configured as error");
	}

	@Test
	public void unconfiguredInvariantIsReportedAsWarning() throws Exception {
		Fixtures.loadStandardLibrary(parseHelper, rs);
		Package pkg = parseHelper.parse(String.join("\n",
				"Package Severities {",
				"    Import all from TDL",
				"    Type T",
				"    T v",
				"    Message Gate mg accepts T",
				"    Component C { gate mg g }",
				"    Configuration Conf {",
				"        C t1 as Tester,",
				"        C t2 as Tester,",
				"        C s as SUT,",
				"        connect t1::g to s::g,",
				"        connect t2::g to s::g",
				"    }",
				"    Test ordered uses Conf {",
				"        alternatively {",
				"            t1::g receives v from s::g",
				"        } or {",
				"            t2::g receives v from s::g",
				"        }",
				"    }",
				"}"), rs);
		List<Issue> issues = issuesStartingWith(pkg, "If the containing 'TestDescription' is locally ordered then all 'Block's");
		Assertions.assertEquals(1, issues.size(), "AlternativeBehaviour::AlternativeBlocksComponent once: " + issues);
		Assertions.assertEquals(Severity.WARNING, issues.get(0).getSeverity(), "not configured: the OCL runtime's default");
	}

	private List<Issue> issuesStartingWith(Package pkg, String prefix) {
		return validationHelper.validate(pkg.eResource()).stream().filter(i -> i.getMessage() != null && i.getMessage().startsWith(prefix))
				.collect(Collectors.toList());
	}
}