1 /* 2 * Copyright (C) 2011 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 "bindings/modules/v8/IDBBindingUtilities.h" 28 29 #include "bindings/core/v8/V8Binding.h" 30 #include "bindings/core/v8/V8PerIsolateData.h" 31 #include "modules/indexeddb/IDBKey.h" 32 #include "modules/indexeddb/IDBKeyPath.h" 33 #include <gtest/gtest.h> 34 35 using namespace blink; 36 37 namespace { 38 39 IDBKey* checkKeyFromValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) 40 { 41 IDBKeyPath idbKeyPath(keyPath); 42 EXPECT_TRUE(idbKeyPath.isValid()); 43 44 return createIDBKeyFromScriptValueAndKeyPath(isolate, value, idbKeyPath); 45 } 46 47 void checkKeyPathNullValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) 48 { 49 ASSERT_FALSE(checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath)); 50 } 51 52 bool injectKey(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) 53 { 54 IDBKeyPath idbKeyPath(keyPath); 55 EXPECT_TRUE(idbKeyPath.isValid()); 56 ScriptValue keyValue = idbKeyToScriptValue(scriptState, key); 57 return injectV8KeyIntoV8Value(scriptState->isolate(), keyValue.v8Value(), value.v8Value(), idbKeyPath); 58 } 59 60 void checkInjection(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) 61 { 62 bool result = injectKey(scriptState, key, value, keyPath); 63 ASSERT_TRUE(result); 64 IDBKey* extractedKey = checkKeyFromValueAndKeyPathInternal(scriptState->isolate(), value, keyPath); 65 EXPECT_TRUE(key->isEqual(extractedKey)); 66 } 67 68 void checkInjectionFails(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) 69 { 70 EXPECT_FALSE(injectKey(scriptState, key, value, keyPath)); 71 } 72 73 void checkKeyPathStringValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, const String& expected) 74 { 75 IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); 76 ASSERT_TRUE(idbKey); 77 ASSERT_EQ(IDBKey::StringType, idbKey->type()); 78 ASSERT_TRUE(expected == idbKey->string()); 79 } 80 81 void checkKeyPathNumberValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, int expected) 82 { 83 IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); 84 ASSERT_TRUE(idbKey); 85 ASSERT_EQ(IDBKey::NumberType, idbKey->type()); 86 ASSERT_TRUE(expected == idbKey->number()); 87 } 88 89 class IDBKeyFromValueAndKeyPathTest : public testing::Test { 90 public: 91 IDBKeyFromValueAndKeyPathTest() 92 : m_scope(v8::Isolate::GetCurrent()) 93 { 94 } 95 96 ScriptState* scriptState() const { return m_scope.scriptState(); } 97 98 private: 99 V8TestingScope m_scope; 100 }; 101 102 TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyStringValue) 103 { 104 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 105 v8::Local<v8::Object> object = v8::Object::New(isolate); 106 object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); 107 108 ScriptValue scriptValue(scriptState(), object); 109 110 checkKeyPathStringValue(isolate, scriptValue, "foo", "zoo"); 111 checkKeyPathNullValue(isolate, scriptValue, "bar"); 112 } 113 114 TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyNumberValue) 115 { 116 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 117 v8::Local<v8::Object> object = v8::Object::New(isolate); 118 object->Set(v8AtomicString(isolate, "foo"), v8::Number::New(isolate, 456)); 119 120 ScriptValue scriptValue(scriptState(), object); 121 122 checkKeyPathNumberValue(isolate, scriptValue, "foo", 456); 123 checkKeyPathNullValue(isolate, scriptValue, "bar"); 124 } 125 126 TEST_F(IDBKeyFromValueAndKeyPathTest, SubProperty) 127 { 128 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 129 v8::Local<v8::Object> object = v8::Object::New(isolate); 130 v8::Local<v8::Object> subProperty = v8::Object::New(isolate); 131 subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); 132 object->Set(v8AtomicString(isolate, "foo"), subProperty); 133 134 ScriptValue scriptValue(scriptState(), object); 135 136 checkKeyPathStringValue(isolate, scriptValue, "foo.bar", "zee"); 137 checkKeyPathNullValue(isolate, scriptValue, "bar"); 138 } 139 140 class InjectIDBKeyTest : public IDBKeyFromValueAndKeyPathTest { 141 }; 142 143 TEST_F(InjectIDBKeyTest, TopLevelPropertyStringValue) 144 { 145 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 146 v8::Local<v8::Object> object = v8::Object::New(isolate); 147 object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); 148 149 ScriptValue foozoo(scriptState(), object); 150 checkInjection(scriptState(), IDBKey::createString("myNewKey"), foozoo, "bar"); 151 checkInjection(scriptState(), IDBKey::createNumber(1234), foozoo, "bar"); 152 153 checkInjectionFails(scriptState(), IDBKey::createString("key"), foozoo, "foo.bar"); 154 } 155 156 TEST_F(InjectIDBKeyTest, SubProperty) 157 { 158 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 159 v8::Local<v8::Object> object = v8::Object::New(isolate); 160 v8::Local<v8::Object> subProperty = v8::Object::New(isolate); 161 subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); 162 object->Set(v8AtomicString(isolate, "foo"), subProperty); 163 164 ScriptValue scriptObject(scriptState(), object); 165 checkInjection(scriptState(), IDBKey::createString("myNewKey"), scriptObject, "foo.baz"); 166 checkInjection(scriptState(), IDBKey::createNumber(789), scriptObject, "foo.baz"); 167 checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "foo.baz"); 168 checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "bar"); 169 checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "foo.baz"); 170 checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "bar"); 171 172 checkInjectionFails(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.bar.baz"); 173 checkInjection(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.xyz.foo"); 174 } 175 176 } // namespace 177