- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / declarative / deduping_factory_unittest.cc
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 "chrome/browser/extensions/api/declarative/deduping_factory.h"
6
7 #include "base/values.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace {
11
12 const char kTypeName[] = "Foo";
13 const char kTypeName2[] = "Foo2";
14
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 };
22
23   explicit BaseClass(Type type) : type_(type) {}
24
25   Type type() const { return type_; }
26
27   // For BaseClassT template:
28   virtual bool Equals(const BaseClass* other) const = 0;
29
30  protected:
31   friend class base::RefCounted<BaseClass>;
32   virtual ~BaseClass() {}
33
34  private:
35   const Type type_;
36 };
37
38 class Foo : public BaseClass {
39  public:
40   explicit Foo(int parameter) : BaseClass(FOO), parameter_(parameter) {}
41   virtual bool Equals(const BaseClass* other) const OVERRIDE {
42     return other->type() == type() &&
43            static_cast<const Foo*>(other)->parameter_ == parameter_;
44   }
45   int parameter() const {
46     return parameter_;
47   }
48
49  private:
50   friend class base::RefCounted<BaseClass>;
51   virtual ~Foo() {}
52
53   // Note that this class must be immutable.
54   const int parameter_;
55   DISALLOW_COPY_AND_ASSIGN(Foo);
56 };
57
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);
69   }
70   return scoped_refptr<const BaseClass>(new Foo(parameter));
71 }
72
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();
77 }
78
79 }  // namespace
80
81 namespace extensions {
82
83 TEST(DedupingFactoryTest, InstantiationParameterized) {
84   DedupingFactory<BaseClass> factory(2);
85   factory.RegisterFactoryMethod(
86       kTypeName, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
87
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));
92
93   std::string error;
94   bool bad_message = false;
95
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());
105
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());
111
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);
117
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));
123
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);
128 }
129
130 TEST(DedupingFactoryTest, InstantiationNonParameterized) {
131   DedupingFactory<BaseClass> factory(2);
132   factory.RegisterFactoryMethod(
133       kTypeName, DedupingFactory<BaseClass>::IS_NOT_PARAMETERIZED, &CreateFoo);
134
135   scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
136   scoped_ptr<base::DictionaryValue> d2(CreateDictWithParameter(2));
137
138   std::string error;
139   bool bad_message = false;
140
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);
152 }
153
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);
160
161   scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
162
163   std::string error;
164   bool bad_message = false;
165
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));
170
171   ASSERT_TRUE(c1_a.get());
172   ASSERT_TRUE(c1_b.get());
173   EXPECT_NE(c1_a, c1_b);
174 }
175
176 TEST(DedupingFactoryTest, Clear) {
177   DedupingFactory<BaseClass> factory(2);
178   factory.RegisterFactoryMethod(
179       kTypeName, DedupingFactory<BaseClass>::IS_PARAMETERIZED, &CreateFoo);
180
181   scoped_ptr<base::DictionaryValue> d1(CreateDictWithParameter(1));
182
183   std::string error;
184   bool bad_message = false;
185
186   scoped_refptr<const BaseClass> c1_a(
187       factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
188
189   factory.ClearPrototypes();
190
191   scoped_refptr<const BaseClass> c1_b(
192       factory.Instantiate(kTypeName, d1.get(), &error, &bad_message));
193
194   ASSERT_TRUE(c1_a.get());
195   ASSERT_TRUE(c1_b.get());
196   EXPECT_NE(c1_a, c1_b);
197 }
198
199 }  // namespace extensions