Initial commit
This commit is contained in:
231
local_pod_repo/objcTox/Tests/OCTAudioEngineTests.m
Normal file
231
local_pod_repo/objcTox/Tests/OCTAudioEngineTests.m
Normal file
@@ -0,0 +1,231 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <OCMock/OCMock.h>
|
||||
#import "OCTCAsserts.h"
|
||||
#import "OCTAudioEngine+Private.h"
|
||||
#import "OCTAudioQueue.h"
|
||||
#import "OCTManagerConstants.h"
|
||||
|
||||
@import AVFoundation;
|
||||
|
||||
static void *refToSelf;
|
||||
|
||||
@interface OCTAudioEngineTests : XCTestCase
|
||||
|
||||
@property (strong, nonatomic) OCTAudioQueue *outputMock;
|
||||
@property (strong, nonatomic) OCTAudioQueue *inputMock;
|
||||
@property (strong, nonatomic) id audioSession;
|
||||
@property (strong, nonatomic) OCTAudioEngine *realAudioEngine;
|
||||
@property (strong, nonatomic) OCTAudioEngine *audioEngine;
|
||||
|
||||
@property (strong, nonatomic) void (^sendDataBlock)(void *, OCTToxAVSampleCount, OCTToxAVSampleRate, OCTToxAVChannels);
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTAudioEngineTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
refToSelf = (__bridge void *)(self);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
self.audioSession = OCMClassMock([AVAudioSession class]);
|
||||
OCMStub([self.audioSession sharedInstance]).andReturn(self.audioSession);
|
||||
OCMStub([self.audioSession sampleRate]).andReturn(44100.00);
|
||||
[OCMStub([self.audioSession setPreferredSampleRate:0 error:[OCMArg anyObjectRef]]).andReturn(YES) ignoringNonObjectArgs];
|
||||
OCMStub([self.audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
[OCMStub([self.audioSession setPreferredIOBufferDuration:0 error:[OCMArg anyObjectRef]]).andReturn(YES) ignoringNonObjectArgs];
|
||||
[OCMStub([self.audioSession overrideOutputAudioPort:0 error:[OCMArg anyObjectRef]]).andReturn(YES) ignoringNonObjectArgs];
|
||||
OCMStub(([self.audioSession setMode:AVAudioSessionModeVoiceChat error:[OCMArg anyObjectRef]])).andReturn(YES);
|
||||
OCMStub([self.audioSession setActive:YES error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.audioSession setActive:NO error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
#endif
|
||||
|
||||
self.realAudioEngine = [[OCTAudioEngine alloc] init];
|
||||
self.audioEngine = OCMPartialMock(self.realAudioEngine);
|
||||
|
||||
self.inputMock = OCMClassMock([OCTAudioQueue class]);
|
||||
self.outputMock = OCMClassMock([OCTAudioQueue class]);
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
refToSelf = NULL;
|
||||
|
||||
self.audioSession = nil;
|
||||
self.audioEngine = nil;
|
||||
self.outputMock = nil;
|
||||
self.inputMock = nil;
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)enableMockQueues
|
||||
{
|
||||
OCMStub([(id)self.audioEngine makeQueues:[OCMArg anyObjectRef]]).andDo(^(NSInvocation *invocation) {
|
||||
id ae;
|
||||
[invocation getArgument:&ae atIndex:0];
|
||||
|
||||
[ae setOutputQueue:self.outputMock];
|
||||
[ae setInputQueue:self.inputMock];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)testStartStopAudioFlow
|
||||
{
|
||||
[self enableMockQueues];
|
||||
|
||||
id toxav = OCMClassMock([OCTToxAV class]);
|
||||
OCMStub([toxav sendAudioFrame:[OCMArg anyPointer] sampleCount:0 channels:0 sampleRate:0 toFriend:0 error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.audioEngine toxav]).andReturn(toxav);
|
||||
|
||||
OCMStub([self.inputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
|
||||
OCMStub([self.inputMock stop:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock stop:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
|
||||
NSError *error = nil;
|
||||
XCTAssertTrue([self.audioEngine startAudioFlow:&error]);
|
||||
XCTAssertTrue([self.audioEngine stopAudioFlow:&error]);
|
||||
}
|
||||
|
||||
- (void)testStartStopAudioFlowFail
|
||||
{
|
||||
[self enableMockQueues];
|
||||
|
||||
OCMStub([self.inputMock begin:[OCMArg anyObjectRef]]).andDo(^(NSInvocation *invocation) {
|
||||
NSError *__autoreleasing *err;
|
||||
[invocation getArgument:&err atIndex:2];
|
||||
|
||||
if (err) {
|
||||
*err = [NSError new];
|
||||
}
|
||||
|
||||
BOOL no = NO;
|
||||
[invocation setReturnValue:&no];
|
||||
});
|
||||
|
||||
OCMStub([self.outputMock begin:[OCMArg anyObjectRef]]).andDo(^(NSInvocation *invocation) {
|
||||
NSError *__autoreleasing *err;
|
||||
[invocation getArgument:&err atIndex:2];
|
||||
|
||||
if (err) {
|
||||
*err = [NSError new];
|
||||
}
|
||||
|
||||
BOOL no = NO;
|
||||
[invocation setReturnValue:&no];
|
||||
});
|
||||
|
||||
|
||||
NSError *error = nil;
|
||||
XCTAssertFalse([self.audioEngine startAudioFlow:&error]);
|
||||
XCTAssertNotNil(error);
|
||||
}
|
||||
|
||||
- (void)testSettingDevice
|
||||
{
|
||||
#if ! TARGET_OS_IPHONE
|
||||
XCTAssertTrue([self.audioEngine setOutputDeviceID:@"Sayle" error:nil]);
|
||||
XCTAssertTrue([self.audioEngine setInputDeviceID:@"Laives" error:nil]);
|
||||
|
||||
// Device ID should stay in sync with set.
|
||||
XCTAssertEqualObjects(self.audioEngine.outputDeviceID, @"Sayle");
|
||||
XCTAssertEqualObjects(self.audioEngine.inputDeviceID, @"Laives");
|
||||
#else
|
||||
XCTAssertTrue([self.audioEngine routeAudioToSpeaker:YES error:nil]);
|
||||
OCMVerify([self.audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:[OCMArg anyObjectRef]]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// No test for iOS because it doesn't do anything anyway
|
||||
- (void)testSettingDevicesLive
|
||||
{
|
||||
#if ! TARGET_OS_IPHONE
|
||||
NSError *err;
|
||||
[self enableMockQueues];
|
||||
|
||||
OCMStub([self.inputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
XCTAssertTrue([self.audioEngine startAudioFlow:&err]);
|
||||
|
||||
OCMStub([self.outputMock setDeviceID:@"Crystinger" error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.inputMock setDeviceID:@"Daxx" error:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock setDeviceID:@"Niles" error:[OCMArg anyObjectRef]]).andReturn(NO);
|
||||
|
||||
XCTAssertTrue([self.audioEngine setOutputDeviceID:@"Crystinger" error:nil]);
|
||||
XCTAssertTrue([self.audioEngine setInputDeviceID:@"Daxx" error:nil]);
|
||||
|
||||
// Device ID should stay in sync with set.
|
||||
XCTAssertEqualObjects(self.audioEngine.outputDeviceID, @"Crystinger");
|
||||
XCTAssertEqualObjects(self.audioEngine.inputDeviceID, @"Daxx");
|
||||
|
||||
// Failed sets should not update the stored id.
|
||||
XCTAssertFalse([self.audioEngine setOutputDeviceID:@"Niles" error:nil]);
|
||||
XCTAssertNotEqualObjects(self.audioEngine.outputDeviceID, @"Niles");
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)testSendDataBlock
|
||||
{
|
||||
[self enableMockQueues];
|
||||
|
||||
id toxav = OCMClassMock([OCTToxAV class]);
|
||||
OCMStub([self.audioEngine toxav]).andReturn(toxav);
|
||||
|
||||
OCMStub([self.inputMock setSendDataBlock:[OCMArg any]]).andDo(^(NSInvocation *invoc) {
|
||||
void (^sendDataBlock)(void *, OCTToxAVSampleCount, OCTToxAVSampleRate, OCTToxAVChannels);
|
||||
[invoc getArgument:&sendDataBlock atIndex:2];
|
||||
self.sendDataBlock = sendDataBlock;
|
||||
});
|
||||
|
||||
OCMStub([self.inputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
|
||||
NSError *error = nil;
|
||||
self.audioEngine.friendNumber = 0;
|
||||
XCTAssertTrue([self.audioEngine startAudioFlow:&error]);
|
||||
|
||||
OCTToxAVPCMData pcm[] = {0x52, 0x2d, 0x4f, 0x2d, 0x4d, 0x2d, 0x41, 0x2d, 0x4e, 0x2d, 0x54, 0x2d, 0x49, 0x2d, 0x43, 0x2d, 0x21, 0x21};
|
||||
self.sendDataBlock((void *)pcm, 9, 48000, 1);
|
||||
|
||||
OCMVerify([toxav sendAudioFrame:pcm sampleCount:9 channels:1 sampleRate:48000 toFriend:0 error:[OCMArg anyObjectRef]]);
|
||||
}
|
||||
|
||||
- (void)testReceiveAudioPackets
|
||||
{
|
||||
[self enableMockQueues];
|
||||
|
||||
TPCircularBuffer buffer;
|
||||
TPCircularBufferInit(&buffer, 256);
|
||||
|
||||
OCMStub([self.inputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock begin:[OCMArg anyObjectRef]]).andReturn(YES);
|
||||
OCMStub([self.outputMock getBufferPointer]).andReturn(&buffer);
|
||||
|
||||
NSError *error = nil;
|
||||
self.audioEngine.friendNumber = 0;
|
||||
XCTAssertTrue([self.audioEngine startAudioFlow:&error]);
|
||||
|
||||
OCTToxAVPCMData pcm[] = {0x52, 0x2d, 0x4f, 0x2d, 0x4d, 0x2d, 0x41, 0x2d, 0x4e, 0x2d, 0x54, 0x2d, 0x49, 0x2d, 0x43, 0x2d, 0x21, 0x21};
|
||||
[self.audioEngine provideAudioFrames:pcm sampleCount:9 channels:1 sampleRate:12 fromFriend:0];
|
||||
|
||||
int32_t nbytes;
|
||||
void *samples = TPCircularBufferTail(&buffer, &nbytes);
|
||||
|
||||
XCTAssertTrue(nbytes == 18);
|
||||
XCTAssertTrue(memcmp(samples, pcm, 18) == 0);
|
||||
|
||||
TPCircularBufferCleanup(&buffer);
|
||||
|
||||
OCMVerify([self.outputMock updateSampleRate:12 numberOfChannels:1 error:[OCMArg anyObjectRef]]);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user