-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathCompilationTests.scala
350 lines (304 loc) · 18.4 KB
/
CompilationTests.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
package dotty
package tools
package dotc
import scala.language.unsafeNulls
import org.junit.{ Test, BeforeClass, AfterClass, Ignore }
import org.junit.Assert._
import org.junit.Assume._
import org.junit.experimental.categories.Category
import java.io.File
import java.nio.file._
import java.util.stream.{ Stream => JStream }
import scala.jdk.CollectionConverters._
import scala.util.matching.Regex
import scala.concurrent.duration._
import TestSources.sources
import reporting.TestReporter
import vulpix._
import dotty.tools.dotc.config.ScalaSettings
class CompilationTests {
import ParallelTesting._
import TestConfiguration._
import CompilationTests._
import CompilationTest.aggregateTests
// Positive tests ------------------------------------------------------------
@Test def pos: Unit = {
implicit val testGroup: TestGroup = TestGroup("compilePos")
var tests = List(
compileFilesInDir("tests/pos", defaultOptions.and("-Wsafe-init", "-Wunused:all", "-Wshadow:private-shadow", "-Wshadow:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos", defaultOptions.and("-Wsafe-init"), FileFilter.exclude(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
compileFilesInDir("tests/pos-special/sourcepath/outer", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
compileFile("tests/pos-special/sourcepath/outer/nested/Test4.scala", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
compileFilesInDir("tests/pos-scala2", defaultOptions.and("-source", "3.0-migration")),
compileFile("tests/pos-special/utf8encoded.scala", defaultOptions.and("-encoding", "UTF8")),
compileFile("tests/pos-special/utf16encoded.scala", defaultOptions.and("-encoding", "UTF16")),
compileDir("tests/pos-special/i18589", defaultOptions.and("-Wsafe-init").without("-Ycheck:all")),
// Run tests for legacy lazy vals
compileFilesInDir("tests/pos", defaultOptions.and("-Wsafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)),
compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")),
) ::: (
// TODO create a folder for capture checking tests with the stdlib, or use tests/pos-custom-args/captures under this mode?
if Properties.usingScalaLibraryCCTasty then List(compileDir("tests/pos-special/stdlib", allowDeepSubtypes))
else Nil
)
if scala.util.Properties.isJavaAtLeast("16") then
tests ::= compileFilesInDir("tests/pos-java16+", defaultOptions.and("-Wsafe-init"))
aggregateTests(tests*).checkCompile()
}
@Test def posCC: Unit =
given TestGroup = TestGroup("compilePosCC")
aggregateTests(
compileFilesInDir("tests/pos-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking")),
).checkCompile()
@Test def rewrites: Unit = {
implicit val testGroup: TestGroup = TestGroup("rewrites")
aggregateTests(
compileFile("tests/rewrites/rewrites.scala", defaultOptions.and("-source", "3.0-migration").and("-rewrite", "-indent")),
compileFile("tests/rewrites/rewrites3x.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/rewrites3x-fatal-warnings.scala", defaultOptions.and("-rewrite", "-source", "future-migration", "-Xfatal-warnings")),
compileFile("tests/rewrites/i21394.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/uninitialized-var.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/with-type-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/private-this.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/alphanumeric-infix-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")),
compileFile("tests/rewrites/filtering-fors.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")),
compileFile("tests/rewrites/refutable-pattern-bindings.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")),
compileFile("tests/rewrites/i8982.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/i9632.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/i11895.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/i12340.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i17187.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i17399.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i20002.scala", defaultOptions.and("-indent", "-rewrite")),
compileDir("tests/rewrites/annotation-named-pararamters", defaultOptions.and("-rewrite", "-source:3.6-migration")),
compileFile("tests/rewrites/i21418.scala", unindentOptions.and("-rewrite", "-source:3.5-migration")),
compileFile("tests/rewrites/infix-named-args.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")),
compileFile("tests/rewrites/ambiguous-named-tuple-assignment.scala", defaultOptions.and("-rewrite", "-source:3.6-migration")),
compileFile("tests/rewrites/i21382.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/unused.scala", defaultOptions.and("-rewrite", "-Wunused:all")),
compileFile("tests/rewrites/i22440.scala", defaultOptions.and("-rewrite")),
compileFile("tests/rewrites/i22792.scala", defaultOptions.and("-rewrite")),
).checkRewrites()
}
@Test def posTwice: Unit = {
implicit val testGroup: TestGroup = TestGroup("posTwice")
aggregateTests(
compileFilesInDir("tests/pos-java-interop", defaultOptions),
compileFilesInDir("tests/pos-java-interop-separate", defaultOptions),
compileFile("tests/pos/t2168.scala", defaultOptions),
compileFile("tests/pos/test-erasure.scala", defaultOptions),
compileFile("tests/pos/Coder.scala", defaultOptions),
compileFile("tests/pos/blockescapes.scala", defaultOptions),
compileFile("tests/pos/functions1.scala", defaultOptions),
compileFile("tests/pos/test-implicits1.scala", defaultOptions),
compileFile("tests/pos/inferred.scala", defaultOptions),
compileFile("tests/pos/selftypes.scala", defaultOptions),
compileFile("tests/pos/varargs.scala", defaultOptions),
compileFile("tests/pos/vararg-pattern.scala", defaultOptions),
compileFile("tests/pos/opassign.scala", defaultOptions),
compileFile("tests/pos/typedapply.scala", defaultOptions),
compileFile("tests/pos/nameddefaults.scala", defaultOptions),
compileFile("tests/pos/test-desugar.scala", defaultOptions),
compileFile("tests/pos/sigs.scala", defaultOptions),
compileFile("tests/pos/test-typers.scala", defaultOptions),
compileDir("tests/pos/typedIdents", defaultOptions),
compileFile("tests/pos/assignments.scala", defaultOptions),
compileFile("tests/pos/packageobject.scala", defaultOptions),
compileFile("tests/pos/overloaded.scala", defaultOptions),
compileFile("tests/pos/overrides.scala", defaultOptions),
compileDir("tests/pos/java-override", defaultOptions),
compileFile("tests/pos/templateParents.scala", defaultOptions),
compileFile("tests/pos/overloadedAccess.scala", defaultOptions),
compileFile("tests/pos/approximateUnion.scala", defaultOptions),
compileFilesInDir("tests/pos/tailcall", defaultOptions),
compileShallowFilesInDir("tests/pos/pos_valueclasses", defaultOptions),
compileFile("tests/pos/subtyping.scala", defaultOptions),
compileFile("tests/pos/i0239.scala", defaultOptions),
compileFile("tests/pos/anonClassSubtyping.scala", defaultOptions),
compileFile("tests/pos/extmethods.scala", defaultOptions),
compileFile("tests/pos/companions.scala", defaultOptions),
compileFile("tests/pos/main.scala", defaultOptions)
).times(2).checkCompile()
}
// Warning tests ------------------------------------------------------------
@Test def warn: Unit = {
implicit val testGroup: TestGroup = TestGroup("compileWarn")
aggregateTests(
compileFilesInDir("tests/warn", defaultOptions),
).checkWarnings()
}
// Negative tests ------------------------------------------------------------
@Test def negAll: Unit = {
implicit val testGroup: TestGroup = TestGroup("compileNeg")
aggregateTests(
compileFilesInDir("tests/neg", defaultOptions, FileFilter.exclude(TestSources.negScala2LibraryTastyExcludelisted)),
compileFilesInDir("tests/neg-deep-subtype", allowDeepSubtypes),
compileFilesInDir("tests/neg-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking")),
compileFile("tests/neg-custom-args/sourcepath/outer/nested/Test1.scala", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath")),
compileDir("tests/neg-custom-args/sourcepath2/hi", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath2", "-Xfatal-warnings")),
compileList("duplicate source", List(
"tests/neg-custom-args/toplevel-samesource/S.scala",
"tests/neg-custom-args/toplevel-samesource/nested/S.scala"),
defaultOptions),
compileFile("tests/neg/i7575.scala", defaultOptions.withoutLanguageFeatures),
).checkExpectedErrors()
}
@Test def fuzzyAll: Unit = {
implicit val testGroup: TestGroup = TestGroup("compileFuzzy")
compileFilesInDir("tests/fuzzy", defaultOptions).checkNoCrash()
}
// Run tests -----------------------------------------------------------------
@Test def runAll: Unit = {
implicit val testGroup: TestGroup = TestGroup("runAll")
aggregateTests(
compileFilesInDir("tests/run", defaultOptions.and("-Wsafe-init")),
compileFilesInDir("tests/run-deep-subtype", allowDeepSubtypes),
compileFilesInDir("tests/run-custom-args/captures", allowDeepSubtypes.and("-language:experimental.captureChecking")),
// Run tests for legacy lazy vals.
compileFilesInDir("tests/run", defaultOptions.and("-Wsafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.runLazyValsAllowlist)),
).checkRuns()
}
// Generic java signatures tests ---------------------------------------------
@Test def genericJavaSignatures: Unit = {
implicit val testGroup: TestGroup = TestGroup("genericJavaSignatures")
compileFilesInDir("tests/generic-java-signatures", defaultOptions).checkRuns()
}
// Pickling Tests ------------------------------------------------------------
@Test def pickling: Unit = {
implicit val testGroup: TestGroup = TestGroup("testPickling")
aggregateTests(
compileFilesInDir("tests/pos", picklingOptions, FileFilter.exclude(TestSources.posTestPicklingExcludelisted)),
compileFilesInDir("tests/run", picklingOptions, FileFilter.exclude(TestSources.runTestPicklingExcludelisted))
).checkCompile()
}
//@Test disabled in favor of posWithCompilerCC to save time.
def recheck: Unit =
given TestGroup = TestGroup("recheck")
aggregateTests(
compileFilesInDir("tests/run", defaultOptions.and("-Yrecheck-test"), FileFilter.exclude(TestSources.runTestRecheckExcluded))
//Disabled to save some time.
//compileFilesInDir("tests/pos", recheckOptions, FileFilter.exclude(TestSources.posTestRecheckExcluded)),
).checkCompile()
// Explicit nulls tests
@Test def explicitNullsNeg: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsNeg")
aggregateTests(
compileFilesInDir("tests/explicit-nulls/neg", explicitNullsOptions),
compileFilesInDir("tests/explicit-nulls/flexible-types-common", explicitNullsOptions and "-Yno-flexible-types"),
compileFilesInDir("tests/explicit-nulls/unsafe-common", explicitNullsOptions and "-Yno-flexible-types"),
)
}.checkExpectedErrors()
@Test def explicitNullsPos: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsPos")
aggregateTests(
compileFilesInDir("tests/explicit-nulls/pos", explicitNullsOptions),
compileFilesInDir("tests/explicit-nulls/flexible-types-common", explicitNullsOptions),
compileFilesInDir("tests/explicit-nulls/unsafe-common", explicitNullsOptions and "-language:unsafeNulls" and "-Yno-flexible-types"),
)
}.checkCompile()
@Test def explicitNullsWarn: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsWarn")
compileFilesInDir("tests/explicit-nulls/warn", explicitNullsOptions)
}.checkWarnings()
@Test def explicitNullsRun: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsRun")
compileFilesInDir("tests/explicit-nulls/run", explicitNullsOptions)
}.checkRuns()
// initialization tests
@Test def checkInitGlobal: Unit = {
implicit val testGroup: TestGroup = TestGroup("checkInitGlobal")
compileFilesInDir("tests/init-global/warn", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings()
compileFilesInDir("tests/init-global/pos", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile()
if Properties.usingScalaLibraryTasty && !Properties.usingScalaLibraryCCTasty then
compileFilesInDir("tests/init-global/warn-tasty", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyExcludelisted)).checkWarnings()
compileFilesInDir("tests/init-global/pos-tasty", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyExcludelisted)).checkCompile()
end if
}
// initialization tests
@Test def checkInit: Unit = {
implicit val testGroup: TestGroup = TestGroup("checkInit")
val options = defaultOptions.and("-Wsafe-init", "-Xfatal-warnings")
compileFilesInDir("tests/init/neg", options).checkExpectedErrors()
compileFilesInDir("tests/init/warn", defaultOptions.and("-Wsafe-init")).checkWarnings()
compileFilesInDir("tests/init/pos", options).checkCompile()
compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile()
// The regression test for i12128 has some atypical classpath requirements.
// The test consists of three files: (a) Reflect_1 (b) Macro_2 (c) Test_3
// which must be compiled separately. In addition:
// - the output from (a) must be on the classpath while compiling (b)
// - the output from (b) must be on the classpath while compiling (c)
// - the output from (a) _must not_ be on the classpath while compiling (c)
locally {
val i12128Group = TestGroup("checkInit/i12128")
val i12128Options = options.without("-Xfatal-warnings")
val outDir1 = defaultOutputDir + i12128Group + "/Reflect_1/i12128/Reflect_1"
val outDir2 = defaultOutputDir + i12128Group + "/Macro_2/i12128/Macro_2"
val tests = List(
compileFile("tests/init/special/i12128/Reflect_1.scala", i12128Options)(i12128Group),
compileFile("tests/init/special/i12128/Macro_2.scala", i12128Options.withClasspath(outDir1))(i12128Group),
compileFile("tests/init/special/i12128/Test_3.scala", options.withClasspath(outDir2))(i12128Group)
).map(_.keepOutput.checkCompile())
tests.foreach(_.delete())
}
/* This tests for errors in the program's TASTy trees.
* The test consists of three files: (a) v1/A, (b) v1/B, and (c) v0/A. (a) and (b) are
* compatible, but (b) and (c) are not. If (b) and (c) are compiled together, there should be
* an error when reading the files' TASTy trees. */
locally {
val tastyErrorGroup = TestGroup("checkInit/tasty-error")
val tastyErrorOptions = options.without("-Xfatal-warnings")
val a0Dir = defaultOutputDir + tastyErrorGroup + "/A/v0/A"
val a1Dir = defaultOutputDir + tastyErrorGroup + "/A/v1/A"
val b1Dir = defaultOutputDir + tastyErrorGroup + "/B/v1/B"
val tests = List(
compileFile("tests/init/tasty-error/v1/A.scala", tastyErrorOptions)(tastyErrorGroup),
compileFile("tests/init/tasty-error/v1/B.scala", tastyErrorOptions.withClasspath(a1Dir))(tastyErrorGroup),
compileFile("tests/init/tasty-error/v0/A.scala", tastyErrorOptions)(tastyErrorGroup),
).map(_.keepOutput.checkCompile())
compileFile("tests/init/tasty-error/Main.scala", tastyErrorOptions.withClasspath(a0Dir).withClasspath(b1Dir))(tastyErrorGroup).checkExpectedErrors()
tests.foreach(_.delete())
}
}
// parallel backend tests
@Test def parallelBackend: Unit = {
given TestGroup = TestGroup("parallelBackend")
val parallelism = Runtime.getRuntime().availableProcessors().min(16)
assumeTrue("Not enough available processors to run parallel tests", parallelism > 1)
val options = defaultOptions.and(s"-Ybackend-parallelism:${parallelism}")
def parCompileDir(directory: String) = compileDir(directory, options)
// Compilation units containing more than 1 source file
aggregateTests(
parCompileDir("tests/pos/i10477"),
parCompileDir("tests/pos/i4758"),
parCompileDir("tests/pos/scala2traits"),
parCompileDir("tests/pos/class-gadt"),
parCompileDir("tests/pos/tailcall"),
parCompileDir("tests/pos/reference"),
parCompileDir("tests/pos/pos_valueclasses")
).checkCompile()
aggregateTests(
parCompileDir("tests/neg/package-implicit"),
parCompileDir("tests/neg/package-export")
).checkExpectedErrors()
aggregateTests(
parCompileDir("tests/run/decorators"),
parCompileDir("tests/run/generic")
).checkRuns()
}
}
object CompilationTests extends ParallelTesting {
// Test suite configuration --------------------------------------------------
def maxDuration = 45.seconds
def numberOfSlaves = Runtime.getRuntime().availableProcessors()
def safeMode = Properties.testsSafeMode
def isInteractive = SummaryReport.isInteractive
def testFilter = Properties.testsFilter
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
def failedTests = TestReporter.lastRunFailedTests
implicit val summaryReport: SummaryReporting = new SummaryReport
@AfterClass def tearDown(): Unit = {
super.cleanup()
summaryReport.echoSummary()
}
}