Skip to content

Commit ca5384d

Browse files
committed
Support parsing only specific unittests (e.g. @betterc-test)
1 parent 28729b5 commit ca5384d

4 files changed

Lines changed: 135 additions & 13 deletions

File tree

posix.mak

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ $(ROOT)/tests_extractor: tests_extractor.d
107107
################################################################################
108108

109109
test_tests_extractor: $(ROOT)/tests_extractor
110-
$< -i ./test/tests_extractor/ascii.d | diff - ./test/tests_extractor/ascii.d.ext
111-
$< -i ./test/tests_extractor/iteration.d | diff - ./test/tests_extractor/iteration.d.ext
110+
for file in ascii iteration ; do \
111+
$< -i "./test/tests_extractor/$${file}.d" | diff -p - "./test/tests_extractor/$${file}.d.ext"; \
112+
done
113+
$< -a betterc -i "./test/tests_extractor/attributes.d" | diff -p - "./test/tests_extractor/attributes.d.ext";
112114

113115
RDMD_TEST_COMPILERS = $(DMD)
114116
RDMD_TEST_EXECUTABLE = $(ROOT)/rdmd

test/tests_extractor/attributes.d

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module attributes;
2+
3+
enum betterc;
4+
5+
@betterc @safe @("foo") unittest
6+
{
7+
assert(1 == 1);
8+
}
9+
10+
@safe @("foo") unittest
11+
{
12+
assert(2 == 2);
13+
}
14+
15+
///
16+
@("foo") unittest
17+
{
18+
assert(3 == 3);
19+
}
20+
21+
@("foo") @betterc unittest
22+
{
23+
assert(4 == 4);
24+
}
25+
26+
@("betterc") @([1, 2, 3]) unittest
27+
{
28+
assert(5 == 5);
29+
}
30+
31+
@nogc @("foo", "betterc", "bar") @safe unittest
32+
{
33+
assert(6 == 6);
34+
}
35+
36+
@nogc @("foo", "better", "bar") @safe unittest
37+
{
38+
assert(7 == 7);
39+
}
40+
41+
@("betterd") unittest
42+
{
43+
assert(8 == 8);
44+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# line 3
2+
unittest
3+
{
4+
import attributes;
5+
6+
assert(1 == 1);
7+
}
8+
9+
# line 19
10+
unittest
11+
{
12+
import attributes;
13+
14+
assert(4 == 4);
15+
}
16+
17+
# line 24
18+
unittest
19+
{
20+
import attributes;
21+
22+
assert(5 == 5);
23+
}
24+
25+
# line 29
26+
unittest
27+
{
28+
import attributes;
29+
30+
assert(6 == 6);
31+
}
32+

tests_extractor.d

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ dependency "libdparse" version="~>0.8.0"
77
* Parses all public unittests that are visible on dlang.org
88
* (= annotated with three slashes)
99
*
10-
* Copyright (C) 2017 by D Language Foundation
10+
* Copyright (C) 2018 by D Language Foundation
1111
*
1212
* Author: Sebastian Wilzbach
1313
*
@@ -33,11 +33,13 @@ class TestVisitor : ASTVisitor
3333
File outFile;
3434
ubyte[] sourceCode;
3535
string moduleName;
36+
string[] attributes;
3637

37-
this(File outFile, ubyte[] sourceCode)
38+
this(File outFile, ubyte[] sourceCode, string[] attributes)
3839
{
3940
this.outFile = outFile;
4041
this.sourceCode = sourceCode;
42+
this.attributes = attributes;
4143
}
4244

4345
alias visit = ASTVisitor.visit;
@@ -58,13 +60,51 @@ class TestVisitor : ASTVisitor
5860

5961
override void visit(const Declaration decl)
6062
{
61-
if (decl.unittest_ !is null && hasDdocHeader(sourceCode, decl))
63+
if (decl.unittest_ !is null && shouldIncludeUnittest(decl))
6264
print(decl.unittest_);
6365

6466
decl.accept(this);
6567
}
6668

6769
private:
70+
71+
bool shouldIncludeUnittest(const Declaration decl)
72+
{
73+
if (!attributes.empty)
74+
return filterForUDAs(decl);
75+
else
76+
return hasDdocHeader(sourceCode, decl);
77+
}
78+
79+
bool filterForUDAs(const Declaration decl)
80+
{
81+
foreach (attr; decl.attributes)
82+
{
83+
// check for @myArg
84+
if (attributes.canFind(attr.atAttribute.identifier.text))
85+
return true;
86+
87+
// support @("myArg") too
88+
if (auto argList = attr.atAttribute.argumentList)
89+
{
90+
foreach (arg; argList.items)
91+
{
92+
if (auto unaryExp = cast(UnaryExpression) arg)
93+
if (auto primaryExp = unaryExp.primaryExpression)
94+
{
95+
auto attribute = primaryExp.primary.text;
96+
if (attribute.length >= 2)
97+
{
98+
attribute = attribute[1 .. $ - 1];
99+
if (attributes.canFind(attribute))
100+
return true;
101+
}
102+
}
103+
}
104+
}
105+
}
106+
return false;
107+
}
68108
void print(const Unittest u)
69109
{
70110
/*
@@ -93,7 +133,7 @@ private:
93133
}
94134
}
95135

96-
void parseFile(File inFile, File outFile)
136+
void parseFile(File inFile, File outFile, string[] attributes)
97137
{
98138
import dparse.lexer;
99139
import dparse.parser : parseModule;
@@ -111,11 +151,11 @@ void parseFile(File inFile, File outFile)
111151

112152
RollbackAllocator rba;
113153
auto m = parseModule(tokens.array, inFile.name, &rba);
114-
auto visitor = new TestVisitor(outFile, sourceCode);
154+
auto visitor = new TestVisitor(outFile, sourceCode, attributes);
115155
visitor.visit(m);
116156
}
117157

118-
void parseFileDir(string inputDir, string fileName, string outputDir)
158+
void parseFileDir(string inputDir, string fileName, string outputDir, string[] attributes)
119159
{
120160
import std.path : buildPath, dirSeparator, buildNormalizedPath;
121161

@@ -132,7 +172,7 @@ void parseFileDir(string inputDir, string fileName, string outputDir)
132172
// convert the file path to a nice output file, e.g. std/uni.d -> std_uni.d
133173
string outName = fileNameNormalized.replace(dirSeparator, "_");
134174

135-
parseFile(File(fileName), File(buildPath(outputDir, outName), "w"));
175+
parseFile(File(fileName), File(buildPath(outputDir, outName), "w"), attributes);
136176
}
137177

138178
void main(string[] args)
@@ -143,12 +183,15 @@ void main(string[] args)
143183
string inputDir;
144184
string outputDir = "./out";
145185
string ignoredFilesStr;
146-
string modulePrefix = "";
186+
string modulePrefix;
187+
string attributesStr;
147188

148189
auto helpInfo = getopt(args, config.required,
149190
"inputdir|i", "Folder to start the recursive search for unittest blocks (can be a single file)", &inputDir,
150191
"outputdir|o", "Folder to which the extracted test files should be saved (stdout for a single file)", &outputDir,
151-
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr);
192+
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr,
193+
"attributes|a", "Comma-separated list of UDAs that the unittest should have", &attributesStr,
194+
);
152195

153196
if (helpInfo.helpWanted)
154197
{
@@ -162,6 +205,7 @@ to in the output directory.
162205

163206
inputDir = inputDir.asNormalizedPath.array;
164207
Algebraic!(string, File) outputLocation = cast(string) outputDir.asNormalizedPath.array;
208+
auto attributes = attributesStr.split(",");
165209

166210
if (!exists(outputDir))
167211
mkdir(outputDir);
@@ -196,8 +240,8 @@ to in the output directory.
196240
{
197241
stderr.writeln("parsing ", file);
198242
outputLocation.visit!(
199-
(string outputFolder) => parseFileDir(inputDir, file, outputFolder),
200-
(File outputFile) => parseFile(File(file.name, "r"), outputFile),
243+
(string outputFolder) => parseFileDir(inputDir, file, outputFolder, attributes),
244+
(File outputFile) => parseFile(File(file.name, "r"), outputFile, attributes),
201245
);
202246
}
203247
else

0 commit comments

Comments
 (0)