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/ui/cocoa/table_row_nsimage_cache.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "third_party/skia/include/core/SkBitmap.h"
9#include "ui/gfx/image/image_skia.h"
10
11namespace {
12
13class TestTable : public TableRowNSImageCache::Table {
14 public:
15
16  std::vector<SkBitmap>* rows() {
17    return &rows_;
18  }
19
20  // TableRowNSImageCache::Table overrides.
21  virtual int RowCount() const OVERRIDE {
22    return rows_.size();
23  }
24  virtual gfx::ImageSkia GetIcon(int index) const OVERRIDE {
25    return gfx::ImageSkia::CreateFrom1xBitmap(rows_[index]);
26  }
27
28 private:
29  std::vector<SkBitmap> rows_;
30};
31
32SkBitmap MakeImage(int width, int height) {
33  SkBitmap image;
34  image.allocN32Pixels(width, height);
35  image.eraseARGB(255, 255, 0, 0);
36  return image;
37}
38
39// Define this as a macro so that the original variable names can be used in
40// test output.
41#define COMPARE_SK_NS_IMG_SIZES(skia, cocoa) \
42  EXPECT_EQ(skia.width(), [cocoa size].width); \
43  EXPECT_EQ(skia.height(), [cocoa size].height);
44
45TEST(TableRowNSImageCacheTest, ModelChanged) {
46  TestTable table;
47  std::vector<SkBitmap>* rows = table.rows();
48  rows->push_back(MakeImage(10, 10));
49  rows->push_back(MakeImage(20, 20));
50  rows->push_back(MakeImage(30, 30));
51  TableRowNSImageCache cache(&table);
52
53  NSImage* image0 = cache.GetImageForRow(0);
54  NSImage* image1 = cache.GetImageForRow(1);
55  NSImage* image2 = cache.GetImageForRow(2);
56
57  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
58  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
59  COMPARE_SK_NS_IMG_SIZES(rows->at(2), image2);
60
61  rows->clear();
62
63  rows->push_back(MakeImage(15, 15));
64  rows->push_back(MakeImage(25, 25));
65  rows->push_back(MakeImage(35, 35));
66  rows->push_back(MakeImage(45, 45));
67
68  // Invalidate the entire model.
69  cache.OnModelChanged();
70
71  EXPECT_NE(image0, cache.GetImageForRow(0));
72  image0 = cache.GetImageForRow(0);
73
74  EXPECT_NE(image1, cache.GetImageForRow(1));
75  image1 = cache.GetImageForRow(1);
76
77  EXPECT_NE(image2, cache.GetImageForRow(2));
78  image2 = cache.GetImageForRow(2);
79
80  NSImage* image3 = cache.GetImageForRow(3);
81
82  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
83  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
84  COMPARE_SK_NS_IMG_SIZES(rows->at(2), image2);
85  COMPARE_SK_NS_IMG_SIZES(rows->at(3), image3);
86}
87
88
89TEST(TableRowNSImageCacheTest, ItemsChanged) {
90  TestTable table;
91  std::vector<SkBitmap>* rows = table.rows();
92  rows->push_back(MakeImage(10, 10));
93  rows->push_back(MakeImage(20, 20));
94  rows->push_back(MakeImage(30, 30));
95  TableRowNSImageCache cache(&table);
96
97  NSImage* image0 = cache.GetImageForRow(0);
98  NSImage* image1 = cache.GetImageForRow(1);
99  NSImage* image2 = cache.GetImageForRow(2);
100
101  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
102  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
103  COMPARE_SK_NS_IMG_SIZES(rows->at(2), image2);
104
105  // Update the middle image.
106  (*rows)[1] = MakeImage(25, 25);
107  cache.OnItemsChanged(/* start=*/1, /* count=*/1);
108
109  // Make sure the other items remained the same.
110  EXPECT_EQ(image0, cache.GetImageForRow(0));
111  EXPECT_EQ(image2, cache.GetImageForRow(2));
112
113  image1 = cache.GetImageForRow(1);
114  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
115
116  // Update more than one image.
117  (*rows)[0] = MakeImage(15, 15);
118  (*rows)[1] = MakeImage(27, 27);
119  EXPECT_EQ(3U, rows->size());
120  cache.OnItemsChanged(0, 2);
121
122  image0 = cache.GetImageForRow(0);
123  image1 = cache.GetImageForRow(1);
124
125  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
126  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
127}
128
129
130TEST(TableRowNSImageCacheTest, ItemsAdded) {
131  TestTable table;
132  std::vector<SkBitmap>* rows = table.rows();
133  rows->push_back(MakeImage(10, 10));
134  rows->push_back(MakeImage(20, 20));
135  TableRowNSImageCache cache(&table);
136
137  NSImage* image0 = cache.GetImageForRow(0);
138  NSImage* image1 = cache.GetImageForRow(1);
139
140  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
141  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
142
143  // Add an item to the end.
144  rows->push_back(MakeImage(30, 30));
145  cache.OnItemsAdded(2, 1);
146
147  // Make sure image 1 stayed the same.
148  EXPECT_EQ(image1, cache.GetImageForRow(1));
149  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
150
151  // Check that image 2 got added correctly.
152  NSImage* image2 = cache.GetImageForRow(2);
153  COMPARE_SK_NS_IMG_SIZES(rows->at(2), image2);
154
155  // Add two items to the begging.
156  rows->insert(rows->begin(), MakeImage(7, 7));
157  rows->insert(rows->begin(), MakeImage(3, 3));
158  cache.OnItemsAdded(0, 2);
159
160  NSImage* image00 = cache.GetImageForRow(0);
161  NSImage* image01 = cache.GetImageForRow(1);
162
163  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image00);
164  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image01);
165}
166
167
168TEST(TableRowNSImageCacheTest, ItemsRemoved) {
169  TestTable table;
170  std::vector<SkBitmap>* rows = table.rows();
171  rows->push_back(MakeImage(10, 10));
172  rows->push_back(MakeImage(20, 20));
173  rows->push_back(MakeImage(30, 30));
174  rows->push_back(MakeImage(40, 40));
175  rows->push_back(MakeImage(50, 50));
176  TableRowNSImageCache cache(&table);
177
178  NSImage* image0 = cache.GetImageForRow(0);
179  NSImage* image1 = cache.GetImageForRow(1);
180  NSImage* image2 = cache.GetImageForRow(2);
181  NSImage* image3 = cache.GetImageForRow(3);
182  NSImage* image4 = cache.GetImageForRow(4);
183
184  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
185  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
186  COMPARE_SK_NS_IMG_SIZES(rows->at(2), image2);
187  COMPARE_SK_NS_IMG_SIZES(rows->at(3), image3);
188  COMPARE_SK_NS_IMG_SIZES(rows->at(4), image4);
189
190  rows->erase(rows->begin() + 1, rows->begin() + 4);  // [20x20, 50x50)
191  cache.OnItemsRemoved(1, 3);
192
193  image0 = cache.GetImageForRow(0);
194  image1 = cache.GetImageForRow(1);
195
196  COMPARE_SK_NS_IMG_SIZES(rows->at(0), image0);
197  COMPARE_SK_NS_IMG_SIZES(rows->at(1), image1);
198}
199
200}  // namespace
201