Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/tools/hiddenapi/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 32 kB image not shown  

Quelle  hiddenapi_test.cc

  Sprache: C
 

/*
 * 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 "android-base/strings.h"

#include "base/unix_file/fd_file.h"
#include "base/zip_archive.h"
#include "common_runtime_test.h"
#include "dex/art_dex_file_loader.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "exec_utils.h"

namespace art {

class HiddenApiTest : public CommonRuntimeTest {
 protected:
  std::string GetHiddenApiCmd() {
    std::string file_path = GetArtBinDir() + "/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> RunHiddenapiEncode(const ScratchFile& flags_csv,
                                                    const std::vector<std::string>& extra_args,
                                                    const ScratchFile& out_dex) {
    std::string error;
    ScratchFile in_dex;
    std::unique_ptr<ZipArchive> jar(
        ZipArchive::Open(GetTestDexFileName("HiddenApi").c_str(), &error));
    if (jar == nullptr) {
      LOG(FATAL) << "Could not open test file " << GetTestDexFileName("HiddenApi") << ": " << error;
      UNREACHABLE();
    }
    std::unique_ptr<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(*in_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.push_back("encode");
    argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
    argv_str.push_back("--input-dex=" + in_dex.GetFilename());
    argv_str.push_back("--output-dex=" + out_dex.GetFilename());
    argv_str.push_back("--api-flags=" + flags_csv.GetFilename());
    argv_str.push_back("--no-force-assign-all");
    int return_code = ExecAndReturnCode(argv_str, &error);
    if (return_code == 0) {
      return OpenDex(out_dex);
    } else {
      LOG(ERROR) << "HiddenApi binary exited with unexpected return code " << return_code;
      return nullptr;
    }
  }

  bool RunHiddenapiList(const ScratchFile& out_flags_csv) {
    std::string error;
    std::string boot_jar = GetTestDexFileName("HiddenApi");
    std::string stub_jar = GetTestDexFileName("HiddenApiStubs");
    std::string boot_cp = android::base::Join(GetLibCoreDexFileNames(), ":");

    std::vector<std::string> argv_str;
    argv_str.push_back(GetHiddenApiCmd());
    argv_str.push_back("list");
    for (const std::string& core_jar : GetLibCoreDexFileNames()) {
      argv_str.push_back("--boot-dex=" + core_jar);
    }
    argv_str.push_back("--boot-dex=" + boot_jar);
    argv_str.push_back("--public-stub-classpath=" + boot_cp + ":" + stub_jar);
    argv_str.push_back("--out-api-flags=" + out_flags_csv.GetFilename());
    int return_code = ExecAndReturnCode(argv_str, &error);
    if (return_code == 0) {
      return true;
    } else {
      LOG(ERROR) << "HiddenApi binary exited with unexpected return code " << return_code;
      return false;
    }
  }

  std::unique_ptr<const DexFile> OpenDex(const ScratchFile& file) {
    std::string error_msg;

    File fd(file.GetFilename(), O_RDONLY, /* check_usage= */ false);
    if (fd.Fd() == -1) {
      PLOG(FATAL) << "Unable to open file '" << file.GetFilename() << "'";
      UNREACHABLE();
    }

    ArtDexFileLoader dex_loader(&fd, file.GetFilename());
    std::unique_ptr<const DexFile> dex_file(dex_loader.Open(
        /*location_checksum=*/0,
        /*verify=*/true,
        /*verify_checksum=*/true,
        &error_msg));
    if (dex_file.get() == nullptr) {
      LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << error_msg;
      UNREACHABLE();
    }

    return dex_file;
  }

  std::ofstream OpenStream(const ScratchFile& file) {
    std::ofstream ofs(file.GetFilename(), std::ofstream::out);
    if (ofs.fail()) {
      PLOG(FATAL) << "Open failed for '" << file.GetFilename() << "'";
      UNREACHABLE();
    }
    return ofs;
  }

  std::map<std::string, std::string> ReadFlagsCsvFile(const ScratchFile& file) {
    std::ifstream ifs(file.GetFilename());
    std::map<std::string, std::string> flags;

    for (std::string line; std::getline(ifs, line);) {
      std::size_t comma = line.find(',');
      if (comma == std::string::npos) {
        flags.emplace(line, "");
      } else {
        flags.emplace(line.substr(0, comma), line.substr(comma + 1));
      }
    }

    return flags;
  }

  std::string SafeMapGet(const std::string& key, const std::map<std::string, std::string>& map) {
    auto it = map.find(key);
    if (it == map.end()) {
      LOG(FATAL) << "Key not found: " << key;
      UNREACHABLE();
    }
    return it->second;
  }

  const dex::ClassDef& FindClass(const char* desc, const DexFile& dex_file) {
    const dex::TypeId* type_id = dex_file.FindTypeId(desc);
    CHECK(type_id != nullptr) << "Could not find class " << desc;
    const dex::ClassDef* found = dex_file.FindClassDef(dex_file.GetIndexForTypeId(*type_id));
    CHECK(found != nullptr) << "Could not find class " << desc;
    return *found;
  }

  hiddenapi::ApiList GetFieldHiddenFlags(const char* name,
                                         uint32_t expected_visibility,
                                         const dex::ClassDef& class_def,
                                         const DexFile& dex_file) {
    ClassAccessor accessor(dex_file, class_def, /* parse hiddenapi flags */ true);
    CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptorView() << " has no data";

    if (!accessor.HasHiddenapiClassData()) {
      return hiddenapi::ApiList::Sdk();
    }

    for (const ClassAccessor::Field& field : accessor.GetFields()) {
      const dex::FieldId& fid = dex_file.GetFieldId(field.GetIndex());
      if (strcmp(name, dex_file.GetFieldName(fid)) == 0) {
        const uint32_t actual_visibility = field.GetAccessFlags() & kAccVisibilityFlags;
        CHECK_EQ(actual_visibility, expected_visibility)
            << "Field " << name << " in class " << accessor.GetDescriptorView();
        return hiddenapi::ApiList::FromDexFlags(field.GetHiddenapiFlags());
      }
    }

    LOG(FATAL) << "Could not find field " << name << " in class "
               << dex_file.GetClassDescriptor(class_def);
    UNREACHABLE();
  }

  hiddenapi::ApiList GetMethodHiddenFlags(const char* name,
                                          uint32_t expected_visibility,
                                          bool expected_native,
                                          const dex::ClassDef& class_def,
                                          const DexFile& dex_file) {
    ClassAccessor accessor(dex_file, class_def, /* parse hiddenapi flags */ true);
    CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptorView() << " has no data";

    if (!accessor.HasHiddenapiClassData()) {
      return hiddenapi::ApiList::Sdk();
    }

    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
      const dex::MethodId& mid = dex_file.GetMethodId(method.GetIndex());
      if (strcmp(name, dex_file.GetMethodName(mid)) == 0) {
        CHECK_EQ(expected_native, method.MemberIsNative())
            << "Method " << name << " in class " << accessor.GetDescriptorView();
        const uint32_t actual_visibility = method.GetAccessFlags() & kAccVisibilityFlags;
        CHECK_EQ(actual_visibility, expected_visibility)
            << "Method " << name << " in class " << accessor.GetDescriptorView();
        return hiddenapi::ApiList::FromDexFlags(method.GetHiddenapiFlags());
      }
    }

    LOG(FATAL) << "Could not find method " << name << " in class "
               << dex_file.GetClassDescriptor(class_def);
    UNREACHABLE();
  }

  hiddenapi::ApiList GetIFieldHiddenFlags(const DexFile& dex_file) {
    return GetFieldHiddenFlags("ifield", kAccPublic, FindClass("LMain;", dex_file), dex_file);
  }

  hiddenapi::ApiList GetSFieldHiddenFlags(const DexFile& dex_file) {
    return GetFieldHiddenFlags("sfield", kAccPrivate, FindClass("LMain;", dex_file), dex_file);
  }

  hiddenapi::ApiList GetIMethodHiddenFlags(const DexFile& dex_file) {
    return GetMethodHiddenFlags(
        "imethod"0/* expected_native= */ false, FindClass("LMain;", dex_file), dex_file);
  }

  hiddenapi::ApiList GetSMethodHiddenFlags(const DexFile& dex_file) {
    return GetMethodHiddenFlags("smethod",
                                kAccPublic,
                                /* expected_native= */ false,
                                FindClass("LMain;", dex_file),
                                dex_file);
  }

  hiddenapi::ApiList GetINMethodHiddenFlags(const DexFile& dex_file) {
    return GetMethodHiddenFlags("inmethod",
                                kAccPublic,
                                /* expected_native= */ true,
                                FindClass("LMain;", dex_file),
                                dex_file);
  }

  hiddenapi::ApiList GetSNMethodHiddenFlags(const DexFile& dex_file) {
    return GetMethodHiddenFlags("snmethod",
                                kAccProtected,
                                /* expected_native= */ true,
                                FindClass("LMain;", dex_file),
                                dex_file);
  }
};

