/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 COPYRIGHT
 * OWNER OR CONTRIBUTORS 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 "modules/indexeddb/IDBTransaction.h"

#include <memory>

#include "base/memory/scoped_refptr.h"
#include "bindings/core/v8/V8BindingForTesting.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/events/EventQueue.h"
#include "modules/indexeddb/IDBDatabase.h"
#include "modules/indexeddb/IDBDatabaseCallbacks.h"
#include "modules/indexeddb/IDBKey.h"
#include "modules/indexeddb/IDBKeyPath.h"
#include "modules/indexeddb/IDBMetadata.h"
#include "modules/indexeddb/IDBObjectStore.h"
#include "modules/indexeddb/IDBTestHelper.h"
#include "modules/indexeddb/IDBValue.h"
#include "modules/indexeddb/IDBValueWrapping.h"
#include "modules/indexeddb/MockWebIDBDatabase.h"
#include "platform/SharedBuffer.h"
#include "platform/testing/TestingPlatformSupport.h"
#include "platform/wtf/PtrUtil.h"
#include "public/platform/WebURLLoaderMockFactory.h"
#include "public/platform/WebURLResponse.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "v8/include/v8.h"

namespace blink {
namespace {

void DeactivateNewTransactions(v8::Isolate* isolate) {
  V8PerIsolateData::From(isolate)->RunEndOfScopeTasks();
}

class FakeIDBDatabaseCallbacks final : public IDBDatabaseCallbacks {
 public:
  static FakeIDBDatabaseCallbacks* Create() {
    return new FakeIDBDatabaseCallbacks();
  }
  void OnVersionChange(int64_t old_version, int64_t new_version) override {}
  void OnForcedClose() override {}
  void OnAbort(int64_t transaction_id, DOMException* error) override {}
  void OnComplete(int64_t transaction_id) override {}

 private:
  FakeIDBDatabaseCallbacks() {}
};

class IDBTransactionTest : public ::testing::Test {
 protected:
  void SetUp() override {
    url_loader_mock_factory_ = platform_->GetURLLoaderMockFactory();
    WebURLResponse response;
    response.SetURL(KURL(NullURL(), "blob:"));
    url_loader_mock_factory_->RegisterURLProtocol(WebString("blob"), response,
                                                  "");
  }

  void TearDown() override {
    url_loader_mock_factory_->UnregisterAllURLsAndClearMemoryCache();
  }

  void BuildTransaction(V8TestingScope& scope,
                        std::unique_ptr<MockWebIDBDatabase> backend) {
    db_ = IDBDatabase::Create(scope.GetExecutionContext(), std::move(backend),
                              FakeIDBDatabaseCallbacks::Create(),
                              scope.GetIsolate());

    HashSet<String> transaction_scope = {"store"};
    transaction_ = IDBTransaction::CreateNonVersionChange(
        scope.GetScriptState(), kTransactionId, transaction_scope,
        kWebIDBTransactionModeReadOnly, db_.Get());

    IDBKeyPath store_key_path("primaryKey");
    scoped_refptr<IDBObjectStoreMetadata> store_metadata = base::AdoptRef(
        new IDBObjectStoreMetadata("store", kStoreId, store_key_path, true, 1));
    store_ = IDBObjectStore::Create(store_metadata, transaction_);
  }

  WebURLLoaderMockFactory* url_loader_mock_factory_;
  Persistent<IDBDatabase> db_;
  Persistent<IDBTransaction> transaction_;
  Persistent<IDBObjectStore> store_;
  ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;

  static constexpr int64_t kTransactionId = 1234;
  static constexpr int64_t kStoreId = 5678;
};

TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1u, live_transactions.size());

