/*
 * Copyright (C) 2016 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/dex_to_dex_decompiler.h"

#include "class_linker.h"
#include "compiler/common_compiler_test.h"
#include "compiler/compiled_method.h"
#include "compiler/driver/compiler_options.h"
#include "compiler/driver/compiler_driver.h"
#include "compiler_callbacks.h"
#include "dex_file.h"
#include "handle_scope-inl.h"
#include "verifier/method_verifier-inl.h"
#include "mirror/class_loader.h"
#include "runtime.h"
#include "thread.h"
#include "scoped_thread_state_change-inl.h"

namespace art {

class DexToDexDecompilerTest : public CommonCompilerTest {
 public:
  void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
    TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
    TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
    compiler_options_->boot_image_ = false;
    compiler_options_->SetCompilerFilter(CompilerFilter::kInterpretOnly);
    compiler_driver_->CompileAll(class_loader,
                                 GetDexFiles(class_loader),
                                 /* verifier_deps */ nullptr,
                                 &timings);
  }

  void RunTest(const char* dex_name) {
    Thread* self = Thread::Current();
    // First load the original dex file.
    jobject original_class_loader;
    {
      ScopedObjectAccess soa(self);
      original_class_loader = LoadDex(dex_name);
    }
    const DexFile* original_dex_file = GetDexFiles(original_class_loader)[0];

    // Load the dex file again and make it writable to quicken them.
    jobject class_loader;
    const DexFile* updated_dex_file = nullptr;
    {
      ScopedObjectAccess soa(self);
      class_loader = LoadDex(dex_name);
      updated_dex_file = GetDexFiles(class_loader)[0];
      Runtime::Current()->GetClassLinker()->RegisterDexFile(
          *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
    }
    // The dex files should be identical.
    int cmp = memcmp(original_dex_file->Begin(),
                     updated_dex_file->Begin(),
                     updated_dex_file->Size());
    ASSERT_EQ(0, cmp);

    updated_dex_file->EnableWrite();
    CompileAll(class_loader);
    // The dex files should be different after quickening.
    cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
    ASSERT_NE(0, cmp);

    // Unquicken the dex file.
    for (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
      const DexFile::ClassDef& class_def = updated_dex_file->GetClassDef(i);
      const uint8_t* class_data = updated_dex_file->GetClassData(class_def);
      if (class_data == nullptr) {
        continue;
      }
      ClassDataItemIterator it(*updated_dex_file, class_data);
      // Skip fields
      while (it.HasNextStaticField()) {
        it.Next();
      }
      while (it.HasNextInstanceField()) {
        it.Next();
      }

      // Unquicken each method.
      while (it.HasNextDirectMethod()) {
        uint32_t method_idx = it.GetMemberIndex();
        CompiledMethod* compiled_method =
            compiler_driver_->GetCompiledMethod(MethodReference(updated_dex_file, method_idx));
        ArrayRef<const uint8_t> table;
        if (compiled_method != nullptr) {
          table = compiled_method->GetVmapTable();
        }
        optimizer::ArtDecompileDEX(
            *it.GetMethodCodeItem(), table, /* decompile_return_instruction */ true);
        it.Next();
      }
      while (it.HasNextVirtualMethod()) {
        uint32_t method_idx = it.GetMemberIndex();
        CompiledMethod* compiled_method =
            compiler_driver_->GetCompiledMethod(MethodReference(updated_dex_file, method_idx));
        ArrayRef<const uint8_t> table;
        if (compiled_method != nullptr) {
          table = compiled_method->GetVmapTable();
        }
        optimizer::ArtDecompileDEX(
            *it.GetMethodCodeItem(), table, /* decompile_return_instruction */ true);
        it.Next();
      }
      DCHECK(!it.HasNext());
    }

    // Make sure after unquickening we go back to the same contents as the original dex file.
    cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
    ASSERT_EQ(0, cmp);
  }
};

TEST_F(DexToDexDecompilerTest, VerifierDeps) {
  RunTest("VerifierDeps");
}

TEST_F(DexToDexDecompilerTest, DexToDexDecompiler) {
  RunTest("DexToDexDecompiler");
}

}  // namespace art
