//
//  ========================================================================
//  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.http;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

import org.junit.Ignore;
import org.junit.Test;

public class HttpTesterTest
{

    @Test
    @Ignore
    public void testExampleUsage() throws Exception
    {
        try(Socket socket = new Socket("www.google.com",80))
        {
            HttpTester.Request request = HttpTester.newRequest();
            request.setMethod("POST");
            request.setURI("/search");
            request.setVersion(HttpVersion.HTTP_1_0);
            request.put(HttpHeader.HOST,"www.google.com");
            request.put("Content-Type","application/x-www-form-urlencoded");
            request.setContent("q=jetty%20server");
            ByteBuffer output = request.generate();

            socket.getOutputStream().write(output.array(),output.arrayOffset()+output.position(),output.remaining());
            HttpTester.Input input = HttpTester.from(socket.getInputStream());
            HttpTester.Response response = HttpTester.parseResponse(input);
            System.err.printf("%s %s %s%n",response.getVersion(),response.getStatus(),response.getReason());
            for (HttpField field:response)
                System.err.printf("%s: %s%n",field.getName(),field.getValue());
            System.err.printf("%n%s%n",response.getContent());
        }
     
    }
    
    
    @Test
    public void testGetRequestBuffer10()
    {
        HttpTester.Request request =HttpTester.parseRequest(
            "GET /uri HTTP/1.0\r\n"+
            "Host: localhost\r\n"+
            "Connection: keep-alive\r\n"+
            "\r\n"+
            "GET /some/other/request /HTTP/1.0\r\n"+
            "Host: localhost\r\n"+
            "\r\n"
        );
        assertThat(request.getMethod(),is("GET"));
        assertThat(request.getUri(),is("/uri"));
        assertThat(request.getVersion(),is(HttpVersion.HTTP_1_0));
        assertThat(request.get(HttpHeader.HOST),is("localhost"));
        assertThat(request.getContent(),is(""));
    }
    
    @Test
    public void testGetRequestBuffer11()
    {
        HttpTester.Request request =HttpTester.parseRequest(
            "GET /uri HTTP/1.1\r\n"+
            "Host: localhost\r\n"+
            "\r\n"+
            "GET /some/other/request /HTTP/1.1\r\n"+
            "Host: localhost\r\n"+
            "\r\n"
        );
        assertThat(request.getMethod(),is("GET"));
        assertThat(request.getUri(),is("/uri"));
        assertThat(request.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(request.get(HttpHeader.HOST),is("localhost"));
        assertThat(request.getContent(),is(""));
    }

    
    
    @Test
    public void testPostRequestBuffer10()
    {
        HttpTester.Request request =HttpTester.parseRequest(
            "POST /uri HTTP/1.0\r\n"+
            "Host: localhost\r\n"+
            "Connection: keep-alive\r\n"+
            "Content-Length: 16\r\n"+
            "\r\n"+
            "0123456789ABCDEF"+
            "\r\n"+
            "GET /some/other/request /HTTP/1.0\r\n"+
            "Host: localhost\r\n"+
            "\r\n"
        );
        assertThat(request.getMethod(),is("POST"));
        assertThat(request.getUri(),is("/uri"));
        assertThat(request.getVersion(),is(HttpVersion.HTTP_1_0));
        assertThat(request.get(HttpHeader.HOST),is("localhost"));
        assertThat(request.getContent(),is("0123456789ABCDEF"));
        
    }
    
    @Test
    public void testPostRequestBuffer11()
    {
        HttpTester.Request request =HttpTester.parseRequest(
            "POST /uri HTTP/1.1\r\n"+
            "Host: localhost\r\n"+
            "Transfer-Encoding: chunked\r\n"+
            "\r\n"+
            "A\r\n"+
            "0123456789\r\n"+
            "6\r\n"+
            "ABCDEF\r\n"+
            "0\r\n"+
            "\r\n"+
            "GET /some/other/request /HTTP/1.1\r\n"+
            "Host: localhost\r\n"+
            "\r\n"
        );
        assertThat(request.getMethod(),is("POST"));
        assertThat(request.getUri(),is("/uri"));
        assertThat(request.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(request.get(HttpHeader.HOST),is("localhost"));
        assertThat(request.getContent(),is("0123456789ABCDEF"));
        
    }
    

    @Test
    public void testResponseEOFBuffer()
    {
        HttpTester.Response response =HttpTester.parseResponse(
            "HTTP/1.1 200 OK\r\n"+
            "Header: value\r\n"+
            "Connection: close\r\n"+
            "\r\n"+
            "0123456789ABCDEF"
        );

        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(200));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Header"),is("value"));
        assertThat(response.getContent(),is("0123456789ABCDEF")); 
    }
    
    @Test
    public void testResponseLengthBuffer()
    {
        HttpTester.Response response =HttpTester.parseResponse(
            "HTTP/1.1 200 OK\r\n"+
            "Header: value\r\n"+
            "Content-Length: 16\r\n"+
            "\r\n"+
            "0123456789ABCDEF"+
            "HTTP/1.1 200 OK\r\n"+
            "\r\n"
        );

        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(200));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Header"),is("value"));
        assertThat(response.getContent(),is("0123456789ABCDEF")); 
    }
    
