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 
22 namespace art {
23 
TEST(CompactDexFileTest,MagicAndVersion)24 TEST(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 
TEST(CompactDexFileTest,CodeItemFields)47 TEST(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