Adding ability to run (custom) tests.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2010-2011 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2010-2011 Sun Microsystems, Inc.
40 package org.netbeans.modules.jackpot30.cmdline;
42 import java.io.ByteArrayOutputStream;
44 import java.io.FileOutputStream;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.PrintStream;
49 import java.net.URISyntaxException;
51 import java.net.URLClassLoader;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.LinkedList;
55 import java.util.List;
56 import java.util.regex.Matcher;
57 import java.util.regex.Pattern;
58 import javax.tools.SimpleJavaFileObject;
59 import javax.tools.ToolProvider;
60 import org.junit.runner.Result;
61 import org.netbeans.api.java.source.TestUtilities;
62 import org.netbeans.junit.NbTestCase;
63 import org.openide.filesystems.FileUtil;
65 /**XXX: should also test error conditions
69 public class MainTest extends NbTestCase {
71 public MainTest(String name) {
75 public void testRunCompiler1() throws Exception {
78 "public class Test {\n" +
79 " private void test(java.util.Collection c) {\n" +
80 " boolean b = c.isEmpty();\n" +
89 "public class Test {\n" +
90 " private void test(java.util.Collection c) {\n" +
91 " boolean b = c.size() == 0;\n" +
97 "Usage of .size() == 0");
100 public void testDoNotApply() throws Exception {
103 "public class Test {\n" +
104 " private void test(java.util.Collection c) {\n" +
105 " boolean b1 = c.size() == 0;\n" +
106 "\tboolean b2 = c.size() == 0;\n" +
110 doRunCompiler(golden,
111 "${workdir}/src/test/Test.java:4: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
112 " boolean b1 = c.size() == 0;\n" +
114 "${workdir}/src/test/Test.java:5: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
115 "\tboolean b2 = c.size() == 0;\n" +
118 "src/test/Test.java",
120 "public class Test {\n" +
121 " private void test(java.util.Collection c) {\n" +
122 " boolean b1 = c.size() == 0;\n" +
123 "\tboolean b2 = c.size() == 0;\n" +
128 "Usage of .size() == 0",
132 public void testConfig() throws Exception {
135 "public class Test {\n" +
136 " private int test(String str) {\n" +
137 " if (\"a\" == str) {\n" +
139 " } else if (\"b\" == str) {\n" +
147 doRunCompiler(golden,
150 "src/test/Test.java",
152 "public class Test {\n" +
153 " private int test(String str) {\n" +
154 " if (\"a\" == str) {\n" +
156 " } else if (\"b\" == str) {\n" +
165 "Use switch over Strings where possible.",
167 "also-equals=false");
170 public void testValidSourceLevel() throws Exception {
173 "public class Test {\n" +
174 " private void test(java.util.Collection c) {\n" +
175 " boolean b = c.isEmpty();\n" +
179 doRunCompiler(golden,
182 "src/test/Test.java",
184 "public class Test {\n" +
185 " private void test(java.util.Collection c) {\n" +
186 " boolean b = c.size() == 0;\n" +
192 "Usage of .size() == 0",
197 public void testConfigurationFile() throws Exception {
200 "public class Test {\n" +
201 " private void test(java.util.Collection c) {\n" +
202 " boolean b = c.isEmpty();\n" +
206 doRunCompiler(golden,
209 "src/test/Test.java",
211 "public class Test {\n" +
212 " private void test(java.util.Collection c) {\n" +
213 " boolean b = c.size() == 0;\n" +
217 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
218 "<hints apply=\"true\">\n" +
220 " <org.netbeans.modules.java.hints.perf.SizeEqualsZero check.not.equals=\"false\" enabled=\"true\" hintSeverity=\"VERIFIER\"/>\n" +
225 "${workdir}/settings.xml",
230 public void testConfigurationFileCmdLineOverride() throws Exception {
233 "public class Test {\n" +
234 " private void test(java.util.Collection c) {\n" +
235 " boolean b = c.size() == 0;\n" +
239 doRunCompiler(golden,
240 "${workdir}/src/test/Test.java:4: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
241 " boolean b = c.size() == 0;\n" +
244 "src/test/Test.java",
246 "public class Test {\n" +
247 " private void test(java.util.Collection c) {\n" +
248 " boolean b = c.size() == 0;\n" +
252 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
253 "<hints apply=\"true\">\n" +
255 " <org.netbeans.modules.java.hints.perf.SizeEqualsZero check.not.equals=\"false\" enabled=\"true\" hintSeverity=\"VERIFIER\"/>\n" +
260 "${workdir}/settings.xml",
266 public void testHintFile() throws Exception {
269 "public class Test {\n" +
270 " private void test(java.util.Collection c) {\n" +
271 " boolean b = c.size() == 0;\n" +
275 doRunCompiler(golden,
278 "src/test/Test.java",
280 "public class Test {\n" +
281 " private void test(java.util.Collection c) {\n" +
282 " boolean b = c.isEmpty();\n" +
286 "$var.isEmpty() => $var.size() == 0;;",
289 "${workdir}/test-rule.hint",
295 public void testConfigurationFileDeclarative1() throws Exception {
298 "public class Test {\n" +
299 " private void test(java.util.Collection c) {\n" +
300 " boolean b1 = c.isEmpty();\n" +
301 " boolean b2 = c.size() <= 0;\n" +
305 doRunCompiler(golden,
308 "src/test/Test.java",
310 "public class Test {\n" +
311 " private void test(java.util.Collection c) {\n" +
312 " boolean b1 = c.size() == 0;\n" +
313 " boolean b2 = c.size() <= 0;\n" +
316 "META-INF/upgrade/test1.hint",
317 "$c.size() == 0 :: $c instanceof java.util.Collection => $c.isEmpty();;\n",
318 "META-INF/upgrade/test2.hint",
319 "$c.size() <= 0 :: $c instanceof java.util.Collection => $c.isEmpty();;\n",
321 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
322 "<hints apply=\"true\" runDeclarative=\"false\">\n" +
324 " <test1.hint enabled=\"true\"/>\n" +
329 "${workdir}/settings.xml",
334 public void testConfigurationFileDeclarative2() throws Exception {
337 "public class Test {\n" +
338 " private void test(java.util.Collection c) {\n" +
339 " boolean b1 = c.isEmpty();\n" +
340 " boolean b2 = c.isEmpty();\n" +
344 doRunCompiler(golden,
347 "src/test/Test.java",
349 "public class Test {\n" +
350 " private void test(java.util.Collection c) {\n" +
351 " boolean b1 = c.size() == 0;\n" +
352 " boolean b2 = c.size() <= 0;\n" +
355 "META-INF/upgrade/test1.hint",
356 "$c.size() == 0 :: $c instanceof java.util.Collection => $c.isEmpty();;\n",
357 "META-INF/upgrade/test2.hint",
358 "$c.size() <= 0 :: $c instanceof java.util.Collection => $c.isEmpty();;\n",
360 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
361 "<hints apply=\"true\" runDeclarative=\"true\">\n" +
363 " <test1.hint enabled=\"true\"/>\n" +
368 "${workdir}/settings.xml",
373 public void testSourcePath() throws Exception {
376 "public class Test {\n" +
377 " private void test() {\n" +
378 " String s = test2.Test2.C;\n" +
382 doRunCompiler(golden,
385 "src/test/Test.java",
387 "public class Test {\n" +
388 " private void test() {\n" +
389 " String s = test2.Test2.C.intern();\n" +
392 "src/test2/Test2.java",
394 "public class Test2 {\n" +
395 " public static final String C = \"a\";\n" +
401 "String.intern() called on constant",
404 "${workdir}/src/test");
407 public void testWarningsAreErrors() throws Exception {
410 "public class Test {\n" +
411 " private void test(java.util.Collection c) {\n" +
412 " boolean b1 = c.size() == 0;\n" +
413 "\tboolean b2 = c.size() == 0;\n" +
417 doRunCompiler(equivalentValidator(code),
419 "${workdir}/src/test/Test.java:4: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
420 " boolean b1 = c.size() == 0;\n" +
422 "${workdir}/src/test/Test.java:5: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
423 "\tboolean b2 = c.size() == 0;\n" +
426 equivalentValidator(null),
428 "src/test/Test.java",
432 "Usage of .size() == 0",
434 "--fail-on-warnings");
437 public void testGroups() throws Exception {
439 "${workdir}/src1/test/Test.java:4: warning: [test] test\n" +
440 " boolean b1 = c.size() == 0;\n" +
442 "${workdir}/src2/test/Test.java:5: warning: [test] test\n" +
443 " boolean b2 = c.size() != 0;\n" +
446 "cp1/META-INF/upgrade/test.hint",
447 "$coll.size() == 0 :: $coll instanceof java.util.Collection;;",
448 "src1/test/Test.java",
450 "public class Test {\n" +
451 " private void test(java.util.Collection c) {\n" +
452 " boolean b1 = c.size() == 0;\n" +
453 " boolean b2 = c.size() != 0;\n" +
456 "cp2/META-INF/upgrade/test.hint",
457 "$coll.size() != 0 :: $coll instanceof java.util.Collection;;",
458 "src2/test/Test.java",
460 "public class Test {\n" +
461 " private void test(java.util.Collection c) {\n" +
462 " boolean b1 = c.size() == 0;\n" +
463 " boolean b2 = c.size() != 0;\n" +
469 "--classpath ${workdir}/cp1 ${workdir}/src1",
471 "--classpath ${workdir}/cp2 ${workdir}/src2");
474 public void testGroupsList() throws Exception {
477 @Override public void validate(String content) {
478 assertTrue("Missing expected content, actual content: " + content, content.contains("test\n"));
482 "cp1/META-INF/upgrade/test.hint",
483 "$coll.size() == 0 :: $coll instanceof java.util.Collection;;",
484 "src1/test/Test.java",
486 "cp2/META-INF/upgrade/test.hint",
487 "$coll.size() != 0 :: $coll instanceof java.util.Collection;;",
488 "src2/test/Test.java",
493 "--classpath ${workdir}/cp1 ${workdir}/src1",
495 "--classpath ${workdir}/cp2 ${workdir}/src2",
499 public void testNoHintsFoundWithGroups() throws Exception {
500 doRunCompiler("package test;\n" +
501 "public class Test {\n" +
502 " private void test(java.util.Collection c) {\n" +
503 " boolean b1 = c.isEmpty();\n" +
504 " boolean b2 = c.size() != 0;\n" +
509 "cp/META-INF/upgrade/test.hint",
510 "$coll.size() == 0 :: $coll instanceof java.util.Collection\n" +
512 "$coll.isEmpty()\n" +
514 "src/test/Test.java",
516 "public class Test {\n" +
517 " private void test(java.util.Collection c) {\n" +
518 " boolean b1 = c.size() == 0;\n" +
519 " boolean b2 = c.size() != 0;\n" +
522 "src2/test/Test.java",
524 "public class Test {\n" +
525 " private void test(java.util.Collection c) {\n" +
526 " boolean b1 = c.size() == 0;\n" +
527 " boolean b2 = c.size() != 0;\n" +
533 "--classpath ${workdir}/cp ${workdir}/src",
539 public void testAutomaticTestRun() throws Exception {
541 private final String commandLineOption;
542 private final int result;
543 private final Validator validator;
545 public Config(String commandLineOption, int result, Validator validator) {
546 this.commandLineOption = commandLineOption;
547 this.result = result;
548 this.validator = validator;
552 Validator testValidator =
553 equivalentValidator("${workdir}/src/META-INF/upgrade/test.test:15: error: [test_failure] Actual results did not match the expected test results. Actual results: []\n" +
554 "%%TestCase pos-neg\n" +
556 "${workdir}/src/META-INF/upgrade/test.test:29: error: [test_failure] Actual results did not match the expected test results. Actual results: [package test;\n" +
557 "public class Test {{\n" +
558 " private void test(java.util.Collection c) {\n" +
559 " boolean b1 = c.isEmpty();\n" +
563 "%%TestCase neg-neg\n" +
565 "${workdir}/src/test/Test.java:4: warning: [test] test\n" +
566 " boolean b1 = c.size() == 0;\n" +
568 List<? extends Config> options =
569 Arrays.asList(new Config("--run-tests", 1, testValidator),
570 new Config(IGNORE, 0, equivalentValidator("${workdir}/src/test/Test.java:4: warning: [test] test\n" +
571 " boolean b1 = c.size() == 0;\n" +
573 for (Config testConfig : options) {
574 doRunCompiler(equivalentValidator("package test;\n" +
575 "public class Test {\n" +
576 " private void test(java.util.Collection c) {\n" +
577 " boolean b1 = c.size() == 0;\n" +
578 " boolean b2 = c.size() != 0;\n" +
581 testConfig.validator,
582 equivalentValidator(""),
584 "src/META-INF/upgrade/test.hint",
585 "$coll.size() == 0 :: $coll instanceof java.util.Collection\n" +
587 "$coll.isEmpty()\n" +
589 "src/META-INF/upgrade/test.test",
590 "%%TestCase pos-pos\n" +
592 "public class Test {{\n" +
593 " private void test(java.util.Collection c) {\n" +
594 " boolean b1 = c.size() == 0;\n" +
599 "public class Test {{\n" +
600 " private void test(java.util.Collection c) {\n" +
601 " boolean b1 = c.isEmpty();\n" +
604 "%%TestCase pos-neg\n" +
606 "public class Test {{\n" +
607 " private void test(java.util.Collection c) {\n" +
608 " boolean b1 = c.size() == 0;\n" +
611 "%%TestCase neg-pos\n" +
613 "public class Test {{\n" +
614 " private void test(java.util.Collection c) {\n" +
615 " boolean b1 = c.size() != 0;\n" +
618 "%%TestCase neg-neg\n" +
620 "public class Test {{\n" +
621 " private void test(java.util.Collection c) {\n" +
622 " boolean b1 = c.size() != 0;\n" +
627 "public class Test {{\n" +
628 " private void test(java.util.Collection c) {\n" +
629 " boolean b1 = c.isEmpty();\n" +
632 "src/test/Test.java",
634 "public class Test {\n" +
635 " private void test(java.util.Collection c) {\n" +
636 " boolean b1 = c.size() == 0;\n" +
637 " boolean b2 = c.size() != 0;\n" +
641 testConfig.commandLineOption,
642 "--sourcepath", "${workdir}/src");
646 public void testGroupsParamEscape() throws Exception {
647 assertEquals(Arrays.asList("a b", "a\\b"),
648 Arrays.asList(Main.splitGroupArg("a\\ b a\\\\b")));
651 private static final String DONT_APPEND_PATH = new String("DONT_APPEND_PATH");
652 private static final String IGNORE = new String("IGNORE");
654 private void doRunCompiler(String golden, String stdOut, String stdErr, String... fileContentAndExtraOptions) throws Exception {
655 doRunCompiler(equivalentValidator(golden), equivalentValidator(stdOut), equivalentValidator(stdErr), fileContentAndExtraOptions);
658 private void doRunCompiler(Validator fileContentValidator, Validator stdOutValidator, Validator stdErrValidator, String... fileContentAndExtraOptions) throws Exception {
659 doRunCompiler(fileContentValidator, stdOutValidator, stdErrValidator, 0, fileContentAndExtraOptions);
662 private void doRunCompiler(Validator fileContentValidator, Validator stdOutValidator, Validator stdErrValidator, int exitcode, String... fileContentAndExtraOptions) throws Exception {
663 List<String> fileAndContent = new LinkedList<String>();
664 List<String> extraOptions = new LinkedList<String>();
665 List<String> fileContentAndExtraOptionsList = Arrays.asList(fileContentAndExtraOptions);
666 int nullPos = fileContentAndExtraOptionsList.indexOf(null);
668 if (nullPos == (-1)) {
669 fileAndContent = fileContentAndExtraOptionsList;
670 extraOptions = Collections.emptyList();
672 fileAndContent = fileContentAndExtraOptionsList.subList(0, nullPos);
673 extraOptions = fileContentAndExtraOptionsList.subList(nullPos + 1, fileContentAndExtraOptionsList.size());
676 assertTrue(fileAndContent.size() % 2 == 0);
680 for (int cntr = 0; cntr < fileAndContent.size(); cntr += 2) {
681 File target = new File(getWorkDir(), fileAndContent.get(cntr));
683 target.getParentFile().mkdirs();
685 TestUtilities.copyStringToFile(target, fileAndContent.get(cntr + 1));
688 File wd = getWorkDir();
689 File source = new File(wd, "src/test/Test.java");
691 List<String> options = new LinkedList<String>();
692 boolean appendPath = true;
694 options.add("--cache");
695 options.add("/tmp/cachex");
696 for (String extraOption : extraOptions) {
697 if (extraOption == DONT_APPEND_PATH) {
701 if (extraOption == IGNORE) {
704 options.add(extraOption.replace("${workdir}", wd.getAbsolutePath()));
708 options.add(wd.getAbsolutePath());
710 String[] output = new String[2];
712 reallyRunCompiler(wd, exitcode, output, options.toArray(new String[0]));
714 if (fileContentValidator != null) {
715 fileContentValidator.validate(TestUtilities.copyFileToString(source));
717 if (stdOutValidator != null) {
718 stdOutValidator.validate(output[0].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
720 if (stdErrValidator != null) {
721 stdErrValidator.validate(output[1].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
725 protected void reallyRunCompiler(File workDir, int exitcode, String[] output, String... params) throws Exception {
726 String oldUserDir = System.getProperty("user.dir");
728 System.setProperty("user.dir", workDir.getAbsolutePath());
730 PrintStream oldOut = System.out;
731 ByteArrayOutputStream outData = new ByteArrayOutputStream();
732 System.setOut(new PrintStream(outData, true, "UTF-8"));
734 PrintStream oldErr = System.err;
735 ByteArrayOutputStream errData = new ByteArrayOutputStream();
736 System.setErr(new PrintStream(errData, true, "UTF-8"));
739 assertEquals(exitcode, Main.compile(params));
741 System.setProperty("user.dir", oldUserDir);
743 output[0] = new String(outData.toByteArray(), "UTF-8");
744 System.setOut(oldOut);
746 output[1] = new String(errData.toByteArray(), "UTF-8");
747 System.setErr(oldErr);
751 //verify that the DeclarativeHintsTestBase works:
752 private static final String CODE_RUN_DECLARATIVE =
753 "package org.netbeans.modules.jackpot30.cmdline.testtool;\n" +
755 "import junit.framework.TestSuite;\n" +
756 "import org.netbeans.modules.java.hints.declarative.test.api.DeclarativeHintsTestBase;\n" +
758 "public class DoRunTests extends DeclarativeHintsTestBase {\n" +
760 " public static TestSuite suite() {\n" +
761 " return suite(DoRunTests.class);\n" +
765 public void testRunTest() throws Exception {
768 File wd = getWorkDir();
769 File classes = new File(wd, "classes");
772 TestUtilities.copyStringToFile(new File(classes, "h.hint"), "$1.equals(\"\") :: $1 instanceof java.lang.String => $1.isEmpty();;");
774 String test = "%%TestCase pos\n" +
776 "public class Test {{\n" +
777 " System.err.println(\"a\".equals(\"\"));\n" +
781 "public class Test {{\n" +
782 " System.err.println(\"a\".isEmpty());\n" +
786 "public class Test {{\n" +
787 " System.err.println(\"a\".equals(\"a\"));\n" +
791 "public class Test {{\n" +
792 " System.err.println(\"a\".isEmpty());\n" +
794 TestUtilities.copyStringToFile(new File(classes, "h.test"), test);
796 List<String> options = Arrays.asList("-d", classes.getAbsolutePath());
797 List<SourceFO> files = Arrays.asList(new SourceFO("DoRunTests.java", CODE_RUN_DECLARATIVE));
799 assertTrue(ToolProvider.getSystemJavaCompiler().getTask(null, null, null, options, null, files).call());
804 private static final class SourceFO extends SimpleJavaFileObject {
806 private final String code;
807 private SourceFO(String name, String code) throws URISyntaxException {
808 super(new URI("mem:///" + name), Kind.SOURCE);
813 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
819 protected void runAndTest(File classes) throws Exception {
820 ClassLoader cl = new URLClassLoader(new URL[] {classes.toURI().toURL()}, MainTest.class.getClassLoader());
821 Class<?> doRunTests = Class.forName("org.netbeans.modules.jackpot30.cmdline.testtool.DoRunTests", true, cl);
822 Result testResult = org.junit.runner.JUnitCore.runClasses(doRunTests);
824 assertEquals(1, testResult.getFailureCount());
825 assertTrue(testResult.getFailures().toString(), testResult.getFailures().get(0).getDescription().getMethodName().endsWith("/h.test/neg"));
828 private static Validator equivalentValidator(final String expected) {
829 if (expected == null) return null;
831 return new Validator() {
832 @Override public void validate(String content) {
833 assertEquals(expected, content);
838 private static interface Validator {
839 public void validate(String content);