/*
 * Copyright (C) 2018 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 "dex/class_accessor-inl.h"

#include "base/common_art_test.h"

namespace art {

class ClassAccessorTest : public CommonArtTest {};

TEST_F(ClassAccessorTest, TestVisiting) {
  std::vector<std::unique_ptr<const DexFile>> dex_files(
      OpenDexFiles(GetLibCoreDexFileNames()[0].c_str()));
  ASSERT_GT(dex_files.size(), 0u);
  for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
    uint32_t class_def_idx = 0u;
    ASSERT_GT(dex_file->NumClassDefs(), 0u);
    for (ClassAccessor accessor : dex_file->GetClasses()) {
      const dex::ClassDef& class_def = dex_file->GetClassDef(accessor.GetClassDefIndex());
      EXPECT_EQ(accessor.GetDescriptor(), dex_file->StringByTypeIdx(class_def.class_idx_));
      EXPECT_EQ(class_def_idx, accessor.GetClassDefIndex());
      ++class_def_idx;
      // Check iterators against visitors.
      auto methods = accessor.GetMethods();
      auto fields = accessor.GetFields();
      auto method_it = methods.begin();
      auto field_it = fields.begin();
      auto instance_fields = accessor.GetInstanceFields();
      auto instance_field_it = instance_fields.begin();
      accessor.VisitFieldsAndMethods(
          // Static fields.
          [&](const ClassAccessor::Field& field) {
            EXPECT_TRUE(field.IsStatic());
            EXPECT_TRUE(field_it->IsStatic());
            EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
            EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
            ++field_it;
          },
          // Instance fields.
          [&](const ClassAccessor::Field& field) {
            EXPECT_FALSE(field.IsStatic());
            EXPECT_FALSE(field_it->IsStatic());
            EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
            EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
            EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex());
            EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags());
            ++field_it;
            ++instance_field_it;
          },
          // Direct methods.
          [&](const ClassAccessor::Method& method) {
            EXPECT_TRUE(method.IsStaticOrDirect());
            EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
            EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
            EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
            EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
            ++method_it;
          },
          // Virtual methods.
          [&](const ClassAccessor::Method& method) {
            EXPECT_FALSE(method.IsStaticOrDirect());
            EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
            EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
            EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
            EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
            ++method_it;
          });
      ASSERT_TRUE(field_it == fields.end());
      ASSERT_TRUE(method_it == methods.end());
      ASSERT_TRUE(instance_field_it == instance_fields.end());
    }
    EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
  }
}

}  // namespace art
