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