Home | History | Annotate | Download | only in unit
      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 
     17 package com.android.mediaframeworktest.unit;
     18 
     19 import android.util.Log;
     20 import android.media.MediaRecorder;
     21 import 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  */
     38 class 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     // FIXME:
     94     // In the past, stop() == reset().
     95     // However, this is no longer true. The plan is to have a STOPPED state.
     96     // and from STOPPED state, start can be called without the need to
     97     // do the recording configuration again.
     98     private void setMediaRecorderToInitialStateAfterStop() {
     99         try {
    100             mMediaRecorder.reset();
    101 /*
    102             mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    103             mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
    104             mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
    105             mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
    106             mMediaRecorder.prepare();
    107             mMediaRecorder.start();
    108             mMediaRecorder.stop();
    109 */
    110         } catch(Exception e) {
    111             fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
    112         }
    113     }
    114 
    115     private void setMediaRecorderToInitializedState() {
    116         try {
    117             mMediaRecorder.reset();
    118             if (mMethodUnderTest.toString() != "setAudioSource()") {
    119                 mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    120             }
    121         } catch(Exception e) {
    122             fail("setMediaRecorderToInitializedState: Exception " + e.getClass().getName() + " was thrown.");
    123         }
    124     }
    125 
    126     private void setMediaRecorderToPreparedState() {
    127         try {
    128             mMediaRecorder.reset();
    129             mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    130             mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
    131             mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
    132             mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
    133             mMediaRecorder.prepare();
    134         } catch(Exception e) {
    135             fail("setMediaRecorderToPreparedState: Exception " + e.getClass().getName() + " was thrown.");
    136         }
    137     }
    138 
    139     private void setMediaRecorderToRecordingState() {
    140         try {
    141             mMediaRecorder.reset();
    142             mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    143             mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
    144             mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
    145             mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
    146             mMediaRecorder.prepare();
    147             mMediaRecorder.start();
    148         } catch(Exception e) {
    149             fail("setMediaRecorderToRecordingState: Exception " + e.getClass().getName() + " was thrown.");
    150         }
    151     }
    152 
    153     private void setMediaRecorderToDataSourceConfiguredState() {
    154         try {
    155             mMediaRecorder.reset();
    156             mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    157             mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
    158 
    159             /* Skip setAudioEncoder() and setOutputFile() calls if
    160              * the method under test is setAudioEncoder() since this
    161              * method can only be called once even in the DATASOURCECONFIGURED state
    162              */
    163             if (mMethodUnderTest.toString() != "setAudioEncoder()") {
    164                 mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
    165             }
    166 
    167             if (mMethodUnderTest.toString() != "setOutputFile()") {
    168                 mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
    169             }
    170         } catch(Exception e) {
    171             fail("setMediaRecorderToDataSourceConfiguredState: Exception " + e.getClass().getName() + " was thrown.");
    172         }
    173     }
    174 
    175     /*
    176      * There are a lot of ways to force the MediaRecorder object to enter
    177      * the Error state. We arbitrary choose one here.
    178      */
    179     private void setMediaRecorderToErrorState() {
    180         try {
    181             mMediaRecorder.reset();
    182 
    183             /* Skip setAudioSource() if the method under test is setAudioEncoder()
    184              * Because, otherwise, it is valid to call setAudioEncoder() after
    185              * start() since start() will fail, and then the mMediaRecorder
    186              * won't be set to the Error state
    187              */
    188             if (mMethodUnderTest.toString() != "setAudioEncoder()") {
    189                 mMediaRecorder.setAudioSource(AUDIO_SOURCE);
    190             }
    191 
    192             /* Skip setOutputFormat if the method under test is setOutputFile()
    193              *  Because, otherwise, it is valid to call setOutputFile() after
    194              * start() since start() will fail, and then the mMediaRecorder
    195              * won't be set to the Error state
    196              */
    197             if (mMethodUnderTest.toString() != "setOutputFile()") {
    198                 mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
    199             }
    200 
    201             mMediaRecorder.start();
    202         } catch(Exception e) {
    203             if (!(e instanceof IllegalStateException)) {
    204                 fail("setMediaRecorderToErrorState: Exception " + e.getClass().getName() + " was thrown.");
    205             }
    206         }
    207         Log.v(TAG, "setMediaRecorderToErrorState: done.");
    208     }
    209 
    210     /*
    211      * Sets the state of the MediaRecorder object to the specified one.
    212      *
    213      * @param state the state of the MediaRecorder object.
    214      */
    215     private void setMediaRecorderToState(MediaRecorderStateErrors.MediaRecorderState state) {
    216         mMediaRecorderState = state;
    217         switch(state) {
    218             case INITIAL:
    219                 // Does nothing.
    220                 break;
    221             case INITIAL_AFTER_RESET:
    222                 setMediaRecorderToInitialStateAfterReset();
    223                 break;
    224             case INITIAL_AFTER_STOP:
    225                 setMediaRecorderToInitialStateAfterStop();
    226                 break;
    227             case INITIALIZED:
    228                 setMediaRecorderToInitializedState();
    229                 break;
    230             case DATASOURCECONFIGURED:
    231                 setMediaRecorderToDataSourceConfiguredState();
    232                 break;
    233             case PREPARED:
    234                 setMediaRecorderToPreparedState();
    235                 break;
    236             case RECORDING:
    237                 setMediaRecorderToRecordingState();
    238                 break;
    239             case ERROR:
    240                 setMediaRecorderToErrorState();
    241                 break;
    242         }
    243     }
    244 
    245     /*
    246      * Sets the error value of the corresponding state to the given error.
    247      *
    248      * @param state the state of the MediaRecorder object.
    249      * @param error the value of the state error to be set.
    250      */
    251     private void setStateError(MediaRecorderStateErrors.MediaRecorderState state, boolean error) {
    252         switch(state) {
    253             case INITIAL:
    254                 mStateErrors.errorInInitialState = error;
    255                 break;
    256             case INITIAL_AFTER_RESET:
    257                 mStateErrors.errorInInitialStateAfterReset = error;
    258                 break;
    259             case INITIAL_AFTER_STOP:
    260                 mStateErrors.errorInInitialStateAfterStop = error;
    261                 break;
    262             case INITIALIZED:
    263                 mStateErrors.errorInInitializedState = error;
    264                 break;
    265             case DATASOURCECONFIGURED:
    266                 mStateErrors.errorInDataSourceConfiguredState = error;
    267                 break;
    268             case PREPARED:
    269                 mStateErrors.errorInPreparedState = error;
    270                 break;
    271             case RECORDING:
    272                 mStateErrors.errorInRecordingState = error;
    273                 break;
    274             case ERROR:
    275                 mStateErrors.errorInErrorState = error;
    276                 break;
    277         }
    278     }
    279 
    280     private void checkInitialState() {
    281         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL);
    282     }
    283 
    284     private void checkInitialStateAfterReset() {
    285         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_RESET);
    286     }
    287 
    288     private void checkInitialStateAfterStop() {
    289         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_STOP);
    290     }
    291 
    292     private void checkInitializedState() {
    293         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIALIZED);
    294     }
    295 
    296     private void checkPreparedState() {
    297         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.PREPARED);
    298     }
    299 
    300     private void checkRecordingState() {
    301         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.RECORDING);
    302     }
    303 
    304     private void checkDataSourceConfiguredState() {
    305         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.DATASOURCECONFIGURED);
    306     }
    307 
    308     private void checkErrorState() {
    309         callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.ERROR);
    310     }
    311 
    312     /*
    313      * Checks the given method under test in all possible states of the MediaRecorder object.
    314      */
    315     private void checkMethodUnderTestInAllPossibleStates() {
    316         // Must be called first.
    317         checkInitialState();
    318 
    319         // The sequence of the following method calls should not
    320         // affect the test results.
    321         checkErrorState();
    322         checkInitialStateAfterReset();
    323         checkInitialStateAfterStop();
    324         checkInitializedState();
    325         checkRecordingState();
    326         checkDataSourceConfiguredState();
    327         checkPreparedState();
    328     }
    329 
    330     /*
    331      * Cleans up all the internal object references.
    332      */
    333     private void cleanUp() {
    334         mMediaRecorder.release();
    335         mMediaRecorder = null;
    336         mMediaRecorderState = null;
    337         mStateErrors = null;
    338         mMethodUnderTest = null;
    339     }
    340 }
    341