com.puppycrawl.tools.checkstyle.MainTest.java Source code

Java tutorial

Introduction

Here is the source code for com.puppycrawl.tools.checkstyle.MainTest.java

Source

////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2015 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import static com.puppycrawl.tools.checkstyle.TestUtils.assertUtilsClassHasPrivateConstructor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.Assertion;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import org.junit.contrib.java.lang.system.SystemErrRule;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.rules.TemporaryFolder;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;

public class MainTest {
    @Rule
    public final TemporaryFolder temporaryFolder = new TemporaryFolder();
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();
    @Rule
    public final SystemErrRule systemErr = new SystemErrRule().enableLog().mute();
    @Rule
    public final SystemOutRule systemOut = new SystemOutRule().enableLog().mute();

    @Test
    public void testIsProperUtilsClass() throws ReflectiveOperationException {
        assertUtilsClassHasPrivateConstructor(Main.class);
    }

    @Test
    public void testVersionPrint() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("Checkstyle version: null" + System.lineSeparator(), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-v");
    }

    @Test
    public void testWrongArgument() throws Exception {
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                String usage = String.format(Locale.ROOT, "Unrecognized option: -w%n"
                        + "usage: java com.puppycrawl.tools.checkstyle.Main [options] -c <config.xml>%n"
                        + "            file...%n" + " -c <arg>   Sets the check configuration file to use.%n"
                        + " -f <arg>   Sets the output format. (plain|xml). Defaults to plain%n"
                        + " -o <arg>   Sets the output file. Defaults to stdout%n"
                        + " -p <arg>   Loads the properties file%n"
                        + " -v         Print product version and exit%n");

                assertEquals(usage, systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-w");
    }

    @Test
    public void testNoConfigSpecified() throws Exception {
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("Must specify a config XML file." + System.lineSeparator(), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testNonExistingTargetFile() throws Exception {
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("Must specify files to process, found 0." + System.lineSeparator(),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "/google_checks.xml", "NonExistingFile.java");
    }

    @Test
    public void testNonExistingConfigFile() throws Exception {
        exit.expectSystemExitWithStatus(-2);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(
                        String.format(Locale.ROOT, "Unable to find: src/main/resources/non_existing_config.xml%n"
                                + "Checkstyle ends with 1 errors.%n"),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/main/resources/non_existing_config.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testNonExistingOutputFormat() throws Exception {
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(
                        String.format(Locale.ROOT,
                                "Invalid output format. " + "Found 'xmlp' but expected 'plain' or 'xml'.%n"),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "/google_checks.xml", "-f", "xmlp",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testNonExistingClass() throws Exception {
        exit.expectSystemExitWithStatus(-2);
        final String cause = "Unable to instantiate 'NonExistingClass' class,"
                + " it is also not possible to instantiate it as"
                + " com.puppycrawl.tools.checkstyle.checks.annotation.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.blocks.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.coding.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.design.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.header.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.imports.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.indentation.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.javadoc.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.metrics.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.modifier.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.naming.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.regexp.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.sizes.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.whitespace.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.checks.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.filters.NonExistingClass,"
                + " com.puppycrawl.tools.checkstyle.NonExistingClass."
                + " Please recheck that class name is specified as canonical name or read"
                + " how to configure short name usage http://checkstyle.sourceforge.net/config.html#Packages."
                + " Please also recheck that provided ClassLoader to Checker is configured correctly.";
        final String expectedExceptionMessage = String.format(Locale.ROOT,
                "cannot initialize module TreeWalker - %1$s%n"
                        + "Cause: com.puppycrawl.tools.checkstyle.api.CheckstyleException: %1$s%n"
                        + "Checkstyle ends with 1 errors.%n",
                cause);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(expectedExceptionMessage, systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });

        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-non-existing-classname.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFile() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(String.format(Locale.ROOT, "Starting audit...%n" + "Audit done.%n"),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFileXmlOutput() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                String currentPath = new File(".").getCanonicalPath();
                String expectedPath = currentPath
                        + "/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java".replace("/",
                                File.separator);
                final ResourceBundle compilationProperties = ResourceBundle.getBundle("checkstylecompilation");
                String version = compilationProperties.getString("checkstyle.compile.version");
                assertEquals(String.format(Locale.ROOT,
                        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n" + "<checkstyle version=\"%s\">%n"
                                + "<file name=\"%s\">%n" + "</file>%n" + "</checkstyle>%n",
                        version, expectedPath), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutput() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(String.format(Locale.ROOT, "Starting audit...%n" + "Audit done.%n"),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "plain",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFileWithViolations() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                String currentPath = new File(".").getCanonicalPath();
                String expectedPath = currentPath
                        + "/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java".replace("/",
                                File.separator);
                assertEquals(String.format(Locale.ROOT, "Starting audit...%n" + "%1$s:3:14: "
                        + "warning: Name 'InputMain' must match pattern '^[a-z0-9]*$'.%n" + "%1$s:5:7: "
                        + "warning: Name 'InputMainInner' must match pattern '^[a-z0-9]*$'.%n" + "Audit done.%n",
                        expectedPath), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname2.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFileWithError() throws Exception {
        exit.expectSystemExitWithStatus(2);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                String currentPath = new File(".").getCanonicalPath();
                String expectedPath = currentPath
                        + "/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java".replace("/",
                                File.separator);
                assertEquals(String.format(Locale.ROOT,
                        "Starting audit...%n" + "%1$s:3:14: error: "
                                + "Name 'InputMain' must match pattern '^[a-z0-9]*$'.%n" + "%1$s:5:7: error: "
                                + "Name 'InputMainInner' must match pattern '^[a-z0-9]*$'.%n" + "Audit done.%n"
                                + "Checkstyle ends with 2 errors.%n",
                        expectedPath), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname2-error.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutputToNonExistingFile() throws Exception {

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("", systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "plain",
                "-o", temporaryFolder.getRoot() + "/output.txt",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutputToFile() throws Exception {
        final File file = temporaryFolder.newFile("file.output");
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("", systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "plain",
                "-o", file.getCanonicalPath(), "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutputToFileWithoutRwPermissions() throws Exception {
        final File file = temporaryFolder.newFile("file.output");
        assertTrue(file.setReadable(true, true));
        assertTrue(file.setWritable(false, false));
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                assertEquals("Permission denied : '" + file.getCanonicalPath() + "'." + System.lineSeparator(),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "plain",
                "-o", file.getCanonicalPath(), "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingFilePlainOutputToFileWithoutReadAndRwPermissions() throws Exception {
        final File file = temporaryFolder.newFile("file.output");
        // That works fine on Linux/Unix, but ....
        // It's not possible to make a file unreadable in Windows NTFS for owner.
        // http://stackoverflow.com/a/4354686
        // https://github.com/google/google-oauth-java-client/issues/55#issuecomment-69403681
        //assertTrue(file.setReadable(false, false));
        assertTrue(file.setWritable(false, false));
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                assertEquals("Permission denied : '" + file.getCanonicalPath() + "'." + System.lineSeparator(),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-classname.xml", "-f", "plain",
                "-o", file.getCanonicalPath(), "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutputProperties() throws Exception {
        //exit.expectSystemExitWithStatus(0);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals(String.format(Locale.ROOT, "Starting audit...%n" + "Audit done.%n"),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/" + "config-classname-prop.xml", "-p",
                "src/test/resources/com/puppycrawl/tools/checkstyle/mycheckstyle.properties",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingTargetFilePlainOutputNonexistingProperties() throws Exception {
        exit.expectSystemExitWithStatus(-1);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertEquals("Could not find file 'nonexisting.properties'." + System.lineSeparator(),
                        systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/" + "config-classname-prop.xml", "-p",
                "nonexisting.properties", "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testExistingIncorrectConfigFile() throws Exception {
        exit.expectSystemExitWithStatus(-2);
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() {
                assertTrue(systemOut.getLog()
                        .startsWith(String.format(Locale.ROOT,
                                "unable to parse configuration stream - Content is not allowed in prolog.:7:1%n"
                                        + "Cause: org.xml.sax.SAXParseException; systemId: file:")));
                assertTrue(systemOut.getLog().endsWith(String.format(Locale.ROOT,
                        "com/puppycrawl/tools/checkstyle/config-Incorrect.xml; lineNumber: 7; columnNumber: 1; "
                                + "Content is not allowed in prolog.%n" + "Checkstyle ends with 1 errors.%n")));
                assertEquals("", systemErr.getLog());
            }
        });
        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/" + "config-Incorrect.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java");
    }

    @Test
    public void testLoadPropertiesIOException() throws Exception {
        Class<?>[] param = new Class<?>[1];
        param[0] = File.class;
        Method method = Main.class.getDeclaredMethod("loadProperties", param);
        method.setAccessible(true);
        try {
            if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows")) {
                // https://support.microsoft.com/en-us/kb/177506 but this only for NTFS
                // WindowsServer 2012 use Resilient File System (ReFS), so any name is ok
                File file = new File(File.separator + ":invalid");
                if (file.exists()) {
                    file.delete();
                }
                method.invoke(null, new File(file.getAbsolutePath()));
            } else {
                method.invoke(null, new File(File.separator + ":invalid"));
            }
            fail("Exception was expected");
        } catch (InvocationTargetException e) {
            assertTrue(e.getCause() instanceof CheckstyleException);
            // We do separate validation for message as in Windows
            // disk drive letter appear in message,
            // so we skip that drive letter for compatibility issues
            assertTrue(e.getCause().getMessage().startsWith("Unable to load properties from file '"));
            assertTrue(e.getCause().getMessage().endsWith(":invalid'."));
        }
    }

    @Test
    public void testCreateListenerIllegalStateException() throws Exception {
        Method method = Main.class.getDeclaredMethod("createListener", String.class, String.class);
        method.setAccessible(true);
        try {
            method.invoke(null, "myformat", null);
            fail();
        } catch (InvocationTargetException e) {
            assertTrue(e.getCause() instanceof IllegalStateException);
            assertTrue(e.getCause().getMessage().startsWith("Invalid output format. Found"));
        }
    }

    @Test
    public void testCreateListenerWithLocationIllegalStateException() throws Exception {
        Method method = Main.class.getDeclaredMethod("createListener", String.class, String.class);
        method.setAccessible(true);
        String outDir = "myfolder123";
        try {
            method.invoke(null, "myformat", outDir);
            fail();
        } catch (InvocationTargetException e) {
            assertTrue(e.getCause() instanceof IllegalStateException);
            assertTrue(e.getCause().getMessage().startsWith("Invalid output format. Found"));
        } finally {
            // method creates output folder
            FileUtils.deleteQuietly(new File(outDir));
        }
    }

    @Test
    public void testExistingDirectoryWithViolations() throws Exception {

        // we just reference there all violations
        final String[][] outputValues = { { "ComplexityOverflow", "1", "172" }, };

        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws IOException {
                String currentPath = new File(".").getCanonicalPath();
                String expectedPath = currentPath
                        + "/src/test/resources/com/puppycrawl/tools/checkstyle/checks/metrics/".replace("/",
                                File.separator);
                StringBuilder sb = new StringBuilder();
                sb.append("Starting audit...").append(System.getProperty("line.separator"));
                String format = "%s.java:%s: warning: File length is %s lines (max allowed is 170).";
                for (String[] outputValue : outputValues) {
                    String line = String.format(Locale.ROOT, format, expectedPath + outputValue[0], outputValue[1],
                            outputValue[2]);
                    sb.append(line).append(System.getProperty("line.separator"));
                }
                sb.append("Audit done.").append(System.getProperty("line.separator"));
                assertEquals(sb.toString(), systemOut.getLog());
                assertEquals("", systemErr.getLog());
            }
        });

        Main.main("-c", "src/test/resources/com/puppycrawl/tools/checkstyle/config-filelength.xml",
                "src/test/resources/com/puppycrawl/tools/checkstyle/checks/metrics/");
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testListFilesNotFile() throws Exception {
        Method method = Main.class.getDeclaredMethod("listFiles", File.class);
        method.setAccessible(true);

        File fileMock = mock(File.class);
        when(fileMock.canRead()).thenReturn(true);
        when(fileMock.isDirectory()).thenReturn(false);
        when(fileMock.isFile()).thenReturn(false);

        List<File> result = (List<File>) method.invoke(null, fileMock);
        assertEquals(0, result.size());
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testListFilesDirectoryWithNull() throws Exception {
        Method method = Main.class.getDeclaredMethod("listFiles", File.class);
        method.setAccessible(true);

        File fileMock = mock(File.class);
        when(fileMock.canRead()).thenReturn(true);
        when(fileMock.isDirectory()).thenReturn(true);
        when(fileMock.listFiles()).thenReturn(null);

        List<File> result = (List<File>) method.invoke(null, fileMock);
        assertEquals(0, result.size());
    }
}