Roll breakpad a513e85:7caf028 (svn 1384:1385)
[chromium-blink-merge.git] / base / mac / scoped_objc_class_swizzler_unittest.mm
blobeacd10518218edfbcafa3370cf9f3a547cdefa82
1 // Copyright 2014 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 #import "base/mac/scoped_objc_class_swizzler.h"
7 #import "base/mac/scoped_nsobject.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 @interface ObjCClassSwizzlerTestOne : NSObject
11 + (NSInteger)function;
12 - (NSInteger)method;
13 - (NSInteger)modifier;
14 @end
16 @interface ObjCClassSwizzlerTestTwo : NSObject
17 + (NSInteger)function;
18 - (NSInteger)method;
19 - (NSInteger)modifier;
20 @end
22 @implementation ObjCClassSwizzlerTestOne : NSObject
24 + (NSInteger)function {
25   return 10;
28 - (NSInteger)method {
29   // Multiply by a modifier to ensure |self| in a swizzled implementation
30   // refers to the original object.
31   return 1 * [self modifier];
34 - (NSInteger)modifier {
35   return 3;
38 @end
40 @implementation ObjCClassSwizzlerTestTwo : NSObject
42 + (NSInteger)function {
43   return 20;
46 - (NSInteger)method {
47   return 2 * [self modifier];
50 - (NSInteger)modifier {
51   return 7;
54 @end
56 @interface ObjCClassSwizzlerTestOne (AlternateCategory)
57 - (NSInteger)alternate;
58 @end
60 @implementation ObjCClassSwizzlerTestOne (AlternateCategory)
61 - (NSInteger)alternate {
62   return 3 * [self modifier];
64 @end
66 @interface ObjCClassSwizzlerTestOneChild : ObjCClassSwizzlerTestOne
67 - (NSInteger)childAlternate;
68 @end
70 @implementation ObjCClassSwizzlerTestOneChild
71 - (NSInteger)childAlternate {
72   return 5 * [self modifier];
74 @end
76 namespace base {
77 namespace mac {
79 TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) {
80   base::scoped_nsobject<ObjCClassSwizzlerTestOne> object_one(
81       [[ObjCClassSwizzlerTestOne alloc] init]);
82   base::scoped_nsobject<ObjCClassSwizzlerTestTwo> object_two(
83       [[ObjCClassSwizzlerTestTwo alloc] init]);
84   EXPECT_EQ(3, [object_one method]);
85   EXPECT_EQ(14, [object_two method]);
87   {
88     base::mac::ScopedObjCClassSwizzler swizzler(
89         [ObjCClassSwizzlerTestOne class],
90         [ObjCClassSwizzlerTestTwo class],
91         @selector(method));
92     EXPECT_EQ(6, [object_one method]);
93     EXPECT_EQ(7, [object_two method]);
95     IMP original = swizzler.GetOriginalImplementation();
96     id expected_result = reinterpret_cast<id>(3);
97     EXPECT_EQ(expected_result, original(object_one, @selector(method)));
98   }
100   EXPECT_EQ(3, [object_one method]);
101   EXPECT_EQ(14, [object_two method]);
104 TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) {
105   EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]);
106   EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]);
108   {
109     base::mac::ScopedObjCClassSwizzler swizzler(
110         [ObjCClassSwizzlerTestOne class],
111         [ObjCClassSwizzlerTestTwo class],
112         @selector(function));
113     EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]);
114     EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]);
116     IMP original = swizzler.GetOriginalImplementation();
117     id expected_result = reinterpret_cast<id>(10);
118     EXPECT_EQ(expected_result, original(nil, @selector(function)));
119   }
121   EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]);
122   EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]);
125 TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) {
126   base::scoped_nsobject<ObjCClassSwizzlerTestOne> object_one(
127       [[ObjCClassSwizzlerTestOne alloc] init]);
128   EXPECT_EQ(3, [object_one method]);
130   {
131     base::mac::ScopedObjCClassSwizzler swizzler(
132         [ObjCClassSwizzlerTestOne class],
133         @selector(method),
134         @selector(alternate));
135     EXPECT_EQ(9, [object_one method]);
137     IMP original = swizzler.GetOriginalImplementation();
138     id expected_result = reinterpret_cast<id>(3);
139     EXPECT_EQ(expected_result, original(object_one, @selector(method)));
140   }
142   EXPECT_EQ(3, [object_one method]);
145 TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) {
146   base::scoped_nsobject<ObjCClassSwizzlerTestOneChild> child(
147       [[ObjCClassSwizzlerTestOneChild alloc] init]);
148   EXPECT_EQ(3, [child method]);
150   {
151     base::mac::ScopedObjCClassSwizzler swizzler(
152         [ObjCClassSwizzlerTestOneChild class],
153         @selector(method),
154         @selector(childAlternate));
155     EXPECT_EQ(15, [child method]);
157     IMP original = swizzler.GetOriginalImplementation();
158     id expected_result = reinterpret_cast<id>(3);
159     EXPECT_EQ(expected_result, original(child, @selector(method)));
160   }
162   EXPECT_EQ(3, [child method]);
165 }  // namespace mac
166 }  // namespace base