Skip to content

Commit

Permalink
Enabled C federated tests with Rust RTI
Browse files Browse the repository at this point in the history
- At first, thirty-five C federated tests are evaluated with Rust RTI
  • Loading branch information
chanijjani committed Feb 18, 2024
1 parent 150cf6a commit 33b6d62
Show file tree
Hide file tree
Showing 60 changed files with 2,595 additions and 8 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/c-tests-with-rust-rti.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: C tests with Rust RTI

on:
workflow_call:
inputs:
all-platforms:
required: false
default: true
type: boolean

jobs:
regular-tests:
strategy:
matrix:
platform: ${{ (inputs.all-platforms && fromJSON('["ubuntu-latest"]')) || fromJSON('["ubuntu-latest"]') }}
runs-on: ${{ matrix.platform }}
timeout-minutes: 30

steps:
- name: Check out lingua-franca repository
uses: actions/checkout@v3
with:
repository: lf-lang/lingua-franca
submodules: true
fetch-depth: 0
- name: Prepare build environment
uses: ./.github/actions/prepare-build-env
- name: Perform federated tests for C target with Rust RTI
# TODO: Drop "git checkout" after this PR is merged.
run: git checkout rust-rti-test; ./gradlew targetTest -Ptarget=RustRti
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.lflang.tests.runtime.CTest;
import org.lflang.tests.runtime.CppTest;
import org.lflang.tests.runtime.PythonTest;
import org.lflang.tests.runtime.RustRtiTest;
import org.lflang.tests.runtime.RustTest;
import org.lflang.tests.runtime.TypeScriptTest;

Expand Down Expand Up @@ -90,6 +91,8 @@ private static Class<? extends TestBase> getTestInstance(Target target) {
return PythonTest.class;
case Rust:
return RustTest.class;
case RustRti:
return RustRtiTest.class;
default:
throw new IllegalArgumentException();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.lflang.tests;

import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.lflang.target.Target;
import org.lflang.tests.TestRegistry.TestCategory;

/**
* A collection of JUnit tests to perform on a given set of targets.
*
* @author Marten Lohstroh
* @author Chanhee Lee
*/
public abstract class SimplifiedRuntimeTest extends TestBase {

/**
* Construct a test instance that runs tests for a single target.
*
* @param target The target to run tests for.
*/
protected SimplifiedRuntimeTest(Target target) {
super(target);
}

/** Whether to enable {@link #runFederatedTests()}. */
protected boolean supportsFederatedExecution() {
return false;
}

@Test
public void runFederatedTestsWithRustRti() {
Assumptions.assumeTrue(supportsFederatedExecution(), Message.NO_FEDERATION_SUPPORT);
runTestsForTargetsWithRustRti(
Message.DESC_FEDERATED_WITH_RUST_RTI,
TestCategory.FEDERATED::equals,
Transformers::noChanges,
Configurators::noChanges,
TestLevel.EXECUTION,
false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*************
* Copyright (c) 2019-2024, The University of California at Berkeley.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***************/
package org.lflang.tests.runtime;

import org.junit.jupiter.api.Test;
import org.lflang.target.Target;
import org.lflang.tests.SimplifiedRuntimeTest;

/**
* Collection of tests for the C target with Rust RTI.
*
* <p>Tests that are implemented in the base class are still overridden so that each test can be
* easily invoked individually from IDEs with JUnit support like Eclipse and IntelliJ. This is
* typically done by right-clicking on the name of the test method and then clicking "Run".*
*
* @author Marten Lohstroh
* @author Chanhee Lee
*/
public class RustRtiTest extends SimplifiedRuntimeTest {

public RustRtiTest() {
super(Target.RustRti);
}

@Override
protected boolean supportsSingleThreadedExecution() {
return true;
}

@Override
protected boolean supportsFederatedExecution() {
return true;
}

@Test
@Override
public void runFederatedTestsWithRustRti() {
super.runFederatedTestsWithRustRti();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,97 @@ public boolean doGenerate(Resource resource, LFGeneratorContext context) throws
return false;
}

/**
* Produce LF code for each federate in a separate file, then invoke a target-specific code
* generator for each of those files.
*
* @param resource The resource that has the federated main reactor in it
* @param context The context in which to carry out the code generation.
* @return False if no errors have occurred, true otherwise.
*/
public boolean doGenerateForRustRTI(Resource resource, LFGeneratorContext context)
throws IOException {
if (!federatedExecutionIsSupported(resource)) return true;
cleanIfNeeded(context);

// In a federated execution, we need keepalive to be true,
// otherwise a federate could exit simply because it hasn't received
// any messages.
KeepaliveProperty.INSTANCE.override(targetConfig, true);

// Process command-line arguments
processCLIArguments(context);

// Find the federated reactor
Reactor federation = FedASTUtils.findFederatedReactor(resource);

// Make sure the RTI host is set correctly.
setRTIHost(federation);

// Create the FederateInstance objects.
ReactorInstance main = createFederateInstances(federation, context);

// Insert reactors that split multiports into many ports.
insertIndexers(main, resource);

// Clear banks so that each bank member becomes a single federate.
for (Instantiation instantiation : ASTUtils.allInstantiations(federation)) {
instantiation.setWidthSpec(null);
instantiation.setWidthSpec(null);
}

// Find all the connections between federates.
// For each connection between federates, replace it in the
// AST with an action (which inherits the delay) and three reactions.
// The action will be physical for physical connections and logical
// for logical connections.
replaceFederateConnectionsWithProxies(federation, main, resource);

FedEmitter fedEmitter =
new FedEmitter(
fileConfig,
ASTUtils.toDefinition(mainDef.getReactorClass()),
messageReporter,
rtiConfig);

// Generate LF code for each federate.
Map<Path, CodeMap> lf2lfCodeMapMap = new HashMap<>();
for (FederateInstance federate : federates) {
lf2lfCodeMapMap.putAll(fedEmitter.generateFederate(context, federate, federates.size()));
}

// Do not invoke target code generators if --no-compile flag is used.
if (context.getTargetConfig().get(NoCompileProperty.INSTANCE)) {
context.finish(Status.GENERATED, lf2lfCodeMapMap);
return false;
}

// If the RTI is to be built locally, set up a build environment for it.
prepareRtiBuildEnvironment(context);

Map<Path, CodeMap> codeMapMap =
compileFederates(
context,
lf2lfCodeMapMap,
subContexts -> {
createDockerFiles(context, subContexts);
generateLaunchScriptForRustRti();
// If an error has occurred during codegen of any federate, report it.
subContexts.forEach(
c -> {
if (c.getErrorReporter().getErrorsOccurred()) {
context
.getErrorReporter()
.at(c.getFileConfig().srcFile)
.error("Failure during code generation of " + c.getFileConfig().srcFile);
}
});
});

context.finish(Status.COMPILED, codeMapMap);
return false;
}

/**
* Prepare a build environment for the rti alongside the generated sources of the federates.
*
Expand Down Expand Up @@ -229,6 +320,11 @@ private void generateLaunchScript() {
.doGenerate(federates, rtiConfig);
}

private void generateLaunchScriptForRustRti() {
new FedLauncherGenerator(this.targetConfig, this.fileConfig, this.messageReporter)
.doGenerateForRustRTI(federates, new RtiConfig());
}

/**
* Generate a Dockerfile for each federate and a docker-compose.yml for the federation.
*
Expand Down
Loading

0 comments on commit 33b6d62

Please sign in to comment.