Home | History | Annotate | Download | only in indexeddb
      1 /*
      2  * Copyright (C) 2012 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "modules/indexeddb/IDBRequest.h"
     28 
     29 #include "core/dom/DOMError.h"
     30 #include "core/dom/Document.h"
     31 #include "modules/indexeddb/IDBCursorBackendInterface.h"
     32 #include "modules/indexeddb/IDBDatabaseBackendInterface.h"
     33 #include "modules/indexeddb/IDBDatabaseCallbacksImpl.h"
     34 #include "modules/indexeddb/IDBKeyRange.h"
     35 #include "modules/indexeddb/IDBOpenDBRequest.h"
     36 
     37 #include <gtest/gtest.h>
     38 
     39 using namespace WebCore;
     40 
     41 namespace {
     42 
     43 class IDBRequestTest : public testing::Test {
     44 public:
     45     IDBRequestTest()
     46         : m_handleScope(v8::Isolate::GetCurrent())
     47         , m_scope(v8::Context::New(v8::Isolate::GetCurrent()))
     48         , m_document(Document::create())
     49     {
     50     }
     51 
     52     ScriptExecutionContext* scriptExecutionContext()
     53     {
     54         return m_document.get();
     55     }
     56 
     57 private:
     58     v8::HandleScope m_handleScope;
     59     v8::Context::Scope m_scope;
     60     RefPtr<Document> m_document;
     61 };
     62 
     63 TEST_F(IDBRequestTest, EventsAfterStopping)
     64 {
     65     IDBTransaction* transaction = 0;
     66     RefPtr<IDBRequest> request = IDBRequest::create(scriptExecutionContext(), IDBAny::createInvalid(), transaction);
     67     EXPECT_EQ(request->readyState(), "pending");
     68     scriptExecutionContext()->stopActiveDOMObjects();
     69 
     70     // Ensure none of the following raise assertions in stopped state:
     71     request->onError(DOMError::create(AbortError, "Description goes here."));
     72     request->onSuccess(Vector<String>());
     73     request->onSuccess(PassRefPtr<IDBCursorBackendInterface>(), IDBKey::createInvalid(), IDBKey::createInvalid(), 0);
     74     request->onSuccess(IDBKey::createInvalid());
     75     request->onSuccess(PassRefPtr<SharedBuffer>(0));
     76     request->onSuccess(PassRefPtr<SharedBuffer>(0), IDBKey::createInvalid(), IDBKeyPath());
     77     request->onSuccess(0LL);
     78     request->onSuccess();
     79     request->onSuccess(IDBKey::createInvalid(), IDBKey::createInvalid(), 0);
     80 }
     81 
     82 TEST_F(IDBRequestTest, AbortErrorAfterAbort)
     83 {
     84     IDBTransaction* transaction = 0;
     85     RefPtr<IDBRequest> request = IDBRequest::create(scriptExecutionContext(), IDBAny::createInvalid(), transaction);
     86     EXPECT_EQ(request->readyState(), "pending");
     87 
     88     // Simulate the IDBTransaction having received onAbort from back end and aborting the request:
     89     request->abort();
     90 
     91     // Now simulate the back end having fired an abort error at the request to clear up any intermediaries.
     92     // Ensure an assertion is not raised.
     93     request->onError(DOMError::create(AbortError, "Description goes here."));
     94 }
     95 
     96 class MockIDBDatabaseBackendInterface : public IDBDatabaseBackendInterface {
     97 public:
     98     static PassRefPtr<MockIDBDatabaseBackendInterface> create()
     99     {
    100         return adoptRef(new MockIDBDatabaseBackendInterface());
    101     }
    102     virtual ~MockIDBDatabaseBackendInterface()
    103     {
    104         EXPECT_TRUE(m_closeCalled);
    105     }
    106 
    107     virtual void createObjectStore(int64_t transactionId, int64_t objectStoreId, const String& name, const IDBKeyPath&, bool autoIncrement) OVERRIDE { }
    108     virtual void deleteObjectStore(int64_t transactionId, int64_t objectStoreId) OVERRIDE { }
    109     virtual void createTransaction(int64_t transactionId, PassRefPtr<IDBDatabaseCallbacks>, const Vector<int64_t>& objectStoreIds, unsigned short mode) OVERRIDE { }
    110     virtual void close(PassRefPtr<IDBDatabaseCallbacks>) OVERRIDE
    111     {
    112         m_closeCalled = true;
    113     }
    114 
    115     virtual void commit(int64_t transactionId) OVERRIDE { }
    116     virtual void abort(int64_t transactionId) OVERRIDE { }
    117 
    118     virtual void createIndex(int64_t transactionId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath&, bool unique, bool multiEntry) OVERRIDE { }
    119     virtual void deleteIndex(int64_t transactionId, int64_t objectStoreId, int64_t indexId) OVERRIDE { }
    120 
    121     virtual void get(int64_t transactionId, int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, bool keyOnly, PassRefPtr<IDBCallbacks>) OVERRIDE { }
    122     virtual void put(int64_t transactionId, int64_t objectStoreId, PassRefPtr<SharedBuffer> value, PassRefPtr<IDBKey>, PutMode, PassRefPtr<IDBCallbacks>, const Vector<int64_t>& indexIds, const Vector<IndexKeys>&) OVERRIDE { }
    123     virtual void setIndexKeys(int64_t transactionId, int64_t objectStoreId, PassRefPtr<IDBKey>, const Vector<int64_t>& indexIds, const Vector<IndexKeys>&) OVERRIDE { }
    124     virtual void setIndexesReady(int64_t transactionId, int64_t objectStoreId, const Vector<int64_t>& indexIds) OVERRIDE { }
    125     virtual void openCursor(int64_t transactionId, int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, IndexedDB::CursorDirection, bool keyOnly, TaskType, PassRefPtr<IDBCallbacks>) OVERRIDE { }
    126     virtual void count(int64_t transactionId, int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>) OVERRIDE { }
    127     virtual void deleteRange(int64_t transactionId, int64_t objectStoreId, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>) OVERRIDE { }
    128     virtual void clear(int64_t transactionId, int64_t objectStoreId, PassRefPtr<IDBCallbacks>) OVERRIDE { }
    129 
    130 private:
    131     MockIDBDatabaseBackendInterface()
    132         : m_closeCalled(false)
    133     {
    134     }
    135 
    136     bool m_closeCalled;
    137 };
    138 
    139 TEST_F(IDBRequestTest, ConnectionsAfterStopping)
    140 {
    141     const int64_t transactionId = 1234;
    142     const int64_t version = 1;
    143     const int64_t oldVersion = 0;
    144     const IDBDatabaseMetadata metadata;
    145     RefPtr<IDBDatabaseCallbacksImpl> callbacks = IDBDatabaseCallbacksImpl::create();
    146 
    147     {
    148         RefPtr<MockIDBDatabaseBackendInterface> interface = MockIDBDatabaseBackendInterface::create();
    149         RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(scriptExecutionContext(), callbacks, transactionId, version);
    150         EXPECT_EQ(request->readyState(), "pending");
    151 
    152         scriptExecutionContext()->stopActiveDOMObjects();
    153         request->onUpgradeNeeded(oldVersion, interface, metadata, WebKit::WebIDBCallbacks::DataLossNone);
    154     }
    155 
    156     {
    157         RefPtr<MockIDBDatabaseBackendInterface> interface = MockIDBDatabaseBackendInterface::create();
    158         RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(scriptExecutionContext(), callbacks, transactionId, version);
    159         EXPECT_EQ(request->readyState(), "pending");
    160 
    161         scriptExecutionContext()->stopActiveDOMObjects();
    162         request->onSuccess(interface, metadata);
    163     }
    164 }
    165 
    166 } // namespace
    167