Encode method and error message inside LevelDB::Status message
[chromium-blink-merge.git] / ui / gfx / image / image_skia_unittest.cc
blobfd17453f8f9e3553d158b969b6746148fee3ecdf
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 "ui/gfx/image/image_skia.h"
7 #include "base/logging.h"
8 #include "base/threading/simple_thread.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "ui/base/layout.h"
12 #include "ui/gfx/image/image_skia_rep.h"
13 #include "ui/gfx/image/image_skia_source.h"
14 #include "ui/gfx/size.h"
16 // Duplicated from base/threading/non_thread_safe.h so that we can be
17 // good citizens there and undef the macro.
18 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
19 #define ENABLE_NON_THREAD_SAFE 1
20 #else
21 #define ENABLE_NON_THREAD_SAFE 0
22 #endif
24 namespace gfx {
26 namespace {
28 class FixedSource : public ImageSkiaSource {
29 public:
30 FixedSource(const ImageSkiaRep& image) : image_(image) {}
32 virtual ~FixedSource() {
35 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
36 return image_;
39 private:
40 ImageSkiaRep image_;
42 DISALLOW_COPY_AND_ASSIGN(FixedSource);
45 class DynamicSource : public ImageSkiaSource {
46 public:
47 DynamicSource(const gfx::Size& size) : size_(size) {}
49 virtual ~DynamicSource() {
52 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
53 return gfx::ImageSkiaRep(size_, scale_factor);
56 private:
57 gfx::Size size_;
59 DISALLOW_COPY_AND_ASSIGN(DynamicSource);
62 class NullSource: public ImageSkiaSource {
63 public:
64 NullSource() {
67 virtual ~NullSource() {
70 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
71 return gfx::ImageSkiaRep();
74 private:
75 DISALLOW_COPY_AND_ASSIGN(NullSource);
78 } // namespace
80 namespace test {
81 class TestOnThread : public base::SimpleThread {
82 public:
83 explicit TestOnThread(ImageSkia* image_skia)
84 : SimpleThread("image_skia_on_thread"),
85 image_skia_(image_skia),
86 can_read_(false),
87 can_modify_(false) {
90 virtual void Run() OVERRIDE {
91 can_read_ = image_skia_->CanRead();
92 can_modify_ = image_skia_->CanModify();
93 if (can_read_)
94 image_skia_->image_reps();
97 void StartAndJoin() {
98 Start();
99 Join();
102 bool can_read() const { return can_read_; }
104 bool can_modify() const { return can_modify_; }
106 private:
107 ImageSkia* image_skia_;
109 bool can_read_;
110 bool can_modify_;
112 DISALLOW_COPY_AND_ASSIGN(TestOnThread);
115 } // namespace test
117 TEST(ImageSkiaTest, FixedSource) {
118 ImageSkiaRep image(Size(100, 200), ui::SCALE_FACTOR_100P);
119 ImageSkia image_skia(new FixedSource(image), Size(100, 200));
120 EXPECT_EQ(0U, image_skia.image_reps().size());
122 const ImageSkiaRep& result_100p =
123 image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
124 EXPECT_EQ(100, result_100p.GetWidth());
125 EXPECT_EQ(200, result_100p.GetHeight());
126 EXPECT_EQ(ui::SCALE_FACTOR_100P, result_100p.scale_factor());
127 EXPECT_EQ(1U, image_skia.image_reps().size());
129 const ImageSkiaRep& result_200p =
130 image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
132 EXPECT_EQ(100, result_200p.GetWidth());
133 EXPECT_EQ(200, result_200p.GetHeight());
134 EXPECT_EQ(100, result_200p.pixel_width());
135 EXPECT_EQ(200, result_200p.pixel_height());
136 EXPECT_EQ(ui::SCALE_FACTOR_100P, result_200p.scale_factor());
137 EXPECT_EQ(1U, image_skia.image_reps().size());
139 // Get the representation again and make sure it doesn't
140 // generate new image skia rep.
141 image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
142 image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
143 EXPECT_EQ(1U, image_skia.image_reps().size());
146 TEST(ImageSkiaTest, DynamicSource) {
147 ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200));
148 EXPECT_EQ(0U, image_skia.image_reps().size());
149 const ImageSkiaRep& result_100p =
150 image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
151 EXPECT_EQ(100, result_100p.GetWidth());
152 EXPECT_EQ(200, result_100p.GetHeight());
153 EXPECT_EQ(ui::SCALE_FACTOR_100P, result_100p.scale_factor());
154 EXPECT_EQ(1U, image_skia.image_reps().size());
156 const ImageSkiaRep& result_200p =
157 image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
158 EXPECT_EQ(100, result_200p.GetWidth());
159 EXPECT_EQ(200, result_200p.GetHeight());
160 EXPECT_EQ(200, result_200p.pixel_width());
161 EXPECT_EQ(400, result_200p.pixel_height());
162 EXPECT_EQ(ui::SCALE_FACTOR_200P, result_200p.scale_factor());
163 EXPECT_EQ(2U, image_skia.image_reps().size());
165 // Get the representation again and make sure it doesn't
166 // generate new image skia rep.
167 image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
168 EXPECT_EQ(2U, image_skia.image_reps().size());
169 image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
170 EXPECT_EQ(2U, image_skia.image_reps().size());
173 // Tests that image_reps returns all of the representations in the
174 // image when there are multiple representations for a scale factor.
175 // This currently is the case with ImageLoader::LoadImages.
176 TEST(ImageSkiaTest, ManyRepsPerScaleFactor) {
177 const int kSmallIcon1x = 16;
178 const int kSmallIcon2x = 32;
179 const int kLargeIcon1x = 32;
181 ImageSkia image(new NullSource(), gfx::Size(kSmallIcon1x, kSmallIcon1x));
182 // Simulate a source which loads images on a delay. Upon
183 // GetImageForScaleFactor, it immediately returns null and starts loading
184 // image reps slowly.
185 image.GetRepresentation(ui::SCALE_FACTOR_100P);
186 image.GetRepresentation(ui::SCALE_FACTOR_200P);
188 // After a lengthy amount of simulated time, finally loaded image reps.
189 image.AddRepresentation(ImageSkiaRep(
190 gfx::Size(kSmallIcon1x, kSmallIcon1x), ui::SCALE_FACTOR_100P));
191 image.AddRepresentation(ImageSkiaRep(
192 gfx::Size(kSmallIcon2x, kSmallIcon2x), ui::SCALE_FACTOR_200P));
193 image.AddRepresentation(ImageSkiaRep(
194 gfx::Size(kLargeIcon1x, kLargeIcon1x), ui::SCALE_FACTOR_100P));
196 std::vector<ImageSkiaRep> image_reps = image.image_reps();
197 EXPECT_EQ(3u, image_reps.size());
199 int num_1x = 0;
200 int num_2x = 0;
201 for (size_t i = 0; i < image_reps.size(); ++i) {
202 if (image_reps[i].scale_factor() == ui::SCALE_FACTOR_100P)
203 num_1x++;
204 else if (image_reps[i].scale_factor() == ui::SCALE_FACTOR_200P)
205 num_2x++;
207 EXPECT_EQ(2, num_1x);
208 EXPECT_EQ(1, num_2x);
211 TEST(ImageSkiaTest, GetBitmap) {
212 ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200));
213 const SkBitmap* bitmap = image_skia.bitmap();
214 EXPECT_NE(static_cast<SkBitmap*>(NULL), bitmap);
215 EXPECT_FALSE(bitmap->isNull());
218 TEST(ImageSkiaTest, GetBitmapFromEmpty) {
219 // Create an image with 1 representation and remove it so the ImageSkiaStorage
220 // is left with no representations.
221 ImageSkia empty_image(ImageSkiaRep(Size(100, 200), ui::SCALE_FACTOR_100P));
222 ImageSkia empty_image_copy(empty_image);
223 empty_image.RemoveRepresentation(ui::SCALE_FACTOR_100P);
225 // Check that ImageSkia::bitmap() still returns a valid SkBitmap pointer for
226 // the image and all its copies.
227 const SkBitmap* bitmap = empty_image_copy.bitmap();
228 ASSERT_NE(static_cast<SkBitmap*>(NULL), bitmap);
229 EXPECT_TRUE(bitmap->isNull());
230 EXPECT_TRUE(bitmap->empty());
233 TEST(ImageSkiaTest, BackedBySameObjectAs) {
234 // Null images should all be backed by the same object (NULL).
235 ImageSkia image;
236 ImageSkia unrelated;
237 EXPECT_TRUE(image.BackedBySameObjectAs(unrelated));
239 image.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
240 ui::SCALE_FACTOR_100P));
241 ImageSkia copy = image;
242 copy.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
243 ui::SCALE_FACTOR_200P));
244 unrelated.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
245 ui::SCALE_FACTOR_100P));
246 EXPECT_TRUE(image.BackedBySameObjectAs(copy));
247 EXPECT_FALSE(image.BackedBySameObjectAs(unrelated));
248 EXPECT_FALSE(copy.BackedBySameObjectAs(unrelated));
251 #if ENABLE_NON_THREAD_SAFE
252 TEST(ImageSkiaTest, EmptyOnThreadTest) {
253 ImageSkia empty;
254 test::TestOnThread empty_on_thread(&empty);
255 empty_on_thread.Start();
256 empty_on_thread.Join();
257 EXPECT_TRUE(empty_on_thread.can_read());
258 EXPECT_TRUE(empty_on_thread.can_modify());
261 TEST(ImageSkiaTest, StaticOnThreadTest) {
262 ImageSkia image(ImageSkiaRep(Size(100, 200), ui::SCALE_FACTOR_100P));
263 EXPECT_FALSE(image.IsThreadSafe());
265 test::TestOnThread image_on_thread(&image);
266 // an image that was never accessed on this thread can be
267 // read by other thread.
268 image_on_thread.StartAndJoin();
269 EXPECT_TRUE(image_on_thread.can_read());
270 EXPECT_TRUE(image_on_thread.can_modify());
271 EXPECT_FALSE(image.CanRead());
272 EXPECT_FALSE(image.CanModify());
274 image.DetachStorageFromThread();
275 // An image is accessed by this thread,
276 // so other thread cannot read/modify it.
277 image.image_reps();
278 test::TestOnThread image_on_thread2(&image);
279 image_on_thread2.StartAndJoin();
280 EXPECT_FALSE(image_on_thread2.can_read());
281 EXPECT_FALSE(image_on_thread2.can_modify());
282 EXPECT_TRUE(image.CanRead());
283 EXPECT_TRUE(image.CanModify());
285 image.DetachStorageFromThread();
286 scoped_ptr<ImageSkia> deep_copy(image.DeepCopy());
287 EXPECT_FALSE(deep_copy->IsThreadSafe());
288 test::TestOnThread deepcopy_on_thread(deep_copy.get());
289 deepcopy_on_thread.StartAndJoin();
290 EXPECT_TRUE(deepcopy_on_thread.can_read());
291 EXPECT_TRUE(deepcopy_on_thread.can_modify());
292 EXPECT_FALSE(deep_copy->CanRead());
293 EXPECT_FALSE(deep_copy->CanModify());
295 scoped_ptr<ImageSkia> deep_copy2(image.DeepCopy());
296 EXPECT_EQ(1U, deep_copy2->image_reps().size());
297 // Access it from current thread so that it can't be
298 // accessed from another thread.
299 deep_copy2->image_reps();
300 EXPECT_FALSE(deep_copy2->IsThreadSafe());
301 test::TestOnThread deepcopy2_on_thread(deep_copy2.get());
302 deepcopy2_on_thread.StartAndJoin();
303 EXPECT_FALSE(deepcopy2_on_thread.can_read());
304 EXPECT_FALSE(deepcopy2_on_thread.can_modify());
305 EXPECT_TRUE(deep_copy2->CanRead());
306 EXPECT_TRUE(deep_copy2->CanModify());
308 image.DetachStorageFromThread();
309 image.SetReadOnly();
310 // A read-only ImageSkia with no source is thread safe.
311 EXPECT_TRUE(image.IsThreadSafe());
312 test::TestOnThread readonly_on_thread(&image);
313 readonly_on_thread.StartAndJoin();
314 EXPECT_TRUE(readonly_on_thread.can_read());
315 EXPECT_FALSE(readonly_on_thread.can_modify());
316 EXPECT_TRUE(image.CanRead());
317 EXPECT_FALSE(image.CanModify());
319 image.DetachStorageFromThread();
320 image.MakeThreadSafe();
321 EXPECT_TRUE(image.IsThreadSafe());
322 test::TestOnThread threadsafe_on_thread(&image);
323 threadsafe_on_thread.StartAndJoin();
324 EXPECT_TRUE(threadsafe_on_thread.can_read());
325 EXPECT_FALSE(threadsafe_on_thread.can_modify());
326 EXPECT_TRUE(image.CanRead());
327 EXPECT_FALSE(image.CanModify());
330 TEST(ImageSkiaTest, SourceOnThreadTest) {
331 ImageSkia image(new DynamicSource(Size(100, 200)), Size(100, 200));
332 EXPECT_FALSE(image.IsThreadSafe());
334 test::TestOnThread image_on_thread(&image);
335 image_on_thread.StartAndJoin();
336 // an image that was never accessed on this thread can be
337 // read by other thread.
338 EXPECT_TRUE(image_on_thread.can_read());
339 EXPECT_TRUE(image_on_thread.can_modify());
340 EXPECT_FALSE(image.CanRead());
341 EXPECT_FALSE(image.CanModify());
343 image.DetachStorageFromThread();
344 // An image is accessed by this thread,
345 // so other thread cannot read/modify it.
346 image.image_reps();
347 test::TestOnThread image_on_thread2(&image);
348 image_on_thread2.StartAndJoin();
349 EXPECT_FALSE(image_on_thread2.can_read());
350 EXPECT_FALSE(image_on_thread2.can_modify());
351 EXPECT_TRUE(image.CanRead());
352 EXPECT_TRUE(image.CanModify());
354 image.DetachStorageFromThread();
355 image.SetReadOnly();
356 EXPECT_FALSE(image.IsThreadSafe());
357 test::TestOnThread readonly_on_thread(&image);
358 readonly_on_thread.StartAndJoin();
359 EXPECT_TRUE(readonly_on_thread.can_read());
360 EXPECT_FALSE(readonly_on_thread.can_modify());
361 EXPECT_FALSE(image.CanRead());
362 EXPECT_FALSE(image.CanModify());
364 image.DetachStorageFromThread();
365 image.MakeThreadSafe();
366 EXPECT_TRUE(image.IsThreadSafe());
367 // Check if image reps are generated for supported scale factors.
368 EXPECT_EQ(ui::GetSupportedScaleFactors().size(),
369 image.image_reps().size());
370 test::TestOnThread threadsafe_on_thread(&image);
371 threadsafe_on_thread.StartAndJoin();
372 EXPECT_TRUE(threadsafe_on_thread.can_read());
373 EXPECT_FALSE(threadsafe_on_thread.can_modify());
374 EXPECT_TRUE(image.CanRead());
375 EXPECT_FALSE(image.CanModify());
377 #endif // ENABLE_NON_THREAD_SAFE
379 // Just in case we ever get lumped together with other compilation units.
380 #undef ENABLE_NON_THREAD_SAFE
382 } // namespace gfx