View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2017 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.imports;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertSame;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.lang.reflect.InvocationTargetException;
32  import java.lang.reflect.Method;
33  import java.net.MalformedURLException;
34  import java.net.URI;
35  import java.net.URL;
36  
37  import org.junit.Test;
38  import org.junit.runner.RunWith;
39  import org.mockito.BDDMockito;
40  import org.mockito.Mockito;
41  import org.powermock.api.mockito.PowerMockito;
42  import org.powermock.core.classloader.annotations.PrepareForTest;
43  import org.powermock.modules.junit4.PowerMockRunner;
44  import org.xml.sax.Attributes;
45  import org.xml.sax.InputSource;
46  import org.xml.sax.SAXException;
47  import org.xml.sax.SAXParseException;
48  import org.xml.sax.helpers.AttributesImpl;
49  
50  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
51  
52  @RunWith(PowerMockRunner.class)
53  @PrepareForTest({ImportControlLoader.class, URI.class})
54  public class ImportControlLoaderTest {
55      private static String getPath(String filename) {
56          return "src/test/resources/com/puppycrawl/tools/"
57                  + "checkstyle/checks/imports/importcontrolloader/" + filename;
58      }
59  
60      @Test
61      public void testLoad() throws CheckstyleException {
62          final ImportControl root =
63                  ImportControlLoader.load(
64                  new File(getPath("InputImportControlLoaderComplete.xml")).toURI());
65          assertNotNull("Import root should not be null", root);
66      }
67  
68      @Test
69      public void testWrongFormatUri() throws Exception {
70          try {
71              ImportControlLoader.load(new URI("aaa://"
72                      + getPath("InputImportControlLoaderComplete.xml")));
73              fail("exception expected");
74          }
75          catch (CheckstyleException ex) {
76              assertSame("Invalid exception class",
77                      MalformedURLException.class, ex.getCause().getClass());
78              assertEquals("Invalid exception message",
79                      "unknown protocol: aaa", ex.getCause().getMessage());
80          }
81      }
82  
83      @Test
84      public void testExtraElementInConfig() throws Exception {
85          final ImportControl root =
86                  ImportControlLoader.load(
87                      new File(getPath("InputImportControlLoaderWithNewElement.xml")).toURI());
88          assertNotNull("Import root should not be null", root);
89      }
90  
91      @Test
92      // UT uses Reflection to avoid removing null-validation from static method
93      public void testSafeGetThrowsException() throws Exception {
94          final AttributesImpl attr = new AttributesImpl() {
95              @Override
96              public String getValue(int index) {
97                  return null;
98                  }
99              };
100         try {
101             final Class<?> clazz = ImportControlLoader.class;
102             final Method privateMethod = clazz.getDeclaredMethod("safeGet",
103                 Attributes.class, String.class);
104             privateMethod.setAccessible(true);
105             privateMethod.invoke(null, attr, "you_cannot_find_me");
106             fail("exception expected");
107         }
108         catch (InvocationTargetException ex) {
109             assertSame("Invalid exception class", SAXException.class, ex.getCause().getClass());
110             assertEquals("Invalid exception message",
111                     "missing attribute you_cannot_find_me", ex.getCause().getMessage());
112         }
113     }
114 
115     @Test
116     // UT uses Reflection to cover IOException from 'loader.parseInputSource(source);'
117     // because this is possible situation (though highly unlikely), which depends on hardware
118     // and is difficult to emulate
119     public void testLoadThrowsException() throws Exception {
120         final InputSource source = new InputSource();
121         try {
122             final Class<?> clazz = ImportControlLoader.class;
123             final Method privateMethod = clazz.getDeclaredMethod("load", InputSource.class,
124                 URI.class);
125             privateMethod.setAccessible(true);
126             privateMethod.invoke(null, source,
127                     new File(getPath("InputImportControlLoaderComplete.xml")).toURI());
128             fail("exception expected");
129         }
130         catch (InvocationTargetException ex) {
131             assertSame("Invalid exception class",
132                     CheckstyleException.class, ex.getCause().getClass());
133             assertTrue("Invalid exception message: " + ex.getCause().getMessage(),
134                     ex.getCause().getMessage().startsWith("unable to read"));
135         }
136     }
137 
138     @Test
139     public void testInputStreamThatFailsOnClose() throws Exception {
140         final InputStream inputStream = PowerMockito.mock(InputStream.class);
141         Mockito.doThrow(IOException.class).when(inputStream).close();
142         final int available = Mockito.doThrow(IOException.class).when(inputStream).available();
143 
144         final URL url = PowerMockito.mock(URL.class);
145         BDDMockito.given(url.openStream()).willReturn(inputStream);
146 
147         final URI uri = PowerMockito.mock(URI.class);
148         BDDMockito.given(uri.toURL()).willReturn(url);
149 
150         try {
151             ImportControlLoader.load(uri);
152             //Using available to bypass 'ignored result' warning
153             fail("exception expected " + available);
154         }
155         catch (CheckstyleException ex) {
156             assertSame("Invalid exception class", IOException.class, ex.getCause().getClass());
157         }
158         Mockito.verify(inputStream).close();
159     }
160 
161     @Test
162     public void testInputStreamFailsOnRead() throws Exception {
163         final InputStream inputStream = PowerMockito.mock(InputStream.class);
164         final int available = Mockito.doThrow(IOException.class).when(inputStream).available();
165 
166         final URL url = PowerMockito.mock(URL.class);
167         BDDMockito.given(url.openStream()).willReturn(inputStream);
168 
169         final URI uri = PowerMockito.mock(URI.class);
170         BDDMockito.given(uri.toURL()).willReturn(url);
171 
172         try {
173             ImportControlLoader.load(uri);
174             //Using available to bypass 'ignored result' warning
175             fail("exception expected " + available);
176         }
177         catch (CheckstyleException ex) {
178             assertSame("Invalid exception class",
179                     SAXParseException.class, ex.getCause().getClass());
180         }
181     }
182 }