View Javadoc

1   package org.apache.maven.shared.release.phase;
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 static org.mockito.Matchers.argThat;
23  import static org.mockito.Matchers.eq;
24  import static org.mockito.Matchers.isA;
25  import static org.mockito.Matchers.isNull;
26  import static org.mockito.Mockito.mock;
27  import static org.mockito.Mockito.verify;
28  import static org.mockito.Mockito.verifyNoMoreInteractions;
29  import static org.mockito.Mockito.when;
30  
31  import java.io.File;
32  import java.util.ArrayList;
33  import java.util.Collections;
34  import java.util.Iterator;
35  import java.util.List;
36  
37  import org.apache.maven.project.MavenProject;
38  import org.apache.maven.scm.ScmException;
39  import org.apache.maven.scm.ScmFile;
40  import org.apache.maven.scm.ScmFileSet;
41  import org.apache.maven.scm.ScmFileStatus;
42  import org.apache.maven.scm.ScmVersion;
43  import org.apache.maven.scm.command.checkin.CheckInScmResult;
44  import org.apache.maven.scm.manager.NoSuchScmProviderException;
45  import org.apache.maven.scm.manager.ScmManager;
46  import org.apache.maven.scm.manager.ScmManagerStub;
47  import org.apache.maven.scm.provider.ScmProvider;
48  import org.apache.maven.scm.provider.ScmProviderStub;
49  import org.apache.maven.scm.repository.ScmRepository;
50  import org.apache.maven.scm.repository.ScmRepositoryException;
51  import org.apache.maven.shared.release.ReleaseExecutionException;
52  import org.apache.maven.shared.release.ReleaseFailureException;
53  import org.apache.maven.shared.release.config.ReleaseDescriptor;
54  import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
55  import org.apache.maven.shared.release.scm.DefaultScmRepositoryConfigurator;
56  import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
57  import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
58  import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
59  import org.apache.maven.shared.release.util.ReleaseUtil;
60  
61  /**
62   * Test the release or branch preparation SCM commit phase.
63   *
64   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
65   */
66  public class ScmCommitPreparationPhaseTest
67      extends AbstractReleaseTestCase
68  {
69      private static final String PREFIX = "[maven-release-manager] prepare release ";
70  
71      protected void setUp()
72          throws Exception
73      {
74          super.setUp();
75  
76          phase = (ReleasePhase) lookup( ReleasePhase.ROLE, "scm-commit-release" );
77      }
78  
79      public void testIsCorrectImplementation()
80      {
81          assertEquals( ScmCommitPreparationPhase.class, phase.getClass() );
82      }
83  
84      public void testResolvesCorrectBranchImplementation()
85          throws Exception
86      {
87          assertEquals( ScmCommitPreparationPhase.class, lookup( ReleasePhase.ROLE, "scm-commit-branch" ).getClass() );
88      }
89  
90      public void testCommit()
91          throws Exception
92      {
93          // prepare
94          List<MavenProject> reactorProjects = createReactorProjects();
95          ReleaseDescriptor descriptor = new ReleaseDescriptor();
96          descriptor.setScmSourceUrl( "scm-url" );
97          MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
98          descriptor.setWorkingDirectory( rootProject.getFile().getParentFile().getAbsolutePath() );
99          descriptor.setScmReleaseLabel( "release-label" );
100 
101         ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile(), rootProject.getFile() );
102 
103         ScmProvider scmProviderMock = mock( ScmProvider.class );
104         when( scmProviderMock.checkIn( isA( ScmRepository.class ), 
105                                        argThat( new IsScmFileSetEquals( fileSet ) ), 
106                                        isNull( ScmVersion.class ),
107                                        eq( PREFIX + "release-label" ) ) ).thenReturn( new CheckInScmResult( "...", Collections.singletonList( new ScmFile( rootProject
108                        .getFile().getPath(), ScmFileStatus.CHECKED_IN ) ) ) );
109         
110         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
111         stub.setScmProvider( scmProviderMock );
112 
113         // execute
114         phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
115 
116         // verify
117         verify( scmProviderMock ).checkIn( isA( ScmRepository.class ), 
118                                             argThat( new IsScmFileSetEquals( fileSet ) ), 
119                                             isNull( ScmVersion.class ),
120                                             eq( PREFIX + "release-label" ) );
121         verifyNoMoreInteractions( scmProviderMock );
122     }
123 
124     public void testCommitMultiModule()
125         throws Exception
126     {
127         // prepare
128         ReleaseDescriptor descriptor = new ReleaseDescriptor();
129         List<MavenProject> reactorProjects = createReactorProjects( "scm-commit/", "multiple-poms" );
130         descriptor.setScmSourceUrl( "scm-url" );
131         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
132         descriptor.setWorkingDirectory( rootProject.getFile().getParentFile().getAbsolutePath() );
133         descriptor.setScmReleaseLabel( "release-label" );
134 
135         List<File> poms = new ArrayList<File>();
136         for ( Iterator<MavenProject> i = reactorProjects.iterator(); i.hasNext(); )
137         {
138             MavenProject project = i.next();
139             poms.add( project.getFile() );
140         }
141         ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile(), poms);
142 
143         ScmProvider scmProviderMock = mock( ScmProvider.class );
144         when( scmProviderMock.checkIn( isA( ScmRepository.class ), 
145                                        argThat( new IsScmFileSetEquals( fileSet ) ), 
146                                        isNull( ScmVersion.class ), 
147                                        eq( PREFIX + "release-label" ) ) ).thenReturn( new CheckInScmResult(
148                                                     "...",
149                                                     Collections.singletonList( new ScmFile( rootProject.getFile().getPath(),
150                                                                                             ScmFileStatus.CHECKED_IN ) ) ) );
151         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
152         stub.setScmProvider( scmProviderMock );
153 
154         // execute
155         phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
156 
157         // verify
158         verify( scmProviderMock ).checkIn( isA( ScmRepository.class ), 
159                                            argThat( new IsScmFileSetEquals( fileSet ) ), 
160                                            isNull( ScmVersion.class ), 
161                                            eq( PREFIX + "release-label" ) );
162         verifyNoMoreInteractions( scmProviderMock );
163     }
164 
165     public void testCommitDevelopment()
166         throws Exception
167     {
168         // prepare
169         phase = (ReleasePhase) lookup( ReleasePhase.ROLE, "scm-commit-development" );
170 
171         ReleaseDescriptor descriptor = new ReleaseDescriptor();
172         List<MavenProject> reactorProjects = createReactorProjects();
173         descriptor.setScmSourceUrl( "scm-url" );
174         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
175         descriptor.setWorkingDirectory( rootProject.getFile().getParentFile().getAbsolutePath() );
176         descriptor.setScmReleaseLabel( "release-label" );
177 
178         ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile(), rootProject.getFile() );
179 
180         ScmProvider scmProviderMock = mock( ScmProvider.class );
181         when( scmProviderMock.checkIn( isA( ScmRepository.class ),
182                                        argThat( new IsScmFileSetEquals( fileSet ) ), 
183                                        isNull( ScmVersion.class ), 
184                                        eq( "[maven-release-manager] prepare for next development iteration" ) ) ).thenReturn( new CheckInScmResult( "...", Collections.singletonList( new ScmFile( rootProject
185                        .getFile().getPath(), ScmFileStatus.CHECKED_IN ) ) ) );
186 
187         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
188         stub.setScmProvider( scmProviderMock );
189 
190         // execute
191         phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
192 
193         // verify
194         verify( scmProviderMock ).checkIn( isA( ScmRepository.class ),
195                                            argThat( new IsScmFileSetEquals( fileSet ) ), 
196                                            isNull( ScmVersion.class ), 
197                                            eq( "[maven-release-manager] prepare for next development iteration" ) );
198         verifyNoMoreInteractions( scmProviderMock );
199     }
200 
201     public void testCommitNoReleaseLabel()
202         throws Exception
203     {
204         ReleaseDescriptor descriptor = new ReleaseDescriptor();
205         List<MavenProject> reactorProjects = createReactorProjects();
206 
207         try
208         {
209             phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
210             fail( "Should have thrown an exception" );
211         }
212         catch ( ReleaseFailureException e )
213         {
214             assertTrue( true );
215         }
216     }
217 
218     public void testCommitGenerateReleasePoms()
219         throws Exception
220     {
221         // prepare
222         List<MavenProject> reactorProjects = createReactorProjects();
223         ReleaseDescriptor descriptor = new ReleaseDescriptor();
224         descriptor.setScmSourceUrl( "scm-url" );
225         descriptor.setGenerateReleasePoms( true );
226         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
227         descriptor.setWorkingDirectory( rootProject.getFile().getParentFile().getAbsolutePath() );
228         descriptor.setScmReleaseLabel( "release-label" );
229 
230         List<File> files = new ArrayList<File>();
231         files.add( rootProject.getFile() );
232         files.add( ReleaseUtil.getReleasePom( rootProject ) );
233         ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile(), files );
234 
235         ScmProvider scmProviderMock = mock( ScmProvider.class );
236         when( scmProviderMock.checkIn( isA( ScmRepository.class ),
237                                        argThat( new IsScmFileSetEquals( fileSet ) ),
238                                        isNull( ScmVersion.class ),
239                                        eq( PREFIX + "release-label" ) ) ).thenReturn( new CheckInScmResult( "...", Collections.singletonList( new ScmFile( rootProject
240                        .getFile().getPath(), ScmFileStatus.CHECKED_IN ) ) ) );
241 
242         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
243         stub.setScmProvider( scmProviderMock );
244 
245         // execute
246         phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
247 
248         // verify
249         verify( scmProviderMock ).checkIn( isA( ScmRepository.class ),
250                                            argThat( new IsScmFileSetEquals( fileSet ) ),
251                                            isNull( ScmVersion.class ),
252                                            eq( PREFIX + "release-label" ) );
253         verifyNoMoreInteractions( scmProviderMock );
254     }
255 
256     public void testSimulateCommit()
257         throws Exception
258     {
259         ReleaseDescriptor descriptor = new ReleaseDescriptor();
260         List<MavenProject> reactorProjects = createReactorProjects();
261         descriptor.setScmSourceUrl( "scm-url" );
262         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
263         descriptor.setWorkingDirectory( rootProject.getFile().getParentFile().getAbsolutePath() );
264         descriptor.setScmReleaseLabel( "release-label" );
265 
266         ScmProvider scmProviderMock = mock( ScmProvider.class );
267         
268         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
269         stub.setScmProvider( scmProviderMock );
270 
271         phase.simulate( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
272 
273         // never invoke scmProviderMock
274         verifyNoMoreInteractions( scmProviderMock );
275     }
276 
277     public void testSimulateCommitNoReleaseLabel()
278         throws Exception
279     {
280         ReleaseDescriptor descriptor = new ReleaseDescriptor();
281         List<MavenProject> reactorProjects = createReactorProjects();
282 
283         try
284         {
285             phase.simulate( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
286             fail( "Should have thrown an exception" );
287         }
288         catch ( ReleaseFailureException e )
289         {
290             assertTrue( true );
291         }
292     }
293 
294     public void testNoSuchScmProviderExceptionThrown()
295         throws Exception
296     {
297         // prepare
298         List<MavenProject> reactorProjects = createReactorProjects();
299         ReleaseDescriptor releaseDescriptor = createReleaseDescriptor();
300 
301         ScmManager scmManagerMock = mock( ScmManager.class );
302         when( scmManagerMock.makeScmRepository( "scm-url" ) ).thenThrow( new NoSuchScmProviderException( "..." ) );
303 
304         DefaultScmRepositoryConfigurator configurator = (DefaultScmRepositoryConfigurator) lookup(
305             ScmRepositoryConfigurator.ROLE );
306         configurator.setScmManager( scmManagerMock );
307 
308         // execute
309         try
310         {
311             phase.execute( releaseDescriptor, new DefaultReleaseEnvironment(), reactorProjects );
312 
313             fail( "Status check should have failed" );
314         }
315         catch ( ReleaseExecutionException e )
316         {
317             assertEquals( "check cause", NoSuchScmProviderException.class, e.getCause().getClass() );
318         }
319         
320         // verify
321         verify( scmManagerMock ).makeScmRepository( "scm-url" );
322         verifyNoMoreInteractions( scmManagerMock );
323     }
324 
325     public void testScmRepositoryExceptionThrown()
326         throws Exception
327     {
328         // prepare
329         List<MavenProject> reactorProjects = createReactorProjects();
330         ReleaseDescriptor releaseDescriptor = createReleaseDescriptor();
331 
332         ScmManager scmManagerMock = mock( ScmManager.class );
333         when( scmManagerMock.makeScmRepository( "scm-url" ) ).thenThrow( new ScmRepositoryException( "..." ) );
334 
335         DefaultScmRepositoryConfigurator configurator = (DefaultScmRepositoryConfigurator) lookup(
336             ScmRepositoryConfigurator.ROLE );
337         configurator.setScmManager( scmManagerMock );
338 
339         // execute
340         try
341         {
342             phase.execute( releaseDescriptor, new DefaultReleaseEnvironment(), reactorProjects );
343 
344             fail( "Status check should have failed" );
345         }
346         catch ( ReleaseScmRepositoryException e )
347         {
348             assertNull( "Check no additional cause", e.getCause() );
349         }
350         
351         // verify
352         verify( scmManagerMock ).makeScmRepository( "scm-url" );
353         verifyNoMoreInteractions( scmManagerMock ); 
354     }
355 
356     public void testScmExceptionThrown()
357         throws Exception
358     {
359         // prepare
360         List<MavenProject> reactorProjects = createReactorProjects();
361         ReleaseDescriptor releaseDescriptor = createReleaseDescriptor();
362 
363         ScmProvider scmProviderMock = mock( ScmProvider.class );
364         when( scmProviderMock.checkIn( isA( ScmRepository.class ),
365                                        isA( ScmFileSet.class ),
366                                        isNull( ScmVersion.class ), 
367                                        isA( String.class ) ) ).thenThrow( new ScmException( "..." ) );
368 
369         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
370         stub.setScmProvider( scmProviderMock );
371 
372         // execute
373         try
374         {
375             phase.execute( releaseDescriptor, new DefaultReleaseEnvironment(), reactorProjects );
376 
377             fail( "Status check should have failed" );
378         }
379         catch ( ReleaseExecutionException e )
380         {
381             assertEquals( "check cause", ScmException.class, e.getCause().getClass() );
382         }
383         
384         //verify
385         verify( scmProviderMock ).checkIn( isA( ScmRepository.class ),
386                                            isA( ScmFileSet.class ),
387                                            isNull( ScmVersion.class ), 
388                                            isA( String.class ) );
389         verifyNoMoreInteractions( scmProviderMock );
390     }
391 
392     public void testScmResultFailure()
393         throws Exception
394     {
395         List<MavenProject> reactorProjects = createReactorProjects();
396         ReleaseDescriptor releaseDescriptor = createReleaseDescriptor();
397 
398         ScmManager scmManager = (ScmManager) lookup( ScmManager.ROLE );
399         ScmProviderStub providerStub = (ScmProviderStub) scmManager.getProviderByUrl(
400             releaseDescriptor.getScmSourceUrl() );
401 
402         providerStub.setCheckInScmResult( new CheckInScmResult( "", "", "", false ) );
403 
404         try
405         {
406             phase.execute( releaseDescriptor, new DefaultReleaseEnvironment(), reactorProjects );
407 
408             fail( "Commit should have failed" );
409         }
410         catch ( ReleaseScmCommandException e )
411         {
412             assertNull( "check no other cause", e.getCause() );
413         }
414     }
415 
416     public void testSuppressCommitWithRemoteTaggingFails()
417         throws Exception
418     {
419         ReleaseDescriptor descriptor = createReleaseDescriptor();
420         List<MavenProject> reactorProjects = createReactorProjects();
421 
422         descriptor.setRemoteTagging( true );
423         descriptor.setSuppressCommitBeforeTagOrBranch( true );
424 
425         ScmProvider scmProviderMock = mock( ScmProvider.class );
426         
427         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
428         stub.setScmProvider( scmProviderMock );
429 
430         try
431         {
432             phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
433 
434             fail( "Commit should have failed with ReleaseFailureException" );
435         }
436         catch ( ReleaseFailureException e )
437         {
438             assertNull( "check no other cause", e.getCause() );
439         }
440 
441         // never invoke scmProviderMock
442         verifyNoMoreInteractions( scmProviderMock );
443     }
444 
445     public void testSuppressCommitAfterBranch()
446         throws Exception
447     {
448         ReleaseDescriptor descriptor = createReleaseDescriptor();
449         List<MavenProject> reactorProjects = createReactorProjects();
450 
451         descriptor.setBranchCreation( true );
452         descriptor.setRemoteTagging( false );
453         descriptor.setSuppressCommitBeforeTagOrBranch( true );
454 
455         ScmProvider scmProviderMock = mock( ScmProvider.class );
456         
457         ScmManagerStub stub = (ScmManagerStub) lookup( ScmManager.ROLE );
458         stub.setScmProvider( scmProviderMock );
459 
460         phase.execute( descriptor, new DefaultReleaseEnvironment(), reactorProjects );
461 
462         // never invoke scmProviderMock
463         verifyNoMoreInteractions( scmProviderMock );
464     }
465 
466     private List<MavenProject> createReactorProjects()
467         throws Exception
468     {
469         return createReactorProjects( "scm-commit/", "single-pom" );
470     }
471 
472     private static ReleaseDescriptor createReleaseDescriptor()
473     {
474         ReleaseDescriptor descriptor = new ReleaseDescriptor();
475         descriptor.setScmSourceUrl( "scm-url" );
476         descriptor.setScmReleaseLabel( "release-label" );
477         descriptor.setWorkingDirectory( getTestFile( "target/test/checkout" ).getAbsolutePath() );
478         return descriptor;
479     }
480 }