• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 #ifndef CHROME_BROWSER_UI_COCOA_COCOA_TEST_HELPER_H_
6 #define CHROME_BROWSER_UI_COCOA_COCOA_TEST_HELPER_H_
7 #pragma once
8 
9 #import <Cocoa/Cocoa.h>
10 
11 #include "base/path_service.h"
12 #import "base/mac/scoped_nsautorelease_pool.h"
13 #import "base/memory/scoped_nsobject.h"
14 #include "chrome/common/chrome_constants.h"
15 #import "content/common/chrome_application_mac.h"
16 #include "testing/platform_test.h"
17 
18 // Background windows normally will not display things such as focus
19 // rings.  This class allows -isKeyWindow to be manipulated to test
20 // such things.
21 @interface CocoaTestHelperWindow : NSWindow {
22  @private
23   BOOL pretendIsKeyWindow_;
24 }
25 
26 // Init a borderless non-deferred window with a backing store.
27 - (id)initWithContentRect:(NSRect)contentRect;
28 
29 // Init with a default frame.
30 - (id)init;
31 
32 // Sets the responder passed in as first responder, and sets the window
33 // so that it will return "YES" if asked if it key window. It does not actually
34 // make the window key.
35 - (void)makePretendKeyWindowAndSetFirstResponder:(NSResponder*)responder;
36 
37 // Clears the first responder duty for the window and returns the window
38 // to being non-key.
39 - (void)clearPretendKeyWindowAndFirstResponder;
40 
41 // Set value to return for -isKeyWindow.
42 - (void)setPretendIsKeyWindow:(BOOL)isKeyWindow;
43 
44 - (BOOL)isKeyWindow;
45 
46 @end
47 
48 // A test class that all tests that depend on AppKit should inherit from.
49 // Sets up NSApplication and paths correctly, and makes sure that any windows
50 // created in the test are closed down properly by the test. If you need to
51 // inherit from a different test class, but need to set up the AppKit runtime
52 // environment, you can call BootstrapCocoa directly from your test class. You
53 // will have to deal with windows on your own though.
54 class CocoaTest : public PlatformTest {
55  public:
56   // Sets up AppKit and paths correctly for unit tests. If you can't inherit
57   // from CocoaTest but are going to be using any AppKit features directly,
58   // or indirectly, you should be calling this from the c'tor or SetUp methods
59   // of your test class.
60   static void BootstrapCocoa();
61 
62   CocoaTest();
63   virtual ~CocoaTest();
64 
65   // Must be called by subclasses that override TearDown. We verify that it
66   // is called in our destructor. Takes care of making sure that all windows
67   // are closed off correctly. If your tests open windows, they must be sure
68   // to close them before CocoaTest::TearDown is called. A standard way of doing
69   // this would be to create them in SetUp (after calling CocoaTest::Setup) and
70   // then close them in TearDown before calling CocoaTest::TearDown.
71   virtual void TearDown();
72 
73   // Retuns a test window that can be used by views and other UI objects
74   // as part of their tests. Is created lazily, and will be closed correctly
75   // in CocoaTest::TearDown. Note that it is a CocoaTestHelperWindow which
76   // has special handling for being Key.
77   CocoaTestHelperWindow* test_window();
78 
79  private:
80   // Return a set of currently open windows. Avoiding NSArray so
81   // contents aren't retained, the pointer values can only be used for
82   // comparison purposes.  Using std::set to make progress-checking
83   // convenient.
84   static std::set<NSWindow*> ApplicationWindows();
85 
86   // Return a set of windows which are in |ApplicationWindows()| but
87   // not |initial_windows_|.
88   std::set<NSWindow*> WindowsLeft();
89 
90   bool called_tear_down_;
91   base::mac::ScopedNSAutoreleasePool pool_;
92 
93   // Windows which existed at the beginning of the test.
94   std::set<NSWindow*> initial_windows_;
95 
96   // Strong. Lazily created. This isn't wrapped in a scoped_nsobject because
97   // we want to call [close] to destroy it rather than calling [release]. We
98   // want to verify that [close] is actually removing our window and that it's
99   // not hanging around because releaseWhenClosed was set to "no" on the window.
100   // It isn't wrapped in a different wrapper class to close it because we
101   // need to close it at a very specific time; just before we enter our clean
102   // up loop in TearDown.
103   CocoaTestHelperWindow* test_window_;
104 };
105 
106 // A macro defining a standard set of tests to run on a view. Since we can't
107 // inherit tests, this macro saves us a lot of duplicate code. Handles simply
108 // displaying the view to make sure it won't crash, as well as removing it
109 // from a window. All tests that work with NSView subclasses and/or
110 // NSViewController subclasses should use it.
111 #define TEST_VIEW(test_fixture, test_view) \
112   TEST_F(test_fixture, test_fixture##_TestViewMacroAddRemove) { \
113     scoped_nsobject<NSView> view([test_view retain]); \
114     EXPECT_EQ([test_window() contentView], [view superview]); \
115     [view removeFromSuperview]; \
116     EXPECT_FALSE([view superview]); \
117   } \
118   TEST_F(test_fixture, test_fixture##_TestViewMacroDisplay) { \
119     [test_view display]; \
120   }
121 
122 // A macro which determines the proper float epsilon for a CGFloat.
123 #if CGFLOAT_IS_DOUBLE
124 #define CGFLOAT_EPSILON DBL_EPSILON
125 #else
126 #define CGFLOAT_EPSILON FLT_EPSILON
127 #endif
128 
129 // A macro which which determines if two CGFloats are equal taking a
130 // proper epsilon into consideration.
131 #define CGFLOAT_EQ(expected, actual) \
132     (actual >= (expected - CGFLOAT_EPSILON) && \
133      actual <= (expected + CGFLOAT_EPSILON))
134 
135 // A test support macro which ascertains if two CGFloats are equal.
136 #define EXPECT_CGFLOAT_EQ(expected, actual) \
137     EXPECT_TRUE(CGFLOAT_EQ(expected, actual)) << \
138                 expected << " != " << actual
139 
140 // A test support macro which compares two NSRects for equality taking
141 // the float epsilon into consideration.
142 #define EXPECT_NSRECT_EQ(expected, actual) \
143     EXPECT_TRUE(CGFLOAT_EQ(expected.origin.x, actual.origin.x) && \
144                 CGFLOAT_EQ(expected.origin.y, actual.origin.y) && \
145                 CGFLOAT_EQ(expected.size.width, actual.size.width) && \
146                 CGFLOAT_EQ(expected.size.height, actual.size.height)) << \
147                 "Rects do not match: " << \
148                 [NSStringFromRect(expected) UTF8String] << \
149                 " != " << [NSStringFromRect(actual) UTF8String]
150 
151 #endif  // CHROME_BROWSER_UI_COCOA_COCOA_TEST_HELPER_H_
152