View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2018 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.checks.coding;
21  
22  import static com.puppycrawl.tools.checkstyle.checks.coding.ModifiedControlVariableCheck.MSG_KEY;
23  import static org.junit.Assert.assertTrue;
24  
25  import java.io.File;
26  import java.util.Collection;
27  import java.util.Optional;
28  import java.util.Set;
29  
30  import org.junit.Assert;
31  import org.junit.Test;
32  
33  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
34  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
35  import com.puppycrawl.tools.checkstyle.JavaParser;
36  import com.puppycrawl.tools.checkstyle.api.DetailAST;
37  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
38  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
39  import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
40  
41  public class ModifiedControlVariableCheckTest
42      extends AbstractModuleTestSupport {
43  
44      @Override
45      protected String getPackageLocation() {
46          return "com/puppycrawl/tools/checkstyle/checks/coding/modifiedcontrolvariable";
47      }
48  
49      @Test
50      public void testModifiedControlVariable() throws Exception {
51          final DefaultConfiguration checkConfig =
52              createModuleConfig(ModifiedControlVariableCheck.class);
53          final String[] expected = {
54              "14:14: " + getCheckMessage(MSG_KEY, "i"),
55              "17:15: " + getCheckMessage(MSG_KEY, "i"),
56              "20:37: " + getCheckMessage(MSG_KEY, "i"),
57              "21:17: " + getCheckMessage(MSG_KEY, "i"),
58              "49:15: " + getCheckMessage(MSG_KEY, "s"),
59              "56:14: " + getCheckMessage(MSG_KEY, "m"),
60              "67:15: " + getCheckMessage(MSG_KEY, "i"),
61              "68:15: " + getCheckMessage(MSG_KEY, "k"),
62              "78:15: " + getCheckMessage(MSG_KEY, "v"),
63          };
64          verify(checkConfig, getPath("InputModifiedControlVariableBothForLoops.java"), expected);
65      }
66  
67      @Test
68      public void testEnhancedForLoopVariableTrue() throws Exception {
69          final DefaultConfiguration checkConfig =
70              createModuleConfig(ModifiedControlVariableCheck.class);
71          checkConfig.addAttribute("skipEnhancedForLoopVariable", "true");
72  
73          final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
74          verify(checkConfig, getPath("InputModifiedControlVariableEnhancedForLoopVariable.java"),
75              expected);
76      }
77  
78      @Test
79      public void testEnhancedForLoopVariableFalse() throws Exception {
80          final DefaultConfiguration checkConfig =
81              createModuleConfig(ModifiedControlVariableCheck.class);
82  
83          final String[] expected = {
84              "9:18: " + getCheckMessage(MSG_KEY, "line"),
85          };
86          verify(checkConfig, getPath("InputModifiedControlVariableEnhancedForLoopVariable.java"),
87              expected);
88      }
89  
90      @Test
91      public void testEnhancedForLoopVariable2() throws Exception {
92          final DefaultConfiguration checkConfig =
93                  createModuleConfig(ModifiedControlVariableCheck.class);
94          checkConfig.addAttribute("skipEnhancedForLoopVariable", "true");
95  
96          final String[] expected = {
97              "14:18: " + getCheckMessage(MSG_KEY, "i"),
98          };
99          verify(checkConfig, getPath("InputModifiedControlVariableEnhancedForLoopVariable2.java"),
100             expected);
101     }
102 
103     @Test
104     public void testTokensNotNull() {
105         final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
106         Assert.assertNotNull("Acceptable tokens should not be null", check.getAcceptableTokens());
107         Assert.assertNotNull("Default tokens should not be null", check.getDefaultTokens());
108         Assert.assertNotNull("Required tokens should not be null", check.getRequiredTokens());
109     }
110 
111     @Test
112     public void testImproperToken() {
113         final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
114 
115         final DetailAST classDefAst = new DetailAST();
116         classDefAst.setType(TokenTypes.CLASS_DEF);
117 
118         try {
119             check.visitToken(classDefAst);
120             Assert.fail("IllegalStateException is expected");
121         }
122         catch (IllegalStateException ex) {
123             // it is OK
124         }
125 
126         try {
127             check.leaveToken(classDefAst);
128             Assert.fail("IllegalStateException is expected");
129         }
130         catch (IllegalStateException ex) {
131             // it is OK
132         }
133     }
134 
135     /**
136      * We cannot reproduce situation when visitToken is called and leaveToken is not.
137      * So, we have to use reflection to be sure that even in such situation
138      * state of the field will be cleared.
139      *
140      * @throws Exception when code tested throws exception
141      */
142     @Test
143     @SuppressWarnings("unchecked")
144     public void testClearState() throws Exception {
145         final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
146         final Optional<DetailAST> methodDef = TestUtil.findTokenInAstByPredicate(
147             JavaParser.parseFile(
148                 new File(getPath("InputModifiedControlVariableEnhancedForLoopVariable.java")),
149                 JavaParser.Options.WITHOUT_COMMENTS),
150             ast -> ast.getType() == TokenTypes.OBJBLOCK);
151 
152         assertTrue("Ast should contain METHOD_DEF", methodDef.isPresent());
153         assertTrue("State is not cleared on beginTree",
154             TestUtil.isStatefulFieldClearedDuringBeginTree(check, methodDef.get(),
155                 "variableStack",
156                 variableStack -> ((Collection<Set<String>>) variableStack).isEmpty()));
157     }
158 
159 }