#include "base/threading/sequence_local_storage_map.h"
#include <memory>
#include <utility>
#include "base/memory/raw_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace internal {
namespace {
constexpr int kSlotId = 1;
class SetOnDestroy {
public:
SetOnDestroy(bool* was_destroyed_ptr)
: was_destroyed_ptr_(was_destroyed_ptr) {
DCHECK(was_destroyed_ptr_);
DCHECK(!(*was_destroyed_ptr_));
}
SetOnDestroy(const SetOnDestroy&) = delete;
SetOnDestroy& operator=(const SetOnDestroy&) = delete;
~SetOnDestroy() {
DCHECK(!(*was_destroyed_ptr_));
*was_destroyed_ptr_ = true;
}
private:
const raw_ptr<bool> was_destroyed_ptr_;
};
template <typename T, typename... Args>
SequenceLocalStorageMap::ValueDestructorPair CreateValueDestructorPair(
Args... args) {
T* value = new T(args...);
SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc* destructor =
[](void* ptr) { std::default_delete<T>()(static_cast<T*>(ptr)); };
SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair{
value, destructor};
return value_destructor_pair;
}
}
TEST(SequenceLocalStorageMapTest, SetGet) {
SequenceLocalStorageMap sequence_local_storage_map;
ScopedSetSequenceLocalStorageMapForCurrentThread
scoped_sequence_local_storage_map(&sequence_local_storage_map);
SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
CreateValueDestructorPair<int>(5);
sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
EXPECT_EQ(*static_cast<int*>(sequence_local_storage_map.Get(kSlotId)), 5);
}
TEST(SequenceLocalStorageMapTest, Destructor) {
bool set_on_destruction = false;
{
SequenceLocalStorageMap sequence_local_storage_map;
ScopedSetSequenceLocalStorageMapForCurrentThread
scoped_sequence_local_storage_map(&sequence_local_storage_map);
SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
}
EXPECT_TRUE(set_on_destruction);
}
TEST(SequenceLocalStorageMapTest, DestructorCalledOnSetOverwrite) {
bool set_on_destruction = false;
bool set_on_destruction2 = false;
{
SequenceLocalStorageMap sequence_local_storage_map;
ScopedSetSequenceLocalStorageMapForCurrentThread
scoped_sequence_local_storage_map(&sequence_local_storage_map);
SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair2 =
CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction2);
sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
ASSERT_FALSE(set_on_destruction);
sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair2));
EXPECT_TRUE(set_on_destruction);
EXPECT_FALSE(set_on_destruction2);
}
EXPECT_TRUE(set_on_destruction2);
}
}
}