1 package org.apache.maven.lifecycle.internal.builder.multithreaded;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import junit.framework.TestCase;
19
20 import org.apache.maven.execution.MavenSession;
21 import org.apache.maven.lifecycle.LifecycleNotFoundException;
22 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
23 import org.apache.maven.lifecycle.internal.ProjectBuildList;
24 import org.apache.maven.lifecycle.internal.ProjectSegment;
25 import org.apache.maven.lifecycle.internal.builder.multithreaded.ThreadOutputMuxer;
26 import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub;
27 import org.apache.maven.plugin.InvalidPluginDescriptorException;
28 import org.apache.maven.plugin.MojoNotFoundException;
29 import org.apache.maven.plugin.PluginDescriptorParsingException;
30 import org.apache.maven.plugin.PluginNotFoundException;
31 import org.apache.maven.plugin.PluginResolutionException;
32 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
33 import org.apache.maven.plugin.version.PluginVersionResolutionException;
34
35 import java.io.ByteArrayOutputStream;
36 import java.io.PrintStream;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.concurrent.Callable;
42 import java.util.concurrent.CompletionService;
43 import java.util.concurrent.ExecutorCompletionService;
44 import java.util.concurrent.ExecutorService;
45 import java.util.concurrent.Executors;
46 import java.util.concurrent.Future;
47
48
49
50
51 public class ThreadOutputMuxerTest
52 extends TestCase
53 {
54
55 final String paid = "Paid";
56
57 final String in = "In";
58
59 final String full = "Full";
60
61 public void testSingleThreaded()
62 throws Exception
63 {
64 ProjectBuildList src = getProjectBuildList();
65 ProjectBuildList projectBuildList =
66 new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) );
67
68 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
69 PrintStream systemOut = new PrintStream( byteArrayOutputStream );
70 ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
71
72 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) );
73 System.out.print( paid );
74 assertEquals( paid.length(), byteArrayOutputStream.size() );
75 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) );
76 System.out.print( in );
77 assertEquals( paid.length(), byteArrayOutputStream.size() );
78 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) );
79 System.out.print( full );
80 assertEquals( paid.length(), byteArrayOutputStream.size() );
81
82 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) );
83 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) );
84 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) );
85 threadOutputMuxer.close();
86 assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() );
87 }
88
89 public void testMultiThreaded()
90 throws Exception
91 {
92 ProjectBuildList projectBuildList = getProjectBuildList();
93
94 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
95 PrintStream systemOut = new PrintStream( byteArrayOutputStream );
96 final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut );
97
98 final List<String> stringList =
99 Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "ain’t", "nuthin", "but", "sweat", "inside",
100 "my", "hand" );
101 Iterator<String> lyrics = stringList.iterator();
102
103 ExecutorService executor = Executors.newFixedThreadPool( 10 );
104 CompletionService<ProjectSegment> service = new ExecutorCompletionService<>( executor );
105
106 List<Future<ProjectSegment>> futures = new ArrayList<>();
107 for ( ProjectSegment projectBuild : projectBuildList )
108 {
109 final Future<ProjectSegment> buildFuture =
110 service.submit( new Outputter( threadOutputMuxer, projectBuild, lyrics.next() ) );
111 futures.add( buildFuture );
112 }
113
114 for ( Future<ProjectSegment> future : futures )
115 {
116 future.get();
117 }
118 int expectedLength = 0;
119 for ( int i = 0; i < projectBuildList.size(); i++ )
120 {
121 expectedLength += stringList.get( i ).length();
122 }
123
124 threadOutputMuxer.close();
125 final byte[] bytes = byteArrayOutputStream.toByteArray();
126 String result = new String( bytes );
127 assertEquals( result, expectedLength, bytes.length );
128
129
130 }
131
132 class Outputter
133 implements Callable<ProjectSegment>
134 {
135 private final ThreadOutputMuxer threadOutputMuxer;
136
137 private final ProjectSegment item;
138
139 private final String response;
140
141 Outputter( ThreadOutputMuxer threadOutputMuxer, ProjectSegment item, String response )
142 {
143 this.threadOutputMuxer = threadOutputMuxer;
144 this.item = item;
145 this.response = response;
146 }
147
148 public ProjectSegment call()
149 throws Exception
150 {
151 threadOutputMuxer.associateThreadWithProjectSegment( item );
152 System.out.print( response );
153 threadOutputMuxer.setThisModuleComplete( item );
154 return item;
155 }
156 }
157
158
159 private ProjectBuildList getProjectBuildList()
160 throws InvalidPluginDescriptorException, PluginVersionResolutionException, PluginDescriptorParsingException,
161 NoPluginFoundForPrefixException, MojoNotFoundException, PluginNotFoundException, PluginResolutionException,
162 LifecyclePhaseNotFoundException, LifecycleNotFoundException
163 {
164 final MavenSession session = ProjectDependencyGraphStub.getMavenSession();
165 return ProjectDependencyGraphStub.getProjectBuildList( session );
166 }
167 }