Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "BreakTest",
"request": "launch",
"mainClass": "org.rascalmpl.compiler.BreakTest",
"projectName": "rascal",
"console": "integratedTerminal"
},
{
"type": "java",
"name": "RascalCheck",
Expand Down
117 changes: 117 additions & 0 deletions src/org/rascalmpl/compiler/BreakTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package org.rascalmpl.compiler;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.rascalmpl.debug.IRascalMonitor;
import org.rascalmpl.shell.RascalShell;
import org.rascalmpl.shell.ShellEvaluatorFactory;
import org.rascalmpl.test.infrastructure.RascalJUnitTestRunner;
import org.rascalmpl.uri.URIResolverRegistry;

import io.usethesource.vallang.ISourceLocation;

public class BreakTest {

private static final String BREAKING_MODULE = "lang::rascalcore::check::tests::ChangeScenarioTests";
private static final String BREAKING_TEST = "fixedErrorsDisappear2";

private static final int PARALLEL_RUNS = 8; // set to 1 to avoid any multi-threading interactions, but it might take 20 rounds or something
private static final int TRIES = 1000 / PARALLEL_RUNS;

public static void main(String[] args) throws IOException, InterruptedException {
RascalShell.setupJavaProcessForREPL();

var term = RascalShell.connectToTerminal();
var monitor = IRascalMonitor.buildConsoleMonitor(term);
var error = monitor instanceof PrintWriter ? (PrintWriter) monitor : new PrintWriter(System.err, false);
try {
AtomicBoolean failed = new AtomicBoolean(false);
AtomicInteger done = new AtomicInteger(0);
for (int t = 0; t < PARALLEL_RUNS; t++) {
var name = "Thread " + (t + 1);
var tr = new Thread(() -> {
try {
if (crashTest(monitor, error, name, failed)) {
failed.set(true);
System.err.println("We got a failure, exiting now!");
Thread.sleep(1000);
System.exit(1);
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.incrementAndGet();
}
});
tr.start();
}
while (done.get() < PARALLEL_RUNS && !failed.get()) {
Thread.sleep(100);
}
} finally {
error.close();
}
}

static boolean crashTest(IRascalMonitor monitor, PrintWriter errorPrinter, String name, AtomicBoolean failed) {
var output = new StringWriter();
var iFailed = new AtomicBoolean(false);
try (var err = new PrintWriter(output, true); var out= new PrintWriter(output, false)) {
var projectRoot = RascalJUnitTestRunner.inferProjectRootFromClass(BreakTest.class);
var evaluator = ShellEvaluatorFactory.getDefaultEvaluatorForLocation(projectRoot, Reader.nullReader(), err, out, monitor, "$test-"+name+"$");
evaluator.getConfiguration().setErrors(true);
// make sure we're writing to the outputs
evaluator.overwritePrintWriter(out, err);

evaluator.doImport(monitor, BREAKING_MODULE);
try {
monitor.job(name, TRIES, (jobname, step) -> {
try {
for (int i = 0; i < TRIES; i++) {
if (failed.get()) {
return false;
}
monitor.jobStep(jobname, "Running: try " + (i + 1));
evaluator.call(BREAKING_TEST);
}

} catch (Throwable e ) {
failed.set(true);
iFailed.set(true);
err.println("❌ test fail ");
err.println(e);
}
return null;
});
} finally {
// clean up memory
var memoryModule = evaluator.getHeap().getModule("lang::rascalcore::check::TestShared");
var testRoot = memoryModule.getFrameVariable("testRoot");
try {
URIResolverRegistry.getInstance().remove((ISourceLocation)testRoot.getValue(), true);
}
catch (Throwable e) {
err.println("Failure to cleanup the cache");
}
}

}

if (iFailed.get()) {
errorPrinter.println("❌❌❌ Test run failed: " + name);
errorPrinter.println("Job output:");
errorPrinter.println(output.toString());
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ tuple[bool, TModel, ModuleStatus] addGrammar(MODID moduleId, set[MODID] imports,
<found, tm1, ms> = getTModelForModule(m, ms);
if(!found) {
msg = error("Cannot add grammar or tmodel since `<moduleId2moduleName(m)>` is not found", ms.moduleLocs[moduleId] ? |unknown:///|);
println(msg); // TODO: Just to record this event; this should probably go to a log file
//println(msg); // TODO: Just to record this event; this should probably go to a log file
ms.messages[moduleId] ? {} += { msg };
tm1 = tmodel(modelName=qualifiedModuleName, messages=[msg]);
return <false, tm1, ms>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ bool uptodateTPls(list[loc] candidates, list[str] mnames, PathConfig pcfg){
for(int i <- index(candidates)){
mloc = candidates[i];
<found, tpl> = getTPLReadLoc(mnames[i], pcfg);
if(!found || lastModified(mloc) > lastModified(tpl)){
if(!found || lastModified(mloc) >= lastModified(tpl)){
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ bool tplOutdated(MODID moduleId, PathConfig pcfg){
lmMloc = lastModified(mloc);
lmTpl = lastModified(tpl);
res = !found || lmMloc > lmTpl;
//println("tplOutdated <qualifiedModuleName>: <res>; mloc: <lmMloc> \> tpl: <lmTpl>: <lmMloc > lmTpl>, (<mloc>, <tpl>)");
// println("tplOutdated <qualifiedModuleName>: <res>; mloc: <lmMloc> \> tpl: <lmTpl>: <lmMloc > lmTpl>, (<mloc>, <tpl>)");
return res;
} catch _: {
return false;
Expand Down
11 changes: 5 additions & 6 deletions src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,11 @@ str getModuleNameFromAnyLogical(loc l){
tuple[bool, ModuleStatus] importsAndExtendsAreBinaryCompatible(TModel tm, set[MODID] importsAndExtends, ModuleStatus ms){
moduleName = tm.modelName;
physical2logical = invertUnique(tm.logical2physical);

modRequires = { lg | l <- range(tm.useDef),
physical2logical[l]?, lg := physical2logical[l],
moduleName !:= getModuleNameFromAnyLogical(lg) };
modRequires = {lg | l <- range(tm.useDef),
l in physical2logical,
lg := physical2logical[l],
moduleName != getModuleNameFromAnyLogical(lg)
};
provided = {};
if(!isEmpty(modRequires)){
for(m <- importsAndExtends){
Expand All @@ -342,8 +343,6 @@ tuple[bool, ModuleStatus] importsAndExtendsAreBinaryCompatible(TModel tm, set[MO
}
}

//println("<moduleName> requires <modRequires>");

if(isEmpty(modRequires - provided)){
//println("importsAndExtendsAreBinaryCompatible <moduleName>: satisfied");
return <true, ms>;
Expand Down
19 changes: 10 additions & 9 deletions src/org/rascalmpl/compiler/lang/rascalcore/check/TestConfigs.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import lang::rascalcore::check::BasicRascalConfig;
import lang::rascalcore::check::RascalConfig;

import lang::rascalcore::check::ModuleLocations;
import lang::rascalcore::check::TestShared;
// import lang::rascalcore::CompilerPathConfig;

// Duplicate in lang::rascalcore::compile::util::Names, factor out
Expand Down Expand Up @@ -74,10 +75,10 @@ public PathConfig getDefaultTestingPathConfig() {
npc += 1;
snpc = "<npc>";
return pathConfig(
srcs = [ |memory:///test-modules/|, |std:///| ],
bin = |memory:///test-modules/rascal-tests-bin-<snpc>|,
generatedSources = |memory:///test-modules/generated-test-sources-<snpc>|,
generatedResources = |memory:///test-modules/generated-test-resources-<snpc>|,
srcs = [ testModulesRoot, |std:///| ],
bin = testRoot + "rascal-tests-bin-<snpc>",
generatedSources = testRoot + "generated-test-sources-<snpc>",
generatedResources = testRoot + "generated-test-resources-<snpc>",
libs = [ ]
);
}
Expand All @@ -92,10 +93,10 @@ public PathConfig getReleasedStandardLibraryTestingPathConfig() {
npc += 1;
snpc = "<npc>";
return pathConfig(
srcs = [ |memory:///test-modules/| ],
bin = |memory:///test-modules/rascal-tests-bin-<snpc>|,
generatedSources = |memory:///test-modules/generated-test-sources-<snpc>|,
generatedResources = |memory:///test-modules/generated-test-resources-<snpc>|,
srcs = [ testModulesRoot ],
bin = testRoot + "rascal-tests-bin-<snpc>",
generatedSources = testRoot + "generated-test-sources-<snpc>",
generatedResources = testRoot + "generated-test-resources-<snpc>",
libs = [ |lib://rascal| ]
);
}
Expand All @@ -108,7 +109,7 @@ public PathConfig getRascalProjectTestingPathConfig() {
snpc = "<npc>";
return pathConfig(
srcs = [|project://rascal/src/org/rascalmpl/library|],
bin = |memory:///test-modules/rascal-lib-bin-<snpc>|,
bin = testModulesRoot + "rascal-lib-bin-<snpc>",
libs = []
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module lang::rascalcore::check::TestShared

import util::UUID;


public loc testRoot = uuid()[scheme="memory"];
public loc testModulesRoot = testRoot + "src";

Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import String;
import lang::rascalcore::check::ModuleLocations;
import util::FileSystem;
import util::SemVer;
import lang::rascalcore::check::TestShared;
import lang::rascalcore::check::tests::StaticTestingUtils;


// ---- Utilities for test setup ----------------------------------------------
Expand All @@ -57,10 +59,10 @@ data PathConfig(loc generatedResources=|unknown:///|, loc generatedSources=|unkn
data Project
= project(str name, map[str moduleName, str moduleText] modules, PathConfig pcfg);

void clearMemory() { remove(|memory:///|, recursive = true); }
void clearMemory() { remove(testRoot, recursive = true); }

loc projectDir(str pname)
= |memory://<pname>/|;
= testRoot + pname;

loc src(str pname)
= projectDir(pname) + "src/";
Expand Down Expand Up @@ -99,6 +101,9 @@ str writeModule(str mname, str mtext){
throw "Parse error in <msrc>";
}

loc getModuleLoc(str mname, Project pd)
= src(pd.name) + "<mname>.rsc";

PathConfig createPathConfig(str pname){
return pathConfig(
srcs=[src(pname)],
Expand All @@ -111,22 +116,28 @@ PathConfig createPathConfig(str pname){

Project addModule(str mname, str mtext, Project pd){
pd.modules[mname] = writeModule(mname, mtext);
writeFile(src(pd.name) + "<mname>.rsc", pd.modules[mname]);
mloc = getModuleLoc(mname, pd);
writeFile(mloc, pd.modules[mname]);
assert exists(mloc) : "<mloc> does not exist after write";
return pd;
}

Project changeModule(str mname, str mtext, Project pd){
if(!pd.modules[mname]?) throw "Module <mname> does not exist in <pd.name>";

pd.modules[mname] = writeModule(mname, mtext);
writeFile(src(pd.name) + "<mname>.rsc", pd.modules[mname]);
mloc = getModuleLoc(mname, pd);
writeFile(mloc, pd.modules[mname]);
assert exists(mloc) : "<mloc> does not exist after write";
return pd;
}

Project removeSourceOfModule(str mname, Project pd){
if(!pd.modules[mname]?) throw "Cannot remove non-existing module <mname>";
pd.modules = delete(pd.modules, mname);
remove(src(pd.name) + "<mname>.rsc", recursive=true);
mloc = getModuleLoc(mname, pd);
remove(mloc, recursive=true);
assert !exists(mloc): "<mloc> not removed";
return pd;
}

Expand Down Expand Up @@ -533,7 +544,7 @@ test bool incompatibleVersionsOfBinaryLibrary(){

// Important: we do not recompile TP (and thus it will contain the outdated version of IO)

// Update Checks' modification time to make sure it will rechecked
// Update Checks' modification time to make sure it will be rechecked
touch(getRascalModuleLocation("Check", core.pcfg));
// Recompile Check and discover the error
return checkExpectErrors("Check", ["Review of dependencies, reconfiguration or recompilation needed: binary module `TP` depends (indirectly) on incompatible module(s)"], core.pcfg, remove = [rascal, typepal, core]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,29 @@ test bool breakingChange1(){
return expectReChecks(D, ["C", "D"]);
}

test bool fixedErrorsDisappear2() { // ht @toinehartman
clearMemory();
pcfg = getDefaultTestingPathConfig();

mlocs = writeModules("
module ParserBase
");

assert checkModulesOK(mlocs, pathConfig=pcfg) : "Precondition failed: no errors expected!";

// Introduce a type error (import of module that does not exist)
l = writeModule("
module ParserBase

import vis::ParseTree; // module does not exist -\> error

");

assert missingModuleInModule(l, pathConfig=pcfg) : "Precondition failed: expected at least one error, but got none!";

return true;
}

test bool fixedErrorsDisappear() { // ht @toinehartman
clearMemory();
pcfg = getReleasedStandardLibraryTestingPathConfig();
Expand Down
Loading
Loading