Home | History | Annotate | Download | only in indexeddb
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "modules/indexeddb/IDBTransaction.h"
     33 
     34 #include "core/dom/DOMError.h"
     35 #include "core/dom/Document.h"
     36 #include "modules/indexeddb/IDBDatabase.h"
     37 #include "modules/indexeddb/IDBDatabaseCallbacks.h"
     38 #include "platform/SharedBuffer.h"
     39 #include "public/platform/WebIDBDatabase.h"
     40 #include <gtest/gtest.h>
     41 #include <v8.h>
     42 
     43 namespace blink {
     44 namespace {
     45 
     46 class IDBTransactionTest : public testing::Test {
     47 public:
     48     IDBTransactionTest()
     49         : m_scope(v8::Isolate::GetCurrent())
     50         , m_executionContext(Document::create())
     51     {
     52         m_scope.scriptState()->setExecutionContext(m_executionContext.get());
     53     }
     54 
     55     ~IDBTransactionTest()
     56     {
     57         m_scope.scriptState()->setExecutionContext(0);
     58     }
     59 
     60     v8::Isolate* isolate() const { return m_scope.isolate(); }
     61     ScriptState* scriptState() const { return m_scope.scriptState(); }
     62     ExecutionContext* executionContext() { return m_scope.scriptState()->executionContext(); }
     63 
     64     void deactivateNewTransactions()
     65     {
     66         V8PerIsolateData::from(isolate())->ensureIDBPendingTransactionMonitor()->deactivateNewTransactions();
     67     }
     68 
     69 private:
     70     V8TestingScope m_scope;
     71     RefPtrWillBePersistent<ExecutionContext> m_executionContext;
     72 };
     73 
     74 class FakeWebIDBDatabase FINAL : public WebIDBDatabase {
     75 public:
     76     static PassOwnPtr<FakeWebIDBDatabase> create() { return adoptPtr(new FakeWebIDBDatabase()); }
     77 
     78     virtual void commit(long long transactionId) OVERRIDE { }
     79     virtual void abort(long long transactionId) OVERRIDE { }
     80     virtual void close() OVERRIDE { }
     81 
     82 private:
     83     FakeWebIDBDatabase() { }
     84 };
     85 
     86 class FakeIDBDatabaseCallbacks FINAL : public IDBDatabaseCallbacks {
     87 public:
     88     static FakeIDBDatabaseCallbacks* create() { return new FakeIDBDatabaseCallbacks(); }
     89     virtual void onVersionChange(int64_t oldVersion, int64_t newVersion) OVERRIDE { }
     90     virtual void onForcedClose() OVERRIDE { }
     91     virtual void onAbort(int64_t transactionId, PassRefPtrWillBeRawPtr<DOMError> error) OVERRIDE { }
     92     virtual void onComplete(int64_t transactionId) OVERRIDE { }
     93 private:
     94     FakeIDBDatabaseCallbacks() { }
     95 };
     96 
     97 TEST_F(IDBTransactionTest, EnsureLifetime)
     98 {
     99     OwnPtr<FakeWebIDBDatabase> backend = FakeWebIDBDatabase::create();
    100     Persistent<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), FakeIDBDatabaseCallbacks::create());
    101 
    102     const int64_t transactionId = 1234;
    103     const Vector<String> transactionScope;
    104     Persistent<IDBTransaction> transaction = IDBTransaction::create(scriptState(), transactionId, transactionScope, WebIDBTransactionModeReadOnly, db.get());
    105     PersistentHeapHashSet<WeakMember<IDBTransaction> > set;
    106     set.add(transaction);
    107 
    108     Heap::collectAllGarbage();
    109     EXPECT_EQ(1u, set.size());
    110 
    111     Persistent<IDBRequest> request = IDBRequest::create(scriptState(), IDBAny::createUndefined(), transaction.get());
    112     deactivateNewTransactions();
    113 
    114     Heap::collectAllGarbage();
    115     EXPECT_EQ(1u, set.size());
    116 
    117     // This will generate an abort() call to the back end which is dropped by the fake proxy,
    118     // so an explicit onAbort call is made.
    119     executionContext()->stopActiveDOMObjects();
    120     transaction->onAbort(DOMError::create(AbortError, "Aborted"));
    121     transaction.clear();
    122 
    123     Heap::collectAllGarbage();
    124     EXPECT_EQ(0u, set.size());
    125 }
    126 
    127 TEST_F(IDBTransactionTest, TransactionFinish)
    128 {
    129     OwnPtr<FakeWebIDBDatabase> backend = FakeWebIDBDatabase::create();
    130     Persistent<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), FakeIDBDatabaseCallbacks::create());
    131 
    132     const int64_t transactionId = 1234;
    133     const Vector<String> transactionScope;
    134     Persistent<IDBTransaction> transaction = IDBTransaction::create(scriptState(), transactionId, transactionScope, WebIDBTransactionModeReadOnly, db.get());
    135     PersistentHeapHashSet<WeakMember<IDBTransaction> > set;
    136     set.add(transaction);
    137 
    138     Heap::collectAllGarbage();
    139     EXPECT_EQ(1u, set.size());
    140 
    141     deactivateNewTransactions();
    142 
    143     Heap::collectAllGarbage();
    144     EXPECT_EQ(1u, set.size());
    145 
    146     transaction.clear();
    147 
    148     Heap::collectAllGarbage();
    149     EXPECT_EQ(1u, set.size());
    150 
    151     // Stop the context, so events don't get queued (which would keep the transaction alive).
    152     executionContext()->stopActiveDOMObjects();
    153 
    154     // Fire an abort to make sure this doesn't free the transaction during use. The test
    155     // will not fail if it is, but ASAN would notice the error.
    156     db->onAbort(transactionId, DOMError::create(AbortError, "Aborted"));
    157 
    158     // onAbort() should have cleared the transaction's reference to the database.
    159     Heap::collectAllGarbage();
    160     EXPECT_EQ(0u, set.size());
    161 }
    162 
    163 } // namespace
    164 } // namespace blink
    165