Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / declarative / deduping_factory_unittest.cc
bloba10cb9c512749d3d0609c3e47e870fd9c9277387
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.
5 #include "extensions/browser/api/declarative/deduping_factory.h"
7 #include "base/values.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 namespace {
12 const char kTypeName[] = "Foo";
13 const char kTypeName2[] = "Foo2";
15 // This serves as an example how to use the DedupingFactory.
16 class BaseClass : public base::RefCounted<BaseClass> {
17 public:
18 // The type is introduced so that we can compare derived classes even though
19 // Equals takes a parameter of type BaseClass. Each derived class gets an
20 // entry in Type.
21 enum Type { FOO };
23 explicit BaseClass(Type type) : type_(type) {}
25 Type type() const { return type_; }
27 // For BaseClassT template:
28 virtual bool Equals(const BaseClass* other) const = 0;
30 protected:
31 friend class base::RefCounted<BaseClass>;
32 virtual ~BaseClass() {}
34 private:
35 const Type type_;
38 class Foo : public BaseClass {
39 public:
40 explicit Foo(int parameter) : BaseClass(FOO), parameter_(parameter) {}
41 bool Equals(const BaseClass* other) const override {
42 return other->type() == type() &&
43 static_cast<const Foo*>(other)->parameter_ == parameter_;
45 int parameter() const {
46 return parameter_;
49 private:
50 friend class base::RefCounted<BaseClass>;
51 ~Foo() override {}
53 // Note that this class must be immutable.
54 const int parameter_;
55 DISALLOW_COPY_AND_ASSIGN(Foo);
58 scoped_refptr<const BaseClass> CreateFoo(const std::string& /*instance_type*/,
59 const base::Value* value,
60 std::string* error,
61 bool* bad_message) {
62 const base::DictionaryValue* dict = NULL;
63 CHECK(value->GetAsDictionary(&dict));
64 int parameter = 0;
65 if (!dict->GetInteger("parameter", &parameter)) {
66 *error = "No parameter";
67 *bad_message = true;
68 return scoped_refptr<const BaseClass>(NULL);
70 return scoped_refptr<const BaseClass>(new Foo(parameter));
73 scoped_ptr<base::DictionaryValue> CreateDictWithParameter(int parameter) {
74 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
75 dict->SetInteger("parameter", parameter);
76 return dict.Pass();
79 } // namespace
81 namespace extensions {
83 TEST(DedupingFactoryTest, InstantiationParameterized) {
84 DedupingFactory<BaseClass> factory(2);
85 factory.RegisterFactoryMethod(
86 kTypeName, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
88 scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
89 scoped_ptr<base::DictionaryValue> d2(CreateDictWithParameter(2));
90 scoped_ptr<base::DictionaryValue> d3(CreateDictWithParameter(3));
91 scoped_ptr<base::DictionaryValue> d4(CreateDictWithParameter(4));
93 std::string error;
94 bool bad_message = false;
96 // Fill factory with 2 different types.
97 scoped_refptr<const BaseClass> c1(
98 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
99 scoped_refptr<const BaseClass> c2(
100 factory.Instantiate(kTypeName, d2.get(), &error, &bad_message));
101 ASSERT_TRUE(c1.get());
102 ASSERT_TRUE(c2.get());
103 EXPECT_EQ(1, static_cast<const Foo*>(c1.get())->parameter());
104 EXPECT_EQ(2, static_cast<const Foo*>(c2.get())->parameter());
106 // This one produces an overflow, now the cache contains [2, 3]
107 scoped_refptr<const BaseClass> c3(
108 factory.Instantiate(kTypeName, d3.get(), &error, &bad_message));
109 ASSERT_TRUE(c3.get());
110 EXPECT_EQ(3, static_cast<const Foo*>(c3.get())->parameter());
112 // Reuse 2, this should give the same instance as c2.
113 scoped_refptr<const BaseClass> c2_b(
114 factory.Instantiate(kTypeName, d2.get(), &error, &bad_message));
115 EXPECT_EQ(2, static_cast<const Foo*>(c2_b.get())->parameter());
116 EXPECT_EQ(c2, c2_b);
118 // Also check that the reuse of 2 moved it to the end, so that the cache is
119 // now [3, 2] and 3 is discarded before 2.
120 // This discards 3, so the cache becomes [2, 1]
121 scoped_refptr<const BaseClass> c1_b(
122 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
124 scoped_refptr<const BaseClass> c2_c(
125 factory.Instantiate(kTypeName, d2.get(), &error, &bad_message));
126 EXPECT_EQ(2, static_cast<const Foo*>(c2_c.get())->parameter());
127 EXPECT_EQ(c2, c2_c);
130 TEST(DedupingFactoryTest, InstantiationNonParameterized) {
131 DedupingFactory<BaseClass> factory(2);
132 factory.RegisterFactoryMethod(
133 kTypeName, DedupingFactory<BaseClass>::IS_NOT_PARAMETERIZED, &CreateFoo);
135 scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
136 scoped_ptr<base::DictionaryValue> d2(CreateDictWithParameter(2));
138 std::string error;
139 bool bad_message = false;
141 // We create two instances with different dictionaries but because the type is
142 // declared to be not parameterized, we should get the same instance.
143 scoped_refptr<const BaseClass> c1(
144 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
145 scoped_refptr<const BaseClass> c2(
146 factory.Instantiate(kTypeName, d2.get(), &error, &bad_message));
147 ASSERT_TRUE(c1.get());
148 ASSERT_TRUE(c2.get());
149 EXPECT_EQ(1, static_cast<const Foo*>(c1.get())->parameter());
150 EXPECT_EQ(1, static_cast<const Foo*>(c2.get())->parameter());
151 EXPECT_EQ(c1, c2);
154 TEST(DedupingFactoryTest, TypeNames) {
155 DedupingFactory<BaseClass> factory(2);
156 factory.RegisterFactoryMethod(
157 kTypeName, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
158 factory.RegisterFactoryMethod(
159 kTypeName2, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
161 scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
163 std::string error;
164 bool bad_message = false;
166 scoped_refptr<const BaseClass> c1_a(
167 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
168 scoped_refptr<const BaseClass> c1_b(
169 factory.Instantiate(kTypeName2, d1.get(), &error, &bad_message));
171 ASSERT_TRUE(c1_a.get());
172 ASSERT_TRUE(c1_b.get());
173 EXPECT_NE(c1_a, c1_b);
176 TEST(DedupingFactoryTest, Clear) {
177 DedupingFactory<BaseClass> factory(2);
178 factory.RegisterFactoryMethod(
179 kTypeName, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
181 scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
183 std::string error;
184 bool bad_message = false;
186 scoped_refptr<const BaseClass> c1_a(
187 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
189 factory.ClearPrototypes();
191 scoped_refptr<const BaseClass> c1_b(
192 factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
194 ASSERT_TRUE(c1_a.get());
195 ASSERT_TRUE(c1_b.get());
196 EXPECT_NE(c1_a, c1_b);
199 } // namespace extensions