xref: /aosp_15_r20/external/cronet/base/apple/scoped_objc_class_swizzler_unittest.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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