// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "mojo/application/public/cpp/application_test_base.h"
#include "mojo/common/message_pump_mojo.h"
#include "mojo/services/network/network_context.h"
#include "mojo/services/network/url_loader_impl.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"

namespace mojo {

class TestURLRequestJob;

TestURLRequestJob* g_current_job = nullptr;

template <class A>
void PassA(A* destination, A value) {
  *destination = value.Pass();
}

class TestURLRequestJob : public net::URLRequestJob {
 public:
  enum Status { CREATED, STARTED, READING, COMPLETED };

  TestURLRequestJob(net::URLRequest* request,
                    net::NetworkDelegate* network_delegate)
      : net::URLRequestJob(request, network_delegate),
        status_(CREATED),
        buf_size_(0) {
    CHECK(!g_current_job);
    g_current_job = this;
  }

  Status status() { return status_; }

  int buf_size() { return buf_size_; }

  void Start() override { status_ = STARTED; }

  bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override {
    status_ = READING;
    buf_size_ = buf_size;
    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
    return false;
  }

  void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); }

  void NotifyReadComplete(int bytes_read) {
    if (bytes_read < 0) {
      status_ = COMPLETED;
      NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, 0));
      net::URLRequestJob::NotifyReadComplete(0);
    } else if (bytes_read == 0) {
      status_ = COMPLETED;
      NotifyDone(net::URLRequestStatus());
      net::URLRequestJob::NotifyReadComplete(bytes_read);
    } else {
      status_ = STARTED;
      SetStatus(net::URLRequestStatus());
      net::URLRequestJob::NotifyReadComplete(bytes_read);
    }
  }

 private:
  ~TestURLRequestJob() override {
    CHECK(g_current_job == this);
    g_current_job = nullptr;
  }

  Status status_;
  int buf_size_;
};

class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override {
    return new TestURLRequestJob(request, network_delegate);
  }

 private:
  ~TestProtocolHandler() override {}
};

class UrlLoaderImplTest : public test::ApplicationTestBase {
 public:
  UrlLoaderImplTest() : message_loop_(common::MessagePumpMojo::Create()) {}

 protected:
  bool ShouldCreateDefaultRunLoop() override {
    return false;
  }

  void SetUp() override {
    ApplicationTestBase::SetUp();

    scoped_ptr<net::TestURLRequestContext> url_request_context(
        new net::TestURLRequestContext(true));
    ASSERT_TRUE(url_request_job_factory_.SetProtocolHandler(
        "http", new TestProtocolHandler()));
    url_request_context->set_job_factory(&url_request_job_factory_);
    url_request_context->Init();
    network_context_.reset(new NetworkContext(url_request_context.Pass()));
    MessagePipe pipe;
    new URLLoaderImpl(network_context_.get(),
                      GetProxy(&url_loader_proxy_),
                      make_scoped_ptr<mojo::AppRefCount>(nullptr));
    EXPECT_TRUE(IsUrlLoaderValid());
  }

  bool IsUrlLoaderValid() {
    return network_context_->GetURLLoaderCountForTesting() > 0u;
  }

  base::MessageLoop message_loop_;
  net::TestJobInterceptor* job_interceptor_;
  net::URLRequestJobFactoryImpl url_request_job_factory_;
  scoped_ptr<NetworkContext> network_context_;
  URLLoaderPtr url_loader_proxy_;
};

TEST_F(UrlLoaderImplTest, ClosedBeforeAnyCall) {
  url_loader_proxy_.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(IsUrlLoaderValid());
}

TEST_F(UrlLoaderImplTest, ClosedWhileWaitingOnTheNetwork) {
  URLRequestPtr request(URLRequest::New());
  request->url = "http://example.com";

  URLResponsePtr response;
  url_loader_proxy_->Start(request.Pass(),
                           base::Bind(&PassA<URLResponsePtr>, &response));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_FALSE(response);
  ASSERT_TRUE(g_current_job);

  g_current_job->NotifyHeadersComplete();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_TRUE(response);
  EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status());

  url_loader_proxy_.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());

  response.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(IsUrlLoaderValid());
}

TEST_F(UrlLoaderImplTest, ClosedWhileWaitingOnThePipeToBeWriteable) {
  URLRequestPtr request(URLRequest::New());
  request->url = "http://example.com";

  URLResponsePtr response;
  url_loader_proxy_->Start(request.Pass(),
                           base::Bind(&PassA<URLResponsePtr>, &response));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_FALSE(response);
  ASSERT_TRUE(g_current_job);

  g_current_job->NotifyHeadersComplete();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_TRUE(response);
  EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status());

  while (g_current_job->status() == TestURLRequestJob::READING) {
    g_current_job->NotifyReadComplete(g_current_job->buf_size());
    base::RunLoop().RunUntilIdle();
  }

  EXPECT_EQ(TestURLRequestJob::STARTED, g_current_job->status());

  url_loader_proxy_.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());

  response.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(IsUrlLoaderValid());
}

TEST_F(UrlLoaderImplTest, RequestCompleted) {
  URLRequestPtr request(URLRequest::New());
  request->url = "http://example.com";

  URLResponsePtr response;
  url_loader_proxy_->Start(request.Pass(),
                           base::Bind(&PassA<URLResponsePtr>, &response));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_FALSE(response);
  ASSERT_TRUE(g_current_job);

  g_current_job->NotifyHeadersComplete();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_TRUE(response);
  EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status());

  url_loader_proxy_.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());

  g_current_job->NotifyReadComplete(0);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(IsUrlLoaderValid());
}

TEST_F(UrlLoaderImplTest, RequestFailed) {
  URLRequestPtr request(URLRequest::New());
  request->url = "http://example.com";

  URLResponsePtr response;
  url_loader_proxy_->Start(request.Pass(),
                           base::Bind(&PassA<URLResponsePtr>, &response));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_FALSE(response);
  ASSERT_TRUE(g_current_job);

  g_current_job->NotifyHeadersComplete();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());
  EXPECT_TRUE(response);
  EXPECT_EQ(TestURLRequestJob::READING, g_current_job->status());

  url_loader_proxy_.reset();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(IsUrlLoaderValid());

  g_current_job->NotifyReadComplete(-1);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(IsUrlLoaderValid());
}

}  // namespace mojo
