001 package org.apache.maven.lifecycle.internal;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
005 * agreements. See the NOTICE file distributed with this work for additional information regarding
006 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance with the License. You may obtain a
008 * copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed under the License
013 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
014 * or implied. See the License for the specific language governing permissions and limitations under
015 * the License.
016 */
017
018 import junit.framework.TestCase;
019 import org.apache.maven.execution.MavenSession;
020 import org.apache.maven.lifecycle.LifecycleNotFoundException;
021 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
022 import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
023 import org.apache.maven.plugin.InvalidPluginDescriptorException;
024 import org.apache.maven.plugin.MojoNotFoundException;
025 import org.apache.maven.plugin.PluginDescriptorParsingException;
026 import org.apache.maven.plugin.PluginNotFoundException;
027 import org.apache.maven.plugin.PluginResolutionException;
028 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
029 import org.apache.maven.plugin.version.PluginVersionResolutionException;
030
031 import java.io.ByteArrayOutputStream;
032 import java.io.PrintStream;
033 import java.util.ArrayList;
034 import java.util.Arrays;
035 import java.util.Iterator;
036 import java.util.List;
037 import java.util.concurrent.Callable;
038 import java.util.concurrent.CompletionService;
039 import java.util.concurrent.ExecutorCompletionService;
040 import java.util.concurrent.ExecutorService;
041 import java.util.concurrent.Executors;
042 import java.util.concurrent.Future;
043
044 /**
045 * @author Kristian Rosenvold
046 */
047 public class ThreadOutputMuxerTest
048 extends TestCase
049 {
050
051 final String paid = "Paid";
052
053 final String in = "In";
054
055 final String full = "Full";
056
057 public void testSingleThreaded()
058 throws Exception
059 {
060 ProjectBuildList src = getProjectBuildList();
061 ProjectBuildList projectBuildList =
062 new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) );
063
064 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
065 PrintStream systemOut = new PrintStream( byteArrayOutputStream );
066 ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
067
068 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) );
069 System.out.print( paid ); // No, this does not print to system.out. It's part of the test
070 assertEquals( paid.length(), byteArrayOutputStream.size() );
071 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) );
072 System.out.print( in ); // No, this does not print to system.out. It's part of the test
073 assertEquals( paid.length(), byteArrayOutputStream.size() );
074 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) );
075 System.out.print( full ); // No, this does not print to system.out. It's part of the test
076 assertEquals( paid.length(), byteArrayOutputStream.size() );
077
078 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) );
079 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) );
080 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) );
081 threadOutputMuxer.close();
082 assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() );
083 }
084
085 public void testMultiThreaded()
086 throws Exception
087 {
088 ProjectBuildList projectBuildList = getProjectBuildList();
089
090 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
091 PrintStream systemOut = new PrintStream( byteArrayOutputStream );
092 final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
093
094 final List<String> stringList =
095 Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "ain’t", "nuthin", "but", "sweat", "inside",
096 "my", "hand" );
097 Iterator<String> lyrics = stringList.iterator();
098
099 ExecutorService executor = Executors.newFixedThreadPool( 10 );
100 CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
101
102 List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
103 for ( ProjectSegment projectBuild : projectBuildList )
104 {
105 final Future<ProjectSegment> buildFuture =
106 service.submit( new Outputter( threadOutputMuxer, projectBuild, lyrics.next() ) );
107 futures.add( buildFuture );
108 }
109
110 for ( Future<ProjectSegment> future : futures )
111 {
112 future.get();
113 }
114 int expectedLength = 0;
115 for ( int i = 0; i < projectBuildList.size(); i++ )
116 {
117 expectedLength += stringList.get( i ).length();
118 }
119
120 threadOutputMuxer.close();
121 final byte[] bytes = byteArrayOutputStream.toByteArray();
122 String result = new String( bytes );
123 assertEquals( result, expectedLength, bytes.length );
124
125
126 }
127
128 class Outputter
129 implements Callable<ProjectSegment>
130 {
131 private final ThreadOutputMuxer threadOutputMuxer;
132
133 private final ProjectSegment item;
134
135 private final String response;
136
137 Outputter( ThreadOutputMuxer threadOutputMuxer, ProjectSegment item, String response )
138 {
139 this.threadOutputMuxer = threadOutputMuxer;
140 this.item = item;
141 this.response = response;
142 }
143
144 public ProjectSegment call()
145 throws Exception
146 {
147 threadOutputMuxer.associateThreadWithProjectSegment( item );
148 System.out.print( response );
149 threadOutputMuxer.setThisModuleComplete( item );
150 return item;
151 }
152 }
153
154
155 private ProjectBuildList getProjectBuildList()
156 throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
157 NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
158 LifecyclePhaseNotFoundException, LifecycleNotFoundException
159 {
160 final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
161 return ProjectDependencyGraphStub.getProjectBuildList( session );
162 }
163 }