  Persistent<IDBRequest> request =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());

  DeactivateNewTransactions(scope.GetIsolate());

  request.Clear();  // The transaction is holding onto the request.
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1u, live_transactions.size());

  // This will generate an Abort() call to the back end which is dropped by the
  // fake proxy, so an explicit OnAbort call is made.
  scope.GetExecutionContext()->NotifyContextDestroyed();
  transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
  transaction_.Clear();
  store_.Clear();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  Persistent<IDBRequest> request =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  DeactivateNewTransactions(scope.GetIsolate());

  // This response should result in an event being enqueued immediately.
  request->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), false));

  request.Clear();  // The transaction is holding onto the request.
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  // This will generate an Abort() call to the back end which is dropped by the
  // fake proxy, so an explicit OnAbort call is made.
  scope.GetExecutionContext()->NotifyContextDestroyed();
  transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
  transaction_.Clear();
  store_.Clear();

  // The request completed, so it has enqueued a success event. Discard the
  // event, so that the transaction can go away.
  EXPECT_EQ(1U, live_transactions.size());
  scope.GetExecutionContext()->GetEventQueue()->Close();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, AckReceivedBlobs(::testing::_)).Times(1);
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  Persistent<IDBRequest> request =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  DeactivateNewTransactions(scope.GetIsolate());

  request->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true));

  request.Clear();  // The transaction is holding onto the request.
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  // This will generate an Abort() call to the back end which is dropped by the
  // fake proxy, so an explicit OnAbort call is made.
  scope.GetExecutionContext()->NotifyContextDestroyed();
  transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
  transaction_.Clear();
  store_.Clear();

  url_loader_mock_factory_->ServeAsynchronousRequests();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, AckReceivedBlobs(::testing::_)).Times(2);
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  Persistent<IDBRequest> request1 =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  Persistent<IDBRequest> request2 =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  DeactivateNewTransactions(scope.GetIsolate());

  request1->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true));
  request2->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true));

  request1.Clear();  // The transaction is holding onto the requests.
  request2.Clear();
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  // This will generate an Abort() call to the back end which is dropped by the
  // fake proxy, so an explicit OnAbort call is made.
  scope.GetExecutionContext()->NotifyContextDestroyed();
  transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
  transaction_.Clear();
  store_.Clear();

  url_loader_mock_factory_->ServeAsynchronousRequests();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

TEST_F(IDBTransactionTest, DocumentShutdownWithQueuedAndBlockedResults) {
  // This test covers the conditions of https://crbug.com/733642

  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, AckReceivedBlobs(::testing::_)).Times(1);
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  Persistent<IDBRequest> request1 =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  Persistent<IDBRequest> request2 =
      IDBRequest::Create(scope.GetScriptState(), IDBAny::Create(store_.Get()),
                         transaction_.Get(), IDBRequest::AsyncTraceState());
  DeactivateNewTransactions(scope.GetIsolate());

  request1->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), true));
  request2->HandleResponse(CreateIDBValueForTesting(scope.GetIsolate(), false));

  request1.Clear();  // The transaction is holding onto the requests.
  request2.Clear();
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  // This will generate an Abort() call to the back end which is dropped by the
  // fake proxy, so an explicit OnAbort call is made.
  scope.GetDocument().Shutdown();
  transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
  transaction_.Clear();
  store_.Clear();

  url_loader_mock_factory_->ServeAsynchronousRequests();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

TEST_F(IDBTransactionTest, TransactionFinish) {
  V8TestingScope scope;
  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
  EXPECT_CALL(*backend, Commit(kTransactionId)).Times(1);
  EXPECT_CALL(*backend, Close()).Times(1);
  BuildTransaction(scope, std::move(backend));

  PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions;
  live_transactions.insert(transaction_);

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  DeactivateNewTransactions(scope.GetIsolate());

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  transaction_.Clear();
  store_.Clear();

  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(1U, live_transactions.size());

  // Stop the context, so events don't get queued (which would keep the
  // transaction alive).
  scope.GetExecutionContext()->NotifyContextDestroyed();

  // Fire an abort to make sure this doesn't free the transaction during use.
  // The test will not fail if it is, but ASAN would notice the error.
  db_->OnAbort(kTransactionId, DOMException::Create(kAbortError, "Aborted"));

  // OnAbort() should have cleared the transaction's reference to the database.
  ThreadState::Current()->CollectAllGarbage();
  EXPECT_EQ(0U, live_transactions.size());
}

}  // namespace
}  // namespace blink
