Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[camera] Remove OCMock from CameraExposureTests and CameraFocusTests #8351

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
4 changes: 4 additions & 0 deletions packages/camera/camera_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.18+1

* Introduces new protocols `FLTCaptureDeviceControlling` and `FLTDeviceOrientationProviding`
mchudy marked this conversation as resolved.
Show resolved Hide resolved

## 0.9.18

* Adds API support query for image streaming.
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,79 @@
@import camera_avfoundation;
@import XCTest;
@import AVFoundation;
#import <OCMock/OCMock.h>

@interface FLTCam : NSObject <FlutterTexture,
AVCaptureVideoDataOutputSampleBufferDelegate,
AVCaptureAudioDataOutputSampleBufferDelegate>

- (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y;
@end
#import "CameraTestUtils.h"
#import "MockCaptureDeviceController.h"
#import "MockDeviceOrientationProvider.h"

@interface CameraExposureTests : XCTestCase
@property(readonly, nonatomic) FLTCam *camera;
@property(readonly, nonatomic) id mockDevice;
@property(readonly, nonatomic) id mockUIDevice;
@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice;
@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider;
@end

@implementation CameraExposureTests

- (void)setUp {
_camera = [[FLTCam alloc] init];
_mockDevice = OCMClassMock([AVCaptureDevice class]);
_mockUIDevice = OCMPartialMock([UIDevice currentDevice]);
}
MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init];
_mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init];
_mockDevice = mockDevice;

- (void)tearDown {
[_mockDevice stopMocking];
[_mockUIDevice stopMocking];
_camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
nil, nil, nil,
^id<FLTCaptureDeviceControlling>(void) {
return mockDevice;
},
_mockDeviceOrientationProvider);
}

- (void)testSetExpsourePointWithResult_SetsExposurePointOfInterest {
- (void)testSetExposurePointWithResult_SetsExposurePointOfInterest {
// UI is currently in landscape left orientation
OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft);
_mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft;
// Exposure point of interest is supported
OCMStub([_mockDevice isExposurePointOfInterestSupported]).andReturn(true);
// Set mock device as the current capture device
[_camera setValue:_mockDevice forKey:@"captureDevice"];
_mockDevice.isExposurePointOfInterestSupported = YES;

// Verify the focus point of interest has been set
__block CGPoint setPoint = CGPointZero;
_mockDevice.setExposurePointOfInterestStub = ^(CGPoint point) {
if (CGPointEqualToPoint(CGPointMake(1, 1), point)) {
setPoint = point;
}
};

// Run test
XCTestExpectation *completionExpectation = [self expectationWithDescription:@"Completion called"];
[_camera setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1]
withCompletion:^(FlutterError *_Nullable error) {
XCTAssertNil(error);
[completionExpectation fulfill];
}];

[self waitForExpectationsWithTimeout:1 handler:nil];
XCTAssertEqual(setPoint.x, 1.0);
XCTAssertEqual(setPoint.y, 1.0);
}

- (void)testSetExposurePoint_WhenNotSupported_ReturnsError {
// UI is currently in landscape left orientation
_mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft;
// Exposure point of interest is not supported
_mockDevice.isExposurePointOfInterestSupported = NO;

XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"];

// Run
[_camera
setExposurePointWithResult:^void(id _Nullable result) {
}
x:1
y:1];
setExposurePoint:[FCPPlatformPoint makeWithX:1 y:1]
withCompletion:^(FlutterError *_Nullable error) {
XCTAssertNotNil(error);
XCTAssertEqualObjects(error.code, @"setExposurePointFailed");
XCTAssertEqualObjects(error.message, @"Device does not have exposure point capabilities");
[expectation fulfill];
}];

// Verify the focus point of interest has been set
OCMVerify([_mockDevice setExposurePointOfInterest:CGPointMake(1, 1)]);
// Verify
[self waitForExpectationsWithTimeout:1 handler:nil];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -8,120 +8,174 @@
#endif
@import XCTest;
@import AVFoundation;
#import <OCMock/OCMock.h>

