1// Copyright 2014 The Chromium Authors 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "base/apple/scoped_objc_class_swizzler.h" 6 7#import <Foundation/Foundation.h> 8 9#include "testing/gtest/include/gtest/gtest.h" 10 11@interface ObjCClassSwizzlerTestOne : NSObject 12+ (NSInteger)function; 13- (NSInteger)method; 14- (NSInteger)modifier; 15@end 16 17@interface ObjCClassSwizzlerTestTwo : NSObject 18+ (NSInteger)function; 19- (NSInteger)method; 20- (NSInteger)modifier; 21@end 22 23@implementation ObjCClassSwizzlerTestOne : NSObject 24 25+ (NSInteger)function { 26 return 10; 27} 28 29- (NSInteger)method { 30 // Multiply by a modifier to ensure |self| in a swizzled implementation 31 // refers to the original object. 32 return 1 * [self modifier]; 33} 34 35- (NSInteger)modifier { 36 return 3; 37} 38 39@end 40 41@implementation ObjCClassSwizzlerTestTwo : NSObject 42 43+ (NSInteger)function { 44 return 20; 45} 46 47- (NSInteger)method { 48 return 2 * [self modifier]; 49} 50 51- (NSInteger)modifier { 52 return 7; 53} 54 55@end 56 57@interface ObjCClassSwizzlerTestOne (AlternateCategory) 58- (NSInteger)alternate; 59@end 60 61@implementation ObjCClassSwizzlerTestOne (AlternateCategory) 62- (NSInteger)alternate { 63 return 3 * [self modifier]; 64} 65@end 66 67@interface ObjCClassSwizzlerTestOneChild : ObjCClassSwizzlerTestOne 68- (NSInteger)childAlternate; 69@end 70 71@implementation ObjCClassSwizzlerTestOneChild 72- (NSInteger)childAlternate { 73 return 5 * [self modifier]; 74} 75@end 76 77namespace base::apple { 78 79TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) { 80 ObjCClassSwizzlerTestOne* object_one = 81 [[ObjCClassSwizzlerTestOne alloc] init]; 82 ObjCClassSwizzlerTestTwo* object_two = 83 [[ObjCClassSwizzlerTestTwo alloc] init]; 84 EXPECT_EQ(3, [object_one method]); 85 EXPECT_EQ(14, [object_two method]); 86 87 { 88 base::apple::ScopedObjCClassSwizzler swizzler( 89 [ObjCClassSwizzlerTestOne class], [ObjCClassSwizzlerTestTwo class], 90 @selector(method)); 91 EXPECT_EQ(6, [object_one method]); 92 EXPECT_EQ(7, [object_two method]); 93 94 EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method))); 95 } 96 97 EXPECT_EQ(3, [object_one method]); 98 EXPECT_EQ(14, [object_two method]); 99} 100 101TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) { 102 EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]); 103 EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]); 104 105 { 106 base::apple::ScopedObjCClassSwizzler swizzler( 107 [ObjCClassSwizzlerTestOne class], [ObjCClassSwizzlerTestTwo class], 108 @selector(function)); 109 EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]); 110 EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]); 111 112 EXPECT_EQ(10, swizzler.InvokeOriginal<int>([ObjCClassSwizzlerTestOne class], 113 @selector(function))); 114 } 115 116 EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]); 117 EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]); 118} 119 120TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) { 121 ObjCClassSwizzlerTestOne* object_one = 122 [[ObjCClassSwizzlerTestOne alloc] init]; 123 EXPECT_EQ(3, [object_one method]); 124 125 { 126 base::apple::ScopedObjCClassSwizzler swizzler( 127 [ObjCClassSwizzlerTestOne class], @selector(method), 128 @selector(alternate)); 129 EXPECT_EQ(9, [object_one method]); 130 131 EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method))); 132 } 133 134 EXPECT_EQ(3, [object_one method]); 135} 136 137TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) { 138 ObjCClassSwizzlerTestOneChild* child = 139 [[ObjCClassSwizzlerTestOneChild alloc] init]; 140 EXPECT_EQ(3, [child method]); 141 142 { 143 base::apple::ScopedObjCClassSwizzler swizzler( 144 [ObjCClassSwizzlerTestOneChild class], @selector(method), 145 @selector(childAlternate)); 146 EXPECT_EQ(15, [child method]); 147 148 EXPECT_EQ(3, swizzler.InvokeOriginal<int>(child, @selector(method))); 149 } 150 151 EXPECT_EQ(3, [child method]); 152} 153 154} // namespace base::apple 155