| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/testing/scoped_block_swizzler.h" |
| #import "base/apple/foundation_util.h" |
| #import "testing/gtest/include/gtest/gtest.h" |
| #import "testing/gtest_mac.h" |
| #import "testing/platform_test.h" |
| |
| // Class containing two methods that will be swizzled by the unittests. |
| @interface ScopedBlockSwizzlerTestClass : NSObject |
| |
| // An NSString property that will be accessed by one of the swizzled methods. |
| @property(nonatomic, copy) NSString* value; |
| |
| + (NSString*)classMethodToSwizzle; |
| - (NSString*)instanceMethodToSwizzle; |
| @end |
| |
| namespace { |
| |
| NSString* const kOriginalClassValue = @"Bar"; |
| NSString* const kSwizzledClassValue = @"Foo"; |
| NSString* const kOriginalInstanceValue = @"Bizz"; |
| NSString* const kSwizzledInstanceValue = @"Buzz"; |
| |
| using ScopedBlockSwizzlerTest = PlatformTest; |
| |
| // Tests that swizzling a class method works properly. |
| TEST_F(ScopedBlockSwizzlerTest, SwizzlingClassMethods) { |
| EXPECT_NSEQ(kOriginalClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| |
| { |
| id block = ^NSString*(id self) { return kSwizzledClassValue; }; |
| ScopedBlockSwizzler swizzler([ScopedBlockSwizzlerTestClass class], |
| @selector(classMethodToSwizzle), block); |
| EXPECT_NSEQ(kSwizzledClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| } |
| |
| EXPECT_NSEQ(kOriginalClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| } |
| |
| // Tests that swizzling an instance method works properly. |
| TEST_F(ScopedBlockSwizzlerTest, SwizzlingInstanceMethod) { |
| ScopedBlockSwizzlerTestClass* target = |
| [[ScopedBlockSwizzlerTestClass alloc] init]; |
| target.value = kSwizzledInstanceValue; |
| |
| EXPECT_NSEQ(kOriginalInstanceValue, [target instanceMethodToSwizzle]); |
| EXPECT_FALSE([[target instanceMethodToSwizzle] |
| isEqualToString:kSwizzledInstanceValue]); |
| |
| { |
| id block = ^NSString*(id self) { |
| return base::apple::ObjCCastStrict<ScopedBlockSwizzlerTestClass>(self) |
| .value; |
| }; |
| ScopedBlockSwizzler swizzler([ScopedBlockSwizzlerTestClass class], |
| @selector(instanceMethodToSwizzle), block); |
| EXPECT_NSEQ(kSwizzledInstanceValue, [target instanceMethodToSwizzle]); |
| } |
| |
| EXPECT_NSEQ(kOriginalInstanceValue, [target instanceMethodToSwizzle]); |
| } |
| |
| // Tests that calling |ScopedBlockSwizzler::reset()| properly unswizzles the |
| // method. |
| TEST_F(ScopedBlockSwizzlerTest, TestReset) { |
| EXPECT_NSEQ(kOriginalClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| |
| id block = ^NSString*(id self) { return kSwizzledClassValue; }; |
| std::unique_ptr<ScopedBlockSwizzler> swizzler( |
| new ScopedBlockSwizzler([ScopedBlockSwizzlerTestClass class], |
| @selector(classMethodToSwizzle), block)); |
| EXPECT_NSEQ(kSwizzledClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| |
| swizzler.reset(); |
| EXPECT_NSEQ(kOriginalClassValue, |
| [ScopedBlockSwizzlerTestClass classMethodToSwizzle]); |
| } |
| |
| } // namespace |
| |
| #pragma mark - ScopedBlockSwizzlerTestClass |
| |
| @implementation ScopedBlockSwizzlerTestClass |
| |
| @synthesize value = _value; |
| |
| + (NSString*)classMethodToSwizzle { |
| return kOriginalClassValue; |
| } |
| |
| - (NSString*)instanceMethodToSwizzle { |
| return kOriginalInstanceValue; |
| } |
| |
| @end |