MediaPlayerMetadataParserTest.java revision a5ccb22a3ddb342fe3f7e5493095c6e6dceda60b
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
24/*
25 * Check the Java layer that parses serialized metadata in Parcel
26 * works as expected.
27 *
28 */
29
30public class MediaPlayerMetadataParserTest extends AndroidTestCase {
31    private static final String TAG = "MediaPlayerMetadataTest";
32    private static final int kToken = 0xdeadbeef;
33    private static final int kMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
34    private static final int kHeaderSize = 8;
35
36    private Metadata mMetadata = null;
37    private Parcel mParcel = null;
38
39    @Override
40    protected void setUp() throws Exception {
41        super.setUp();
42        mMetadata = new Metadata();
43        mParcel = Parcel.obtain();
44
45        resetParcel();
46    }
47
48    // Check parsing of the parcel fails. Make sure the parser rewind
49    // the parcel properly.
50    private void assertParseFail() throws Exception {
51        mParcel.setDataPosition(0);
52        assertFalse(mMetadata.parse(mParcel));
53        assertEquals(0, mParcel.dataPosition());
54    }
55
56    // Check parsing of the parcel is successful. Before the
57    // invocation of the parser a token is inserted. When the parser
58    // returns, the parcel should be positioned at the token (check it
59    // does not read too much data).
60    private void assertParse() throws Exception {
61        mParcel.writeInt(kToken);
62        mParcel.setDataPosition(0);
63        assertTrue(mMetadata.parse(mParcel));
64        assertEquals(kToken, mParcel.readInt());
65    }
66
67    // Write the number of bytes from the start of the parcel to the
68    // current position at the beginning of the parcel (offset 0).
69    private void adjustSize() {
70        adjustSize(0);
71    }
72
73    // Write the number of bytes from the offset to the current
74    // position at position pointed by offset.
75    private void adjustSize(int offset) {
76        final int pos = mParcel.dataPosition();
77
78        mParcel.setDataPosition(offset);
79        mParcel.writeInt(pos - offset);
80        mParcel.setDataPosition(pos);
81    }
82
83    // Rewind the parcel and insert the header.
84    private void resetParcel() {
85        mParcel.setDataPosition(0);
86        // Most tests will use a properly formed parcel with a size
87        // and the meta marker so we add them by default.
88        mParcel.writeInt(-1);  // Placeholder for the size
89        mParcel.writeInt(kMarker);
90    }
91
92    // Insert a string record at the current position.
93    private void writeStringRecord(int metadataId, String val) {
94        final int start = mParcel.dataPosition();
95        mParcel.writeInt(-1);  // Placeholder for the length
96        mParcel.writeInt(metadataId);
97        mParcel.writeInt(Metadata.STRING_VAL);
98        mParcel.writeString(val);
99        adjustSize(start);
100    }
101
102    // ----------------------------------------------------------------------
103    // START OF THE TESTS
104
105
106    // There should be at least 8 bytes in the parcel, 4 for the size
107    // and 4 for the 'M' 'E' 'T' 'A' marker.
108    @SmallTest
109    public void testMissingSizeAndMarker() throws Exception {
110        for (int i = 0; i < kHeaderSize; ++i) {
111            mParcel.setDataPosition(0);
112            mParcel.setDataSize(i);
113
114            assertEquals(i, mParcel.dataAvail());
115            assertParseFail();
116        }
117    }
118
119    // There should be at least 'size' bytes in the parcel.
120    @SmallTest
121    public void testMissingData() throws Exception {
122        final int size = 20;
123
124        mParcel.writeInt(size);
125        mParcel.setDataSize(size - 1);
126        assertParseFail();
127    }
128
129    // Empty parcel is fine
130    @SmallTest
131    public void testEmptyIsOk() throws Exception {
132        adjustSize();
133        assertParse();
134    }
135
136    // RECORDS
137
138    // A record header should be at least 12 bytes long
139    @SmallTest
140    public void testRecordMissingId() throws Exception {
141        mParcel.writeInt(13); // record length
142        // misses metadata id and metadata type.
143        adjustSize();
144        assertParseFail();
145    }
146
147    @SmallTest
148    public void testRecordMissingType() throws Exception {
149        mParcel.writeInt(13); // record length lies
150        mParcel.writeInt(Metadata.TITLE);
151        // misses metadata type
152        adjustSize();
153        assertParseFail();
154    }
155
156    @SmallTest
157    public void testRecordWithZeroPayload() throws Exception {
158        mParcel.writeInt(0);
159        adjustSize();
160        assertParseFail();
161    }
162
163    // A record cannot be empty.
164    @SmallTest
165    public void testRecordMissingPayload() throws Exception {
166        mParcel.writeInt(12);
167        mParcel.writeInt(Metadata.TITLE);
168        mParcel.writeInt(Metadata.STRING_VAL);
169        // misses payload
170        adjustSize();
171        assertParseFail();
172    }
173
174    // Check records can be found.
175    @SmallTest
176    public void testRecordsFound() throws Exception {
177        writeStringRecord(Metadata.TITLE, "a title");
178        writeStringRecord(Metadata.GENRE, "comedy");
179        writeStringRecord(Metadata.firstCustomId(), "custom");
180        adjustSize();
181        assertParse();
182        assertTrue(mMetadata.has(Metadata.TITLE));
183        assertTrue(mMetadata.has(Metadata.GENRE));
184        assertTrue(mMetadata.has(Metadata.firstCustomId()));
185        assertFalse(mMetadata.has(Metadata.DRM_CRIPPLED));
186        assertEquals(3, mMetadata.keySet().size());
187    }
188
189    // Detects bad metadata type
190    @SmallTest
191    public void testBadMetadataType() throws Exception {
192        final int start = mParcel.dataPosition();
193        mParcel.writeInt(-1);  // Placeholder for the length
194        mParcel.writeInt(Metadata.TITLE);
195        mParcel.writeInt(0);  // Invalid type.
196        mParcel.writeString("dummy");
197        adjustSize(start);
198
199        adjustSize();
200        assertParseFail();
201    }
202
203    // Check a Metadata instance can be reused, i.e the parse method
204    // wipes out the existing states/keys.
205    @SmallTest
206    public void testParseClearState() throws Exception {
207        writeStringRecord(Metadata.TITLE, "a title");
208        writeStringRecord(Metadata.GENRE, "comedy");
209        writeStringRecord(Metadata.firstCustomId(), "custom");
210        adjustSize();
211        assertParse();
212
213        resetParcel();
214        writeStringRecord(Metadata.MIME_TYPE, "audio/mpg");
215        adjustSize();
216        assertParse();
217
218        // Only the mime type metadata should be present.
219        assertEquals(1, mMetadata.keySet().size());
220        assertTrue(mMetadata.has(Metadata.MIME_TYPE));
221
222        assertFalse(mMetadata.has(Metadata.TITLE));
223        assertFalse(mMetadata.has(Metadata.GENRE));
224        assertFalse(mMetadata.has(Metadata.firstCustomId()));
225    }
226}
227