View Javadoc
1   package org.apache.maven.it;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.it.util.ResourceExtractor;
23  import org.apache.maven.shared.utils.io.FileUtils;
24  import org.eclipse.jetty.server.Handler;
25  import org.eclipse.jetty.server.NetworkConnector;
26  import org.eclipse.jetty.server.Request;
27  import org.eclipse.jetty.server.Server;
28  import org.eclipse.jetty.server.handler.AbstractHandler;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  import java.io.File;
33  import java.io.IOException;
34  import java.util.Deque;
35  import java.util.Properties;
36  import java.util.concurrent.ConcurrentLinkedDeque;
37  
38  /**
39   * This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-3415">MNG-3415</a>.
40   */
41  public class MavenITmng3415JunkRepositoryMetadataTest
42      extends AbstractMavenIntegrationTestCase
43  {
44      private static final String RESOURCE_BASE = "/mng-3415";
45  
46      public MavenITmng3415JunkRepositoryMetadataTest()
47      {
48          // we're going to control the test execution according to the maven version present within each test method.
49          // all methods should execute as long as we're using maven 2.0.9+, but the specific tests may vary a little
50          // depending on which version we're using above 2.0.8.
51          super( "(2.0.8,)" ); // only test in 2.0.9+
52      }
53  
54      /**
55       * This test simply verifies that when a metadata transfer fails (network error, etc.)
56       * no metadata file is written to the local repository.
57       * <p>
58       * Steps executed to verify this test:
59       * </p>
60       * 0. Find the local repository directory:
61       * a. build the maven-find-local-repo-plugin, then run it, to spit out the path of the
62       * local repository in use by default. Read the output file to get this path.
63       * (Yes, it's heavy, but it's reliable.)
64       * 1. Setup the test:
65       * a. Make sure the metadata for the test-repo is NOT in the local repository.
66       * b. Make sure the dependency POM IS in the local repository, so we're not
67       * distracted by failed builds that are unrelated.
68       * c. Create the settings file for use in this test, which contains the invalid
69       * remote repository entry.
70       * 2. Build the test project the first time
71       * a. Verify that a TransferFailedException is in the build output for the test-repo
72       * b. Verify that the metadata for the dependency POM is NOT in the local
73       * repository afterwards.
74       * 3. Build the test project the second time
75       * a. See (2.a) and (2.b) above; the same criteria applies here.
76       *
77       * @throws Exception in case of failure
78       */
79      public void testitTransferFailed()
80          throws Exception
81      {
82          String methodName = getMethodName();
83  
84          File testDir = ResourceExtractor.simpleExtractResources( getClass(), RESOURCE_BASE );
85  
86          Verifier verifier;
87  
88          verifier = newVerifier( testDir.getAbsolutePath() );
89          verifier.setAutoclean( false );
90          verifier.deleteArtifacts( "org.apache.maven.its.mng3415" );
91  
92          setupDummyDependency( verifier, testDir, true );
93  
94          Properties filterProps = verifier.newDefaultFilterProperties();
95          filterProps.put( "@protocol@", "invalid" );
96          filterProps.put( "@port@", "0" );
97          File settings = verifier.filterFile( "settings-template.xml", "settings-a.xml", "UTF-8", filterProps );
98  
99          verifier.addCliOption( "-X" );
100         verifier.addCliOption( "-s" );
101         verifier.addCliOption( settings.getName() );
102 
103         verifier.setLogFileName( "log-" + methodName + "-firstBuild.txt" );
104         verifier.executeGoal( "validate" );
105 
106         verifier.verifyErrorFreeLog();
107 
108         assertMetadataMissing( verifier );
109 
110         setupDummyDependency( verifier, testDir, true );
111 
112         verifier.setLogFileName( "log-" + methodName + "-secondBuild.txt" );
113         verifier.executeGoal( "validate" );
114 
115         verifier.verifyErrorFreeLog();
116         verifier.resetStreams();
117 
118         assertMetadataMissing( verifier );
119     }
120 
121     private String getMethodName()
122     {
123         return new Throwable().getStackTrace()[1].getMethodName();
124     }
125 
126     /**
127      * This test simply verifies that when metadata doesn't exist on the remote
128      * repository, a basic metadata file is written to the local repository.
129      * <p>
130      * Steps executed to verify this test:
131      * </p>
132      * 0. Find the local repository directory:
133      * a. build the maven-find-local-repo-plugin, then run it, to spit out the path of the
134      * local repository in use by default. Read the output file to get this path.
135      * (Yes, it's heavy, but it's reliable.)
136      * 1. Setup the test:
137      * a. Make sure the metadata for the test-repo is NOT in the local repository.
138      * b. Make sure the dependency POM IS in the local repository, so we're not
139      * distracted by failed builds that are unrelated.
140      * c. Create the settings file for use in this test, which contains the VALID
141      * remote repository entry.
142      * 2. Build the test project the first time
143      * a. Verify that the remote repository is checked for the metadata file
144      * 3. Build the test project the second time
145      * a. Verify that the remote repository is NOT checked for the metadata file again
146      * b. Verify that the file used for updateInterval calculations was NOT changed from
147      * the first build.
148      *
149      * @throws Exception in case of failure
150      */
151     public void testShouldNotRepeatedlyUpdateOnResourceNotFoundException()
152         throws Exception
153     {
154         String methodName = getMethodName();
155 
156         File testDir = ResourceExtractor.simpleExtractResources( getClass(), RESOURCE_BASE );
157 
158         Verifier verifier;
159 
160         verifier = newVerifier( testDir.getAbsolutePath() );
161         verifier.setAutoclean( false );
162         verifier.deleteArtifacts( "org.apache.maven.its.mng3415" );
163 
164         final Deque<String> requestUris = new ConcurrentLinkedDeque<>();
165 
166         Handler repoHandler = new AbstractHandler()
167         {
168             @Override
169             public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response )
170             {
171                 System.out.println( "Handling " + request.getMethod() + " " + request.getRequestURL() );
172 
173                 requestUris.add( request.getRequestURI() );
174 
175                 response.setStatus( HttpServletResponse.SC_NOT_FOUND );
176 
177                 ( (Request) request ).setHandled( true );
178             }
179         };
180 
181         Server server = new Server( 0 );
182         server.setHandler( repoHandler );
183 
184         try
185         {
186             server.start();
187             if ( server.isFailed() )
188             {
189                 fail( "Couldn't bind the server socket to a free port!" );
190             }
191 
192             int port = ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
193             System.out.println( "Bound server socket to the port " + port );
194 
195             Properties filterProps = verifier.newDefaultFilterProperties();
196             filterProps.put( "@protocol@", "http" );
197             filterProps.put( "@port@", Integer.toString( port ) );
198             File settings = verifier.filterFile( "settings-template.xml", "settings-b.xml", "UTF-8", filterProps );
199 
200             verifier.addCliOption( "-X" );
201             verifier.addCliOption( "-s" );
202             verifier.addCliOption( settings.getName() );
203 
204             setupDummyDependency( verifier, testDir, true );
205 
206             verifier.setLogFileName( "log-" + methodName + "-firstBuild.txt" );
207             verifier.executeGoal( "validate" );
208 
209             verifier.verifyErrorFreeLog();
210 
211             assertTrue( requestUris.toString(), requestUris.contains(
212                 "/org/apache/maven/its/mng3415/missing/1.0-SNAPSHOT/maven-metadata.xml" ) );
213 
214             requestUris.clear();
215 
216             File updateCheckFile = getUpdateCheckFile( verifier );
217             long firstLastMod = updateCheckFile.lastModified();
218 
219             setupDummyDependency( verifier, testDir, false );
220 
221             verifier.setLogFileName( "log-" + methodName + "-secondBuild.txt" );
222             verifier.executeGoal( "validate" );
223 
224             verifier.verifyErrorFreeLog();
225             verifier.resetStreams();
226 
227             assertFalse( requestUris.toString(), requestUris.contains(
228                 "/org/apache/maven/its/mng3415/missing/1.0-SNAPSHOT/maven-metadata.xml" ) );
229 
230             assertEquals(
231                 "Last-modified time should be unchanged from first build through second build for the file we use for"
232                     + " updateInterval checks.",
233                 firstLastMod, updateCheckFile.lastModified() );
234         }
235         finally
236         {
237             server.stop();
238             server.join();
239         }
240     }
241 
242     private void assertMetadataMissing( Verifier verifier )
243     {
244         File metadata = getMetadataFile( verifier );
245 
246         assertFalse( "Metadata file should NOT be present in local repository: " + metadata.getAbsolutePath(),
247                      metadata.exists() );
248     }
249 
250     private void setupDummyDependency( Verifier verifier, File testDir, boolean resetUpdateInterval )
251         throws IOException
252     {
253         String gid = "org.apache.maven.its.mng3415";
254         String aid = "missing";
255         String version = "1.0-SNAPSHOT";
256 
257         if ( resetUpdateInterval )
258         {
259             verifier.deleteArtifacts( gid );
260         }
261 
262         File pom = new File( verifier.getArtifactPath( gid, aid, version, "pom" ) );
263 
264         File pomSrc = new File( testDir, "dependency-pom.xml" );
265 
266         System.out.println( "Copying dependency POM\nfrom: " + pomSrc + "\nto: " + pom );
267         FileUtils.copyFile( pomSrc, pom );
268     }
269 
270     private File getMetadataFile( Verifier verifier )
271     {
272         String gid = "org.apache.maven.its.mng3415";
273         String aid = "missing";
274         String version = "1.0-SNAPSHOT";
275         String name = "maven-metadata-testing-repo.xml";
276 
277         return new File( verifier.getArtifactMetadataPath( gid, aid, version, name ) );
278     }
279 
280     /**
281      * If the current maven version is < 3.0, we'll use the metadata file itself (old maven-artifact code)...
282      * otherwise, use the new resolver-status.properties file (new artifact code).
283      */
284     private File getUpdateCheckFile( Verifier verifier )
285     {
286         String gid = "org.apache.maven.its.mng3415";
287         String aid = "missing";
288         String version = "1.0-SNAPSHOT";
289         String name;
290 
291         // < 3.0 (including snapshots)
292         if ( matchesVersionRange( "(2.0.8,3.0-alpha-1)" ) )
293         {
294             name = "maven-metadata-testing-repo.xml";
295         }
296         else
297         {
298             name = "resolver-status.properties";
299         }
300 
301         return new File( verifier.getArtifactMetadataPath( gid, aid, version, name ) );
302     }
303 }