blob: 4f9466bf13fc2ac3988366846be0f827727275d3 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2016-2019 Vector Informatik GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vector Informatik GmbH - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.amalthea.validation.ta.tests
import java.util.List
import java.util.stream.Collectors
import org.eclipse.app4mc.amalthea.model.Amalthea
import org.eclipse.app4mc.amalthea.model.AmaltheaFactory
import org.eclipse.app4mc.amalthea.model.EnumMode
import org.eclipse.app4mc.amalthea.model.ModeConditionConjunction
import org.eclipse.app4mc.amalthea.model.ModeLabel
import org.eclipse.app4mc.amalthea.model.ModeSwitchEntry
import org.eclipse.app4mc.amalthea.model.ModeValueCondition
import org.eclipse.app4mc.amalthea.model.OsEvent
import org.eclipse.app4mc.amalthea.model.RelationalOperator
import org.eclipse.app4mc.amalthea.model.Runnable
import org.eclipse.app4mc.amalthea.model.builder.AmaltheaBuilder
import org.eclipse.app4mc.amalthea.model.builder.SoftwareBuilder
import org.eclipse.app4mc.amalthea.validations.ta.TimingArchitectsProfile
import org.eclipse.app4mc.validation.core.Severity
import org.eclipse.app4mc.validation.core.ValidationDiagnostic
import org.eclipse.app4mc.validation.util.ValidationExecutor
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1
import org.junit.Test
import static org.junit.Assert.assertFalse
import static org.junit.Assert.assertTrue
class TASoftwareModelValidatorTests {
extension AmaltheaBuilder b1 = new AmaltheaBuilder
extension SoftwareBuilder b2 = new SoftwareBuilder
val executor = new ValidationExecutor(TimingArchitectsProfile)
def List<ValidationDiagnostic> validate(Amalthea model) {
executor.validate(model)
executor.results
}
def void modeConditionSingleConjunction(ModeSwitchEntry container, Procedure1<ModeValueCondition> initializer) {
if (container.condition === null) {
container.condition = AmaltheaFactory.eINSTANCE.createModeConditionDisjunction
container.condition.entries += AmaltheaFactory.eINSTANCE.createModeConditionConjunction
}
val obj = AmaltheaFactory.eINSTANCE.createModeValueCondition
var mcc = container.condition.entries.get(0) as ModeConditionConjunction
mcc.entries += obj
initializer.apply(obj)
}
@Test
def void test_TASoftwareOsEvent() {
val model = amalthea [
softwareModel [
osEvent [name = "ev_ok"]
osEvent [name = "ev_wait"]
task [
name = "t1"
activityGraph [
setEvent [eventMask(_find(OsEvent, "ev_ok"))]
waitEvent [eventMask(_find(OsEvent, "ev_ok"))]
]
]
task [
name = "t2"
activityGraph [
waitEvent [eventMask(_find(OsEvent, "ev_wait"))]
]
]
]
]
val validationResult = validate(model)
val result = validationResult.stream.filter[it.severityLevel == Severity.ERROR].map[it.message].collect(Collectors.toList)
assertTrue(result.contains("Os Event \"ev_wait\" is waited upon, but it is never set."))
assertFalse(result.contains("Os Event \"ev_ok\" is waited upon, but it is never set."))
}
@Test
def void test_TASoftwareModeConditionConjunctionAlwaysFalse() {
val model = amalthea [
softwareModel [
mode_Enum[
name = "enumerated"
literal [name = "first"]
literal [name = "second"]
]
modeLabel [name = "ml" mode = _find(EnumMode, "enumerated") initialValue = "first"]
runnable [
name = "r"
activityGraph [
modeSwitch [entry [name = "r_mse_ok"
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "first" relation = RelationalOperator.EQUAL]
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "second" relation = RelationalOperator.NOT_EQUAL]
]]
modeSwitch [entry [name = "r_mse_twoLitEQ"
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "first" relation = RelationalOperator.EQUAL]
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "second" relation = RelationalOperator.EQUAL]
]]
modeSwitch [entry [name = "r_mse_twoLitUnEQ"
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "first" relation = RelationalOperator.NOT_EQUAL]
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "second" relation = RelationalOperator.NOT_EQUAL]
]]
modeSwitch [entry [name = "r_mse_sameLiteral"
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "first" relation = RelationalOperator.EQUAL]
modeConditionSingleConjunction [label = _find(ModeLabel, "ml") value = "first" relation = RelationalOperator.NOT_EQUAL]
]]
]
]
]
]
val validationResult = validate(model)
val result = validationResult.stream.filter[it.severityLevel == Severity.WARNING].map[it.message].collect(Collectors.toList)
assertTrue(result.contains("Conjoining equality of mode literals [first, second] in Mode Switch Entry \"r_mse_twoLitEQ\" always evaluates to FALSE, which might not be intended here."))
assertTrue(result.contains("Conjoining unequality of mode literals [first, second] in Mode Switch Entry \"r_mse_twoLitUnEQ\" always evaluates to FALSE, which might not be intended here."))
assertTrue(result.contains("Conjoining mode conditions on the same Mode Literal \"first\" with relations [EQUAL, NOT_EQUAL] in Mode Switch Entry \"r_mse_sameLiteral\" always evaluates to FALSE, which might not be intended here."))
assertFalse(result.contains("Conjoining equality of mode literals [first, second] in Mode Switch Entry \"r_mse_ok\" always evaluates to FALSE, which might not be intended here."))
assertFalse(result.contains("Conjoining unequality of mode literals [first, second] in Mode Switch Entry \"r_mse_ok\" always evaluates to FALSE, which might not be intended here."))
assertFalse(result.contains("Conjoining mode conditions on the same Mode Literal \"first\" with relations [EQUAL, NOT_EQUAL] in Mode Switch Entry \"r_mse_ok\" always evaluates to FALSE, which might not be intended here."))
}
@Test
def void test_TASoftwareServerCall() {
val model = amalthea [
softwareModel [
runnable [
name = "server_runnable"
]
runnable [
name = "r_ok"
activityGraph [asynchronousServerCall [serverRunnable = _find(Runnable, "server_runnable")]]
]
runnable [
name = "r_looped"
activityGraph [asynchronousServerCall [serverRunnable = containingRunnable]]
]
]
]
val validationResult = validate(model)
val result = validationResult.stream.filter[it.severityLevel == Severity.ERROR].map[it.message].collect(Collectors.toList)
assertTrue(result.contains("The server runnable called by Asynchronous Server Call in Runnable \"r_looped\" must not refer to the containing runnable."))
assertFalse(result.contains("The server runnable called by Asynchronous Server Call in Runnable \"r_ok\" must not refer to the containing runnable."))
}
@Test
def void test_TASoftwareRunnableCall() {
val model = amalthea [
softwareModel [
runnable [
name = "other_runnable"
]
runnable [
name = "r_ok"
activityGraph [asynchronousServerCall [serverRunnable = _find(Runnable, "other_runnable")]]
]
runnable [
name = "r_looped"
activityGraph [runnableCall [runnable = containingRunnable]]
]
]
]
val validationResult = validate(model)
val result = validationResult.stream.filter[it.severityLevel == Severity.ERROR].map[it.message].collect(Collectors.toList)
assertTrue(result.contains("The runnable called by Runnable Call in Runnable \"r_looped\" must not refer to the containing runnable."))
assertFalse(result.contains("The runnable called by Runnable Call in Runnable \"r_ok\" must not refer to the containing runnable."))
}
}