Index: ui/gfx/image/image_skia_unittest.cc |
diff --git a/ui/gfx/image/image_skia_unittest.cc b/ui/gfx/image/image_skia_unittest.cc |
index 9967a2f09e6f1a24b415e40b83cbfca6169aee28..bb559ccc2ad2558c839dd59e6b534019eebddd2d 100644 |
--- a/ui/gfx/image/image_skia_unittest.cc |
+++ b/ui/gfx/image/image_skia_unittest.cc |
@@ -4,6 +4,8 @@ |
#include "ui/gfx/image/image_skia.h" |
+#include "base/logging.h" |
+#include "base/threading/simple_thread.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/base/layout.h" |
@@ -11,6 +13,14 @@ |
#include "ui/gfx/image/image_skia_source.h" |
#include "ui/gfx/size.h" |
+// Duplicated from base/threading/non_thread_safe.h so that we can be |
+// good citizens there and undef the macro. |
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) |
+#define ENABLE_NON_THREAD_SAFE 1 |
+#else |
+#define ENABLE_NON_THREAD_SAFE 0 |
+#endif |
+ |
namespace gfx { |
namespace { |
@@ -67,6 +77,43 @@ class NullSource: public ImageSkiaSource { |
} // namespace |
+namespace test { |
+class TestOnThread : public base::SimpleThread { |
+ public: |
+ explicit TestOnThread(ImageSkia* image_skia) |
+ : SimpleThread("image_skia_on_thread"), |
+ image_skia_(image_skia), |
+ can_read_(false), |
+ can_modify_(false) { |
+ } |
+ |
+ virtual void Run() OVERRIDE { |
+ can_read_ = image_skia_->CanRead(); |
+ can_modify_ = image_skia_->CanModify(); |
+ if (can_read_) |
+ image_skia_->image_reps(); |
+ } |
+ |
+ void StartAndJoin() { |
+ Start(); |
+ Join(); |
+ } |
+ |
+ bool can_read() const { return can_read_; } |
+ |
+ bool can_modify() const { return can_modify_; } |
+ |
+ private: |
+ ImageSkia* image_skia_; |
+ |
+ bool can_read_; |
+ bool can_modify_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestOnThread); |
+}; |
+ |
+} // namespace test |
+ |
TEST(ImageSkiaTest, FixedSource) { |
ImageSkiaRep image(Size(100, 200), ui::SCALE_FACTOR_100P); |
ImageSkia image_skia(new FixedSource(image), Size(100, 200)); |
@@ -123,13 +170,10 @@ TEST(ImageSkiaTest, DynamicSource) { |
EXPECT_EQ(2U, image_skia.image_reps().size()); |
} |
-#if defined(OS_MACOSX) |
- |
-// Tests that GetRepresentations returns all of the representations in the |
+// Tests that image_reps returns all of the representations in the |
// image when there are multiple representations for a scale factor. |
-// This currently is the case with ImageLoadingTracker::LoadImages, to |
-// load the application shortcut icon on Mac in particular. |
-TEST(ImageSkiaTest, GetRepresentationsManyRepsPerScaleFactor) { |
+// This currently is the case with ImageLoadingTracker::LoadImages. |
+TEST(ImageSkiaTest, ManyRepsPerScaleFactor) { |
const int kSmallIcon1x = 16; |
const int kSmallIcon2x = 32; |
const int kLargeIcon1x = 32; |
@@ -149,7 +193,7 @@ TEST(ImageSkiaTest, GetRepresentationsManyRepsPerScaleFactor) { |
image.AddRepresentation(ImageSkiaRep( |
gfx::Size(kLargeIcon1x, kLargeIcon1x), ui::SCALE_FACTOR_100P)); |
- std::vector<ImageSkiaRep> image_reps = image.GetRepresentations(); |
+ std::vector<ImageSkiaRep> image_reps = image.image_reps(); |
EXPECT_EQ(3u, image_reps.size()); |
int num_1x = 0; |
@@ -164,8 +208,6 @@ TEST(ImageSkiaTest, GetRepresentationsManyRepsPerScaleFactor) { |
EXPECT_EQ(1, num_2x); |
} |
-#endif // OS_MACOSX |
- |
TEST(ImageSkiaTest, GetBitmap) { |
ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200)); |
const SkBitmap* bitmap = image_skia.bitmap(); |
@@ -216,4 +258,135 @@ TEST(ImageSkiaTest, BackedBySameObjectAs) { |
EXPECT_FALSE(copy.BackedBySameObjectAs(unrelated)); |
} |
+#if ENABLE_NON_THREAD_SAFE |
+TEST(ImageSkiaTest, EmptyOnThreadTest) { |
+ ImageSkia empty; |
+ test::TestOnThread empty_on_thread(&empty); |
+ empty_on_thread.Start(); |
+ empty_on_thread.Join(); |
+ EXPECT_TRUE(empty_on_thread.can_read()); |
+ EXPECT_TRUE(empty_on_thread.can_modify()); |
+} |
+ |
+TEST(ImageSkiaTest, StaticOnThreadTest) { |
+ ImageSkia image(ImageSkiaRep(Size(100, 200), ui::SCALE_FACTOR_100P)); |
+ EXPECT_FALSE(image.IsThreadSafe()); |
+ |
+ test::TestOnThread image_on_thread(&image); |
+ // an image that was never accessed on this thread can be |
+ // read by other thread. |
+ image_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(image_on_thread.can_read()); |
+ EXPECT_TRUE(image_on_thread.can_modify()); |
+ EXPECT_FALSE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ // An image is accessed by this thread, |
+ // so other thread cannot read/modify it. |
+ image.image_reps(); |
+ test::TestOnThread image_on_thread2(&image); |
+ image_on_thread2.StartAndJoin(); |
+ EXPECT_FALSE(image_on_thread2.can_read()); |
+ EXPECT_FALSE(image_on_thread2.can_modify()); |
+ EXPECT_TRUE(image.CanRead()); |
+ EXPECT_TRUE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ ImageSkia deep_copy = image.DeepCopy(); |
+ EXPECT_FALSE(deep_copy.IsThreadSafe()); |
+ test::TestOnThread deepcopy_on_thread(&deep_copy); |
+ deepcopy_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(deepcopy_on_thread.can_read()); |
+ EXPECT_TRUE(deepcopy_on_thread.can_modify()); |
+ EXPECT_FALSE(deep_copy.CanRead()); |
+ EXPECT_FALSE(deep_copy.CanModify()); |
+ |
+ ImageSkia deep_copy2 = image.DeepCopy(); |
+ EXPECT_EQ(1U, deep_copy2.image_reps().size()); |
+ // Access it from current thread so that it can't be |
+ // accessed from another thread. |
+ deep_copy2.image_reps(); |
+ EXPECT_FALSE(deep_copy2.IsThreadSafe()); |
+ test::TestOnThread deepcopy2_on_thread(&deep_copy2); |
+ deepcopy2_on_thread.StartAndJoin(); |
+ EXPECT_FALSE(deepcopy2_on_thread.can_read()); |
+ EXPECT_FALSE(deepcopy2_on_thread.can_modify()); |
+ EXPECT_TRUE(deep_copy2.CanRead()); |
+ EXPECT_TRUE(deep_copy2.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ image.SetReadOnly(); |
+ // A read-only ImageSkia with no source is thread safe. |
+ EXPECT_TRUE(image.IsThreadSafe()); |
+ test::TestOnThread readonly_on_thread(&image); |
+ readonly_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(readonly_on_thread.can_read()); |
+ EXPECT_FALSE(readonly_on_thread.can_modify()); |
+ EXPECT_TRUE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ image.MakeThreadSafe(); |
+ EXPECT_TRUE(image.IsThreadSafe()); |
+ test::TestOnThread threadsafe_on_thread(&image); |
+ threadsafe_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(threadsafe_on_thread.can_read()); |
+ EXPECT_FALSE(threadsafe_on_thread.can_modify()); |
+ EXPECT_TRUE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+} |
+ |
+TEST(ImageSkiaTest, SourceOnThreadTest) { |
+ ImageSkia image(new DynamicSource(Size(100, 200)), Size(100, 200)); |
+ EXPECT_FALSE(image.IsThreadSafe()); |
+ |
+ test::TestOnThread image_on_thread(&image); |
+ image_on_thread.StartAndJoin(); |
+ // an image that was never accessed on this thread can be |
+ // read by other thread. |
+ EXPECT_TRUE(image_on_thread.can_read()); |
+ EXPECT_TRUE(image_on_thread.can_modify()); |
+ EXPECT_FALSE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ // An image is accessed by this thread, |
+ // so other thread cannot read/modify it. |
+ image.image_reps(); |
+ test::TestOnThread image_on_thread2(&image); |
+ image_on_thread2.StartAndJoin(); |
+ EXPECT_FALSE(image_on_thread2.can_read()); |
+ EXPECT_FALSE(image_on_thread2.can_modify()); |
+ EXPECT_TRUE(image.CanRead()); |
+ EXPECT_TRUE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ image.SetReadOnly(); |
+ EXPECT_FALSE(image.IsThreadSafe()); |
+ test::TestOnThread readonly_on_thread(&image); |
+ readonly_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(readonly_on_thread.can_read()); |
+ EXPECT_FALSE(readonly_on_thread.can_modify()); |
+ EXPECT_FALSE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+ |
+ image.DetachStorageFromThread(); |
+ image.MakeThreadSafe(); |
+ EXPECT_TRUE(image.IsThreadSafe()); |
+ // Check if image reps are generated for supported scale factors. |
+ EXPECT_EQ(ui::GetSupportedScaleFactors().size(), |
+ image.image_reps().size()); |
+ test::TestOnThread threadsafe_on_thread(&image); |
+ threadsafe_on_thread.StartAndJoin(); |
+ EXPECT_TRUE(threadsafe_on_thread.can_read()); |
+ EXPECT_FALSE(threadsafe_on_thread.can_modify()); |
+ EXPECT_TRUE(image.CanRead()); |
+ EXPECT_FALSE(image.CanModify()); |
+} |
+#endif // ENABLE_NON_THREAD_SAFE |
+ |
+// Just in case we ever get lumped together with other compilation units. |
+#undef ENABLE_NON_THREAD_SAFE |
+ |
} // namespace gfx |