Permalink
Browse files

Issue #4675: increase coverage of pitest-checks-misc to 100%

  • Loading branch information...
Nimfadora committed Sep 11, 2017
1 parent f494a4f commit 42b90c917550a29f49eff91708f326ff52241550
View
@@ -1644,7 +1644,8 @@
<param>com.puppycrawl.tools.checkstyle.checks.FinalParametersCheck</param>
<param>com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck</param>
<param>com.puppycrawl.tools.checkstyle.checks.OuterTypeFilenameCheck</param>
<param>com.puppycrawl.tools.checkstyle.checks.SuppressWarningsHolder</param>
<!-- this class will be rewritten in future releases -->
<!--<param>com.puppycrawl.tools.checkstyle.checks.SuppressWarningsHolder</param>-->
<param>com.puppycrawl.tools.checkstyle.checks.TodoCommentCheck</param>
<param>com.puppycrawl.tools.checkstyle.checks.TrailingCommentCheck</param>
<param>com.puppycrawl.tools.checkstyle.checks.TranslationCheck</param>
@@ -1668,7 +1669,7 @@
<param>com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest</param>
<param>com.puppycrawl.tools.checkstyle.checks.UpperEllCheckTest</param>
</targetTests>
<mutationThreshold>96</mutationThreshold>
<mutationThreshold>100</mutationThreshold>
<timeoutFactor>${pitest.plugin.timeout.factor}</timeoutFactor>
<timeoutConstant>${pitest.plugin.timeout.constant}</timeoutConstant>
<threads>${pitest.plugin.threads}</threads>
View
@@ -14,7 +14,7 @@ env:
- PROFILE="-Ppitest-checks-regexp,no-validations"; POST_ACTION=check_survived
- PROFILE="-Ppitest-checks-sizes,no-validations"; POST_ACTION=check_survived
- PROFILE="-Ppitest-checks-whitespace,no-validations"; POST_ACTION=check_survived_whitespace
- PROFILE="-Ppitest-checks-misc,no-validations"
- PROFILE="-Ppitest-checks-misc,no-validations"; POST_ACTION=check_survived
- PROFILE="-Ppitest-checks-blocks,no-validations"; POST_ACTION=check_survived_blocks
- PROFILE="-Ppitest-checks-coding,no-validations"; POST_ACTION=check_survived_coding
- PROFILE="-Ppitest-checks-design,no-validations"; POST_ACTION=check_survived
@@ -47,7 +47,6 @@
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
/**
@@ -325,11 +324,9 @@ private void checkExistenceOfRequiredTranslations(ResourceBundle bundle) {
* @param fileName file name.
*/
private void logMissingTranslation(String filePath, String fileName) {
final MessageDispatcher dispatcher = getMessageDispatcher();
dispatcher.fireFileStarted(filePath);
log(0, MSG_KEY_MISSING_TRANSLATION_FILE, fileName);
fireErrors(filePath);
dispatcher.fireFileFinished(filePath);
getMessageDispatcher().fireFileFinished(filePath);
}
/**
@@ -434,7 +431,7 @@ private static String getPath(String fileNameWithPath) {
*/
private void checkTranslationKeys(ResourceBundle bundle) {
final Set<File> filesInBundle = bundle.getFiles();
if (filesInBundle.size() > 1) {
if (filesInBundle.size() >= 2) {
// build a map from files to the keys they contain
final Set<String> allTranslationKeys = new HashSet<>();
final SetMultimap<File, String> filesAssociatedWithKeys = HashMultimap.create();
@@ -456,9 +453,6 @@ private void checkTranslationKeys(ResourceBundle bundle) {
private void checkFilesForConsistencyRegardingTheirKeys(SetMultimap<File, String> fileKeys,
Set<String> keysThatMustExist) {
for (File currentFile : fileKeys.keySet()) {
final MessageDispatcher dispatcher = getMessageDispatcher();
final String path = currentFile.getPath();
dispatcher.fireFileStarted(path);
final Set<String> currentFileKeys = fileKeys.get(currentFile);
final Set<String> missingKeys = keysThatMustExist.stream()
.filter(e -> !currentFileKeys.contains(e)).collect(Collectors.toSet());
@@ -467,8 +461,9 @@ private void checkFilesForConsistencyRegardingTheirKeys(SetMultimap<File, String
log(0, MSG_KEY, key);
}
}
final String path = currentFile.getPath();
fireErrors(path);
dispatcher.fireFileFinished(path);
getMessageDispatcher().fireFileFinished(path);
}
}
@@ -94,9 +94,6 @@ public void beginTree(DetailAST rootAST) {
@Override
public void leaveToken(DetailAST ast) {
if (ast.getType() == TokenTypes.CLASS_DEF) {
if (classDepth == 1) {
currentClass = null;
}
classDepth--;
}
}
@@ -21,18 +21,33 @@
import static com.puppycrawl.tools.checkstyle.checks.TranslationCheck.MSG_KEY;
import static com.puppycrawl.tools.checkstyle.checks.TranslationCheck.MSG_KEY_MISSING_TRANSLATION_FILE;
import static java.util.Locale.ENGLISH;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
@@ -41,17 +56,26 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Closeables;
import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
import com.puppycrawl.tools.checkstyle.XMLLogger;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
import com.puppycrawl.tools.checkstyle.api.SeverityLevelCounter;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
@RunWith(MockitoJUnitRunner.class)
@RunWith(PowerMockRunner.class)
@PrepareForTest(Closeables.class)
public class TranslationCheckTest extends AbstractModuleTestSupport {
@Captor
private ArgumentCaptor<SortedSet<LocalizedMessage>> captor;
@@ -78,6 +102,95 @@ public void testTranslation() throws Exception {
expected);
}
/**
* Even when we pass several files to AbstractModuleTestSupport#verify,
* the check processes it during one run, so we cannot reproduce situation
* when TranslationCheck#beginProcessing called several times during single run.
* So, we have to use reflection to check this particular case.
*
* @throws Exception when code tested throws exception
*/
@Test
@SuppressWarnings("unchecked")
public void testStateIsCleared() throws Exception {
final File fileToProcess = new File(
getPath("InputTranslationCheckFireErrors_de.properties")
);
final String charset = StandardCharsets.UTF_8.name();
final TranslationCheck check = new TranslationCheck();
check.beginProcessing(charset);
check.processFiltered(fileToProcess, new FileText(fileToProcess, charset));
check.beginProcessing(charset);
final Field field = check.getClass().getDeclaredField("filesToProcess");
field.setAccessible(true);
assertTrue("Stateful field is not cleared on beginProcessing",
((Collection<File>) field.get(check)).isEmpty());
}
@Test
public void testFileExtension() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
checkConfig.addAttribute("baseName", "^InputTranslation.*$");
final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
final File[] propertyFiles = {
new File(getPath("InputTranslation_de.txt")),
};
verify(createChecker(checkConfig),
propertyFiles,
getPath("InputTranslation_de.txt"),
expected);
}
@Test
public void testLogOutput() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
checkConfig.addAttribute("requiredTranslations", "ja,de");
checkConfig.addAttribute("baseName", "^InputTranslation.*$");
final Checker checker = createChecker(checkConfig);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final XMLLogger logger = new XMLLogger(out, AutomaticBean.OutputStreamOptions.NONE);
checker.addListener(logger);
final String defaultProps = getPath("InputTranslationCheckFireErrors.properties");
final String translationProps = getPath("InputTranslationCheckFireErrors_de.properties");
final File[] propertyFiles = {
new File(defaultProps),
new File(translationProps),
};
final String line = "0: ";
final String firstErrorMessage = getCheckMessage(MSG_KEY_MISSING_TRANSLATION_FILE,
"InputTranslationCheckFireErrors_ja.properties");
final String secondErrorMessage = getCheckMessage(MSG_KEY, "anotherKey");
verify(checker, propertyFiles, ImmutableMap.of(
getPath(""), Collections.singletonList(line + firstErrorMessage),
translationProps, Collections.singletonList(line + secondErrorMessage)));
final String osName = System.getProperty("os.name").toLowerCase(ENGLISH);
String expectedLogOutput;
// till https://github.com/checkstyle/checkstyle/issues/5103
if (osName.startsWith("windows")) {
expectedLogOutput = readFile("OutputTranslationCheckWindows.xml");
}
else if (osName.startsWith("linux")) {
expectedLogOutput = readFile("OutputTranslationCheckLinux.xml");
}
else {
expectedLogOutput = readFile("OutputTranslationCheckMacOS.xml");
}
expectedLogOutput = expectedLogOutput.replace("path_to_file", getPackageAbsolutePath());
expectedLogOutput = String.format(Locale.getDefault(), expectedLogOutput,
firstErrorMessage, secondErrorMessage).replace("'", "&apos;");
assertEquals("Unexpected log output", expectedLogOutput,
out.toString(StandardCharsets.UTF_8.name()));
}
@Test
public void testOnePropertyFileSet() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
@@ -102,13 +215,16 @@ public void testLogIoExceptionFileNotFound() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
check.configure(checkConfig);
final Checker checker = createChecker(checkConfig);
final SeverityLevelCounter counter = new SeverityLevelCounter(SeverityLevel.ERROR);
checker.addListener(counter);
check.setMessageDispatcher(checker);
final Method loadKeys =
check.getClass().getDeclaredMethod("getTranslationKeys", File.class);
loadKeys.setAccessible(true);
final Set<String> keys = (Set<String>) loadKeys.invoke(check, new File(""));
assertTrue("Translation keys should be empty when File is not found", keys.isEmpty());
assertEquals("Invalid error count", 1, counter.getCount());
}
@Test
@@ -276,6 +392,36 @@ public void testTranslationFileWithLanguageCountryVariantArePresent() throws Exc
expected);
}
/**
* Pitest requires all closes of streams and readers to be verified. Using PowerMock
* is almost only posibility to check it without rewriting production code.
*
* @throws Exception when code tested throws some exception
*/
@Test
public void testResourcesAreClosed() throws Exception {
mockStatic(Closeables.class);
doNothing().when(Closeables.class);
Closeables.closeQuietly(any(InputStream.class));
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
checkConfig.addAttribute("requiredTranslations", "es");
final File[] propertyFiles = {
new File(getPath("messages_home.properties")),
new File(getPath("messages_home_es_US.properties")),
};
final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
verify(
createChecker(checkConfig),
propertyFiles,
getPath(""),
expected);
verifyStatic(times(2));
Closeables.closeQuietly(any(FileInputStream.class));
}
@Test
public void testBaseNameOption() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(TranslationCheck.class);
@@ -428,4 +574,13 @@ public void testWrongUserSpecifiedLanguageCodes() {
exceptionMessage, endsWith("[TranslationCheck]"));
}
}
private String readFile(String fileName) throws IOException {
return new String(Files.readAllBytes(Paths.get(getPath(fileName))),
StandardCharsets.UTF_8);
}
private String getPackageAbsolutePath() throws IOException {
return new File(getPath("")).getAbsolutePath();
}
}
@@ -0,0 +1,2 @@
someKey=Some key
anotherKey=one more
@@ -0,0 +1,12 @@
# input file for TranslationCheck
# a key that is available in all translations
hello=Hallo
# whitespace at end of key should be trimmed before comparing.
# the german translation does not contain whitespace, no error should
# be reported here
cancel=Abbrechen
# a key that is missing in german translation
#only.english=only english
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="8.3-SNAPSHOT">
<file name="path_to_file/InputTranslationCheckFireErrors.properties">
</file>
<file name="path_to_file/InputTranslationCheckFireErrors_de.properties">
</file>
<file name="path_to_file">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
<file name="path_to_file/InputTranslationCheckFireErrors_de.properties">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
<file name="path_to_file/InputTranslationCheckFireErrors.properties">
</file>
</checkstyle>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="8.3-SNAPSHOT">
<file name="path_to_file/InputTranslationCheckFireErrors.properties">
</file>
<file name="path_to_file/InputTranslationCheckFireErrors_de.properties">
</file>
<file name="path_to_file">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
<file name="path_to_file/InputTranslationCheckFireErrors.properties">
</file>
<file name="path_to_file/InputTranslationCheckFireErrors_de.properties">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
</checkstyle>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="8.3-SNAPSHOT">
<file name="path_to_file\InputTranslationCheckFireErrors.properties">
</file>
<file name="path_to_file\InputTranslationCheckFireErrors_de.properties">
</file>
<file name="path_to_file">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
<file name="path_to_file\InputTranslationCheckFireErrors_de.properties">
<error line="0" severity="error" message="%s" source="com.puppycrawl.tools.checkstyle.checks.TranslationCheck"/>
</file>
<file name="path_to_file\InputTranslationCheckFireErrors.properties">
</file>
</checkstyle>

0 comments on commit 42b90c9

Please sign in to comment.