1 /*
2 * Copyright (C) 2023 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 "dex/proto_reference.h"
18 #include <vector>
19
20 #include "dex/dex_file_types.h"
21 #include "dex/test_dex_file_builder.h"
22 #include "gtest/gtest.h"
23
24 namespace art {
25
TEST(ProtoReference,WithinOneDexFile)26 TEST(ProtoReference, WithinOneDexFile) {
27 TestDexFileBuilder builder;
28 builder.AddMethod("LClass", "()I", "sideEffect2");
29 builder.AddMethod("LClass", "(I)Ljava/lang/String;", "toString");
30 builder.AddMethod("LClass", "(II)Ljava/lang/String;", "toString");
31 builder.AddMethod("LClass", "(IJ)Ljava/lang/String;", "toString");
32 builder.AddMethod("LClass", "(JJ)Ljava/lang/String;", "toString");
33 builder.AddMethod("LClass", "()V", "sideEffect1");
34
35 std::unique_ptr<const DexFile> dex_file = builder.Build("fake location");
36 const size_t num_protos = 6u;
37 EXPECT_EQ(num_protos, dex_file->NumProtoIds());
38
39 std::vector<ProtoReference> protos;
40
41 for (size_t i = 0; i < num_protos; ++i) {
42 protos.emplace_back(ProtoReference(dex_file.get(), dex::ProtoIndex(i)));
43 }
44
45 ProtoReferenceValueComparator cmp;
46 for (size_t i = 0; i < num_protos; ++i) {
47 for (size_t j = 0; j < num_protos; ++j) {
48 EXPECT_EQ(cmp(protos[i], protos[j]), i < j)
49 << "Inconsistent at i=" << i << " and j=" << j;
50 }
51 }
52 }
53
TEST(ProtoReference,AcrossDifferentDexFiles)54 TEST(ProtoReference, AcrossDifferentDexFiles) {
55 TestDexFileBuilder builder1;
56 builder1.AddMethod("LClass", "()I", "sideEffect2");
57 builder1.AddMethod("LClass", "(I)Ljava/lang/String;", "toString");
58 builder1.AddMethod("LClass", "(II)Ljava/lang/String;", "toString");
59 builder1.AddMethod("LClass", "(IJ)Ljava/lang/String;", "toString");
60 builder1.AddMethod("LClass", "(IJZ)Ljava/lang/String;", "toString");
61 builder1.AddMethod("LClass", "()V", "sideEffect1");
62
63 std::unique_ptr<const DexFile> dex_file1 = builder1.Build("fake location");
64 EXPECT_EQ(6u, dex_file1->NumProtoIds());
65
66 TestDexFileBuilder builder2;
67 builder2.AddMethod("LClass2", "(IJ)Ljava/lang/String;", "toString");
68 builder2.AddMethod("LClass2", "()V", "sideEffect1");
69 builder2.AddMethod("LClass2", "(I)V", "sideEffect2");
70
71 std::unique_ptr<const DexFile> dex_file2 = builder2.Build("fake location 2");
72 EXPECT_EQ(3u, dex_file2->NumProtoIds());
73
74 ProtoReference V_dex1 = ProtoReference(dex_file1.get(), dex::ProtoIndex(5));
75 ProtoReference V_dex2 = ProtoReference(dex_file2.get(), dex::ProtoIndex(1));
76
77 ProtoReferenceValueComparator cmp;
78
79 EXPECT_FALSE(cmp(V_dex1, V_dex2));
80 EXPECT_FALSE(cmp(V_dex2, V_dex1));
81
82 ProtoReference IString_dex1 = ProtoReference(dex_file1.get(), dex::ProtoIndex(1));
83 ProtoReference IIString_dex1 = ProtoReference(dex_file1.get(), dex::ProtoIndex(2));
84 ProtoReference IJString_dex1 = ProtoReference(dex_file1.get(), dex::ProtoIndex(3));
85 ProtoReference IJZString_dex1 = ProtoReference(dex_file1.get(), dex::ProtoIndex(4));
86
87 ProtoReference IJString_dex2 = ProtoReference(dex_file2.get(), dex::ProtoIndex(0));
88
89 EXPECT_TRUE(cmp(IString_dex1, V_dex2));
90
91 EXPECT_TRUE(cmp(IString_dex1, IJString_dex2));
92 EXPECT_TRUE(cmp(IIString_dex1, IJString_dex2));
93 EXPECT_FALSE(cmp(IJString_dex1, IJString_dex2));
94 EXPECT_FALSE(cmp(IJString_dex2, IJString_dex1));
95 EXPECT_FALSE(cmp(IJZString_dex1, IJString_dex2));
96
97 EXPECT_TRUE(cmp(IJString_dex2, IJZString_dex1));
98 }
99
100 } // namespace art
101