TEST_F(HiddenApiTest, InstanceFieldNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:I,max-target-o" << std::endl
      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:I,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:I,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:I,blocked,unsupported" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,unsupported,max-target-o" << std::endl
      << "LMain;->ifield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticFieldNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticFieldLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:Ljava/lang/Object;,unsupported" << std::endl
      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticFieldDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
      << "LMain;->sfield:Ljava/lang/Object;,max-target-o" << std::endl
      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticFieldblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
      << "LMain;->sfield:Ljava/lang/Object;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticFieldTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:LBadType1;,unsupported" << std::endl
      << "LMain;->sfield:Ljava/lang/Object;,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticFieldTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:LBadType2;,max-target-o" << std::endl
      << "LMain;->sfield:Ljava/lang/Object;,blocked,unsupported" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticFieldTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->sfield:Ljava/lang/Object;,unsupported,max-target-o" << std::endl
      << "LMain;->sfield:LBadType3;,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceMethodNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceMethodLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(J)V,unsupported" << std::endl
      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceMethodDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->imethod(J)V,max-target-o" << std::endl
      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetIMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceMethodblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->imethod(J)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->imethod(J)V,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->imethod(J)V,blocked,unsupported" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->imethod(J)V,unsupported,max-target-o" << std::endl
      << "LMain;->imethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticMethodNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticMethodLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(Ljava/lang/Object;)V,unsupported" << std::endl
      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticMethodDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->smethod(Ljava/lang/Object;)V,max-target-o" << std::endl
      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticMethodblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->smethod(Ljava/lang/Object;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticMethodTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->smethod(Ljava/lang/Object;)V,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticMethodTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->smethod(Ljava/lang/Object;)V,blocked,unsupported" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticMethodTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->smethod(Ljava/lang/Object;)V,unsupported,max-target-o" << std::endl
      << "LMain;->smethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceNativeMethodNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetINMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceNativeMethodLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(C)V,unsupported" << std::endl
      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetINMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceNativeMethodDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->inmethod(C)V,max-target-o" << std::endl
      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetINMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceNativeMethodblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->inmethod(C)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetINMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->inmethod(C)V,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(C)V,blocked,unsupported" << std::endl
      << "LMain;->inmethod(LBadType2;)V,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->inmethod(C)V,unsupported,max-target-o" << std::endl
      << "LMain;->inmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticNativeMethodNoMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetSNMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticNativeMethodLightunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(Ljava/lang/Integer;)V,unsupported" << std::endl
      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetSNMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticNativeMethodDarkunsupportedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->snmethod(Ljava/lang/Integer;)V,max-target-o" << std::endl
      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetO(), GetSNMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticNativeMethodblockedMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl
      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetSNMethodHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch1) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(LBadType1;)V,unsupported" << std::endl
      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch2) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(Ljava/lang/Integer;)V,blocked,unsupported" << std::endl
      << "LMain;->snmethod(LBadType2;)V,max-target-o" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->snmethod(Ljava/lang/Integer;)V,unsupported,max-target-o" << std::endl
      << "LMain;->snmethod(LBadType3;)V,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceFieldCorePlatformApiMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:I,unsupported,core-platform-api" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Combine(hiddenapi::ApiList::CorePlatformApi(),
                                        hiddenapi::ApiList::Unsupported()),
            GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldTestApiMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:I,unsupported,test-api" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(
      hiddenapi::ApiList::Combine(hiddenapi::ApiList::TestApi(), hiddenapi::ApiList::Unsupported()),
      GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldUnknownFlagMatch) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:LBadType1;,unsupported" << std::endl
      << "LMain;->ifield:LBadType2;,max-target-o" << std::endl
      << "LMain;->ifield:I,unsupported,unknown-flag" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceFieldMaxSdkHigherThanMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,max-target-r" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-q"}, dex);
  ASSERT_EQ(dex_file.get(), nullptr);
}

