001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license 003 * agreements. See the NOTICE file distributed with this work for additional information regarding 004 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the 005 * "License"); you may not use this file except in compliance with the License. You may obtain a 006 * copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software distributed under the License 011 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 012 * or implied. See the License for the specific language governing permissions and limitations under 013 * the License. 014 */ 015 package org.apache.maven.lifecycle.internal; 016 017 import junit.framework.TestCase; 018 import org.apache.maven.execution.MavenSession; 019 import org.apache.maven.lifecycle.LifecycleNotFoundException; 020 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException; 021 import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub; 022 import org.apache.maven.plugin.InvalidPluginDescriptorException; 023 import org.apache.maven.plugin.MojoNotFoundException; 024 import org.apache.maven.plugin.PluginDescriptorParsingException; 025 import org.apache.maven.plugin.PluginNotFoundException; 026 import org.apache.maven.plugin.PluginResolutionException; 027 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException; 028 import org.apache.maven.plugin.version.PluginVersionResolutionException; 029 030 import java.io.ByteArrayOutputStream; 031 import java.io.PrintStream; 032 import java.util.ArrayList; 033 import java.util.Arrays; 034 import java.util.Iterator; 035 import java.util.List; 036 import java.util.concurrent.Callable; 037 import java.util.concurrent.CompletionService; 038 import java.util.concurrent.ExecutorCompletionService; 039 import java.util.concurrent.ExecutorService; 040 import java.util.concurrent.Executors; 041 import java.util.concurrent.Future; 042 043 /** 044 * @author Kristian Rosenvold 045 */ 046 public class ThreadOutputMuxerTest 047 extends TestCase 048 { 049 050 final String paid = "Paid"; 051 052 final String in = "In"; 053 054 final String full = "Full"; 055 056 public void testSingleThreaded() 057 throws Exception 058 { 059 ProjectBuildList src = getProjectBuildList(); 060 ProjectBuildList projectBuildList = 061 new ProjectBuildList( Arrays.asList( src.get( 0 ), src.get( 1 ), src.get( 2 ) ) ); 062 063 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 064 PrintStream systemOut = new PrintStream( byteArrayOutputStream ); 065 ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut ); 066 067 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 0 ) ); 068 System.out.print( paid ); // No, this does not print to system.out. It's part of the test 069 assertEquals( paid.length(), byteArrayOutputStream.size() ); 070 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 1 ) ); 071 System.out.print( in ); // No, this does not print to system.out. It's part of the test 072 assertEquals( paid.length(), byteArrayOutputStream.size() ); 073 threadOutputMuxer.associateThreadWithProjectSegment( projectBuildList.get( 2 ) ); 074 System.out.print( full ); // No, this does not print to system.out. It's part of the test 075 assertEquals( paid.length(), byteArrayOutputStream.size() ); 076 077 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 0 ) ); 078 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 1 ) ); 079 threadOutputMuxer.setThisModuleComplete( projectBuildList.get( 2 ) ); 080 threadOutputMuxer.close(); 081 assertEquals( ( paid + in + full ).length(), byteArrayOutputStream.size() ); 082 } 083 084 public void testMultiThreaded() 085 throws Exception 086 { 087 ProjectBuildList projectBuildList = getProjectBuildList(); 088 089 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 090 PrintStream systemOut = new PrintStream( byteArrayOutputStream ); 091 final ThreadOutputMuxer threadOutputMuxer = new ThreadOutputMuxer( projectBuildList, systemOut ); 092 093 final List<String> stringList = 094 Arrays.asList( "Thinkin", "of", "a", "master", "plan", "Cuz", "ain’t", "nuthin", "but", "sweat", "inside", 095 "my", "hand" ); 096 Iterator<String> lyrics = stringList.iterator(); 097 List<Outputter> outputters = new ArrayList<Outputter>(); 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 }