    @Test
    public void testResponseChunkedBuffer()
    {
        HttpTester.Response response =HttpTester.parseResponse(
            "HTTP/1.1 200 OK\r\n"+
            "Header: value\r\n"+
            "Transfer-Encoding: chunked\r\n"+
            "\r\n"+
            "A\r\n"+
            "0123456789\r\n"+
            "6\r\n"+
            "ABCDEF\r\n"+
            "0\r\n"+
            "\r\n"+
            "HTTP/1.1 200 OK\r\n"+
            "\r\n"
        );

        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(200));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Header"),is("value"));
        assertThat(response.getContent(),is("0123456789ABCDEF")); 
    }

    @Test
    public void testResponsesInput() throws Exception
    {
        ByteArrayInputStream stream = new ByteArrayInputStream((
            "HTTP/1.1 200 OK\r\n"+
            "Header: value\r\n"+
            "Transfer-Encoding: chunked\r\n"+
            "\r\n"+
            "A\r\n"+
            "0123456789\r\n"+
            "6\r\n"+
            "ABCDEF\r\n"+
            "0\r\n"+
            "\r\n"+
            "HTTP/1.1 400 OK\r\n"+
            "Next: response\r\n"+
            "Content-Length: 16\r\n"+
            "\r\n"+
            "0123456789ABCDEF").getBytes(StandardCharsets.ISO_8859_1)
        );

        HttpTester.Input in = HttpTester.from(stream);
        
        HttpTester.Response response = HttpTester.parseResponse(in);
        
        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(200));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Header"),is("value"));
        assertThat(response.getContent(),is("0123456789ABCDEF")); 
        
        response = HttpTester.parseResponse(in);
        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(400));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Next"),is("response"));
        assertThat(response.getContent(),is("0123456789ABCDEF"));    
    }
    
    @Test
    public void testResponsesSplitInput() throws Exception
    {
        PipedOutputStream src = new PipedOutputStream();
        PipedInputStream stream = new PipedInputStream(src)
        {
            @Override
            public synchronized int read(byte[] b, int off, int len) throws IOException
            {
                if (available()==0)
                    return 0;
                return super.read(b,off,len);
            }
        };
        
        HttpTester.Input in = HttpTester.from(stream);
        
        src.write((
            "HTTP/1.1 200 OK\r\n"+
            "Header: value\r\n"+
            "Transfer-Encoding: chunked\r\n"+
            "\r\n"+
            "A\r\n"+
            "0123456789\r\n"+
            "6\r\n"+
            "ABC"
            ).getBytes(StandardCharsets.ISO_8859_1)
        );

        HttpTester.Response response = HttpTester.parseResponse(in);
        assertThat(response,nullValue());
        src.write((
            "DEF\r\n"+
            "0\r\n"+
            "\r\n"+
            "HTTP/1.1 400 OK\r\n"+
            "Next: response\r\n"+
            "Content-Length: 16\r\n"+
            "\r\n"+
            "0123456789"
            ).getBytes(StandardCharsets.ISO_8859_1)
        );
        
        
        response = HttpTester.parseResponse(in);
        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(200));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Header"),is("value"));
        assertThat(response.getContent(),is("0123456789ABCDEF")); 
        
        response = HttpTester.parseResponse(in);
        assertThat(response,nullValue());
        
        src.write((
            "ABCDEF"
            ).getBytes(StandardCharsets.ISO_8859_1)
        );
        
        response = HttpTester.parseResponse(in);
        assertThat(response.getVersion(),is(HttpVersion.HTTP_1_1));
        assertThat(response.getStatus(),is(400));
        assertThat(response.getReason(),is("OK"));
        assertThat(response.get("Next"),is("response"));
        assertThat(response.getContent(),is("0123456789ABCDEF"));    
    }
    
    
    
    

}
