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 #include "index_bss_mapping_encoder.h"
18 
19 #include "base/enums.h"
20 #include "gtest/gtest.h"
21 
22 namespace art {
23 namespace linker {
24 
TEST(IndexBssMappingEncoder,TryMerge16BitIndex)25 TEST(IndexBssMappingEncoder, TryMerge16BitIndex) {
26   for (PointerSize pointer_size : {PointerSize::k32, PointerSize::k64}) {
27     size_t raw_pointer_size = static_cast<size_t>(pointer_size);
28     IndexBssMappingEncoder encoder(/* number_of_indexes */ 0x10000, raw_pointer_size);
29     encoder.Reset(1u, 0u);
30     ASSERT_FALSE(encoder.TryMerge(5u, raw_pointer_size + 1));       // Wrong bss_offset difference.
31     ASSERT_FALSE(encoder.TryMerge(18u, raw_pointer_size));          // Index out of range.
32     ASSERT_TRUE(encoder.TryMerge(5u, raw_pointer_size));
33     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
34     ASSERT_EQ(raw_pointer_size,
35               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
36     ASSERT_EQ(IndexBssMappingLookup::npos,
37               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 17u, raw_pointer_size));
38     ASSERT_FALSE(encoder.TryMerge(17u, 2 * raw_pointer_size + 1));  // Wrong bss_offset difference.
39     ASSERT_FALSE(encoder.TryMerge(18u, 2 * raw_pointer_size));      // Index out of range.
40     ASSERT_TRUE(encoder.TryMerge(17u, 2 * raw_pointer_size));
41     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
42     ASSERT_EQ(raw_pointer_size,
43               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
44     ASSERT_EQ(2 * raw_pointer_size,
45               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 17u, raw_pointer_size));
46     ASSERT_EQ(0x00110000u | 17u, encoder.GetEntry().index_and_mask);
47     ASSERT_FALSE(encoder.TryMerge(18u, 3 * raw_pointer_size));      // Index out of range.
48   }
49 }
50 
TEST(IndexBssMappingEncoder,TryMerge8BitIndex)51 TEST(IndexBssMappingEncoder, TryMerge8BitIndex) {
52   for (PointerSize pointer_size : {PointerSize::k32, PointerSize::k64}) {
53     size_t raw_pointer_size = static_cast<size_t>(pointer_size);
54     IndexBssMappingEncoder encoder(/* number_of_indexes */ 0x100, raw_pointer_size);
55     encoder.Reset(1u, 0u);
56     ASSERT_FALSE(encoder.TryMerge(5u, raw_pointer_size + 1));       // Wrong bss_offset difference.
57     ASSERT_FALSE(encoder.TryMerge(26u, raw_pointer_size));          // Index out of range.
58     ASSERT_TRUE(encoder.TryMerge(5u, raw_pointer_size));
59     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
60     ASSERT_EQ(raw_pointer_size,
61               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
62     ASSERT_EQ(IndexBssMappingLookup::npos,
63               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 17u, raw_pointer_size));
64     ASSERT_FALSE(encoder.TryMerge(25u, 2 * raw_pointer_size + 1));  // Wrong bss_offset difference.
65     ASSERT_FALSE(encoder.TryMerge(26u, 2 * raw_pointer_size));      // Index out of range.
66     ASSERT_TRUE(encoder.TryMerge(25u, 2 * raw_pointer_size));
67     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
68     ASSERT_EQ(raw_pointer_size,
69               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
70     ASSERT_EQ(2 * raw_pointer_size,
71               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 25u, raw_pointer_size));
72     ASSERT_EQ(0x00001100u | 25u, encoder.GetEntry().index_and_mask);
73     ASSERT_FALSE(encoder.TryMerge(26u, 3 * raw_pointer_size));      // Index out of range.
74   }
75 }
76 
TEST(IndexBssMappingEncoder,TryMerge20BitIndex)77 TEST(IndexBssMappingEncoder, TryMerge20BitIndex) {
78   for (PointerSize pointer_size : {PointerSize::k32, PointerSize::k64}) {
79     size_t raw_pointer_size = static_cast<size_t>(pointer_size);
80     IndexBssMappingEncoder encoder(/* number_of_indexes */ 0x100000, raw_pointer_size);
81     encoder.Reset(1u, 0u);
82     ASSERT_FALSE(encoder.TryMerge(5u, raw_pointer_size + 1));       // Wrong bss_offset difference.
83     ASSERT_FALSE(encoder.TryMerge(14u, raw_pointer_size));          // Index out of range.
84     ASSERT_TRUE(encoder.TryMerge(5u, raw_pointer_size));
85     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
86     ASSERT_EQ(raw_pointer_size,
87               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
88     ASSERT_EQ(IndexBssMappingLookup::npos,
89               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 17u, raw_pointer_size));
90     ASSERT_FALSE(encoder.TryMerge(13u, 2 * raw_pointer_size + 1));  // Wrong bss_offset difference.
91     ASSERT_FALSE(encoder.TryMerge(14u, 2 * raw_pointer_size));      // Index out of range.
92     ASSERT_TRUE(encoder.TryMerge(13u, 2 * raw_pointer_size));
93     ASSERT_EQ(0u, encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 1u, raw_pointer_size));
94     ASSERT_EQ(raw_pointer_size,
95               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 5u, raw_pointer_size));
96     ASSERT_EQ(2 * raw_pointer_size,
97               encoder.GetEntry().GetBssOffset(encoder.GetIndexBits(), 13u, raw_pointer_size));
98     ASSERT_EQ(0x01100000u | 13u, encoder.GetEntry().index_and_mask);
99     ASSERT_FALSE(encoder.TryMerge(14u, 3 * raw_pointer_size));      // Index out of range.
100   }
101 }
102 
103 }  // namespace linker
104 }  // namespace art
105