1// Copyright 2016 The Chromium Authors. All rights reserved. 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 "ios/chrome/browser/ui/voice/text_to_speech_player.h" 6 7#import <UIKit/UIKit.h> 8 9#include "base/mac/foundation_util.h" 10#import "base/test/ios/wait_util.h" 11#include "base/time/time.h" 12#import "ios/chrome/browser/ui/voice/voice_search_notification_names.h" 13#include "ios/web/public/test/web_task_environment.h" 14#include "testing/gtest/include/gtest/gtest.h" 15#include "testing/gtest_mac.h" 16#include "testing/platform_test.h" 17#include "url/gurl.h" 18 19#if !defined(__has_feature) || !__has_feature(objc_arc) 20#error "This file requires ARC support." 21#endif 22 23#pragma mark - TTSPlayerObserver 24 25// Test object that listens for TTS notifications. 26@interface TTSPlayerObserver : NSObject 27 28// The TextToSpeechPlayer passed on initialization. 29@property(nonatomic, strong) TextToSpeechPlayer* player; 30 31// Whether notifications have been received. 32@property(nonatomic, readonly) BOOL readyNotificationReceived; 33@property(nonatomic, readonly) BOOL willStartNotificationReceived; 34@property(nonatomic, readonly) BOOL didStopNotificationReceived; 35 36// Notification handlers. 37- (void)handleReadyNotification:(NSNotification*)notification; 38- (void)handleWillStartNotification:(NSNotification*)notification; 39- (void)handleDidStopNotification:(NSNotification*)notification; 40 41@end 42 43@implementation TTSPlayerObserver 44@synthesize player = _player; 45@synthesize readyNotificationReceived = _readyNotificationReceived; 46@synthesize willStartNotificationReceived = _willStartNotificationReceived; 47@synthesize didStopNotificationReceived = _didStopNotificationReceived; 48 49- (void)setPlayer:(TextToSpeechPlayer*)player { 50 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; 51 [defaultCenter removeObserver:self]; 52 _player = player; 53 if (player) { 54 [defaultCenter addObserver:self 55 selector:@selector(handleReadyNotification:) 56 name:kTTSAudioReadyForPlaybackNotification 57 object:player]; 58 [defaultCenter addObserver:self 59 selector:@selector(handleWillStartNotification:) 60 name:kTTSWillStartPlayingNotification 61 object:player]; 62 [defaultCenter addObserver:self 63 selector:@selector(handleDidStopNotification:) 64 name:kTTSDidStopPlayingNotification 65 object:player]; 66 } 67} 68 69- (TextToSpeechPlayer*)player { 70 return _player; 71} 72 73- (void)handleReadyNotification:(NSNotification*)notification { 74 ASSERT_EQ(notification.object, self.player); 75 _readyNotificationReceived = YES; 76} 77 78- (void)handleWillStartNotification:(NSNotification*)notification { 79 ASSERT_EQ(notification.object, self.player); 80 _willStartNotificationReceived = YES; 81} 82 83- (void)handleDidStopNotification:(NSNotification*)notification { 84 ASSERT_EQ(notification.object, self.player); 85 _didStopNotificationReceived = YES; 86} 87 88@end 89 90#pragma mark - TextToSpeechPlayerTest 91 92class TextToSpeechPlayerTest : public PlatformTest { 93 protected: 94 void SetUp() override { 95 tts_player_ = [[TextToSpeechPlayer alloc] init]; 96 tts_player_observer_ = [[TTSPlayerObserver alloc] init]; 97 [tts_player_observer_ setPlayer:tts_player_]; 98 } 99 100 TextToSpeechPlayer* tts_player_; 101 TTSPlayerObserver* tts_player_observer_; 102 web::WebTaskEnvironment task_environment_; 103}; 104 105// Tests that kTTSAudioReadyForPlaybackNotification is received and that 106// TTSPlayer state is updated. 107TEST_F(TextToSpeechPlayerTest, ReadyForPlayback) { 108 NSData* audio_data = [@"audio_data" dataUsingEncoding:NSUTF8StringEncoding]; 109 [tts_player_ prepareToPlayAudioData:audio_data]; 110 EXPECT_TRUE([tts_player_observer_ readyNotificationReceived]); 111 EXPECT_TRUE([tts_player_ isReadyForPlayback]); 112} 113 114// Tests that kTTSAudioReadyForPlaybackNotification is received and that 115// TTSPlayer's |-readyForPlayback| is NO for empty data. 116TEST_F(TextToSpeechPlayerTest, ReadyForPlaybackEmtpyData) { 117 NSData* audio_data = [@"" dataUsingEncoding:NSUTF8StringEncoding]; 118 [tts_player_ prepareToPlayAudioData:audio_data]; 119 EXPECT_TRUE([tts_player_observer_ readyNotificationReceived]); 120 EXPECT_FALSE([tts_player_ isReadyForPlayback]); 121} 122 123// Tests that kTTSWillStartPlayingNotification is received when playback begins 124// and kTTSDidStopPlayingNotification is received when it is cancelled. 125// TODO(rohitrao): Disabled because the bots do not have a valid sound output 126// device. 127TEST_F(TextToSpeechPlayerTest, DISABLED_ValidPlaybackNotifications) { 128 NSString* path = 129 [[NSBundle mainBundle] pathForResource:@"test_sound" 130 ofType:@"m4a" 131 inDirectory:@"ios/chrome/test/data/voice"]; 132 NSData* audio_data = [[NSData alloc] initWithContentsOfFile:path]; 133 [tts_player_ prepareToPlayAudioData:audio_data]; 134 [tts_player_ beginPlayback]; 135 EXPECT_TRUE([tts_player_observer_ willStartNotificationReceived]); 136 EXPECT_TRUE([tts_player_ isPlayingAudio]); 137 [tts_player_ cancelPlayback]; 138 EXPECT_TRUE([tts_player_observer_ didStopNotificationReceived]); 139 EXPECT_FALSE([tts_player_ isPlayingAudio]); 140} 141 142// Tests that playback is cancelled when the application enters the background 143// while playback is occurring. 144// TODO(rohitrao): Disabled because the bots do not have a valid sound output 145// device. 146TEST_F(TextToSpeechPlayerTest, DISABLED_BackgroundNotification) { 147 NSString* path = 148 [[NSBundle mainBundle] pathForResource:@"test_sound" 149 ofType:@"m4a" 150 inDirectory:@"ios/chrome/test/data/voice"]; 151 NSData* audio_data = [[NSData alloc] initWithContentsOfFile:path]; 152 [tts_player_ prepareToPlayAudioData:audio_data]; 153 [tts_player_ beginPlayback]; 154 EXPECT_TRUE([tts_player_observer_ willStartNotificationReceived]); 155 EXPECT_TRUE([tts_player_ isPlayingAudio]); 156 [[NSNotificationCenter defaultCenter] 157 postNotificationName:UIApplicationDidEnterBackgroundNotification 158 object:[UIApplication sharedApplication]]; 159 EXPECT_TRUE([tts_player_observer_ didStopNotificationReceived]); 160 EXPECT_FALSE([tts_player_ isPlayingAudio]); 161} 162