1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#include "compact_dex_file.h"
19#include "dex_file_loader.h"
20#include "gtest/gtest.h"
21
22namespace art {
23
24TEST(CompactDexFileTest, MagicAndVersion) {
25  // Test permutations of valid/invalid headers.
26  for (size_t i = 0; i < 2; ++i) {
27    for (size_t j = 0; j < 2; ++j) {
28      static const size_t len = CompactDexFile::kDexVersionLen + CompactDexFile::kDexMagicSize;
29      uint8_t header[len] = {};
30      std::fill_n(header, len, 0x99);
31      const bool valid_magic = (i & 1) == 0;
32      const bool valid_version = (j & 1) == 0;
33      if (valid_magic) {
34        CompactDexFile::WriteMagic(header);
35      }
36      if (valid_version) {
37        CompactDexFile::WriteCurrentVersion(header);
38      }
39      EXPECT_EQ(valid_magic, CompactDexFile::IsMagicValid(header));
40      EXPECT_EQ(valid_version, CompactDexFile::IsVersionValid(header));
41      EXPECT_EQ(valid_magic, DexFileLoader::IsMagicValid(header));
42      EXPECT_EQ(valid_magic && valid_version, DexFileLoader::IsVersionAndMagicValid(header));
43    }
44  }
45}
46
47TEST(CompactDexFileTest, CodeItemFields) {
48  auto test_and_write = [&] (uint16_t registers_size,
49                             uint16_t ins_size,
50                             uint16_t outs_size,
51                             uint16_t tries_size,
52                             uint32_t insns_size_in_code_units) {
53    ASSERT_GE(registers_size, ins_size);
54    uint16_t buffer[sizeof(CompactDexFile::CodeItem) +
55                        CompactDexFile::CodeItem::kMaxPreHeaderSize] = {};
56    CompactDexFile::CodeItem* code_item = reinterpret_cast<CompactDexFile::CodeItem*>(
57        &buffer[CompactDexFile::CodeItem::kMaxPreHeaderSize]);
58    const uint16_t* preheader_ptr = code_item->Create(registers_size,
59                                                      ins_size,
60                                                      outs_size,
61                                                      tries_size,
62                                                      insns_size_in_code_units,
63                                                      code_item->GetPreHeader());
64    ASSERT_GT(preheader_ptr, buffer);
65
66    uint16_t out_registers_size;
67    uint16_t out_ins_size;
68    uint16_t out_outs_size;
69    uint16_t out_tries_size;
70    uint32_t out_insns_size_in_code_units;
71    code_item->DecodeFields</*kDecodeOnlyInstructionCount*/false>(&out_insns_size_in_code_units,
72                                                                  &out_registers_size,
73                                                                  &out_ins_size,
74                                                                  &out_outs_size,
75                                                                  &out_tries_size);
76    ASSERT_EQ(registers_size, out_registers_size);
77    ASSERT_EQ(ins_size, out_ins_size);
78    ASSERT_EQ(outs_size, out_outs_size);
79    ASSERT_EQ(tries_size, out_tries_size);
80    ASSERT_EQ(insns_size_in_code_units, out_insns_size_in_code_units);
81
82    ++out_insns_size_in_code_units;  // Force value to change.
83    code_item->DecodeFields</*kDecodeOnlyInstructionCount*/true>(&out_insns_size_in_code_units,
84                                                                 /*registers_size*/ nullptr,
85                                                                 /*ins_size*/ nullptr,
86                                                                 /*outs_size*/ nullptr,
87                                                                 /*tries_size*/ nullptr);
88    ASSERT_EQ(insns_size_in_code_units, out_insns_size_in_code_units);
89  };
90  static constexpr uint32_t kMax32 = std::numeric_limits<uint32_t>::max();
91  static constexpr uint16_t kMax16 = std::numeric_limits<uint16_t>::max();
92  test_and_write(0, 0, 0, 0, 0);
93  test_and_write(kMax16, kMax16, kMax16, kMax16, kMax32);
94  test_and_write(kMax16 - 1, kMax16 - 2, kMax16 - 3, kMax16 - 4, kMax32 - 5);
95  test_and_write(kMax16 - 4, kMax16 - 5, kMax16 - 3, kMax16 - 2, kMax32 - 1);
96  test_and_write(5, 4, 3, 2, 1);
97  test_and_write(5, 0, 3, 2, 1);
98  test_and_write(kMax16, 0, kMax16 / 2, 1234, kMax32 / 4);
99}
100
101}  // namespace art
102