diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 4a241bc2c08..099549f0726 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -144,6 +144,7 @@ import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.jps.build.* import org.jetbrains.kotlin.jps.build.android.AbstractAndroidJpsTestCase import org.jetbrains.kotlin.jps.incremental.AbstractProtoComparisonTest +import org.jetbrains.kotlin.js.test.AbstractDceTest import org.jetbrains.kotlin.js.test.semantics.* import org.jetbrains.kotlin.jvm.compiler.* import org.jetbrains.kotlin.jvm.runtime.AbstractJvm8RuntimeDescriptorLoaderTest @@ -1351,6 +1352,10 @@ fun main(args: Array) { testClass { model("outputPrefixPostfix/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS) } + + testClass { + model("dce/", pattern = "(.+)\\.js", targetBackend = TargetBackend.JS) + } } testGroup("js/js.tests/test", "compiler/testData") { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractDceTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractDceTest.kt new file mode 100644 index 00000000000..778dec3210b --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractDceTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test + +import junit.framework.TestCase +import org.jetbrains.kotlin.js.dce.DeadCodeElimination +import org.jetbrains.kotlin.js.dce.InputFile +import java.io.File + +abstract class AbstractDceTest : TestCase() { + fun doTest(filePath: String) { + val file = File(filePath) + val fileContents = file.readText() + val inputFile = InputFile(filePath, File(pathToOutputDir, file.relativeTo(File(pathToTestDir)).path).path, "main") + val dceResult = DeadCodeElimination.run(setOf(inputFile), extractDeclarations(REQUEST_REACHABLE_PATTERN, fileContents)) {} + val reachableNodeStrings = dceResult.reachableNodes.map { it.toString().removePrefix(".") }.toSet() + + for (assertedDeclaration in extractDeclarations(ASSERT_REACHABLE_PATTERN, fileContents)) { + TestCase.assertTrue("Declaration $assertedDeclaration not reached", assertedDeclaration in reachableNodeStrings) + } + for (assertedDeclaration in extractDeclarations(ASSERT_UNREACHABLE_PATTERN, fileContents)) { + TestCase.assertTrue("Declaration $assertedDeclaration reached", assertedDeclaration !in reachableNodeStrings) + } + } + + private fun extractDeclarations(regex: Regex, fileContents: String): Set = + regex.findAll(fileContents).map { it.groupValues[1] }.toSet() + + companion object { + private val ASSERT_REACHABLE_PATTERN = Regex("^ *// *ASSERT_REACHABLE: (.+) *$", RegexOption.MULTILINE) + private val ASSERT_UNREACHABLE_PATTERN = Regex("^ *// *ASSERT_UNREACHABLE: (.+) *$", RegexOption.MULTILINE) + private val REQUEST_REACHABLE_PATTERN = Regex("^ *// *REQUEST_REACHABLE: (.+) *$", RegexOption.MULTILINE) + + private val pathToTestDir = "js/js.translator/testData/dce" + private val pathToOutputDir = "js/js.translator/testData/out/dce" + } +} \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/DceTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/DceTestGenerated.java new file mode 100644 index 00000000000..7f36ea54e35 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/DceTestGenerated.java @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("js/js.translator/testData/dce") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class DceTestGenerated extends AbstractDceTest { + public void testAllFilesPresentInDce() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/dce"), Pattern.compile("(.+)\\.js"), TargetBackend.JS, true); + } + + @TestMetadata("amd.js") + public void testAmd() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/dce/amd.js"); + doTest(fileName); + } + + @TestMetadata("commonjs.js") + public void testCommonjs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/dce/commonjs.js"); + doTest(fileName); + } + + @TestMetadata("cycle.js") + public void testCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/dce/cycle.js"); + doTest(fileName); + } +} diff --git a/js/js.translator/testData/dce/amd.js b/js/js.translator/testData/dce/amd.js new file mode 100644 index 00000000000..4c1b295fb70 --- /dev/null +++ b/js/js.translator/testData/dce/amd.js @@ -0,0 +1,19 @@ +define(['exports'], function (exports) { + function foo() { + } + function bar() { + } + function ignore() { + } + + bar(); + + exports.foo = foo; + exports.bar = bar; + exports.ignore = ignore; +}); + +// REQUEST_REACHABLE: main.foo +// ASSERT_REACHABLE: main.foo +// ASSERT_REACHABLE: main.bar +// ASSERT_UNREACHABLE: main.ignore \ No newline at end of file diff --git a/js/js.translator/testData/dce/commonjs.js b/js/js.translator/testData/dce/commonjs.js new file mode 100644 index 00000000000..49af27fe29c --- /dev/null +++ b/js/js.translator/testData/dce/commonjs.js @@ -0,0 +1,17 @@ +function foo() { +} +function bar() { +} +function ignore() { +} + +bar(); + +module.exports.foo = foo; +module.exports.bar = bar; +module.exports.ignore = ignore; + +// REQUEST_REACHABLE: main.foo +// ASSERT_REACHABLE: main.bar +// ASSERT_REACHABLE: main.foo +// ASSERT_UNREACHABLE: main.ignore \ No newline at end of file diff --git a/js/js.translator/testData/dce/cycle.js b/js/js.translator/testData/dce/cycle.js new file mode 100644 index 00000000000..f42ab73e5f0 --- /dev/null +++ b/js/js.translator/testData/dce/cycle.js @@ -0,0 +1,4 @@ +function A() { +} +A.prototype = Object.create(A); +A.prototype.constructor = A;