package com.wizzardo.http;

import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by wizzardo on 20.06.15.
 */
public class PipeliningTest extends ServerTest {

    @Test
    public void test_1() throws IOException {
        handler = new UrlHandler()
                .append("/", (request, response) -> response.setBody("ok")) //length = 123
                .append("/foo", (request, response) -> response.setBody("foo")) //length = 124
                .append("/foobar", (request, response) -> response.setBody("foobar")) //length = 127
        ;

        Assert.assertTrue(response(request("/"), 123).endsWith("\r\n\r\nok"));

        String response = response(request("/") + request("/foo") + request("/foobar"), 123 + 124 + 127);
        Assert.assertTrue(response.contains("\r\n\r\nok"));
        Assert.assertTrue(response.contains("\r\n\r\nfoo"));
        Assert.assertTrue(response.endsWith("\r\n\r\nfoobar"));
    }

    protected String response(String request, int limit) {
        try {
            Socket socket = new Socket("localhost", port);
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();

            byte[] response = new byte[limit];
            AtomicBoolean wait = new AtomicBoolean(true);
            new Thread(() -> {
                int r = 0;
                int total = 0;
                try {
                    while (total < limit && (r = in.read(response, total, limit - total)) != -1) {
                        total += r;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    assert false;
                }
                synchronized (PipeliningTest.this) {
                    wait.set(false);
                    PipeliningTest.this.notify();
                }
            }).start();
            out.write(request.getBytes());

            synchronized (PipeliningTest.this) {
                if (wait.get())
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
            return new String(response);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    protected String request(String path) {
        return "GET " + path + " HTTP/1.1\r\n" +
                "Host: localhost:" + port + "\r\n" +
                "Connection: Keep-Alive\r\n" +
                "\r\n";
    }

}

@@ -322,16 +322,209 @@
 erTest %7B
+%0A    @Override%0A    public void setUp() throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException %7B%0A        workers = 0; // todo: fix multithreading%0A        super.setUp();%0A    %7D
 %0A%0A    @T
@@ -1276,32 +1276,516 @@
 obar%22));%0A    %7D%0A%0A
+    @Test%0A    public void test_2() throws IOException %7B%0A        handler = new UrlHandler()%0A                .append(%22/%22, (request, response) -%3E response.setBody(%22ok%22)) //length = 123%0A        ;%0A%0A        StringBuilder sb = new StringBuilder();%0A        int n = 4000;%0A        for (int i = 0; i %3C n; i++) %7B%0A            sb.append(request(%22/%22));%0A        %7D%0A        String response = response(sb.toString(), n * 123);%0A        Assert.assertEquals(n, response.split(%22%5Cr%5Cn%5Cr%5Cnok%22).length);%0A    %7D%0A%0A
     protected St

add test