forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Internal implementation is done via base::SupportsUserData. This CL also introduces ios_consumer_unittests. Review URL: https://chromiumcodereview.appspot.com/17641002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208485 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
blundell@chromium.org
committed
Jun 25, 2013
1 parent
3b9ea9c
commit c6c1d08
Showing
4 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "ios/consumer/public/base/supports_user_data.h" | ||
|
||
#include "base/memory/scoped_ptr.h" | ||
#include "base/supports_user_data.h" | ||
|
||
namespace ios { | ||
|
||
// Class that wraps a ios::SupportsUserData::Data object in a | ||
// base::SupportsUserData::Data object. The wrapper object takes ownership of | ||
// the wrapped object and will delete it on destruction. | ||
class DataAdaptor : public base::SupportsUserData::Data { | ||
public: | ||
DataAdaptor(SupportsUserData::Data* data); | ||
virtual ~DataAdaptor(); | ||
|
||
SupportsUserData::Data* data() { return data_.get(); } | ||
|
||
private: | ||
scoped_ptr<SupportsUserData::Data> data_; | ||
}; | ||
|
||
DataAdaptor::DataAdaptor(SupportsUserData::Data* data) | ||
: data_(data) {} | ||
|
||
DataAdaptor::~DataAdaptor() {} | ||
|
||
// Class that subclasses base::SupportsUserData in order to enable it to | ||
// support ios::SupportsUserData::Data objects. It accomplishes this by | ||
// wrapping these objects internally in ios::DataAdaptor objects. | ||
class SupportsUserDataInternal : public base::SupportsUserData { | ||
public: | ||
// Returns the data that is associated with |key|, or NULL if there is no | ||
// such associated data. | ||
ios::SupportsUserData::Data* GetIOSUserData(const void* key); | ||
|
||
// Associates |data| with |key|. Takes ownership of |data| and will delete it | ||
// on either a call to |RemoveUserData(key)| or otherwise on destruction. | ||
void SetIOSUserData(const void* key, ios::SupportsUserData::Data* data); | ||
|
||
private: | ||
SupportsUserDataInternal() {} | ||
virtual ~SupportsUserDataInternal() {} | ||
|
||
friend class ios::SupportsUserData; | ||
}; | ||
|
||
ios::SupportsUserData::Data* SupportsUserDataInternal::GetIOSUserData( | ||
const void* key) { | ||
DataAdaptor* adaptor = static_cast<DataAdaptor*>( | ||
base::SupportsUserData::GetUserData(key)); | ||
if (!adaptor) | ||
return NULL; | ||
return adaptor->data(); | ||
} | ||
|
||
void SupportsUserDataInternal::SetIOSUserData( | ||
const void* key, ios::SupportsUserData::Data* data) { | ||
base::SupportsUserData::SetUserData(key, new DataAdaptor(data)); | ||
} | ||
|
||
// ios::SupportsUserData implementation. | ||
SupportsUserData::SupportsUserData() | ||
: internal_helper_(new SupportsUserDataInternal()) { | ||
} | ||
|
||
SupportsUserData::~SupportsUserData() { | ||
delete internal_helper_; | ||
} | ||
|
||
SupportsUserData::Data* SupportsUserData::GetUserData(const void* key) const { | ||
return internal_helper_->GetIOSUserData(key); | ||
} | ||
|
||
void SupportsUserData::SetUserData(const void* key, Data* data) { | ||
internal_helper_->SetIOSUserData(key, data); | ||
} | ||
|
||
void SupportsUserData::RemoveUserData(const void* key) { | ||
internal_helper_->RemoveUserData(key); | ||
} | ||
|
||
void SupportsUserData::DetachUserDataThread() { | ||
internal_helper_->DetachUserDataThread(); | ||
} | ||
|
||
} // namespace ios |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "ios/consumer/public/base/supports_user_data.h" | ||
|
||
#include "base/memory/scoped_ptr.h" | ||
#include "testing/gmock/include/gmock/gmock.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
#include "testing/platform_test.h" | ||
|
||
namespace ios { | ||
|
||
namespace { | ||
const char* kTestData1Key = "test_data1"; | ||
const char* kTestData2Key = "test_data2"; | ||
} // namespace | ||
|
||
class TestData : public SupportsUserData::Data { | ||
public: | ||
TestData(bool* was_destroyed) | ||
: was_destroyed_(was_destroyed) { | ||
*was_destroyed_ = false; | ||
} | ||
virtual ~TestData() { | ||
*was_destroyed_ = true; | ||
} | ||
|
||
private: | ||
bool* was_destroyed_; | ||
}; | ||
|
||
class TestSupportsUserData : public SupportsUserData { | ||
public: | ||
TestSupportsUserData() {} | ||
virtual ~TestSupportsUserData() {} | ||
}; | ||
|
||
class SupportsUserDataTest : public PlatformTest { | ||
public: | ||
virtual void SetUp() OVERRIDE { | ||
PlatformTest::SetUp(); | ||
|
||
test_data1_was_destroyed_ = false; | ||
test_data1_ = new TestData(&test_data1_was_destroyed_); | ||
test_data2_was_destroyed_ = false; | ||
test_data2_ = new TestData(&test_data2_was_destroyed_); | ||
supports_user_data_.reset(new TestSupportsUserData()); | ||
} | ||
|
||
virtual void TearDown() OVERRIDE { | ||
if (!test_data1_was_destroyed_ && | ||
supports_user_data_ && | ||
supports_user_data_->GetUserData(kTestData1Key) != test_data1_) | ||
delete test_data1_; | ||
if (!test_data2_was_destroyed_ && | ||
supports_user_data_ && | ||
supports_user_data_->GetUserData(kTestData2Key) != test_data2_) | ||
delete test_data2_; | ||
|
||
PlatformTest::TearDown(); | ||
} | ||
|
||
protected: | ||
scoped_ptr<TestSupportsUserData> supports_user_data_; | ||
bool test_data1_was_destroyed_; | ||
TestData* test_data1_; | ||
bool test_data2_was_destroyed_; | ||
TestData* test_data2_; | ||
}; | ||
|
||
TEST_F(SupportsUserDataTest, SetAndGetData) { | ||
EXPECT_FALSE(supports_user_data_->GetUserData(kTestData1Key)); | ||
supports_user_data_->SetUserData(kTestData1Key, test_data1_); | ||
EXPECT_EQ(supports_user_data_->GetUserData(kTestData1Key), test_data1_); | ||
} | ||
|
||
TEST_F(SupportsUserDataTest, DataDestroyedOnDestruction) { | ||
EXPECT_FALSE(supports_user_data_->GetUserData(kTestData1Key)); | ||
supports_user_data_->SetUserData(kTestData1Key, test_data1_); | ||
EXPECT_FALSE(test_data1_was_destroyed_); | ||
supports_user_data_.reset(); | ||
EXPECT_TRUE(test_data1_was_destroyed_); | ||
} | ||
|
||
TEST_F(SupportsUserDataTest, DataDestroyedOnRemoval) { | ||
EXPECT_FALSE(supports_user_data_->GetUserData(kTestData1Key)); | ||
supports_user_data_->SetUserData(kTestData1Key, test_data1_); | ||
EXPECT_FALSE(test_data1_was_destroyed_); | ||
supports_user_data_->RemoveUserData(kTestData1Key); | ||
EXPECT_TRUE(test_data1_was_destroyed_); | ||
} | ||
|
||
TEST_F(SupportsUserDataTest, DistinctDataStoredSeparately) { | ||
EXPECT_FALSE(supports_user_data_->GetUserData(kTestData2Key)); | ||
supports_user_data_->SetUserData(kTestData1Key, test_data1_); | ||
EXPECT_FALSE(supports_user_data_->GetUserData(kTestData2Key)); | ||
supports_user_data_->SetUserData(kTestData2Key, test_data2_); | ||
EXPECT_EQ(supports_user_data_->GetUserData(kTestData2Key), test_data2_); | ||
} | ||
|
||
TEST_F(SupportsUserDataTest, DistinctDataDestroyedSeparately) { | ||
supports_user_data_->SetUserData(kTestData1Key, test_data1_); | ||
supports_user_data_->SetUserData(kTestData2Key, test_data2_); | ||
EXPECT_FALSE(test_data1_was_destroyed_); | ||
EXPECT_FALSE(test_data2_was_destroyed_); | ||
|
||
supports_user_data_->RemoveUserData(kTestData2Key); | ||
EXPECT_FALSE(test_data1_was_destroyed_); | ||
EXPECT_TRUE(test_data2_was_destroyed_); | ||
|
||
supports_user_data_.reset(); | ||
EXPECT_TRUE(test_data1_was_destroyed_); | ||
} | ||
|
||
} // namespace ios |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef IOS_BASE_SUPPORTS_USER_DATA_H_ | ||
#define IOS_BASE_SUPPORTS_USER_DATA_H_ | ||
|
||
namespace ios { | ||
|
||
class SupportsUserDataInternal; | ||
|
||
// This is a helper for classes that want to allow users to stash random data by | ||
// key. At destruction all the objects will be destructed. | ||
class SupportsUserData { | ||
public: | ||
SupportsUserData(); | ||
|
||
// Derive from this class and add your own data members to associate extra | ||
// information with this object. Alternatively, add this as a public base | ||
// class to any class with a virtual destructor. | ||
class Data { | ||
public: | ||
virtual ~Data() {} | ||
}; | ||
|
||
// The user data allows the clients to associate data with this object. | ||
// Multiple user data values can be stored under different keys. | ||
// This object will TAKE OWNERSHIP of the given data pointer, and will | ||
// delete the object if it is changed or the object is destroyed. | ||
Data* GetUserData(const void* key) const; | ||
void SetUserData(const void* key, Data* data); | ||
void RemoveUserData(const void* key); | ||
|
||
// SupportsUserData is not thread-safe, and on debug build will assert it is | ||
// only used on one thread. Calling this method allows the caller to hand | ||
// the SupportsUserData instance across threads. Use only if you are taking | ||
// full control of the synchronization of that handover. | ||
void DetachUserDataThread(); | ||
|
||
protected: | ||
virtual ~SupportsUserData(); | ||
|
||
private: | ||
// Owned by this object and scoped to its lifetime. | ||
SupportsUserDataInternal* internal_helper_; | ||
}; | ||
|
||
} // namespace ios | ||
|
||
#endif // IOS_BASE_SUPPORTS_USER_DATA_H_ |