Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 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 | //#define LOG_NDEBUG 0 |
| 18 | #define LOG_TAG "ID3Test" |
| 19 | #include <utils/Log.h> |
| 20 | |
| 21 | #include <ctype.h> |
| 22 | #include <string> |
| 23 | #include <sys/stat.h> |
| 24 | #include <datasource/FileSource.h> |
| 25 | |
| 26 | #include <media/stagefright/foundation/hexdump.h> |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 27 | #include <media/MediaExtractorPluginHelper.h> |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 28 | #include <ID3.h> |
| 29 | |
| 30 | #include "ID3TestEnvironment.h" |
| 31 | |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 32 | |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 33 | using namespace android; |
| 34 | |
| 35 | static ID3TestEnvironment *gEnv = nullptr; |
| 36 | |
| 37 | class ID3tagTest : public ::testing::TestWithParam<string> {}; |
| 38 | class ID3versionTest : public ::testing::TestWithParam<pair<string, int>> {}; |
| 39 | class ID3textTagTest : public ::testing::TestWithParam<pair<string, int>> {}; |
| 40 | class ID3albumArtTest : public ::testing::TestWithParam<pair<string, bool>> {}; |
| 41 | class ID3multiAlbumArtTest : public ::testing::TestWithParam<pair<string, int>> {}; |
| 42 | |
| 43 | TEST_P(ID3tagTest, TagTest) { |
| 44 | string path = gEnv->getRes() + GetParam(); |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 45 | ALOGV(" ===== TagTest for %s", path.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 46 | sp<FileSource> file = new FileSource(path.c_str()); |
| 47 | ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 48 | DataSourceHelper helper(file->wrap()); |
| 49 | ID3 tag(&helper); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 50 | ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; |
| 51 | |
| 52 | ID3::Iterator it(tag, nullptr); |
| 53 | while (!it.done()) { |
| 54 | String8 id; |
| 55 | it.getID(&id); |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 56 | ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size"; |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 57 | ALOGV("Found ID tag: %s\n", String8(id).c_str()); |
| 58 | it.next(); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | TEST_P(ID3versionTest, VersionTest) { |
| 63 | int versionNumber = GetParam().second; |
| 64 | string path = gEnv->getRes() + GetParam().first; |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 65 | ALOGV(" ===== VersionTest for %s", path.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 66 | sp<android::FileSource> file = new FileSource(path.c_str()); |
| 67 | ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; |
| 68 | |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 69 | DataSourceHelper helper(file->wrap()); |
| 70 | ID3 tag(&helper); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 71 | ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 72 | ASSERT_EQ(tag.version(), versionNumber) |
Ray Essick | 0c89ab2 | 2020-04-25 13:00:09 -0700 | [diff] [blame] | 73 | << "Found version: " << tag.version() << " Expected version: " << versionNumber; |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | TEST_P(ID3textTagTest, TextTagTest) { |
| 77 | int numTextFrames = GetParam().second; |
| 78 | string path = gEnv->getRes() + GetParam().first; |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 79 | ALOGV(" ===== TextTagTest for %s", path.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 80 | sp<android::FileSource> file = new FileSource(path.c_str()); |
| 81 | ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; |
| 82 | |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 83 | DataSourceHelper helper(file->wrap()); |
| 84 | ID3 tag(&helper); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 85 | ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; |
| 86 | int countTextFrames = 0; |
| 87 | ID3::Iterator it(tag, nullptr); |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 88 | if (tag.version() != ID3::ID3_V1 && tag.version() != ID3::ID3_V1_1) { |
| 89 | while (!it.done()) { |
| 90 | String8 id; |
| 91 | it.getID(&id); |
| 92 | ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size"; |
| 93 | if (id[0] == 'T') { |
| 94 | String8 text; |
| 95 | countTextFrames++; |
| 96 | it.getString(&text); |
Tomasz Wasilczyk | 03fc55f | 2023-08-11 17:05:05 +0000 | [diff] [blame] | 97 | ALOGV("Found text frame %s : %s \n", id.c_str(), text.c_str()); |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 98 | } |
| 99 | it.next(); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 100 | } |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 101 | } else { |
| 102 | while (!it.done()) { |
| 103 | String8 id; |
| 104 | String8 text; |
| 105 | it.getID(&id); |
| 106 | ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size"; |
| 107 | it.getString(&text); |
| 108 | // if the tag has a value |
Tomasz Wasilczyk | 03fc55f | 2023-08-11 17:05:05 +0000 | [diff] [blame] | 109 | if (strcmp(text.c_str(), "")) { |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 110 | countTextFrames++; |
| 111 | ALOGV("ID: %s\n", id.c_str()); |
Tomasz Wasilczyk | 03fc55f | 2023-08-11 17:05:05 +0000 | [diff] [blame] | 112 | ALOGV("Text string: %s\n", text.c_str()); |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 113 | } |
| 114 | it.next(); |
| 115 | } |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 116 | } |
| 117 | ASSERT_EQ(countTextFrames, numTextFrames) |
| 118 | << "Expected " << numTextFrames << " text frames, found " << countTextFrames; |
| 119 | } |
| 120 | |
| 121 | TEST_P(ID3albumArtTest, AlbumArtTest) { |
| 122 | bool albumArtPresent = GetParam().second; |
| 123 | string path = gEnv->getRes() + GetParam().first; |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 124 | ALOGV(" ===== AlbumArt for %s", path.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 125 | sp<android::FileSource> file = new FileSource(path.c_str()); |
| 126 | ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; |
| 127 | |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 128 | DataSourceHelper helper(file->wrap()); |
| 129 | ID3 tag(&helper); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 130 | ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; |
| 131 | size_t dataSize; |
| 132 | String8 mime; |
| 133 | const void *data = tag.getAlbumArt(&dataSize, &mime); |
| 134 | |
| 135 | if (albumArtPresent) { |
| 136 | if (data) { |
Tomasz Wasilczyk | 03fc55f | 2023-08-11 17:05:05 +0000 | [diff] [blame] | 137 | ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 138 | } |
Ray Essick | 0c89ab2 | 2020-04-25 13:00:09 -0700 | [diff] [blame] | 139 | ASSERT_NE(data, nullptr) << "Expected album art, found none! " << path; |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 140 | } else { |
| 141 | ASSERT_EQ(data, nullptr) << "Found album art when expected none!"; |
| 142 | } |
Ray Essick | 6fd7409 | 2021-04-25 15:06:21 -0700 | [diff] [blame] | 143 | |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 144 | #if (LOG_NDEBUG == 0) |
| 145 | hexdump(data, dataSize > 128 ? 128 : dataSize); |
| 146 | #endif |
| 147 | } |
| 148 | |
| 149 | TEST_P(ID3multiAlbumArtTest, MultiAlbumArtTest) { |
| 150 | int numAlbumArt = GetParam().second; |
| 151 | string path = gEnv->getRes() + GetParam().first; |
| 152 | sp<android::FileSource> file = new FileSource(path.c_str()); |
| 153 | ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; |
| 154 | |
Harish Mahendrakar | d1056c2 | 2020-05-01 12:28:33 -0700 | [diff] [blame] | 155 | DataSourceHelper helper(file->wrap()); |
| 156 | ID3 tag(&helper); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 157 | ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; |
| 158 | int count = 0; |
| 159 | ID3::Iterator it(tag, nullptr); |
| 160 | while (!it.done()) { |
| 161 | String8 id; |
| 162 | it.getID(&id); |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 163 | ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size"; |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 164 | // Check if the tag is an "APIC/PIC" tag. |
| 165 | if (String8(id) == "APIC" || String8(id) == "PIC") { |
| 166 | count++; |
| 167 | size_t dataSize; |
| 168 | String8 mime; |
| 169 | const void *data = tag.getAlbumArt(&dataSize, &mime); |
| 170 | if (data) { |
Tomasz Wasilczyk | 03fc55f | 2023-08-11 17:05:05 +0000 | [diff] [blame] | 171 | ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str()); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 172 | #if (LOG_NDEBUG == 0) |
| 173 | hexdump(data, dataSize > 128 ? 128 : dataSize); |
| 174 | #endif |
| 175 | } |
Ray Essick | 0c89ab2 | 2020-04-25 13:00:09 -0700 | [diff] [blame] | 176 | ASSERT_NE(data, nullptr) << "Expected album art, found none! " << path; |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 177 | } |
| 178 | it.next(); |
| 179 | } |
| 180 | ASSERT_EQ(count, numAlbumArt) << "Found " << count << " album arts, expected " << numAlbumArt |
| 181 | << " album arts! \n"; |
| 182 | } |
| 183 | |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 184 | // we have a test asset with large album art -- which is larger than our 3M cap |
| 185 | // that we inserted intentionally in the ID3 parsing routine. |
| 186 | // Rather than have it fail all the time, we have wrapped it under an #ifdef |
| 187 | // so that the tests will pass. |
| 188 | #undef TEST_LARGE |
| 189 | |
| 190 | |
| 191 | // it appears that bbb_2sec_v24_unsynchronizedAllFrames.mp3 is not a legal file, |
| 192 | // so we've commented it out of the list of files to be tested |
| 193 | // |
| 194 | |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 195 | INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3tagTest, |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 196 | ::testing::Values("bbb_1sec_v23.mp3", |
| 197 | "bbb_1sec_1_image.mp3", |
| 198 | "bbb_1sec_2_image.mp3", |
| 199 | "bbb_2sec_v24.mp3", |
| 200 | "bbb_2sec_1_image.mp3", |
| 201 | "bbb_2sec_2_image.mp3", |
| 202 | "bbb_2sec_largeSize.mp3", |
| 203 | "bbb_1sec_v23_3tags.mp3", |
| 204 | "bbb_1sec_v1_5tags.mp3", |
| 205 | "bbb_2sec_v24_unsynchronizedOneFrame.mp3", |
Ray Essick | 6fd7409 | 2021-04-25 15:06:21 -0700 | [diff] [blame] | 206 | "idv24_unsynchronized.mp3")); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 207 | |
| 208 | INSTANTIATE_TEST_SUITE_P( |
| 209 | id3TestAll, ID3versionTest, |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 210 | ::testing::Values(make_pair("bbb_1sec_v23.mp3", ID3::ID3_V2_3), |
| 211 | make_pair("bbb_1sec_1_image.mp3", ID3::ID3_V2_3), |
| 212 | make_pair("bbb_1sec_2_image.mp3", ID3::ID3_V2_3), |
| 213 | make_pair("bbb_2sec_v24.mp3", ID3::ID3_V2_4), |
| 214 | make_pair("bbb_2sec_1_image.mp3", ID3::ID3_V2_4), |
| 215 | make_pair("bbb_2sec_2_image.mp3", ID3::ID3_V2_4), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 216 | #if TEST_LARGE |
| 217 | make_pair("bbb_2sec_largeSize.mp3", ID3::ID3_V2_4), // FAIL |
| 218 | #endif |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 219 | make_pair("bbb_1sec_v23_3tags.mp3", ID3::ID3_V2_3), |
| 220 | make_pair("bbb_1sec_v1_5tags.mp3", ID3::ID3_V1_1), |
| 221 | make_pair("bbb_1sec_v1_3tags.mp3", ID3::ID3_V1_1), |
| 222 | make_pair("bbb_2sec_v24_unsynchronizedOneFrame.mp3", ID3::ID3_V2_4), |
Ray Essick | 6fd7409 | 2021-04-25 15:06:21 -0700 | [diff] [blame] | 223 | make_pair("idv24_unsynchronized.mp3", ID3::ID3_V2_4))); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 224 | |
| 225 | INSTANTIATE_TEST_SUITE_P( |
| 226 | id3TestAll, ID3textTagTest, |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 227 | ::testing::Values( |
| 228 | make_pair("bbb_1sec_v23.mp3", 1), |
| 229 | make_pair("bbb_1sec_1_image.mp3", 1), |
| 230 | make_pair("bbb_1sec_2_image.mp3", 1), |
| 231 | make_pair("bbb_2sec_v24.mp3", 1), |
| 232 | make_pair("bbb_2sec_1_image.mp3", 1), |
| 233 | make_pair("bbb_2sec_2_image.mp3", 1), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 234 | #if TEST_LARGE |
| 235 | make_pair("bbb_2sec_largeSize.mp3", 1), // FAIL |
| 236 | #endif |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 237 | make_pair("bbb_1sec_v23_3tags.mp3", 3), |
| 238 | make_pair("bbb_1sec_v1_5tags.mp3", 5), |
| 239 | make_pair("bbb_1sec_v1_3tags.mp3", 3), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 240 | make_pair("bbb_2sec_v24_unsynchronizedOneFrame.mp3", 3) |
| 241 | )); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 242 | |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 243 | INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3albumArtTest, |
| 244 | ::testing::Values(make_pair("bbb_1sec_v23.mp3", false), |
| 245 | make_pair("bbb_1sec_1_image.mp3", true), |
| 246 | make_pair("bbb_1sec_2_image.mp3", true), |
| 247 | make_pair("bbb_2sec_v24.mp3", false), |
| 248 | make_pair("bbb_2sec_1_image.mp3", true), |
| 249 | make_pair("bbb_2sec_2_image.mp3", true), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 250 | #if TEST_LARGE |
| 251 | make_pair("bbb_2sec_largeSize.mp3", true), // FAIL |
| 252 | #endif |
Ray Essick | 6fd7409 | 2021-04-25 15:06:21 -0700 | [diff] [blame] | 253 | make_pair("bbb_1sec_v1_5tags.mp3", false), |
| 254 | make_pair("idv24_unsynchronized.mp3", true) |
| 255 | )); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 256 | |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 257 | INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3multiAlbumArtTest, |
| 258 | ::testing::Values(make_pair("bbb_1sec_v23.mp3", 0), |
| 259 | make_pair("bbb_2sec_v24.mp3", 0), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 260 | #if TEST_LARGE |
| 261 | make_pair("bbb_2sec_largeSize.mp3", 3), // FAIL |
| 262 | #endif |
Neelkamal Semwal | e821a50 | 2020-04-08 14:28:53 +0530 | [diff] [blame] | 263 | make_pair("bbb_1sec_1_image.mp3", 1), |
| 264 | make_pair("bbb_2sec_1_image.mp3", 1), |
| 265 | make_pair("bbb_1sec_2_image.mp3", 2), |
Ray Essick | 6626fd2 | 2021-04-28 19:08:44 -0700 | [diff] [blame] | 266 | make_pair("bbb_2sec_2_image.mp3", 2) |
| 267 | )); |
Neelkamal Semwal | 8776dd4 | 2019-11-26 10:21:10 +0530 | [diff] [blame] | 268 | |
| 269 | int main(int argc, char **argv) { |
| 270 | gEnv = new ID3TestEnvironment(); |
| 271 | ::testing::AddGlobalTestEnvironment(gEnv); |
| 272 | ::testing::InitGoogleTest(&argc, argv); |
| 273 | int status = gEnv->initFromOptions(argc, argv); |
| 274 | if (status == 0) { |
| 275 | status = RUN_ALL_TESTS(); |
| 276 | ALOGI("ID3 Test result = %d\n", status); |
| 277 | } |
| 278 | return status; |
| 279 | } |