summaryrefslogtreecommitdiff
path: root/tools/hiddenapi/hiddenapi_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/hiddenapi/hiddenapi_test.cc')
-rw-r--r--tools/hiddenapi/hiddenapi_test.cc600
1 files changed, 600 insertions, 0 deletions
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
new file mode 100644
index 0000000000..1f37f40f6e
--- /dev/null
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <fstream>
+
+#include "base/unix_file/fd_file.h"
+#include "common_runtime_test.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file-inl.h"
+#include "exec_utils.h"
+#include "zip_archive.h"
+
+namespace art {
+
+class HiddenApiTest : public CommonRuntimeTest {
+ protected:
+ std::string GetHiddenApiCmd() {
+ std::string file_path = GetTestAndroidRoot();
+ file_path += "/bin/hiddenapi";
+ if (kIsDebugBuild) {
+ file_path += "d";
+ }
+ if (!OS::FileExists(file_path.c_str())) {
+ LOG(FATAL) << "Could not find binary " << file_path;
+ UNREACHABLE();
+ }
+ return file_path;
+ }
+
+ std::unique_ptr<const DexFile> RunHiddenApi(const ScratchFile& light_greylist,
+ const ScratchFile& dark_greylist,
+ const ScratchFile& blacklist,
+ const std::vector<std::string>& extra_args,
+ ScratchFile* out_dex) {
+ std::string error;
+ ZipArchive* jar = ZipArchive::Open(GetTestDexFileName("HiddenApi").c_str(), &error);
+ if (jar == nullptr) {
+ LOG(FATAL) << "Could not open test file " << GetTestDexFileName("HiddenApi") << ": " << error;
+ UNREACHABLE();
+ }
+ ZipEntry* jar_classes_dex = jar->Find("classes.dex", &error);
+ if (jar_classes_dex == nullptr) {
+ LOG(FATAL) << "Could not find classes.dex in test file " << GetTestDexFileName("HiddenApi")
+ << ": " << error;
+ UNREACHABLE();
+ } else if (!jar_classes_dex->ExtractToFile(*out_dex->GetFile(), &error)) {
+ LOG(FATAL) << "Could not extract classes.dex from test file "
+ << GetTestDexFileName("HiddenApi") << ": " << error;
+ UNREACHABLE();
+ }
+
+ std::vector<std::string> argv_str;
+ argv_str.push_back(GetHiddenApiCmd());
+ argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
+ argv_str.push_back("--dex=" + out_dex->GetFilename());
+ argv_str.push_back("--light-greylist=" + light_greylist.GetFilename());
+ argv_str.push_back("--dark-greylist=" + dark_greylist.GetFilename());
+ argv_str.push_back("--blacklist=" + blacklist.GetFilename());
+ int return_code = ExecAndReturnCode(argv_str, &error);
+ if (return_code != 0) {
+ LOG(FATAL) << "HiddenApi binary exited with unexpected return code " << return_code;
+ }
+ return OpenDex(*out_dex);
+ }
+
+ std::unique_ptr<const DexFile> OpenDex(const ScratchFile& file) {
+ ArtDexFileLoader dex_loader;
+ std::string error_msg;
+
+ File fd(file.GetFilename(), O_RDONLY, /* check_usage */ false);
+ if (fd.Fd() == -1) {
+ LOG(FATAL) << "Unable to open file '" << file.GetFilename() << "': " << strerror(errno);
+ UNREACHABLE();
+ }
+
+ std::unique_ptr<const DexFile> dex_file(dex_loader.OpenDex(
+ fd.Release(), /* location */ file.GetFilename(), /* verify */ false,
+ /* verify_checksum */ true, /* mmap_shared */ false, &error_msg));
+ if (dex_file.get() == nullptr) {
+ LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << error_msg;
+ UNREACHABLE();
+ } else if (!dex_file->IsStandardDexFile()) {
+ LOG(FATAL) << "Expected a standard dex file '" << file.GetFilename() << "'";
+ UNREACHABLE();
+ }
+
+ return dex_file;
+ }
+
+ std::ofstream OpenStream(const ScratchFile& file) {
+ std::ofstream ofs(file.GetFilename(), std::ofstream::out);
+ if (ofs.fail()) {
+ LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << strerror(errno);
+ UNREACHABLE();
+ }
+ return ofs;
+ }
+
+ const DexFile::ClassDef& FindClass(const char* desc, const DexFile& dex_file) {
+ for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
+ const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
+ if (strcmp(desc, dex_file.GetClassDescriptor(class_def)) == 0) {
+ return class_def;
+ }
+ }
+ LOG(FATAL) << "Could not find class " << desc;
+ UNREACHABLE();
+ }
+
+ DexHiddenAccessFlags::ApiList GetFieldHiddenFlags(const char* name,
+ uint32_t expected_visibility,
+ const DexFile::ClassDef& class_def,
+ const DexFile& dex_file) {
+ const uint8_t* class_data = dex_file.GetClassData(class_def);
+ if (class_data == nullptr) {
+ LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data";
+ UNREACHABLE();
+ }
+
+ for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) {
+ if (it.IsAtMethod()) {
+ break;
+ }
+ const DexFile::FieldId& fid = dex_file.GetFieldId(it.GetMemberIndex());
+ if (strcmp(name, dex_file.GetFieldName(fid)) == 0) {
+ uint32_t actual_visibility = it.GetFieldAccessFlags() & kAccVisibilityFlags;
+ if (actual_visibility != expected_visibility) {
+ LOG(FATAL) << "Field " << name << " in class " << dex_file.GetClassDescriptor(class_def)
+ << " does not have the expected visibility flags (" << expected_visibility
+ << " != " << actual_visibility << ")";
+ UNREACHABLE();
+ }
+ return it.DecodeHiddenAccessFlags();
+ }
+ }
+
+ LOG(FATAL) << "Could not find field " << name << " in class "
+ << dex_file.GetClassDescriptor(class_def);
+ UNREACHABLE();
+ }
+
+ DexHiddenAccessFlags::ApiList GetMethodHiddenFlags(const char* name,
+ uint32_t expected_visibility,
+ bool expected_native,
+ const DexFile::ClassDef& class_def,
+ const DexFile& dex_file) {
+ const uint8_t* class_data = dex_file.GetClassData(class_def);
+ if (class_data == nullptr) {
+ LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data";
+ UNREACHABLE();
+ }
+
+ for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) {
+ if (!it.IsAtMethod()) {
+ continue;
+ }
+ const DexFile::MethodId& mid = dex_file.GetMethodId(it.GetMemberIndex());
+ if (strcmp(name, dex_file.GetMethodName(mid)) == 0) {
+ if (expected_native != it.MemberIsNative()) {
+ LOG(FATAL) << "Expected native=" << expected_native << " for method " << name
+ << " in class " << dex_file.GetClassDescriptor(class_def);
+ UNREACHABLE();
+ }
+ uint32_t actual_visibility = it.GetMethodAccessFlags() & kAccVisibilityFlags;
+ if (actual_visibility != expected_visibility) {
+ LOG(FATAL) << "Method " << name << " in class " << dex_file.GetClassDescriptor(class_def)
+ << " does not have the expected visibility flags (" << expected_visibility
+ << " != " << actual_visibility << ")";
+ UNREACHABLE();
+ }
+ return it.DecodeHiddenAccessFlags();
+ }
+ }
+
+ LOG(FATAL) << "Could not find method " << name << " in class "
+ << dex_file.GetClassDescriptor(class_def);
+ UNREACHABLE();
+ }
+
+ DexHiddenAccessFlags::ApiList GetIFieldHiddenFlags(const DexFile& dex_file) {
+ return GetFieldHiddenFlags("ifield", kAccPublic, FindClass("LMain;", dex_file), dex_file);
+ }
+
+ DexHiddenAccessFlags::ApiList GetSFieldHiddenFlags(const DexFile& dex_file) {
+ return GetFieldHiddenFlags("sfield", kAccPrivate, FindClass("LMain;", dex_file), dex_file);
+ }
+
+ DexHiddenAccessFlags::ApiList GetIMethodHiddenFlags(const DexFile& dex_file) {
+ return GetMethodHiddenFlags(
+ "imethod", 0, /* native */ false, FindClass("LMain;", dex_file), dex_file);
+ }
+
+ DexHiddenAccessFlags::ApiList GetSMethodHiddenFlags(const DexFile& dex_file) {
+ return GetMethodHiddenFlags(
+ "smethod", kAccPublic, /* native */ false, FindClass("LMain;", dex_file), dex_file);
+ }
+
+ DexHiddenAccessFlags::ApiList GetINMethodHiddenFlags(const DexFile& dex_file) {
+ return GetMethodHiddenFlags(
+ "inmethod", kAccPublic, /* native */ true, FindClass("LMain;", dex_file), dex_file);
+ }
+
+ DexHiddenAccessFlags::ApiList GetSNMethodHiddenFlags(const DexFile& dex_file) {
+ return GetMethodHiddenFlags(
+ "snmethod", kAccProtected, /* native */ true, FindClass("LMain;", dex_file), dex_file);
+ }
+};
+
+TEST_F(HiddenApiTest, InstanceFieldNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
+ OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetIFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:LBadType1;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticFieldTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
+ OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSFieldHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetIMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticMethodTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetINMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodNoMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kWhitelist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodLightGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kLightGreylist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodDarkGreylistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodBlacklistMatch) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch1) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(LBadType1;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch2) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) {
+ ScratchFile dex, light_greylist, dark_greylist, blacklist;
+ OpenStream(light_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
+ OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
+ auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_EQ(DexHiddenAccessFlags::kDarkGreylist, GetSNMethodHiddenFlags(*dex_file));
+}
+
+} // namespace art