/* * 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 com.google.devtools.treeshaker; import com.google.common.base.Joiner; import com.google.common.io.Files; import com.google.devtools.j2objc.util.CodeReferenceMap; import com.google.devtools.j2objc.util.CodeReferenceMap.Builder; import com.google.devtools.j2objc.util.ErrorUtil; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; /** * System tests for the TreeShaker tool. * * @author Priyank Malvania */ public class TreeShakerTest extends TestCase { File tempDir; List<String> inputFiles; static { // Prevents errors and warnings from being printed to the console. ErrorUtil.setTestMode(); } @Override protected void setUp() throws IOException { tempDir = createTempDir(); inputFiles = new ArrayList<>(); } @Override protected void tearDown() { ErrorUtil.reset(); } private CodeReferenceMap getUnusedCode() throws IOException { return getUnusedCode(null); } private CodeReferenceMap getUnusedCode(CodeReferenceMap rootSetMap) throws IOException { Options options = new Options(); options.setSourceFiles(inputFiles); options.setClasspath(System.getProperty("java.class.path")); TreeShaker shaker = new TreeShaker(options); CodeReferenceMap map = shaker.getUnusedCode(rootSetMap); if (ErrorUtil.errorCount() > 0) { fail("TreeShaker failed with errors:\n" + Joiner.on("\n").join(ErrorUtil.getErrorMessages())); } return map; } public void testUnusedCodeAcrossFiles() throws IOException { addSourceFile("A.java", "class A { static { launch(); }\n" + "public static void launch() { new B().abc(\"zoo\"); } }"); addSourceFile("B.java", "class B { public void abc(String s) {} }"); addSourceFile("C.java", "class C { public void xyz(String s) {} }"); CodeReferenceMap unusedCodeMap = getUnusedCode(); assertFalse(unusedCodeMap.containsClass("A")); assertFalse(unusedCodeMap.containsClass("B")); assertFalse(unusedCodeMap.containsMethod("B", "abc", "(Ljava/lang/String;)V")); assertTrue(unusedCodeMap.containsClass("C")); assertTrue(unusedCodeMap.containsMethod("C", "xyz", "(Ljava/lang/String;)V")); } public void testNoPublicRootSet() throws IOException { addSourceFile("A.java", "class A { public void launch() { new B().abc(\"zoo\"); } }"); addSourceFile("B.java", "class B { public void abc(String s) {} }"); addSourceFile("C.java", "class C { public void xyz(String s) {} }"); CodeReferenceMap unusedCodeMap = getUnusedCode(); assertTrue(unusedCodeMap.containsClass("A")); assertTrue(unusedCodeMap.containsClass("B")); assertTrue(unusedCodeMap.containsMethod("B", "abc", "(Ljava/lang/String;)V")); assertTrue(unusedCodeMap.containsClass("C")); assertTrue(unusedCodeMap.containsMethod("C", "xyz", "(Ljava/lang/String;)V")); } public void testWithPublicRootSet() throws IOException { addSourceFile("A.java", "class A { public void launch() { new B().abc(\"zoo\"); } }"); addSourceFile("B.java", "class B { public void abc(String s) {} }"); addSourceFile("C.java", "class C { public void xyz(String s) {} }"); CodeReferenceMap rootSet = new Builder().addClass("A").build(); CodeReferenceMap unusedCodeMap = getUnusedCode(rootSet); assertFalse(unusedCodeMap.containsClass("A")); assertFalse(unusedCodeMap.containsClass("B")); assertFalse(unusedCodeMap.containsMethod("B", "abc", "(Ljava/lang/String;)V")); assertTrue(unusedCodeMap.containsClass("C")); assertTrue(unusedCodeMap.containsMethod("C", "xyz", "(Ljava/lang/String;)V")); } private void addSourceFile(String fileName, String source) throws IOException { File file = new File(tempDir, fileName); file.getParentFile().mkdirs(); Files.write(source, file, Charset.defaultCharset()); inputFiles.add(file.getAbsolutePath()); } private File createTempDir() throws IOException { File tempDir = File.createTempFile("treeshaker_testout", ""); tempDir.delete(); tempDir.mkdir(); return tempDir; } }