FlipperClient tests on iOS
Summary: This diff adds few tests for flipper client on iOS side. This tests are similar to the ones which exists in xplat but this tests the iOS side of flipper client. Following tests are added - connect , disconnect block called on plugin - background plugin activated before init method - crash getting suppressed Reviewed By: jknoxville Differential Revision: D13167637 fbshipit-source-id: 6c21d5cf2f08e7e3c17ecacbf3badfbde80fb5d1
This commit is contained in:
committed by
Facebook Github Bot
parent
bf3be3e16c
commit
912d3c4bcb
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
@@ -15,6 +15,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#include "SKStateUpdateCPPWrapper.h"
|
||||
#import "FlipperDiagnosticsViewController.h"
|
||||
#import "FlipperClient+Testing.h"
|
||||
|
||||
#if !TARGET_OS_SIMULATOR
|
||||
//#import "SKPortForwardingServer.h"
|
||||
@@ -177,4 +178,15 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlipperClient (Testing)
|
||||
|
||||
- (instancetype)initWithCppClient:(facebook::flipper::FlipperClient *)cppClient {
|
||||
if (self = [super init]) {
|
||||
_cppClient = cppClient;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
@@ -17,5 +17,6 @@ typedef void (^DisconnectBlock)();
|
||||
@interface BlockBasedSonarPlugin : NSObject<FlipperPlugin>
|
||||
|
||||
- (instancetype)initIdentifier:(NSString *)identifier connect:(ConnectBlock)connect disconnect:(DisconnectBlock)disconnect;
|
||||
- (instancetype)initIdentifier:(NSString *)identifier connect:(ConnectBlock)connect disconnect:(DisconnectBlock)disconnect runInBackground:(BOOL)runInBackground;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
NSString *_identifier;
|
||||
ConnectBlock _connect;
|
||||
DisconnectBlock _disconnect;
|
||||
BOOL _runInBackground;
|
||||
}
|
||||
|
||||
- (instancetype)initIdentifier:(NSString *)identifier connect:(ConnectBlock)connect disconnect:(DisconnectBlock)disconnect
|
||||
@@ -20,6 +21,17 @@
|
||||
_identifier = identifier;
|
||||
_connect = connect;
|
||||
_disconnect = disconnect;
|
||||
_runInBackground = false;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initIdentifier:(NSString *)identifier connect:(ConnectBlock)connect disconnect:(DisconnectBlock)disconnect runInBackground:(BOOL)runInBackground {
|
||||
if (self = [super init]) {
|
||||
_identifier = identifier;
|
||||
_connect = connect;
|
||||
_disconnect = disconnect;
|
||||
_runInBackground = runInBackground;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -38,9 +50,13 @@
|
||||
|
||||
- (void)didDisconnect
|
||||
{
|
||||
if (_connect) {
|
||||
if (_disconnect) {
|
||||
_disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)runInBackground {
|
||||
return _runInBackground;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
224
iOS/FlipperKitTests/FlipperClientTests.mm
Normal file
224
iOS/FlipperKitTests/FlipperClientTests.mm
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/FlipperPlugin.h>
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import <FlipperKit/FlipperClient+Testing.h>
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import <FlipperKitTestUtils/BlockBasedSonarPlugin.h>
|
||||
#import <FlipperTestLib/FlipperConnectionManagerMock.h>
|
||||
#import <FlipperTestLib/FlipperPluginMock.h>
|
||||
#import <folly/json.h>
|
||||
|
||||
@interface FlipperClientTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlipperClientTests
|
||||
facebook::flipper::FlipperClient *client;
|
||||
facebook::flipper::test::FlipperConnectionManagerMock *socket;
|
||||
FlipperClient *objcClient;
|
||||
|
||||
- (void)setUp {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
socket = new facebook::flipper::test::FlipperConnectionManagerMock;
|
||||
auto state = std::make_shared<FlipperState>();
|
||||
|
||||
client = new facebook::flipper::FlipperClient(std::unique_ptr<facebook::flipper::test::FlipperConnectionManagerMock>{socket}, state);
|
||||
objcClient = [[FlipperClient alloc] initWithCppClient:client];
|
||||
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
delete client;
|
||||
}
|
||||
|
||||
- (void)testGetPlugin {
|
||||
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:nil disconnect:nil];
|
||||
BlockBasedSonarPlugin *dog = [[BlockBasedSonarPlugin alloc] initIdentifier:@"dog" connect:nil disconnect:nil];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient addPlugin:dog];
|
||||
|
||||
NSObject<FlipperPlugin> *retrievedPlugin = [objcClient pluginWithIdentifier:@"cat"];
|
||||
XCTAssertEqual(retrievedPlugin, cat);
|
||||
retrievedPlugin = [objcClient pluginWithIdentifier:@"dog"];
|
||||
XCTAssertEqual(retrievedPlugin, dog);
|
||||
}
|
||||
|
||||
|
||||
- (void)testRemovePlugin {
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:nil disconnect:nil];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient removePlugin:cat];
|
||||
|
||||
folly::dynamic message = folly::dynamic::object("id", 1)("method", "getPlugins");
|
||||
socket->callbacks->onMessageReceived(message);
|
||||
folly::dynamic expected = folly::dynamic::object("id", 1)("success", folly::dynamic::object("plugins", folly::dynamic::array()));
|
||||
XCTAssertEqual(socket->messages.back(), expected);
|
||||
}
|
||||
|
||||
- (void) testPluginActivatedInBackgroundMode {
|
||||
__block BOOL pluginConnected = NO;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:^(id<FlipperConnection>) {
|
||||
pluginConnected = YES;
|
||||
} disconnect:^{
|
||||
pluginConnected = NO;
|
||||
|
||||
} runInBackground: YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
XCTAssertTrue(pluginConnected);
|
||||
}
|
||||
|
||||
- (void) testPluginNotActivatedInNonBackgroundMode {
|
||||
__block BOOL pluginConnected = NO;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:^(id<FlipperConnection>) {
|
||||
pluginConnected = YES;
|
||||
} disconnect:^{
|
||||
pluginConnected = NO;
|
||||
|
||||
} runInBackground: NO];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
XCTAssertFalse(pluginConnected);
|
||||
}
|
||||
|
||||
- (void)testConnectAndDisconnectCallbackForNonBackgroundCase {
|
||||
__block BOOL pluginConnected = NO;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:^(id<FlipperConnection>) {
|
||||
pluginConnected = YES;
|
||||
} disconnect:^{
|
||||
pluginConnected = NO;
|
||||
} runInBackground: NO];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
|
||||
folly::dynamic messageInit = folly::dynamic::object("method", "init")("params", folly::dynamic::object("plugin", "cat"));
|
||||
socket->callbacks->onMessageReceived(messageInit);
|
||||
XCTAssertTrue(pluginConnected);
|
||||
[objcClient stop];
|
||||
XCTAssertFalse(pluginConnected);
|
||||
}
|
||||
|
||||
- (void)testConnectAndDisconnectCallbackForBackgroundCase {
|
||||
__block BOOL pluginConnected = YES;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:^(id<FlipperConnection>) {
|
||||
pluginConnected = YES;
|
||||
} disconnect:^{
|
||||
pluginConnected = NO;
|
||||
} runInBackground: YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
XCTAssertTrue(pluginConnected);
|
||||
[objcClient stop];
|
||||
XCTAssertFalse(pluginConnected);
|
||||
}
|
||||
|
||||
- (void)testCrashSuppressionInDidConnectCallback {
|
||||
__block BOOL pluginConnected = NO;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:^(id<FlipperConnection>) {
|
||||
pluginConnected = YES;
|
||||
NSArray *array = @[];
|
||||
[array objectAtIndex:10]; //This will throw an exception
|
||||
} disconnect:nil runInBackground: YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
// Since background plugin's didconnect is called as soon as flipper client starts
|
||||
XCTAssertNoThrow([objcClient start]);
|
||||
XCTAssertTrue(pluginConnected); // To be sure that connect block is called
|
||||
}
|
||||
|
||||
- (void)testCrashSuppressionInDisconnectCallback {
|
||||
__block BOOL isCalled = NO;
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"cat" connect:nil disconnect:^{
|
||||
isCalled = YES;
|
||||
NSArray *array = @[];
|
||||
[array objectAtIndex:10]; //This will throw an exception
|
||||
} runInBackground: YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
|
||||
XCTAssertNoThrow([objcClient stop]); // Stopping client will call disconnect of the plugin
|
||||
XCTAssertTrue(isCalled); // To be sure that connect block is called
|
||||
}
|
||||
|
||||
- (void)testMethodBlockIsCalledNonBackgroundCase {
|
||||
__block BOOL isCalled = NO;
|
||||
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"PluginIdentifier" connect:^(id<FlipperConnection> connection) {
|
||||
|
||||
[connection receive:@"MethodName" withBlock:^(NSDictionary * dict, id<FlipperResponder> responder) {
|
||||
isCalled = YES;
|
||||
}];
|
||||
} disconnect:nil];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
|
||||
folly::dynamic messageInit = folly::dynamic::object("method", "init")("params", folly::dynamic::object("plugin", "PluginIdentifier"));
|
||||
socket->callbacks->onMessageReceived(messageInit);
|
||||
folly::dynamic message = folly::dynamic::object("id", 1)("method", "execute")("params", folly::dynamic::object("api", "PluginIdentifier")("method", "MethodName"));
|
||||
socket->callbacks->onMessageReceived(message);
|
||||
|
||||
XCTAssertTrue(isCalled);
|
||||
}
|
||||
|
||||
- (void)testMethodBlockIsCalledBackgroundCase {
|
||||
__block BOOL isCalled = NO;
|
||||
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"PluginIdentifier" connect:^(id<FlipperConnection> connection) {
|
||||
|
||||
[connection receive:@"MethodName" withBlock:^(NSDictionary * dict, id<FlipperResponder> responder) {
|
||||
isCalled = YES;
|
||||
}];
|
||||
} disconnect:nil runInBackground:YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
|
||||
folly::dynamic message = folly::dynamic::object("id", 1)("method", "execute")("params", folly::dynamic::object("api", "PluginIdentifier")("method", "MethodName"));
|
||||
socket->callbacks->onMessageReceived(message);
|
||||
|
||||
XCTAssertTrue(isCalled);
|
||||
}
|
||||
|
||||
- (void)testExceptionSuppressionInMethodBlock {
|
||||
__block BOOL isCalled = NO;
|
||||
|
||||
BlockBasedSonarPlugin *cat = [[BlockBasedSonarPlugin alloc] initIdentifier:@"PluginIdentifier" connect:^(id<FlipperConnection> connection) {
|
||||
|
||||
[connection receive:@"MethodName" withBlock:^(NSDictionary * dict, id<FlipperResponder> responder) {
|
||||
isCalled = YES;
|
||||
NSArray *array = @[];
|
||||
[array objectAtIndex:10]; //This will throw an exception
|
||||
}];
|
||||
} disconnect:nil runInBackground:YES];
|
||||
|
||||
[objcClient addPlugin:cat];
|
||||
[objcClient start];
|
||||
|
||||
folly::dynamic message = folly::dynamic::object("id", 1)("method", "execute")("params", folly::dynamic::object("api", "PluginIdentifier")("method", "MethodName"));
|
||||
|
||||
XCTAssertNoThrow(socket->callbacks->onMessageReceived(message)); // This will call
|
||||
XCTAssertTrue(isCalled);
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
Reference in New Issue
Block a user