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 }