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