Home | History | Annotate | Download | only in unit
      1 /*
      2  * Copyright (C) 2009 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 import android.media.Metadata;
     19 import android.os.Parcel;
     20 import android.test.AndroidTestCase;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 import android.util.Log;
     23 
     24 import java.util.Calendar;
     25 import java.util.Date;
     26 
     27 /*
     28  * Check the Java layer that parses serialized metadata in Parcel
     29  * works as expected.
     30  *
     31  */
     32 
     33 public class MediaPlayerMetadataParserTest extends AndroidTestCase {
     34     private static final String TAG = "MediaPlayerMetadataTest";
     35     private static final int kMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
     36     private static final int kHeaderSize = 8;
     37 
     38     private Metadata mMetadata = null;
     39     private Parcel mParcel = null;
     40 
     41     @Override
     42     protected void setUp() throws Exception {
     43         super.setUp();
     44         mMetadata = new Metadata();
     45         mParcel = Parcel.obtain();
     46 
     47         resetParcel();
     48     }
     49 
     50     // Check parsing of the parcel fails. Make sure the parser rewind
     51     // the parcel properly.
     52     private void assertParseFail() throws Exception {
     53         mParcel.setDataPosition(0);
     54         assertFalse(mMetadata.parse(mParcel));
     55         assertEquals(0, mParcel.dataPosition());
     56     }
     57 
     58     // Check parsing of the parcel is successful.
     59     private void assertParse() throws Exception {
     60         mParcel.setDataPosition(0);
     61         assertTrue(mMetadata.parse(mParcel));
     62     }
     63 
     64     // Write the number of bytes from the start of the parcel to the
     65     // current position at the beginning of the parcel (offset 0).
     66     private void adjustSize() {
     67         adjustSize(0);
     68     }
     69 
     70     // Write the number of bytes from the offset to the current
     71     // position at position pointed by offset.
     72     private void adjustSize(int offset) {
     73         final int pos = mParcel.dataPosition();
     74 
     75         mParcel.setDataPosition(offset);
     76         mParcel.writeInt(pos - offset);
     77         mParcel.setDataPosition(pos);
     78     }
     79 
     80     // Rewind the parcel and insert the header.
     81     private void resetParcel() {
     82         mParcel.setDataPosition(0);
     83         // Most tests will use a properly formed parcel with a size
     84         // and the meta marker so we add them by default.
     85         mParcel.writeInt(-1);  // Placeholder for the size
     86         mParcel.writeInt(kMarker);
     87     }
     88 
     89     // ----------------------------------------------------------------------
     90     // START OF THE TESTS
     91 
     92 
     93     // There should be at least 8 bytes in the parcel, 4 for the size
     94     // and 4 for the 'M' 'E' 'T' 'A' marker.
     95     @SmallTest
     96     public void testMissingSizeAndMarker() throws Exception {
     97         for (int i = 0; i < kHeaderSize; ++i) {
     98             mParcel.setDataPosition(0);
     99             mParcel.setDataSize(i);
    100 
    101             assertEquals(i, mParcel.dataAvail());
    102             assertParseFail();
    103         }
    104     }
    105 
    106     // There should be at least 'size' bytes in the parcel.
    107     @SmallTest
    108     public void testMissingData() throws Exception {
    109         final int size = 20;
    110 
    111         mParcel.writeInt(size);
    112         mParcel.setDataSize(size - 1);
    113         assertParseFail();
    114     }
    115 
    116     // Empty parcel is fine
    117     @SmallTest
    118     public void testEmptyIsOk() throws Exception {
    119         adjustSize();
    120         assertParse();
    121     }
    122 
    123     // ----------------------------------------------------------------------
    124     // RECORDS
    125     // ----------------------------------------------------------------------
    126 
    127     // A record header should be at least 12 bytes long
    128     @SmallTest
    129     public void testRecordMissingId() throws Exception {
    130         mParcel.writeInt(13); // record length
    131         // misses metadata id and metadata type.
    132         adjustSize();
    133         assertParseFail();
    134     }
    135 
    136     @SmallTest
    137     public void testRecordMissingType() throws Exception {
    138         mParcel.writeInt(13); // record length lies
    139         mParcel.writeInt(Metadata.TITLE);
    140         // misses metadata type
    141         adjustSize();
    142         assertParseFail();
    143     }
    144 
    145     @SmallTest
    146     public void testRecordWithZeroPayload() throws Exception {
    147         mParcel.writeInt(0);
    148         adjustSize();
    149         assertParseFail();
    150     }
    151 
    152     // A record cannot be empty.
    153     @SmallTest
    154     public void testRecordMissingPayload() throws Exception {
    155         mParcel.writeInt(12);
    156         mParcel.writeInt(Metadata.TITLE);
    157         mParcel.writeInt(Metadata.STRING_VAL);
    158         // misses payload
    159         adjustSize();
    160         assertParseFail();
    161     }
    162 
    163     // Check records can be found.
    164     @SmallTest
    165     public void testRecordsFound() throws Exception {
    166         writeStringRecord(Metadata.TITLE, "a title");
    167         writeStringRecord(Metadata.GENRE, "comedy");
    168         writeStringRecord(Metadata.firstCustomId(), "custom");
    169         adjustSize();
    170         assertParse();
    171         assertTrue(mMetadata.has(Metadata.TITLE));
    172         assertTrue(mMetadata.has(Metadata.GENRE));
    173         assertTrue(mMetadata.has(Metadata.firstCustomId()));
    174         assertFalse(mMetadata.has(Metadata.DRM_CRIPPLED));
    175         assertEquals(3, mMetadata.keySet().size());
    176     }
    177 
    178     // Detects bad metadata type
    179     @SmallTest
    180     public void testBadMetadataType() throws Exception {
    181         final int start = mParcel.dataPosition();
    182         mParcel.writeInt(-1);  // Placeholder for the length
    183         mParcel.writeInt(Metadata.TITLE);
    184         mParcel.writeInt(0);  // Invalid type.
    185         mParcel.writeString("dummy");
    186         adjustSize(start);
    187 
    188         adjustSize();
    189         assertParseFail();
    190     }
    191 
    192     // Check a Metadata instance can be reused, i.e the parse method
    193     // wipes out the existing states/keys.
    194     @SmallTest
    195     public void testParseClearState() throws Exception {
    196         writeStringRecord(Metadata.TITLE, "a title");
    197         writeStringRecord(Metadata.GENRE, "comedy");
    198         writeStringRecord(Metadata.firstCustomId(), "custom");
    199         adjustSize();
    200         assertParse();
    201 
    202         resetParcel();
    203         writeStringRecord(Metadata.MIME_TYPE, "audio/mpg");
    204         adjustSize();
    205         assertParse();
    206 
    207         // Only the mime type metadata should be present.
    208         assertEquals(1, mMetadata.keySet().size());
    209         assertTrue(mMetadata.has(Metadata.MIME_TYPE));
    210 
    211         assertFalse(mMetadata.has(Metadata.TITLE));
    212         assertFalse(mMetadata.has(Metadata.GENRE));
    213         assertFalse(mMetadata.has(Metadata.firstCustomId()));
    214     }
    215 
    216     // ----------------------------------------------------------------------
    217     // GETTERS
    218     // ----------------------------------------------------------------------
    219 
    220     // getString
    221     @SmallTest
    222     public void testGetString() throws Exception {
    223         writeStringRecord(Metadata.TITLE, "a title");
    224         writeStringRecord(Metadata.GENRE, "comedy");
    225         adjustSize();
    226         assertParse();
    227 
    228         assertEquals("a title", mMetadata.getString(Metadata.TITLE));
    229         assertEquals("comedy", mMetadata.getString(Metadata.GENRE));
    230     }
    231 
    232     // get an empty string.
    233     @SmallTest
    234     public void testGetEmptyString() throws Exception {
    235         writeStringRecord(Metadata.TITLE, "");
    236         adjustSize();
    237         assertParse();
    238 
    239         assertEquals("", mMetadata.getString(Metadata.TITLE));
    240     }
    241 
    242     // get a string when a NULL value was in the parcel
    243     @SmallTest
    244     public void testGetNullString() throws Exception {
    245         writeStringRecord(Metadata.TITLE, null);
    246         adjustSize();
    247         assertParse();
    248 
    249         assertEquals(null, mMetadata.getString(Metadata.TITLE));
    250     }
    251 
    252     // get a string when an integer is actually present
    253     @SmallTest
    254     public void testWrongType() throws Exception {
    255         writeIntRecord(Metadata.DURATION, 5);
    256         adjustSize();
    257         assertParse();
    258 
    259         try {
    260             mMetadata.getString(Metadata.DURATION);
    261         } catch (IllegalStateException ise) {
    262             return;
    263         }
    264         fail("Exception was not thrown");
    265     }
    266 
    267     // getInt
    268     @SmallTest
    269     public void testGetInt() throws Exception {
    270         writeIntRecord(Metadata.CD_TRACK_NUM, 1);
    271         adjustSize();
    272         assertParse();
    273 
    274         assertEquals(1, mMetadata.getInt(Metadata.CD_TRACK_NUM));
    275     }
    276 
    277     // getBoolean
    278     @SmallTest
    279     public void testGetBoolean() throws Exception {
    280         writeBooleanRecord(Metadata.PAUSE_AVAILABLE, true);
    281         writeBooleanRecord(Metadata.SEEK_AVAILABLE, true);
    282         writeBooleanRecord(Metadata.SEEK_BACKWARD_AVAILABLE, true);
    283         writeBooleanRecord(Metadata.SEEK_FORWARD_AVAILABLE, true);
    284         adjustSize();
    285         assertParse();
    286 
    287         assertEquals(true, mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE));
    288         assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_AVAILABLE));
    289         assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE));
    290         assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE));
    291     }
    292 
    293     // getLong
    294     @SmallTest
    295     public void testGetLong() throws Exception {
    296         writeLongRecord(Metadata.DURATION, 1L);
    297         adjustSize();
    298         assertParse();
    299 
    300         assertEquals(1L, mMetadata.getLong(Metadata.DURATION));
    301     }
    302 
    303     // getDouble
    304     @SmallTest
    305     public void testGetDouble() throws Exception {
    306         writeDoubleRecord(Metadata.VIDEO_FRAME_RATE, 29.97);
    307         adjustSize();
    308         assertParse();
    309 
    310         assertEquals(29.97, mMetadata.getDouble(Metadata.VIDEO_FRAME_RATE));
    311     }
    312 
    313     // getByteArray
    314     @SmallTest
    315     public void testGetByteArray() throws Exception {
    316         byte data[] = new byte[]{1,2,3,4,5};
    317 
    318         writeByteArrayRecord(Metadata.ALBUM_ART, data);
    319         adjustSize();
    320         assertParse();
    321 
    322         byte res[] = mMetadata.getByteArray(Metadata.ALBUM_ART);
    323         for (int i = 0; i < data.length; ++i) {
    324             assertEquals(data[i], res[i]);
    325         }
    326     }
    327 
    328     // getDate
    329     @SmallTest
    330     public void testGetDate() throws Exception {
    331         writeDateRecord(Metadata.DATE, 0, "PST");
    332         adjustSize();
    333         assertParse();
    334 
    335         assertEquals(new Date(0), mMetadata.getDate(Metadata.DATE));
    336     }
    337 
    338     // ----------------------------------------------------------------------
    339     // HELPERS TO APPEND RECORDS
    340     // ----------------------------------------------------------------------
    341 
    342     // Insert a string record at the current position.
    343     private void writeStringRecord(int metadataId, String val) {
    344         final int start = mParcel.dataPosition();
    345         mParcel.writeInt(-1);  // Placeholder for the length
    346         mParcel.writeInt(metadataId);
    347         mParcel.writeInt(Metadata.STRING_VAL);
    348         mParcel.writeString(val);
    349         adjustSize(start);
    350     }
    351 
    352     // Insert an int record at the current position.
    353     private void writeIntRecord(int metadataId, int val) {
    354         final int start = mParcel.dataPosition();
    355         mParcel.writeInt(-1);  // Placeholder for the length
    356         mParcel.writeInt(metadataId);
    357         mParcel.writeInt(Metadata.INTEGER_VAL);
    358         mParcel.writeInt(val);
    359         adjustSize(start);
    360     }
    361 
    362     // Insert a boolean record at the current position.
    363     private void writeBooleanRecord(int metadataId, boolean val) {
    364         final int start = mParcel.dataPosition();
    365         mParcel.writeInt(-1);  // Placeholder for the length
    366         mParcel.writeInt(metadataId);
    367         mParcel.writeInt(Metadata.BOOLEAN_VAL);
    368         mParcel.writeInt(val ? 1 : 0);
    369         adjustSize(start);
    370     }
    371 
    372     // Insert a Long record at the current position.
    373     private void writeLongRecord(int metadataId, long val) {
    374         final int start = mParcel.dataPosition();
    375         mParcel.writeInt(-1);  // Placeholder for the length
    376         mParcel.writeInt(metadataId);
    377         mParcel.writeInt(Metadata.LONG_VAL);
    378         mParcel.writeLong(val);
    379         adjustSize(start);
    380     }
    381 
    382     // Insert a Double record at the current position.
    383     private void writeDoubleRecord(int metadataId, double val) {
    384         final int start = mParcel.dataPosition();
    385         mParcel.writeInt(-1);  // Placeholder for the length
    386         mParcel.writeInt(metadataId);
    387         mParcel.writeInt(Metadata.DOUBLE_VAL);
    388         mParcel.writeDouble(val);
    389         adjustSize(start);
    390     }
    391 
    392     // Insert a ByteArray record at the current position.
    393     private void writeByteArrayRecord(int metadataId, byte[] val) {
    394         final int start = mParcel.dataPosition();
    395         mParcel.writeInt(-1);  // Placeholder for the length
    396         mParcel.writeInt(metadataId);
    397         mParcel.writeInt(Metadata.BYTE_ARRAY_VAL);
    398         mParcel.writeByteArray(val);
    399         adjustSize(start);
    400     }
    401 
    402     // Insert a Date record at the current position.
    403     private void writeDateRecord(int metadataId, long time, String tz) {
    404         final int start = mParcel.dataPosition();
    405         mParcel.writeInt(-1);  // Placeholder for the length
    406         mParcel.writeInt(metadataId);
    407         mParcel.writeInt(Metadata.DATE_VAL);
    408         mParcel.writeLong(time);
    409         mParcel.writeString(tz);
    410         adjustSize(start);
    411     }
    412 }
    413