Skip to content
Merged
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
4 changes: 2 additions & 2 deletions runtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ val fcovTestReport = tasks.register<JavaExec>("fcovTestReport") {
mainClass = "dev.ionfusion.fusion.cli.Cli"
args = listOf("report_coverage",
"--configFile", fcovConfig.asFile.path,
fcovDataDir.get().asFile.path,
fcovReportDir.get().asFile.path)
"--htmlDir", fcovReportDir.get().asFile.path,
fcovDataDir.get().asFile.path)

enableAssertions = true
}
Expand Down
80 changes: 53 additions & 27 deletions runtime/src/main/java/dev/ionfusion/fusion/cli/Cover.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
*
Expand All @@ -24,10 +26,12 @@ class Cover
private static final String HELP_ONE_LINER =
"Generate a code coverage report.";
private static final String HELP_USAGE =
"report_coverage [--configFile FILE] COVERAGE_DATA_DIR REPORT_DIR";
"report_coverage [--configFile FILE] --htmlDir REPORT_DIR DATA_DIR ...";
private static final String HELP_BODY =
"Reads Fusion code-coverage data from the COVERAGE_DATA_DIR, then writes an\n" +
"HTML report to the REPORT_DIR.";
"Reads Fusion code-coverage data from the DATA_DIRs, then writes an\n" +
"HTML report to the REPORT_DIR.\n" +
"\n" +
"Multiple data directories can be given, generating an aggregate report.";


Cover()
Expand All @@ -45,6 +49,7 @@ Object makeOptions(GlobalOptions globals)
private class Options
{
private Path myConfigFile;
private Path myHtmlDir;

public void setConfigFile(Path configFile)
throws UsageException
Expand All @@ -55,6 +60,16 @@ public void setConfigFile(Path configFile)
}
myConfigFile = configFile;
}

public void setHtmlDir(Path dir)
throws UsageException
{
if (exists(dir) && !isDirectory(dir))
{
throw usage("--htmlDir is not a directory: " + dir);
}
myHtmlDir = dir;
}
}


Expand All @@ -65,45 +80,51 @@ public void setConfigFile(Path configFile)
Executor makeExecutor(GlobalOptions globals, Object locals, String[] args)
throws UsageException
{
if (args.length != 2) return null;
if (args.length == 0) return null;

String dataPath = args[0];
if (dataPath.isEmpty()) return null;

// TODO Support multiple data directories, to generate an aggregate
// report from a few test suites, Gradle subprojects, etc.
Path dataDir = Paths.get(dataPath);
if (!isDirectory(dataDir) || !isReadable(dataDir))
List<Path> dataDirs = new ArrayList<>();
for (String dataPath : args)
{
throw usage("Coverage data directory is not a readable directory: " + dataPath);
// Avoid resolving to the current directory.
if (dataPath.isEmpty()) return null;

Path dataDir = Paths.get(dataPath);
if (!isDirectory(dataDir) || !isReadable(dataDir))
{
throw usage("Coverage data directory is not a readable directory: " + dataDir);
}
dataDirs.add(dataDir);
}

String reportPath = args[1];
if (reportPath.isEmpty()) return null;
Options options = (Options) locals;

Path reportDir = Paths.get(reportPath);
if (exists(reportDir) && !isDirectory(reportDir))
if (options.myHtmlDir == null)
{
throw usage("Report directory is not a directory: " + reportPath);
throw usage("No HTML output directory given; provide with --htmlDir");
}

return new Executor(globals, (Options) locals, dataDir, reportDir);
if (options.myConfigFile == null && dataDirs.size() > 1)
{
throw usage("Must provide --configFile when generating an aggregate report");
}

return new Executor(globals, options, dataDirs);
}


static class Executor
extends StdioExecutor
{
private final Options myLocals;
private final Path myDataDir;
private final Path myReportDir;
private final Options myLocals;
private final List<Path> myDataDirs;
private final Path myReportDir;

private Executor(GlobalOptions globals, Options locals, Path dataDir, Path reportDir)
private Executor(GlobalOptions globals, Options locals, List<Path> dataDirs)
{
super(globals);
myLocals = locals;
myDataDir = dataDir;
myReportDir = reportDir;
myLocals = locals;
myDataDirs = dataDirs;
myReportDir = locals.myHtmlDir;
}

@Override
Expand All @@ -117,10 +138,15 @@ public int execute(PrintWriter out, PrintWriter err)
}
else
{
config = CoverageConfiguration.forDataDir(myDataDir);
assert myDataDirs.size() == 1; // Checked in makeExecutor()
config = CoverageConfiguration.forDataDir(myDataDirs.get(0));
}

