/*
 * libjingle
 * Copyright 2004--2011, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include "talk/base/asynchttprequest.h"
#include "talk/base/gunit.h"
#include "talk/base/httpserver.h"
#include "talk/base/socketstream.h"
#include "talk/base/thread.h"

namespace talk_base {

static const SocketAddress kServerAddr("127.0.0.1", 0);
static const SocketAddress kServerHostnameAddr("localhost", 0);
static const char kServerGetPath[] = "/get";
static const char kServerPostPath[] = "/post";
static const char kServerResponse[] = "This is a test";
  
class TestHttpServer : public HttpServer, public sigslot::has_slots<> {
 public:
  TestHttpServer(Thread* thread, const SocketAddress& addr)
      : socket_(thread->socketserver()->CreateAsyncSocket(SOCK_STREAM)) {
    socket_->Bind(addr);
    socket_->Listen(5);
    socket_->SignalReadEvent.connect(this, &TestHttpServer::OnAccept);
  }

  SocketAddress address() const { return socket_->GetLocalAddress(); }

 private:
  void OnAccept(AsyncSocket* socket) {
    AsyncSocket* new_socket = socket_->Accept(NULL);
    if (new_socket) {
      HandleConnection(new SocketStream(new_socket));
    }
  }
  talk_base::scoped_ptr<AsyncSocket> socket_;
};

class AsyncHttpRequestTest : public testing::Test,
                             public sigslot::has_slots<> {
 public:
  AsyncHttpRequestTest()
      : done_(false), server_(Thread::Current(), kServerAddr) {
    server_.SignalHttpRequest.connect(this, &AsyncHttpRequestTest::OnRequest);
  }

  bool done() const { return done_; }

  AsyncHttpRequest* CreateGetRequest(const std::string& host, int port,
                                     const std::string& path) {
    talk_base::AsyncHttpRequest* request =
        new talk_base::AsyncHttpRequest("unittest");
    request->SignalWorkDone.connect(this,
        &AsyncHttpRequestTest::OnRequestDone);
    request->request().verb = talk_base::HV_GET;
    request->set_host(host);
    request->set_port(port);
    request->request().path = path;
    request->response().document.reset(new MemoryStream());
    return request;
  }
  AsyncHttpRequest* CreatePostRequest(const std::string& host, int port,
                                      const std::string& path,
                                      const std::string content_type,
                                      StreamInterface* content) {
    talk_base::AsyncHttpRequest* request =
        new talk_base::AsyncHttpRequest("unittest");
    request->SignalWorkDone.connect(this,
        &AsyncHttpRequestTest::OnRequestDone);
    request->request().verb = talk_base::HV_POST;
    request->set_host(host);
    request->set_port(port);
    request->request().path = path;
    request->request().setContent(content_type, content);
    request->response().document.reset(new MemoryStream());
    return request;
  }

  const TestHttpServer& server() const { return server_; }

 protected:
  void OnRequest(HttpServer* server, HttpServerTransaction* t) {
    if (t->request.path == kServerGetPath) {
      t->response.set_success("text/plain", new MemoryStream(kServerResponse));
    } else if (t->request.path == kServerPostPath) {
      // reverse the data and reply
      size_t size;
      StreamInterface* in = t->request.document.get();
      StreamInterface* out = new MemoryStream();
      in->GetSize(&size);
      for (size_t i = 0; i < size; ++i) {
        char ch;
        in->SetPosition(size - i - 1);
        in->Read(&ch, 1, NULL, NULL);
        out->Write(&ch, 1, NULL, NULL);
      }
      out->Rewind();
      t->response.set_success("text/plain", out);
    } else {
      t->response.set_error(404);
    }
    server_.Respond(t);
  }
  void OnRequestDone(SignalThread* thread) {
    done_ = true;
  }

 private:
  bool done_;
  TestHttpServer server_;
};

TEST_F(AsyncHttpRequestTest, TestGetSuccess) {
  AsyncHttpRequest* req = CreateGetRequest(
      kServerHostnameAddr.hostname(), server().address().port(),
      kServerGetPath);
  req->Start();
  EXPECT_TRUE_WAIT(done(), 5000);
  std::string response;
  EXPECT_EQ(200U, req->response().scode);
  ASSERT_TRUE(req->response().document.get() != NULL);
  req->response().document->Rewind();
  req->response().document->ReadLine(&response);
  EXPECT_EQ(kServerResponse, response);
  req->Release();
}

TEST_F(AsyncHttpRequestTest, TestGetNotFound) {
  AsyncHttpRequest* req = CreateGetRequest(
      kServerHostnameAddr.hostname(), server().address().port(),
      "/bad");
  req->Start();
  EXPECT_TRUE_WAIT(done(), 5000);
  size_t size;
  EXPECT_EQ(404U, req->response().scode);
  ASSERT_TRUE(req->response().document.get() != NULL);
  req->response().document->GetSize(&size);
  EXPECT_EQ(0U, size);
  req->Release();
}

TEST_F(AsyncHttpRequestTest, TestPostSuccess) {
  AsyncHttpRequest* req = CreatePostRequest(
      kServerHostnameAddr.hostname(), server().address().port(),
      kServerPostPath, "text/plain", new MemoryStream("abcd1234"));
  req->Start();
  EXPECT_TRUE_WAIT(done(), 5000);
  std::string response;
  EXPECT_EQ(200U, req->response().scode);
  ASSERT_TRUE(req->response().document.get() != NULL);
  req->response().document->Rewind();
  req->response().document->ReadLine(&response);
  EXPECT_EQ("4321dcba", response);
  req->Release();
}

// Ensure that we shut down properly even if work is outstanding.
TEST_F(AsyncHttpRequestTest, TestCancel) {
  AsyncHttpRequest* req = CreateGetRequest(
      kServerHostnameAddr.hostname(), server().address().port(),
      kServerGetPath);
  req->Start();
  req->Destroy(true);
}

}  // namespace talk_base
