From 8776dd4c8d7a24bb079662165dfcf71e70e307f7 Mon Sep 17 00:00:00 2001 From: Neelkamal Semwal Date: Tue, 26 Nov 2019 10:21:10 +0530 Subject: [PATCH] MediaTesting: Add ID3 Test Test: ID3Test -P /data/local/tmp/ID3/ Bug: 144753028 Change-Id: Ibec2d69d394bd00e127dd93d046ab5e52bfae906 --- media/libstagefright/id3/test/Android.bp | 48 ++++ media/libstagefright/id3/test/ID3Test.cpp | 217 ++++++++++++++++++ .../id3/test/ID3TestEnvironment.h | 73 ++++++ media/libstagefright/id3/test/README.md | 34 +++ 4 files changed, 372 insertions(+) create mode 100644 media/libstagefright/id3/test/Android.bp create mode 100644 media/libstagefright/id3/test/ID3Test.cpp create mode 100644 media/libstagefright/id3/test/ID3TestEnvironment.h create mode 100644 media/libstagefright/id3/test/README.md diff --git a/media/libstagefright/id3/test/Android.bp b/media/libstagefright/id3/test/Android.bp new file mode 100644 index 0000000000..9d26eecb68 --- /dev/null +++ b/media/libstagefright/id3/test/Android.bp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +cc_test { + name: "ID3Test", + gtest: true, + + srcs: ["ID3Test.cpp"], + + static_libs: [ + "libdatasource", + "libstagefright_id3", + "libstagefright", + "libstagefright_foundation", + ], + + shared_libs: [ + "libutils", + "liblog", + "libbinder", + ], + + cflags: [ + "-Werror", + "-Wall", + ], + + sanitize: { + cfi: true, + misc_undefined: [ + "unsigned-integer-overflow", + "signed-integer-overflow", + ], + }, +} diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/libstagefright/id3/test/ID3Test.cpp new file mode 100644 index 0000000000..a8f14706f6 --- /dev/null +++ b/media/libstagefright/id3/test/ID3Test.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ID3Test" +#include + +#include +#include +#include +#include + +#include +#include + +#include "ID3TestEnvironment.h" + +using namespace android; + +static ID3TestEnvironment *gEnv = nullptr; + +class ID3tagTest : public ::testing::TestWithParam {}; +class ID3versionTest : public ::testing::TestWithParam> {}; +class ID3textTagTest : public ::testing::TestWithParam> {}; +class ID3albumArtTest : public ::testing::TestWithParam> {}; +class ID3multiAlbumArtTest : public ::testing::TestWithParam> {}; + +TEST_P(ID3tagTest, TagTest) { + string path = gEnv->getRes() + GetParam(); + sp file = new FileSource(path.c_str()); + ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; + ID3 tag(file.get()); + ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; + + ID3::Iterator it(tag, nullptr); + while (!it.done()) { + String8 id; + it.getID(&id); + ASSERT_GT(id.length(), 0) << "No ID tag found! \n"; + ALOGV("Found ID tag: %s\n", String8(id).c_str()); + it.next(); + } +} + +TEST_P(ID3versionTest, VersionTest) { + int versionNumber = GetParam().second; + string path = gEnv->getRes() + GetParam().first; + sp file = new FileSource(path.c_str()); + ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; + + ID3 tag(file.get()); + ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; + ASSERT_TRUE(tag.version() >= versionNumber) + << "Expected version: " << tag.version() << " Found version: " << versionNumber; +} + +TEST_P(ID3textTagTest, TextTagTest) { + int numTextFrames = GetParam().second; + string path = gEnv->getRes() + GetParam().first; + sp file = new FileSource(path.c_str()); + ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; + + ID3 tag(file.get()); + ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; + int countTextFrames = 0; + ID3::Iterator it(tag, nullptr); + while (!it.done()) { + String8 id; + it.getID(&id); + ASSERT_GT(id.length(), 0); + if (id[0] == 'T') { + String8 text; + countTextFrames++; + it.getString(&text); + ALOGV("Found text frame %s : %s \n", id.string(), text.string()); + } + it.next(); + } + ASSERT_EQ(countTextFrames, numTextFrames) + << "Expected " << numTextFrames << " text frames, found " << countTextFrames; +} + +TEST_P(ID3albumArtTest, AlbumArtTest) { + bool albumArtPresent = GetParam().second; + string path = gEnv->getRes() + GetParam().first; + sp file = new FileSource(path.c_str()); + ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; + + ID3 tag(file.get()); + ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; + size_t dataSize; + String8 mime; + const void *data = tag.getAlbumArt(&dataSize, &mime); + + if (albumArtPresent) { + if (data) { + ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string()); + } + ASSERT_NE(data, nullptr) << "Expected album art, found none!" << path; + } else { + ASSERT_EQ(data, nullptr) << "Found album art when expected none!"; + } +#if (LOG_NDEBUG == 0) + hexdump(data, dataSize > 128 ? 128 : dataSize); +#endif +} + +TEST_P(ID3multiAlbumArtTest, MultiAlbumArtTest) { + int numAlbumArt = GetParam().second; + string path = gEnv->getRes() + GetParam().first; + sp file = new FileSource(path.c_str()); + ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n"; + + ID3 tag(file.get()); + ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n"; + int count = 0; + ID3::Iterator it(tag, nullptr); + while (!it.done()) { + String8 id; + it.getID(&id); + ASSERT_GT(id.length(), 0); + // Check if the tag is an "APIC/PIC" tag. + if (String8(id) == "APIC" || String8(id) == "PIC") { + count++; + size_t dataSize; + String8 mime; + const void *data = tag.getAlbumArt(&dataSize, &mime); + if (data) { + ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string()); +#if (LOG_NDEBUG == 0) + hexdump(data, dataSize > 128 ? 128 : dataSize); +#endif + } + ASSERT_NE(data, nullptr) << "Expected album art, found none!" << path; + } + it.next(); + } + ASSERT_EQ(count, numAlbumArt) << "Found " << count << " album arts, expected " << numAlbumArt + << " album arts! \n"; +} + +INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3tagTest, + ::testing::Values("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", + "bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", + "bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", + "bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", + "bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", + "bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", + "bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", + "bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3")); + +INSTANTIATE_TEST_SUITE_P( + id3TestAll, ID3versionTest, + ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 4), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3", 4))); + +INSTANTIATE_TEST_SUITE_P( + id3TestAll, ID3textTagTest, + ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3", 5))); + +INSTANTIATE_TEST_SUITE_P( + id3TestAll, ID3albumArtTest, + ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", false), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", true), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", true), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", false), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", true), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", true), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", true))); + +INSTANTIATE_TEST_SUITE_P( + id3TestAll, ID3multiAlbumArtTest, + ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 0), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 1), + make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 2), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 2), + make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 3))); + +int main(int argc, char **argv) { + gEnv = new ID3TestEnvironment(); + ::testing::AddGlobalTestEnvironment(gEnv); + ::testing::InitGoogleTest(&argc, argv); + int status = gEnv->initFromOptions(argc, argv); + if (status == 0) { + status = RUN_ALL_TESTS(); + ALOGI("ID3 Test result = %d\n", status); + } + return status; +} diff --git a/media/libstagefright/id3/test/ID3TestEnvironment.h b/media/libstagefright/id3/test/ID3TestEnvironment.h new file mode 100644 index 0000000000..2229718728 --- /dev/null +++ b/media/libstagefright/id3/test/ID3TestEnvironment.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ID3_TEST_ENVIRONMENT_H__ +#define __ID3_TEST_ENVIRONMENT_H__ + +#include + +#include + +using namespace std; + +class ID3TestEnvironment : public::testing::Environment { + public: + ID3TestEnvironment() : res("/data/local/tmp/") {} + + // Parses the command line arguments + int initFromOptions(int argc, char **argv); + + void setRes(const char *_res) { res = _res; } + + const string getRes() const { return res; } + + private: + string res; +}; + +int ID3TestEnvironment::initFromOptions(int argc, char **argv) { + static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}}; + + while (true) { + int index = 0; + int c = getopt_long(argc, argv, "P:", options, &index); + if (c == -1) { + break; + } + + switch (c) { + case 'P': { + setRes(optarg); + break; + } + default: + break; + } + } + + if (optind < argc) { + fprintf(stderr, + "unrecognized option: %s\n\n" + "usage: %s \n\n" + "test options are:\n\n" + "-P, --path: Resource files directory location\n", + argv[optind ?: 1], argv[0]); + return 2; + } + return 0; +} + +#endif // __ID3_TEST_ENVIRONMENT_H__ diff --git a/media/libstagefright/id3/test/README.md b/media/libstagefright/id3/test/README.md new file mode 100644 index 0000000000..72f730ce50 --- /dev/null +++ b/media/libstagefright/id3/test/README.md @@ -0,0 +1,34 @@ +## Media Testing ## +--- +#### ID3 Test : +The ID3 Test Suite validates the ID3 parser available in libstagefright. + +Run the following command in the id3 folder to build the test suite: +``` +m ID3Test +``` + +The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/ + +The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/ + +To test 64-bit binary push binaries from nativetest64. +``` +adb push ${OUT}/data/nativetest64/ID3Test/ID3Test /data/local/tmp/ +``` + +To test 32-bit binary push binaries from nativetest. +``` +adb push ${OUT}/data/nativetest/ID3Test/ID3Test /data/local/tmp/ +``` + +The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/1pt5HFVSysbqfyqY1sVJ9MTupZKCdqjYZ). Push these files into device for testing. +Download ID3 folder and push all the files in this folder to /data/local/tmp/ID3 on the device. +``` +adb push ID3/. /data/local/tmp/ID3 +``` + +usage: ID3Test -P \ +``` +adb shell /data/local/tmp/ID3Test -P /data/local/tmp/ID3/ +```