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