MediaRecorderStateUnitTestTemplate.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mediaframeworktest.unit; 18 19import android.util.Log; 20import android.media.MediaRecorder; 21import android.test.AndroidTestCase; 22 23/** 24 * A template class for running a method under test in all possible 25 * states of a MediaRecorder object. 26 * 27 * @see com.android.mediaframeworktest.unit.MediaRecorderStopStateUnitTest 28 * for an example of using this class. 29 * 30 * A typical concrete unit test class would implement the 31 * MediaRecorderMethodUnderTest interface and have a reference to an object of 32 * this class. Then it calls runTestOnMethod() to actually perform the unit 33 * tests. It is recommended that the toString() method of the concrete unit test 34 * class be overridden to use the actual method name under test for logging 35 * purpose. 36 * 37 */ 38class MediaRecorderStateUnitTestTemplate extends AndroidTestCase { 39 public static final String RECORD_OUTPUT_PATH = "/sdcard/recording.3gp"; 40 public static final int OUTPUT_FORMAT= MediaRecorder.OutputFormat.THREE_GPP; 41 public static final int AUDIO_ENCODER = MediaRecorder.AudioEncoder.AMR_NB; 42 public static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC; 43 private static final String TAG = "MediaRecorderStateUnitTest"; 44 private MediaRecorderStateErrors mStateErrors = new MediaRecorderStateErrors(); 45 private MediaRecorder mMediaRecorder = new MediaRecorder(); 46 private MediaRecorderStateErrors.MediaRecorderState mMediaRecorderState = null; 47 private MediaRecorderMethodUnderTest mMethodUnderTest = null; 48 49 /** 50 * Runs the given method under test in all possible states of a MediaRecorder 51 * object. 52 * 53 * @param testMethod the method under test. 54 */ 55 public void runTestOnMethod(MediaRecorderMethodUnderTest testMethod) { 56 mMethodUnderTest = testMethod; 57 if (mMethodUnderTest != null) { // Method under test has been set? 58 checkMethodUnderTestInAllPossibleStates(); 59 mMethodUnderTest.checkStateErrors(mStateErrors); 60 cleanUp(); 61 } 62 } 63 64 /* 65 * Calls method under test in the given state of the MediaRecorder object. 66 * 67 * @param state the MediaRecorder state in which the method under test is called. 68 */ 69 private void callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState state) { 70 Log.v(TAG, "call " + mMethodUnderTest + ": started in state " + state); 71 setMediaRecorderToState(state); 72 try { 73 mMethodUnderTest.invokeMethodUnderTest(mMediaRecorder); 74 } catch(Exception e) { 75 setStateError(mMediaRecorderState, true); 76 } 77 Log.v(TAG, "call " + mMethodUnderTest + ": ended in state " + state); 78 } 79 80 /* 81 * The following setMediaRecorderToXXXStateXXX methods sets the MediaRecorder 82 * object to the corresponding state, given the assumption that reset() 83 * always resets the MediaRecorder object to Initial (after reset) state. 84 */ 85 private void setMediaRecorderToInitialStateAfterReset() { 86 try { 87 mMediaRecorder.reset(); 88 } catch(Exception e) { 89 fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown."); 90 } 91 } 92 93 private void setMediaRecorderToInitialStateAfterStop() { 94 try { 95 mMediaRecorder.reset(); 96 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 97 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT); 98 mMediaRecorder.setAudioEncoder(AUDIO_ENCODER); 99 mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH); 100 mMediaRecorder.prepare(); 101 mMediaRecorder.start(); 102 mMediaRecorder.stop(); 103 } catch(Exception e) { 104 fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown."); 105 } 106 } 107 108 private void setMediaRecorderToInitializedState() { 109 try { 110 mMediaRecorder.reset(); 111 if (mMethodUnderTest.toString() != "setAudioSource()") { 112 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 113 } 114 } catch(Exception e) { 115 fail("setMediaRecorderToInitializedState: Exception " + e.getClass().getName() + " was thrown."); 116 } 117 } 118 119 private void setMediaRecorderToPreparedState() { 120 try { 121 mMediaRecorder.reset(); 122 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 123 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT); 124 mMediaRecorder.setAudioEncoder(AUDIO_ENCODER); 125 mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH); 126 mMediaRecorder.prepare(); 127 } catch(Exception e) { 128 fail("setMediaRecorderToPreparedState: Exception " + e.getClass().getName() + " was thrown."); 129 } 130 } 131 132 private void setMediaRecorderToRecordingState() { 133 try { 134 mMediaRecorder.reset(); 135 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 136 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT); 137 mMediaRecorder.setAudioEncoder(AUDIO_ENCODER); 138 mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH); 139 mMediaRecorder.prepare(); 140 mMediaRecorder.start(); 141 } catch(Exception e) { 142 fail("setMediaRecorderToRecordingState: Exception " + e.getClass().getName() + " was thrown."); 143 } 144 } 145 146 private void setMediaRecorderToDataSourceConfiguredState() { 147 try { 148 mMediaRecorder.reset(); 149 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 150 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT); 151 152 /* Skip setAudioEncoder() and setOutputFile() calls if 153 * the method under test is setAudioEncoder() since this 154 * method can only be called once even in the DATASOURCECONFIGURED state 155 */ 156 if (mMethodUnderTest.toString() != "setAudioEncoder()") { 157 mMediaRecorder.setAudioEncoder(AUDIO_ENCODER); 158 } 159 160 if (mMethodUnderTest.toString() != "setOutputFile()") { 161 mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH); 162 } 163 } catch(Exception e) { 164 fail("setMediaRecorderToDataSourceConfiguredState: Exception " + e.getClass().getName() + " was thrown."); 165 } 166 } 167 168 /* 169 * There are a lot of ways to force the MediaRecorder object to enter 170 * the Error state. We arbitrary choose one here. 171 */ 172 private void setMediaRecorderToErrorState() { 173 try { 174 mMediaRecorder.reset(); 175 176 /* Skip setAudioSource() if the method under test is setAudioEncoder() 177 * Because, otherwise, it is valid to call setAudioEncoder() after 178 * start() since start() will fail, and then the mMediaRecorder 179 * won't be set to the Error state 180 */ 181 if (mMethodUnderTest.toString() != "setAudioEncoder()") { 182 mMediaRecorder.setAudioSource(AUDIO_SOURCE); 183 } 184 185 /* Skip setOutputFormat if the method under test is setOutputFile() 186 * Because, otherwise, it is valid to call setOutputFile() after 187 * start() since start() will fail, and then the mMediaRecorder 188 * won't be set to the Error state 189 */ 190 if (mMethodUnderTest.toString() != "setOutputFile()") { 191 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT); 192 } 193 194 mMediaRecorder.start(); 195 } catch(Exception e) { 196 if (!(e instanceof IllegalStateException)) { 197 fail("setMediaRecorderToErrorState: Exception " + e.getClass().getName() + " was thrown."); 198 } 199 } 200 Log.v(TAG, "setMediaRecorderToErrorState: done."); 201 } 202 203 /* 204 * Sets the state of the MediaRecorder object to the specified one. 205 * 206 * @param state the state of the MediaRecorder object. 207 */ 208 private void setMediaRecorderToState(MediaRecorderStateErrors.MediaRecorderState state) { 209 mMediaRecorderState = state; 210 switch(state) { 211 case INITIAL: 212 // Does nothing. 213 break; 214 case INITIAL_AFTER_RESET: 215 setMediaRecorderToInitialStateAfterReset(); 216 break; 217 case INITIAL_AFTER_STOP: 218 setMediaRecorderToInitialStateAfterStop(); 219 break; 220 case INITIALIZED: 221 setMediaRecorderToInitializedState(); 222 break; 223 case DATASOURCECONFIGURED: 224 setMediaRecorderToDataSourceConfiguredState(); 225 break; 226 case PREPARED: 227 setMediaRecorderToPreparedState(); 228 break; 229 case RECORDING: 230 setMediaRecorderToRecordingState(); 231 break; 232 case ERROR: 233 setMediaRecorderToErrorState(); 234 break; 235 } 236 } 237 238 /* 239 * Sets the error value of the corresponding state to the given error. 240 * 241 * @param state the state of the MediaRecorder object. 242 * @param error the value of the state error to be set. 243 */ 244 private void setStateError(MediaRecorderStateErrors.MediaRecorderState state, boolean error) { 245 switch(state) { 246 case INITIAL: 247 mStateErrors.errorInInitialState = error; 248 break; 249 case INITIAL_AFTER_RESET: 250 mStateErrors.errorInInitialStateAfterReset = error; 251 break; 252 case INITIAL_AFTER_STOP: 253 mStateErrors.errorInInitialStateAfterStop = error; 254 break; 255 case INITIALIZED: 256 mStateErrors.errorInInitializedState = error; 257 break; 258 case DATASOURCECONFIGURED: 259 mStateErrors.errorInDataSourceConfiguredState = error; 260 break; 261 case PREPARED: 262 mStateErrors.errorInPreparedState = error; 263 break; 264 case RECORDING: 265 mStateErrors.errorInRecordingState = error; 266 break; 267 case ERROR: 268 mStateErrors.errorInErrorState = error; 269 break; 270 } 271 } 272 273 private void checkInitialState() { 274 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL); 275 } 276 277 private void checkInitialStateAfterReset() { 278 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_RESET); 279 } 280 281 private void checkInitialStateAfterStop() { 282 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_STOP); 283 } 284 285 private void checkInitializedState() { 286 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIALIZED); 287 } 288 289 private void checkPreparedState() { 290 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.PREPARED); 291 } 292 293 private void checkRecordingState() { 294 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.RECORDING); 295 } 296 297 private void checkDataSourceConfiguredState() { 298 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.DATASOURCECONFIGURED); 299 } 300 301 private void checkErrorState() { 302 callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.ERROR); 303 } 304 305 /* 306 * Checks the given method under test in all possible states of the MediaRecorder object. 307 */ 308 private void checkMethodUnderTestInAllPossibleStates() { 309 // Must be called first. 310 checkInitialState(); 311 312 // The sequence of the following method calls should not 313 // affect the test results. 314 checkErrorState(); 315 checkInitialStateAfterReset(); 316 checkInitialStateAfterStop(); 317 checkInitializedState(); 318 checkRecordingState(); 319 checkDataSourceConfiguredState(); 320 checkPreparedState(); 321 } 322 323 /* 324 * Cleans up all the internal object references. 325 */ 326 private void cleanUp() { 327 mMediaRecorder.release(); 328 mMediaRecorder = null; 329 mMediaRecorderState = null; 330 mStateErrors = null; 331 mMethodUnderTest = null; 332 } 333} 334