View Javadoc

1   package org.apache.maven.continuum.scm.queue;
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 java.io.File;
23  import java.io.IOException;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.continuum.buildmanager.BuildsManager;
29  import org.apache.continuum.buildmanager.ParallelBuildsManager;
30  import org.apache.continuum.dao.ProjectScmRootDao;
31  import org.apache.continuum.model.project.ProjectScmRoot;
32  import org.apache.continuum.taskqueue.BuildProjectTask;
33  import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
34  import org.apache.maven.continuum.AbstractContinuumTest;
35  import org.apache.maven.continuum.configuration.ConfigurationService;
36  import org.apache.maven.continuum.core.action.AbstractContinuumAction;
37  import org.apache.maven.continuum.model.project.BuildDefinition;
38  import org.apache.maven.continuum.model.project.Project;
39  import org.apache.maven.continuum.model.project.ProjectGroup;
40  import org.apache.maven.continuum.project.ContinuumProjectState;
41  import org.apache.maven.continuum.project.builder.ContinuumProjectBuilder;
42  import org.apache.maven.continuum.project.builder.ContinuumProjectBuilderException;
43  import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
44  import org.apache.maven.continuum.project.builder.maven.MavenTwoContinuumProjectBuilder;
45  import org.codehaus.plexus.action.ActionManager;
46  import org.codehaus.plexus.taskqueue.TaskQueue;
47  import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
48  import org.codehaus.plexus.util.StringUtils;
49  
50  public class PrepareBuildProjectsTaskExecutorTest
51      extends AbstractContinuumTest
52  {
53      private ContinuumProjectBuilder projectBuilder;
54  
55      private TaskQueue prepareBuildQueue;
56  
57      private TaskQueueExecutor prepareBuildTaskQueueExecutor;
58  
59      private ActionManager actionManager;
60  
61      private ProjectScmRootDao projectScmRootDao;
62  
63      private ConfigurationService configurationService;
64  
65      private BuildsManager buildsManager;
66  
67      @Override
68      protected void setUp()
69          throws Exception
70      {
71          super.setUp();
72  
73          projectBuilder =
74              (ContinuumProjectBuilder) lookup( ContinuumProjectBuilder.ROLE, MavenTwoContinuumProjectBuilder.ID );
75  
76          prepareBuildQueue = (TaskQueue) lookup( TaskQueue.ROLE, "prepare-build-project" );
77  
78          prepareBuildTaskQueueExecutor = (TaskQueueExecutor) lookup( TaskQueueExecutor.ROLE, "prepare-build-project" );
79  
80          projectScmRootDao = (ProjectScmRootDao) lookup( ProjectScmRootDao.class.getName() );
81  
82          actionManager = (ActionManager) lookup( ActionManager.ROLE );
83  
84          configurationService =  (ConfigurationService ) lookup( "configurationService" );
85  
86          buildsManager = (ParallelBuildsManager) lookup( BuildsManager.class, "parallel" );
87      }
88  
89      public void testCheckoutPrepareBuildMultiModuleProject()
90          throws Exception
91      {
92          PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", false, false );
93  
94          this.prepareBuildQueue.put( task );
95  
96          List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
97  
98          assertEquals( "failed to add all projects", 3, projects.size() );
99  
100         Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
101         Project moduleA = getProjectDao().getProjectByName( "module-A" );
102         Project moduleB = getProjectDao().getProjectByName( "module-B" );
103 
104         // wait while task finishes prepare build
105         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
106                         prepareBuildTaskQueueExecutor.getCurrentTask() != null )
107         {
108             Thread.sleep( 10 );
109         }
110 
111         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
112         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
113 
114         File workingDir = configurationService.getWorkingDirectory();
115 
116         assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", new File( workingDir, Integer.toString( rootProject.getId() ) ).exists() );
117 
118         assertTrue( "checkout directory of project 'module-A' does not exist.", new File( workingDir, Integer.toString( moduleA.getId() ) ).exists() );
119 
120         assertTrue( "checkout directory of project 'module-B' does not exist.", new File( workingDir, Integer.toString( moduleB.getId() ) ).exists() );
121 
122         while( !buildsManager.getCurrentBuilds().isEmpty() ||
123                         isAnyProjectInBuildQueue() )
124         {
125             Thread.sleep( 10 );
126         }
127     }
128 
129     public void testCheckoutPrepareBuildMultiModuleProjectFreshBuild()
130         throws Exception
131     {
132         PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", false, true );
133 
134         this.prepareBuildQueue.put( task );
135 
136         List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
137 
138         assertEquals( "failed to add all projects", 3, projects.size() );
139 
140         Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
141         Project moduleA = getProjectDao().getProjectByName( "module-A" );
142         Project moduleB = getProjectDao().getProjectByName( "module-B" );
143 
144         // wait while task finishes prepare build
145         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
146                         prepareBuildTaskQueueExecutor.getCurrentTask() != null )
147         {
148             Thread.sleep( 10 );
149         }
150 
151         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
152         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
153 
154         File workingDir = configurationService.getWorkingDirectory();
155 
156         assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", new File( workingDir, Integer.toString( rootProject.getId() ) ).exists() );
157 
158         assertTrue( "checkout directory of project 'module-A' does not exist.", new File( workingDir, Integer.toString( moduleA.getId() ) ).exists() );
159 
160         assertTrue( "checkout directory of project 'module-B' does not exist.", new File( workingDir, Integer.toString( moduleB.getId() ) ).exists() );
161 
162         while( !buildsManager.getCurrentBuilds().isEmpty() ||
163                         isAnyProjectInBuildQueue() )
164         {
165             Thread.sleep( 10 );
166         }
167     }
168 /*
169     public void testCheckoutPrepareBuildSingleCheckedoutMultiModuleProject()
170         throws Exception
171     {
172         PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", true, false );
173 
174         this.prepareBuildQueue.put( task );
175 
176         List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
177 
178         assertEquals( "failed to add all projects", 3, projects.size() );
179 
180         Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
181 
182         // wait while task finishes prepare build
183         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
184                         prepareBuildTaskQueueExecutor.getCurrentTask() != null )
185         {
186             Thread.sleep( 10 );
187         }
188 
189         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
190         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
191 
192         File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString( rootProject.getId() ) );
193 
194         assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", checkedOutDir.exists() );
195 
196         assertTrue( "module-A was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-A" ).exists() );
197 
198         assertTrue( "module-B was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-B" ).exists() );
199     }
200 
201     public void testCheckoutPrepareBuildSingleCheckedoutMultiModuleProjectFreshBuild()
202         throws Exception
203     {
204         PrepareBuildProjectsTask task = createTask( "src/test-projects/multi-module/pom.xml", true, true );
205 
206         this.prepareBuildQueue.put( task );
207 
208         List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
209 
210         assertEquals( "failed to add all projects", 3, projects.size() );
211 
212         Project rootProject = getProjectDao().getProjectByName( "multi-module-parent" );
213 
214         // wait while task finishes prepare build
215         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
216                         prepareBuildTaskQueueExecutor.getCurrentTask() != null )
217         {
218             Thread.sleep( 10 );
219         }
220 
221         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
222         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
223 
224         File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString( rootProject.getId() ) );
225 
226         assertTrue( "checkout directory of project 'multi-module-parent' does not exist.", checkedOutDir.exists() );
227 
228         assertTrue( "module-A was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-A" ).exists() );
229 
230         assertTrue( "module-B was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-B" ).exists() );
231     }
232 
233     public void testCheckoutPrepareBuildSingleCheckoutFlatMultiModuleProject()
234         throws Exception
235     {
236         PrepareBuildProjectsTask task = createTask( "src/test-projects/flat-multi-module/parent-project/pom.xml", true, false );
237 
238         this.prepareBuildQueue.put( task );
239 
240         List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
241 
242         assertEquals( "failed to add all projects", 3, projects.size() );
243 
244         Project rootProject = getProjectDao().getProjectByName( "parent-project" );
245 
246         // wait while task finishes prepare build
247         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
248                         prepareBuildTaskQueueExecutor.getCurrentTask() != null )
249         {
250             Thread.sleep( 10 );
251         }
252 
253         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
254         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
255 
256         File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString( rootProject.getId() ) );
257 
258         assertTrue( "checkout directory of project 'parent-project' does not exist.", new File( checkedOutDir, "parent-project" ).exists() );
259 
260         assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-a" ).exists() );
261 
262         assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-b" ).exists() );
263     }
264 
265     public void testCheckoutPrepareBuildSingleCheckoutFlatMultiModuleProjectBuildFresh()
266         throws Exception
267     {
268         PrepareBuildProjectsTask task = createTask( "src/test-projects/flat-multi-module/parent-project/pom.xml", true, true );
269 
270         this.prepareBuildQueue.put( task );
271 
272         List<Project> projects = getProjectDao().getProjectsInGroup( task.getProjectGroupId() );
273 
274         assertEquals( "failed to add all projects", 3, projects.size() );
275 
276         Project rootProject = getProjectDao().getProjectByName( "parent-project" );
277 
278         ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
279         // wait while task finishes prepare build
280         while( !prepareBuildQueue.getQueueSnapshot().isEmpty() || 
281                         prepareBuildTaskQueueExecutor.getCurrentTask() != null || scmRoot.getState() == ContinuumProjectState.UPDATING )
282         {
283             Thread.sleep( 10 );
284 
285             scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
286         }
287 
288         scmRoot = projectScmRootDao.getProjectScmRoot( task.getProjectScmRootId() );
289         assertEquals( "Failed to update multi-module project", ContinuumProjectState.UPDATED, scmRoot.getState() );
290 
291         File checkedOutDir = new File( configurationService.getWorkingDirectory(), Integer.toString( rootProject.getId() ) );
292 
293         assertTrue( "checkout directory of project 'parent-project' does not exist.", new File( checkedOutDir, "parent-project" ).exists() );
294 
295         assertTrue( "module-a was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-a" ).exists() );
296 
297         assertTrue( "module-b was not checked out in the same directory as it's parent.", new File( checkedOutDir, "module-b" ).exists() );
298     }
299 */
300     
301     private PrepareBuildProjectsTask createTask( String pomResource, boolean singleCheckout, boolean buildFresh )
302         throws Exception
303     {
304         ProjectGroup projectGroup = getProjectGroup( pomResource, singleCheckout );
305 
306         BuildDefinition buildDefinition = new BuildDefinition();
307         buildDefinition.setId( 0 );
308         buildDefinition.setGoals( "clean" );
309         buildDefinition.setBuildFresh( buildFresh );
310         
311         projectGroup.addBuildDefinition( buildDefinition );
312 
313         Map<String, Object> pgContext = new HashMap<String, Object>();
314 
315         AbstractContinuumAction.setWorkingDirectory( pgContext, configurationService.getWorkingDirectory().getAbsolutePath() );
316 
317         AbstractContinuumAction.setUnvalidatedProjectGroup( pgContext, projectGroup );
318 
319         actionManager.lookup( "validate-project-group" ).execute( pgContext );
320 
321         actionManager.lookup( "store-project-group" ).execute( pgContext );
322 
323         int projectGroupId = AbstractContinuumAction.getProjectGroupId( pgContext );
324 
325         projectGroup = getProjectGroupDao().getProjectGroupWithBuildDetailsByProjectGroupId( projectGroupId );
326 
327         String scmRootUrl = getScmRootUrl( projectGroup );
328 
329         assertNotNull( scmRootUrl );
330 
331         ProjectScmRoot scmRoot = getProjectScmRoot( projectGroup, scmRootUrl );
332 
333         assertNotNull( scmRoot );
334 
335         buildDefinition = (BuildDefinition) projectGroup.getBuildDefinitions().get( 0 );
336 
337         Map<Integer, Integer> map = new HashMap<Integer, Integer>();
338 
339         Project rootProject = null;
340 
341         List<Project> projects = (List<Project>) projectGroup.getProjects();
342 
343         for ( Project project : projects )
344         {
345             assertFalse( project.getId() == 0 );
346             
347             map.put( project.getId(), buildDefinition.getId() );
348 
349             if ( rootProject == null || rootProject.getId() > project.getId() )
350             {
351                 rootProject = project;
352             }
353         }
354 
355         assertEquals( 3, map.size() );
356         PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( map, 1, 
357                                                                       projectGroupId, projectGroup.getName(), 
358                                                                       scmRoot.getScmRootAddress(), scmRoot.getId() );
359 
360         return task;
361     }
362 
363     private ProjectGroup getProjectGroup( String pomResource, boolean singleCheckout )
364         throws ContinuumProjectBuilderException, IOException
365     {
366         File pom = getTestFile( pomResource );
367     
368         assertNotNull( "Can't find project " + pomResource, pom );
369 
370         //ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( pom.toURL(), null, null, true, singleCheckout );
371         ContinuumProjectBuildingResult result = projectBuilder.buildProjectsFromMetadata( pom.toURL(), null, null, true );
372 
373         // some assertions to make sure our expectations match. This is NOT
374         // meant as a unit test for the projectbuilder!
375     
376         assertNotNull( "Project list not null", result.getProjects() );
377     
378         assertEquals( "#Projectgroups", 1, result.getProjectGroups().size() );
379     
380         ProjectGroup pg = result.getProjectGroups().get( 0 );
381     
382         if ( !result.getProjects().isEmpty() )
383         {
384             for ( Project p : result.getProjects() )
385             {
386                 pg.addProject( p );
387             }
388         }
389 
390         return pg;
391     }
392 
393     private ProjectScmRoot getProjectScmRoot ( ProjectGroup pg, String url )
394         throws Exception
395     {
396         if ( StringUtils.isEmpty( url ) )
397         {
398             return null;
399         }
400 
401         ProjectScmRoot scmRoot =
402             projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( pg.getId(), url );
403 
404         if ( scmRoot != null )
405         {
406             return scmRoot;
407         }
408 
409         ProjectScmRoot projectScmRoot = new ProjectScmRoot();
410 
411         projectScmRoot.setProjectGroup( pg );
412 
413         projectScmRoot.setScmRootAddress( url );
414 
415         projectScmRoot.setState( ContinuumProjectState.ERROR );
416 
417         return projectScmRootDao.addProjectScmRoot( projectScmRoot );
418     }
419 
420     private String getScmRootUrl( ProjectGroup pg )
421     {
422         String scmRootUrl = null;
423 
424         for ( Project project : (List<Project>) pg.getProjects() )
425         {
426             String scmUrl = project.getScmUrl();
427 
428             scmRootUrl = getCommonPath( scmUrl, scmRootUrl );
429         }
430 
431         return scmRootUrl;
432     }
433 
434     private String getCommonPath( String path1, String path2 )
435     {
436         if ( path2 == null || path2.equals( "" ) )
437         {
438             return path1;
439         }
440         else
441         {
442             int indexDiff = StringUtils.differenceAt( path1, path2 );
443             return path1.substring( 0, indexDiff );
444         }
445     }
446 
447     private boolean isAnyProjectInBuildQueue()
448         throws Exception
449     {
450         Map<String, List<BuildProjectTask>> buildTasks = buildsManager.getProjectsInBuildQueues();
451 
452         for ( String queue : buildTasks.keySet() )
453         {
454             if ( !buildTasks.get( queue ).isEmpty() )
455             {
456                 return true;
457             }
458         }
459 
460         return false;
461     }
462 }