#import "CameraTestUtils.h"
#import "MockCaptureDeviceController.h"
#import "MockDeviceOrientationProvider.h"

@interface CameraFocusTests : XCTestCase
@property(readonly, nonatomic) FLTCam *camera;
@property(readonly, nonatomic) id mockDevice;
@property(readonly, nonatomic) id mockUIDevice;
@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice;
@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider;
@end

@implementation CameraFocusTests

- (void)setUp {
_camera = [[FLTCam alloc] init];
_mockDevice = OCMClassMock([AVCaptureDevice class]);
_mockUIDevice = OCMPartialMock([UIDevice currentDevice]);
}

- (void)tearDown {
[_mockDevice stopMocking];
[_mockUIDevice stopMocking];
MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init];
_mockDevice = mockDevice;
_mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init];

_camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
nil, nil, nil,
^id<FLTCaptureDeviceControlling>(void) {
return mockDevice;
},
_mockDeviceOrientationProvider);
}

- (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus {
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true);
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true);

// Don't expect setFocusMode:AVCaptureFocusModeAutoFocus
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
// AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeContinuousAutoFocus are supported
_mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) {
return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus;
};

__block BOOL setFocusModeContinuousAutoFocusCalled = NO;

_mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) {
// Don't expect setFocusMode:AVCaptureFocusModeAutoFocus
if (mode == AVCaptureFocusModeAutoFocus) {
XCTFail(@"Unexpected call to setFocusMode");
} else if (mode == AVCaptureFocusModeContinuousAutoFocus) {
setFocusModeContinuousAutoFocusCalled = YES;
}
};

// Run test
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];

// Expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]);
XCTAssertTrue(setFocusModeContinuousAutoFocusCalled);
}

- (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus {
// AVCaptureFocusModeContinuousAutoFocus is not supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
.andReturn(false);
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true);
// AVCaptureFocusModeAutoFocus is supported
_mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) {
return mode == AVCaptureFocusModeAutoFocus;
};

__block BOOL setFocusModeAutoFocusCalled = NO;

// Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
_mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) {
if (mode == AVCaptureFocusModeContinuousAutoFocus) {
XCTFail(@"Unexpected call to setFocusMode");
} else if (mode == AVCaptureFocusModeAutoFocus) {
setFocusModeAutoFocusCalled = YES;
}
};

// Run test
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];

// Expect setFocusMode:AVCaptureFocusModeAutoFocus
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]);
XCTAssertTrue(setFocusModeAutoFocusCalled);
}

- (void)testAutoFocusWithNoModeSupported_ShouldSetNothing {
// AVCaptureFocusModeContinuousAutoFocus is not supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
.andReturn(false);
// AVCaptureFocusModeContinuousAutoFocus is not supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false);
// No modes are supported
_mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) {
return NO;
};

// Don't expect any setFocus
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
_mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) {
XCTFail(@"Unexpected call to setFocusMode");
};

// Run test
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];
}

- (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus {
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true);
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true);

// Don't expect any setFocus
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
// AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported
_mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) {
return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus;
};

__block BOOL setFocusModeAutoFocusCalled = NO;

// Expect only setFocusMode:AVCaptureFocusModeAutoFocus
_mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) {
if (mode == AVCaptureFocusModeContinuousAutoFocus) {
XCTFail(@"Unexpected call to setFocusMode");
} else if (mode == AVCaptureFocusModeAutoFocus) {
setFocusModeAutoFocusCalled = YES;
}
};

// Run test
[_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice];

// Expect setFocusMode:AVCaptureFocusModeAutoFocus
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]);
XCTAssertTrue(setFocusModeAutoFocusCalled);
}

- (void)testLockedFocusWithModeNotSupported_ShouldSetNothing {
// AVCaptureFocusModeContinuousAutoFocus is supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true);
// AVCaptureFocusModeContinuousAutoFocus is not supported
OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false);
_mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) {
return mode == AVCaptureFocusModeContinuousAutoFocus;
};

