1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/message_loop/message_loop.h" 7 #include "base/strings/utf_string_conversions.h" 8 #include "base/threading/thread.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 #include "webkit/common/database/database_connections.h" 11 12 namespace webkit_database { 13 14 namespace { 15 16 void RemoveConnectionTask( 17 const std::string& origin_id, const base::string16& database_name, 18 scoped_refptr<DatabaseConnectionsWrapper> obj, 19 bool* did_task_execute) { 20 *did_task_execute = true; 21 obj->RemoveOpenConnection(origin_id, database_name); 22 } 23 24 void ScheduleRemoveConnectionTask( 25 base::Thread* thread, const std::string& origin_id, 26 const base::string16& database_name, 27 scoped_refptr<DatabaseConnectionsWrapper> obj, 28 bool* did_task_execute) { 29 thread->message_loop()->PostTask( 30 FROM_HERE, 31 base::Bind(&RemoveConnectionTask, origin_id, database_name, obj, 32 did_task_execute)); 33 } 34 35 } // anonymous namespace 36 37 TEST(DatabaseConnectionsTest, DatabaseConnectionsTest) { 38 const std::string kOriginId("origin_id"); 39 const base::string16 kName(ASCIIToUTF16("database_name")); 40 const base::string16 kName2(ASCIIToUTF16("database_name2")); 41 const int64 kSize = 1000; 42 43 DatabaseConnections connections; 44 45 EXPECT_TRUE(connections.IsEmpty()); 46 EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName)); 47 EXPECT_FALSE(connections.IsOriginUsed(kOriginId)); 48 49 connections.AddConnection(kOriginId, kName); 50 EXPECT_FALSE(connections.IsEmpty()); 51 EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName)); 52 EXPECT_TRUE(connections.IsOriginUsed(kOriginId)); 53 EXPECT_EQ(0, connections.GetOpenDatabaseSize(kOriginId, kName)); 54 connections.SetOpenDatabaseSize(kOriginId, kName, kSize); 55 EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName)); 56 57 connections.RemoveConnection(kOriginId, kName); 58 EXPECT_TRUE(connections.IsEmpty()); 59 EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName)); 60 EXPECT_FALSE(connections.IsOriginUsed(kOriginId)); 61 62 connections.AddConnection(kOriginId, kName); 63 connections.SetOpenDatabaseSize(kOriginId, kName, kSize); 64 EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName)); 65 connections.AddConnection(kOriginId, kName); 66 EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName)); 67 EXPECT_FALSE(connections.IsEmpty()); 68 EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName)); 69 EXPECT_TRUE(connections.IsOriginUsed(kOriginId)); 70 connections.AddConnection(kOriginId, kName2); 71 EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName2)); 72 73 DatabaseConnections another; 74 another.AddConnection(kOriginId, kName); 75 another.AddConnection(kOriginId, kName2); 76 77 std::vector<std::pair<std::string, base::string16> > closed_dbs; 78 connections.RemoveConnections(another, &closed_dbs); 79 EXPECT_EQ(1u, closed_dbs.size()); 80 EXPECT_EQ(kOriginId, closed_dbs[0].first); 81 EXPECT_EQ(kName2, closed_dbs[0].second); 82 EXPECT_FALSE(connections.IsDatabaseOpened(kOriginId, kName2)); 83 EXPECT_TRUE(connections.IsDatabaseOpened(kOriginId, kName)); 84 EXPECT_EQ(kSize, connections.GetOpenDatabaseSize(kOriginId, kName)); 85 another.RemoveAllConnections(); 86 connections.RemoveAllConnections(); 87 EXPECT_TRUE(connections.IsEmpty()); 88 89 // Ensure the return value properly indicates the initial 90 // addition and final removal. 91 EXPECT_TRUE(connections.AddConnection(kOriginId, kName)); 92 EXPECT_FALSE(connections.AddConnection(kOriginId, kName)); 93 EXPECT_FALSE(connections.AddConnection(kOriginId, kName)); 94 EXPECT_FALSE(connections.RemoveConnection(kOriginId, kName)); 95 EXPECT_FALSE(connections.RemoveConnection(kOriginId, kName)); 96 EXPECT_TRUE(connections.RemoveConnection(kOriginId, kName)); 97 } 98 99 TEST(DatabaseConnectionsTest, DatabaseConnectionsWrapperTest) { 100 const std::string kOriginId("origin_id"); 101 const base::string16 kName(ASCIIToUTF16("database_name")); 102 103 base::MessageLoop message_loop; 104 scoped_refptr<DatabaseConnectionsWrapper> obj(new DatabaseConnectionsWrapper); 105 EXPECT_FALSE(obj->HasOpenConnections()); 106 obj->AddOpenConnection(kOriginId, kName); 107 EXPECT_TRUE(obj->HasOpenConnections()); 108 obj->AddOpenConnection(kOriginId, kName); 109 EXPECT_TRUE(obj->HasOpenConnections()); 110 obj->RemoveOpenConnection(kOriginId, kName); 111 EXPECT_TRUE(obj->HasOpenConnections()); 112 obj->RemoveOpenConnection(kOriginId, kName); 113 EXPECT_FALSE(obj->HasOpenConnections()); 114 obj->WaitForAllDatabasesToClose(); // should return immediately 115 116 // Test WaitForAllDatabasesToClose with the last connection 117 // being removed on the current thread. 118 obj->AddOpenConnection(kOriginId, kName); 119 bool did_task_execute = false; 120 base::MessageLoop::current()->PostTask( 121 FROM_HERE, 122 base::Bind(&RemoveConnectionTask, kOriginId, kName, obj, 123 &did_task_execute)); 124 obj->WaitForAllDatabasesToClose(); // should return after the task executes 125 EXPECT_TRUE(did_task_execute); 126 EXPECT_FALSE(obj->HasOpenConnections()); 127 128 // Test WaitForAllDatabasesToClose with the last connection 129 // being removed on another thread. 130 obj->AddOpenConnection(kOriginId, kName); 131 base::Thread thread("WrapperTestThread"); 132 thread.Start(); 133 did_task_execute = false; 134 base::MessageLoop::current()->PostTask( 135 FROM_HERE, 136 base::Bind(&ScheduleRemoveConnectionTask, &thread, kOriginId, kName, obj, 137 &did_task_execute)); 138 obj->WaitForAllDatabasesToClose(); // should return after the task executes 139 EXPECT_TRUE(did_task_execute); 140 EXPECT_FALSE(obj->HasOpenConnections()); 141 } 142 143 } // namespace webkit_database 144