-
-
Notifications
You must be signed in to change notification settings - Fork 146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support parsing only specific unittests (e.g. @betterc-test) #357
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module attributes; | ||
|
||
enum betterc; | ||
|
||
@betterc @safe @("foo") unittest | ||
{ | ||
assert(1 == 1); | ||
} | ||
|
||
@safe @("foo") unittest | ||
{ | ||
assert(2 == 2); | ||
} | ||
|
||
/// | ||
@("foo") unittest | ||
{ | ||
assert(3 == 3); | ||
} | ||
|
||
@("foo") @betterc unittest | ||
{ | ||
assert(4 == 4); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that this has a version(D_BetterC)
{
assert(4 == 4);
}
else
{
assert(0);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. The idea here is just to selectively filter out unittests. Such rewrites would just complicate the job of this extraction tool and mess up the line matching. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But I don't see the test proving that the extraction tool only extracts those test with the correct attribute, as all tests in this file succeed. Though, I also don't understand the purpose of the .ext file either. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, now I get it. Ok it's good! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the record: the |
||
} | ||
|
||
@("betterc") @([1, 2, 3]) unittest | ||
{ | ||
assert(5 == 5); | ||
} | ||
|
||
@nogc @("foo", "betterc", "bar") @safe unittest | ||
{ | ||
assert(6 == 6); | ||
} | ||
|
||
@nogc @("foo", "better", "bar") @safe unittest | ||
{ | ||
assert(7 == 7); | ||
} | ||
|
||
@("betterd") unittest | ||
{ | ||
assert(8 == 8); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# line 3 | ||
unittest | ||
{ | ||
import attributes; | ||
|
||
assert(1 == 1); | ||
} | ||
|
||
# line 19 | ||
unittest | ||
{ | ||
import attributes; | ||
|
||
assert(4 == 4); | ||
} | ||
|
||
# line 24 | ||
unittest | ||
{ | ||
import attributes; | ||
|
||
assert(5 == 5); | ||
} | ||
|
||
# line 29 | ||
unittest | ||
{ | ||
import attributes; | ||
|
||
assert(6 == 6); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module betterc; | ||
|
||
/// | ||
unittest | ||
{ | ||
int a = 1; | ||
assert(a == 2); | ||
} | ||
|
||
/// | ||
unittest | ||
{ | ||
int b = 2; | ||
assert(b == 2); | ||
assert(b == 3); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# line 2 | ||
unittest | ||
{ | ||
import betterc; | ||
|
||
int a = 1; | ||
assert(a == 2); | ||
} | ||
|
||
# line 9 | ||
unittest | ||
{ | ||
import betterc; | ||
|
||
int b = 2; | ||
assert(b == 2); | ||
assert(b == 3); | ||
} | ||
|
||
extern(C) void main() | ||
{ | ||
static foreach(u; __traits(getUnitTests, __traits(parent, main))) | ||
u(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ dependency "libdparse" version="~>0.8.0" | |
* Parses all public unittests that are visible on dlang.org | ||
* (= annotated with three slashes) | ||
* | ||
* Copyright (C) 2017 by D Language Foundation | ||
* Copyright (C) 2018 by D Language Foundation | ||
* | ||
* Author: Sebastian Wilzbach | ||
* | ||
|
@@ -33,11 +33,13 @@ class TestVisitor : ASTVisitor | |
File outFile; | ||
ubyte[] sourceCode; | ||
string moduleName; | ||
VisitorConfig config; | ||
|
||
this(File outFile, ubyte[] sourceCode) | ||
this(File outFile, ubyte[] sourceCode, VisitorConfig config) | ||
{ | ||
this.outFile = outFile; | ||
this.sourceCode = sourceCode; | ||
this.config = config; | ||
} | ||
|
||
alias visit = ASTVisitor.visit; | ||
|
@@ -54,17 +56,67 @@ class TestVisitor : ASTVisitor | |
moduleName = outFile.name.replace(".d", "").replace(dirSeparator, ".").replace(".package", ""); | ||
} | ||
m.accept(this); | ||
// -betterC doesn't run unittests out of the box | ||
if (config.betterCOutput) | ||
{ | ||
outFile.writeln(q{extern(C) void main() | ||
{ | ||
static foreach(u; __traits(getUnitTests, __traits(parent, main))) | ||
u(); | ||
}}); | ||
} | ||
} | ||
|
||
override void visit(const Declaration decl) | ||
{ | ||
if (decl.unittest_ !is null && hasDdocHeader(sourceCode, decl)) | ||
if (decl.unittest_ !is null && shouldIncludeUnittest(decl)) | ||
print(decl.unittest_); | ||
|
||
decl.accept(this); | ||
} | ||
|
||
private: | ||
|
||
bool shouldIncludeUnittest(const Declaration decl) | ||
{ | ||
if (!config.attributes.empty) | ||
return filterForUDAs(decl); | ||
else | ||
return hasDdocHeader(sourceCode, decl); | ||
} | ||
|
||
bool filterForUDAs(const Declaration decl) | ||
{ | ||
foreach (attr; decl.attributes) | ||
{ | ||
if (attr.atAttribute is null) | ||
continue; | ||
|
||
// check for @myArg | ||
if (config.attributes.canFind(attr.atAttribute.identifier.text)) | ||
return true; | ||
|
||
// support @("myArg") too | ||
if (auto argList = attr.atAttribute.argumentList) | ||
{ | ||
foreach (arg; argList.items) | ||
{ | ||
if (auto unaryExp = cast(UnaryExpression) arg) | ||
if (auto primaryExp = unaryExp.primaryExpression) | ||
{ | ||
auto attribute = primaryExp.primary.text; | ||
if (attribute.length >= 2) | ||
{ | ||
attribute = attribute[1 .. $ - 1]; | ||
if (config.attributes.canFind(attribute)) | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
void print(const Unittest u) | ||
{ | ||
/* | ||
|
@@ -93,7 +145,7 @@ private: | |
} | ||
} | ||
|
||
void parseFile(File inFile, File outFile) | ||
void parseFile(File inFile, File outFile, VisitorConfig visitorConfig) | ||
{ | ||
import dparse.lexer; | ||
import dparse.parser : parseModule; | ||
|
@@ -111,11 +163,11 @@ void parseFile(File inFile, File outFile) | |
|
||
RollbackAllocator rba; | ||
auto m = parseModule(tokens.array, inFile.name, &rba); | ||
auto visitor = new TestVisitor(outFile, sourceCode); | ||
auto visitor = new TestVisitor(outFile, sourceCode, visitorConfig); | ||
visitor.visit(m); | ||
} | ||
|
||
void parseFileDir(string inputDir, string fileName, string outputDir) | ||
void parseFileDir(string inputDir, string fileName, string outputDir, VisitorConfig visitorConfig) | ||
{ | ||
import std.path : buildPath, dirSeparator, buildNormalizedPath; | ||
|
||
|
@@ -132,7 +184,13 @@ void parseFileDir(string inputDir, string fileName, string outputDir) | |
// convert the file path to a nice output file, e.g. std/uni.d -> std_uni.d | ||
string outName = fileNameNormalized.replace(dirSeparator, "_"); | ||
|
||
parseFile(File(fileName), File(buildPath(outputDir, outName), "w")); | ||
parseFile(File(fileName), File(buildPath(outputDir, outName), "w"), visitorConfig); | ||
} | ||
|
||
struct VisitorConfig | ||
{ | ||
string[] attributes; /// List of attributes to extract; | ||
bool betterCOutput; /// Add custom extern(C) main method for running D's unittests | ||
} | ||
|
||
void main(string[] args) | ||
|
@@ -143,12 +201,17 @@ void main(string[] args) | |
string inputDir; | ||
string outputDir = "./out"; | ||
string ignoredFilesStr; | ||
string modulePrefix = ""; | ||
string modulePrefix; | ||
string attributesStr; | ||
VisitorConfig visitorConfig; | ||
|
||
auto helpInfo = getopt(args, config.required, | ||
"inputdir|i", "Folder to start the recursive search for unittest blocks (can be a single file)", &inputDir, | ||
"outputdir|o", "Folder to which the extracted test files should be saved (stdout for a single file)", &outputDir, | ||
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr); | ||
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr, | ||
"attributes|a", "Comma-separated list of UDAs that the unittest should have", &attributesStr, | ||
"betterC", "Add custom extern(C) main method for running D's unittests", &visitorConfig.betterCOutput, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's better to rename this to |
||
); | ||
|
||
if (helpInfo.helpWanted) | ||
{ | ||
|
@@ -162,6 +225,7 @@ to in the output directory. | |
|
||
inputDir = inputDir.asNormalizedPath.array; | ||
Algebraic!(string, File) outputLocation = cast(string) outputDir.asNormalizedPath.array; | ||
visitorConfig.attributes = attributesStr.split(","); | ||
|
||
if (!exists(outputDir)) | ||
mkdir(outputDir); | ||
|
@@ -196,8 +260,8 @@ to in the output directory. | |
{ | ||
stderr.writeln("parsing ", file); | ||
outputLocation.visit!( | ||
(string outputFolder) => parseFileDir(inputDir, file, outputFolder), | ||
(File outputFile) => parseFile(File(file.name, "r"), outputFile), | ||
(string outputFolder) => parseFileDir(inputDir, file, outputFolder, visitorConfig), | ||
(File outputFile) => parseFile(File(file.name, "r"), outputFile, visitorConfig), | ||
); | ||
} | ||
else | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name should be
betterC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a test to check whether the attribute filter works. It could be any attribute. See the
-a betterc
line inposix.mak