CoverageDatabase database = CoverageDatabase.loadSessions(myDataDir);
CoverageDatabase database = new CoverageDatabase();
for (Path dataDir : myDataDirs)
{
database.loadSessions(dataDir);
}

CoverageReportWriter renderer = new CoverageReportWriter(config, database);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,14 @@ public int compare(SourceLocation a, SourceLocation b)
private final Map<SourceLocation,Boolean> myLocations = new HashMap<>();


CoverageDatabase()
public CoverageDatabase()
{
}


public static CoverageDatabase loadSessions(Path dataDir)
public void loadSessions(Path dataDir)
throws IOException
{
CoverageDatabase db = new CoverageDatabase();

Path sessionsDir = dataDir.resolve("sessions");
if (Files.exists(sessionsDir))
{
Expand All @@ -103,12 +101,11 @@ public static CoverageDatabase loadSessions(Path dataDir)
{
if (isRegularFile(p))
{
db.loadSession(p);
loadSession(p);
}
}
}
}
return db;
}


Expand Down
53 changes: 49 additions & 4 deletions runtime/src/test/java/dev/ionfusion/fusion/cli/CoverTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,32 @@ public void testNoArgs()
}


@Test
public void testNoDataDirArg()
throws Exception
{
run(1, "report_coverage", "--htmlDir", reportDir().getPath());
assertThat(stderrText, containsString("Usage:"));
}


@Test
public void testDataDirArgIsEmpty()
throws Exception
{
run(1, "report_coverage", "--htmlDir", reportDir().getPath(), "");
assertThat(stderrText, containsString("Usage:"));
}


@Test
public void testDataDirIsMissing()
throws Exception
{
File f = new File(myFolder, "no file");
assertFalse(f.exists());

run(1, "report_coverage", f.getPath(), reportDir().getPath());
run(1, "report_coverage", "--htmlDir", reportDir().getPath(), f.getPath());

assertThat(stderrText, containsString("not a readable directory"));
assertThat(stderrText, containsString(f.getPath()));
Expand All @@ -72,7 +90,7 @@ public void testDataDirIsFile()
{
String f = plainFile().getPath();

run(1, "report_coverage", f, reportDir().getPath());
run(1, "report_coverage", "--htmlDir", reportDir().getPath(), f);

assertThat(stderrText, containsString("not a readable directory"));
assertThat(stderrText, containsString(f));
Expand All @@ -84,7 +102,7 @@ public void testReportDirIsFile()
{
String f = plainFile().getPath();

run(1, "report_coverage", dataDir().getPath(), f);
run(1, "report_coverage", "--htmlDir", f, dataDir().getPath());

assertThat(stderrText, containsString("not a directory"));
assertThat(stderrText, containsString(f));
Expand All @@ -99,7 +117,7 @@ public void testCoverCompletionMessage()
String reportDir = reportDir().getPath();

// I'm surprised this works without any coverage data!
run(0, "report_coverage", dataDir, reportDir);
run(0, "report_coverage", "--htmlDir", reportDir, dataDir);
assertThat(stdoutText,
allOf(containsString("Wrote Fusion coverage report to "),
containsString(reportDir)));
Expand All @@ -108,6 +126,33 @@ public void testCoverCompletionMessage()
assertTrue(new File(reportDir, "index.html").isFile());
}

@Test
public void testMultipleDataDirs()
throws Exception
{
File dataDir1 = dataDir();
File dataDir2 = newFolder(myFolder, "dataDir2");
run(0, "report_coverage",
"--htmlDir", reportDir().getPath(),
"--configFile", plainFile().getPath(),
dataDir1.getPath(),
dataDir2.getPath());
}

@Test
public void testMultipleDataDirsNoConfig()
throws Exception
{
File dataDir1 = dataDir();
File dataDir2 = newFolder(myFolder, "dataDir2");
run(1, "report_coverage",
"--htmlDir", reportDir().getPath(),
dataDir1.getPath(),
dataDir2.getPath());
assertThat(stderrText, containsString("Must provide --configFile"));
}


private static File newFolder(File root, String... subDirs) throws IOException {
String subFolder = String.join("/", subDirs);
File result = new File(root, subFolder);
Expand Down