package org.jenkinsci.plugins.unity3d;

import hudson.Launcher;
import hudson.remoting.Callable;
import hudson.remoting.Future;
import hudson.remoting.Pipe;
import hudson.remoting.VirtualChannel;
import hudson.slaves.DumbSlave;
import hudson.util.StreamCopyThread;
import hudson.util.StreamTaskListener;
import org.jvnet.hudson.test.HudsonTestCase;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutionException;

/**
 * @see ProcTest in Jenkins
 * @author Jerome Lacoste
 */
public class PipingTest extends HudsonTestCase implements Serializable {

    private VirtualChannel createSlaveChannel() throws Exception {
        DumbSlave s = createSlave();
        s.toComputer().connect(false).get();
        VirtualChannel ch=null;
        while (ch==null) {
            ch = s.toComputer().getChannel();
            Thread.sleep(100);
        }
        return ch;
    }

    public void testPipingFromRemoteWithLocalLaunch() throws Exception {
        doPipingFromRemoteTest(new Launcher.LocalLauncher(new StreamTaskListener(System.out, Charset.defaultCharset())));
    }

    public void testPipingFromRemoteWithRemoteLaunch() throws Exception {
        doPipingFromRemoteTest(new Launcher.RemoteLauncher(
                new StreamTaskListener(System.out, Charset.defaultCharset()),
                createSlaveChannel(), true));
    }



    private void doPipingFromRemoteTest(Launcher l) throws IOException, InterruptedException, ExecutionException {
        final Pipe p = Pipe.createRemoteToLocal();
        Future<String> piping = l.getChannel().callAsync(new PipingCallable(p));
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Thread t = new StreamCopyThread("Test", p.getIn(), os);
        t.start();
        
        assertEquals("DONE", piping.get());
        t.join();
        assertEquals("Hello", os.toString());

    }

    private static class PipingCallable implements Callable<String, Throwable>, Serializable {
        private final Pipe p;

        public PipingCallable(Pipe p) {
            this.p = p;
        }

        public String call() throws Throwable {
            OutputStream out = p.getOut();
            if (out == null) {
                throw new IllegalStateException("null output");
            }
            out.write("Hello".getBytes());
            out.close();
            return "DONE";
        }
    }
}

@@ -84,115 +84,9 @@
 ing.
-Callable;%0Aimport hudson.remoting.Future;%0Aimport hudson.remoting.Pipe;%0Aimport hudson.remoting.VirtualChannel
+*
 ;%0Aim
@@ -256,208 +256,287 @@
 .io.
-ByteArrayOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.OutputStream;%0Aimport java.io.Serializable;%0Aimport java.nio.charset.Charset;%0Aimport java.util.concurrent.ExecutionException;%0A%0A/**%0A * @s
+*;%0Aimport java.nio.charset.Charset;%0Aimport java.util.concurrent.ExecutionException;%0A%0A/**%0A * This test was written to find a solution to the piping issue. The Pipe class in Jenkins 1.446 doesn't work properly with asyncCall if the master and slave are on the same machine.%0A *%0A * S
 ee P
@@ -553,16 +553,34 @@
  Jenkins
+ for similar class
 %0A * @aut
@@ -1464,18 +1464,16 @@
 %0A    %7D%0A%0A
-%0A%0A
     priv
@@ -1591,51 +1591,287 @@
     
-final Pipe p = Pipe.createRemoteToLocal(
+PipedInputStream pis = new PipedInputStream();%0A        PipedOutputStream pos = new PipedOutputStream(pis);%0A%0A        boolean isLocal = l instanceof Launcher.LocalLauncher;%0A        System.out.println(%22IS LOCAL %22 + isLocal);%0A        OutputStream ros = new RemoteOutputStream(pos
 );%0A
+%0A
     
@@ -1942,17 +1942,19 @@
 allable(
-p
+ros
 ));%0A    
@@ -2066,16 +2066,10 @@
 %22, p
-.getIn()
+is
 , os
@@ -2332,22 +2332,32 @@
 e final 
-Pipe p
+OutputStream out
 ;%0A%0A     
@@ -2385,14 +2385,24 @@
 ble(
-Pipe p
+OutputStream out
 ) %7B%0A
@@ -2422,13 +2422,17 @@
 his.
-p = p
+out = out
 ;%0A  
@@ -2492,51 +2492,8 @@
 e %7B%0A
-            OutputStream out = p.getOut();%0A
     

Fix the test: remoteOutputStream works better than Pipe for our needs