TEST_F(HiddenApiTest, InstanceFieldMaxSdkEqualsMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,max-target-r" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetR(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldMaxSdkLowerThanMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,max-target-q" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::MaxTargetQ(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldBlockedUnchangedByMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,blocked" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Blocked(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldUnsupportedUnchangedByMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,unsupported" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Unsupported(), GetIFieldHiddenFlags(*dex_file));
}

TEST_F(HiddenApiTest, InstanceFieldSdkUnchangedByMaxHiddenApiLevel) {
  ScratchFile dex, flags_csv;
  OpenStream(flags_csv)
      << "LMain;->ifield:I,sdk" << std::endl;
  auto dex_file = RunHiddenapiEncode(flags_csv, {"--max-hiddenapi-level=max-target-r"}, dex);
  ASSERT_NE(dex_file.get(), nullptr);
  ASSERT_EQ(hiddenapi::ApiList::Sdk(), GetIFieldHiddenFlags(*dex_file));
}

// The following tests use this class hierarchy:
//
//    AbstractPackageClass  PublicInterface
//           |                     |
//           |    ┌----------------┘
//           |    |
//        PackageClass
//
// Only PublicInterface is in stubs.

// Test a method declared in PublicInterface and defined in PackageClass.
TEST_F(HiddenApiTest, InterfaceMethodImplemented) {
  ScratchFile flags_csv;
  ASSERT_TRUE(RunHiddenapiList(flags_csv));
  auto flags = ReadFlagsCsvFile(flags_csv);
  ASSERT_EQ(SafeMapGet("LPackageClass;->publicMethod1()V", flags), "public-api");
}

// Test a method declared in PublicInterface, defined in AbstractPackageClass and
// inherited by PackageClass.
TEST_F(HiddenApiTest, InterfaceMethodImplementedInParent) {
  ScratchFile flags_csv;
  ASSERT_TRUE(RunHiddenapiList(flags_csv));
  auto flags = ReadFlagsCsvFile(flags_csv);
  ASSERT_EQ(SafeMapGet("LAbstractPackageClass;->publicMethod2()V", flags), "public-api");
}

}  // namespace art

Messung V0.5 in Prozent
C=91 H=92 G=91

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.