// Don't expect any setFocus
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
_mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) {
XCTFail(@"Unexpected call to setFocusMode");
};

// Run test
[_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice];
}

- (void)testSetFocusPointWithResult_SetsFocusPointOfInterest {
// UI is currently in landscape left orientation
OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft);
_mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft;
// Focus point of interest is supported
OCMStub([_mockDevice isFocusPointOfInterestSupported]).andReturn(true);
// Set mock device as the current capture device
[_camera setValue:_mockDevice forKey:@"captureDevice"];
_mockDevice.isFocusPointOfInterestSupported = YES;

__block BOOL setFocusPointOfInterestCalled = NO;
_mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) {
if (point.x == 1 && point.y == 1) {
setFocusPointOfInterestCalled = YES;
}
};

// Run test
[_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1]
withCompletion:^(FlutterError *_Nullable error){
}];

// Verify the focus point of interest has been set
OCMVerify([_mockDevice setFocusPointOfInterest:CGPointMake(1, 1)]);
XCTAssertTrue(setFocusPointOfInterestCalled);
}

- (void)testSetFocusPoint_WhenNotSupported_ReturnsError {
// UI is currently in landscape left orientation
_mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft;
// Exposure point of interest is not supported
_mockDevice.isFocusPointOfInterestSupported = NO;

XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"];

// Run
[_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1]
withCompletion:^(FlutterError *_Nullable error) {
XCTAssertNotNil(error);
XCTAssertEqualObjects(error.code, @"setFocusPointFailed");
XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities");
[expectation fulfill];
}];

// Verify
[self waitForExpectationsWithTimeout:1 handler:nil];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#import <OCMock/OCMock.h>

#import "MockCaptureDeviceController.h"

@interface StubGlobalEventApi : FCPCameraGlobalEventApi
@property(nonatomic) BOOL called;
@property(nonatomic) FCPPlatformDeviceOrientation lastOrientation;
Expand All @@ -35,10 +37,21 @@ - (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString
#pragma mark -

@interface CameraOrientationTests : XCTestCase
@property(readonly, nonatomic) FLTCam *camera;
@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice;
@property(readonly, nonatomic) StubGlobalEventApi *eventAPI;
@end

@implementation CameraOrientationTests

- (void)setUp {
[super setUp];
_mockDevice = [[MockCaptureDeviceController alloc] init];
_camera = [[FLTCam alloc] init];

[_camera setValue:_mockDevice forKey:@"captureDevice"];
}

// Ensure that the given queue and then the main queue have both cycled, to wait for any pending
// async events that may have been bounced between them.
- (void)waitForRoundTripWithQueue:(dispatch_queue_t)queue {
Expand Down Expand Up @@ -97,13 +110,13 @@ - (void)testOrientationNotificationsNotCalledForFaceDown {
- (void)testOrientationUpdateMustBeOnCaptureSessionQueue {
XCTestExpectation *queueExpectation = [self
expectationWithDescription:@"Orientation update must happen on the capture session queue"];

CameraPlugin *camera = [[CameraPlugin alloc] initWithRegistry:nil messenger:nil];
const char *captureSessionQueueSpecific = "capture_session_queue";
dispatch_queue_set_specific(camera.captureSessionQueue, captureSessionQueueSpecific,
(void *)captureSessionQueueSpecific, NULL);
FLTCam *mockCam = OCMClassMock([FLTCam class]);
camera.camera = mockCam;

OCMStub([mockCam setDeviceOrientation:UIDeviceOrientationLandscapeLeft])
.andDo(^(NSInvocation *invocation) {
if (dispatch_get_specific(captureSessionQueueSpecific)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#endif
@import XCTest;
@import AVFoundation;
#import <OCMock/OCMock.h>

@interface CameraPreviewPauseTests : XCTestCase
@end
Expand Down
Loading
Loading