1 /* 2 * Copyright (c) 2011-2025 Yegor Bugayenko 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 1) Redistributions of source code must retain the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer. 2) Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following 12 * disclaimer in the documentation and/or other materials provided 13 * with the distribution. 3) Neither the name of the Qulice.com nor 14 * the names of its contributors may be used to endorse or promote 15 * products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 20 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 package com.qulice.pmd; 32 33 import org.hamcrest.Matcher; 34 import org.hamcrest.core.CombinableMatcher; 35 import org.hamcrest.core.IsEqual; 36 import org.hamcrest.core.StringContains; 37 import org.hamcrest.text.IsEmptyString; 38 import org.junit.jupiter.api.Test; 39 import org.junit.jupiter.params.ParameterizedTest; 40 import org.junit.jupiter.params.provider.ValueSource; 41 42 /** 43 * Test case for {@link com.qulice.pmd.rules.UseStringIsEmptyRule}. 44 * @since 0.18 45 */ 46 final class UseStringIsEmptyRuleTest { 47 48 /** 49 * UseStringIsEmpty can detect when used String.length(), when checking for 50 * empty string. 51 * @param file File name. 52 * @throws Exception If something goes wrong. 53 */ 54 @ParameterizedTest 55 @ValueSource( 56 strings = { 57 "StringLengthGreaterThanZero.java", 58 "StringLengthGreaterOrEqualZero.java", 59 "StringLengthGreaterOrEqualOne.java", 60 "StringLengthLessThanOne.java", 61 "StringLengthLessOrEqualZero.java", 62 "StringLengthEqualsZero.java", 63 "StringLengthNotEqualsZero.java" 64 } 65 ) 66 void detectLengthComparisons(final String file) throws Exception { 67 new PmdAssert( 68 file, new IsEqual<>(false), 69 new CombinableMatcher<>(containsMatcher(file, 46)) 70 .and(containsMatcher(file, 50)) 71 .and(containsMatcher(file, 54)) 72 .and(containsMatcher(file, 58)) 73 .and(containsMatcher(file, 62)) 74 ).validate(); 75 } 76 77 /** 78 * UseStringIsEmpty not detect when used String[].length, when checking for 79 * empty string. 80 * @throws Exception If something goes wrong. 81 */ 82 @Test 83 void notDetectOnArrayOfStrings() throws Exception { 84 new PmdAssert( 85 "ArrayOfStringsLengthGreaterThanZero.java", 86 new IsEqual<>(true), 87 IsEmptyString.emptyString() 88 ).validate(); 89 } 90 91 /** 92 * Constructs StringContains matcher for error message. 93 * @param file File name. 94 * @param line Line number. 95 * @return StringContains matcher. 96 */ 97 private static Matcher<String> containsMatcher( 98 final String file, final int line 99 ) { 100 final String message = 101 "Use String.isEmpty() when checking for empty string"; 102 return new StringContains( 103 String.format( 104 "PMD: %1$s[%2$d-%2$d]: %3$s (UseStringIsEmptyRule)", 105 file, line, message 106 ) 107 ); 108 } 109 }