| // Copyright 2011 Google Inc. All Rights Reserved. |
| |
| #include "dex_file.h" |
| |
| #include "UniquePtr.h" |
| #include "common_test.h" |
| |
| namespace art { |
| |
| class DexFileTest : public CommonTest {}; |
| |
| TEST_F(DexFileTest, Open) { |
| UniquePtr<const DexFile> dex(OpenTestDexFile("Nested")); |
| ASSERT_TRUE(dex.get() != NULL); |
| } |
| |
| // Although this is the same content logically as the Nested test dex, |
| // the DexFileHeader test is sensitive to subtle changes in the |
| // contents due to the checksum etc, so we embed the exact input here. |
| // |
| // class Nested { |
| // class Inner { |
| // } |
| // } |
| static const char kRawDex[] = |
| "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP" |
| "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B" |
| "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA" |
| "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA" |
| "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA" |
| "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA" |
| "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA" |
| "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu" |
| "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" |
| "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz" |
| "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA" |
| "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA" |
| "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH" |
| "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ" |
| "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA" |
| "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA=="; |
| |
| TEST_F(DexFileTest, Header) { |
| ScratchFile tmp; |
| UniquePtr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename())); |
| ASSERT_TRUE(raw.get() != NULL); |
| |
| const DexFile::Header& header = raw->GetHeader(); |
| // TODO: header.magic_ |
| EXPECT_EQ(0x00d87910U, header.checksum_); |
| // TODO: header.signature_ |
| EXPECT_EQ(904U, header.file_size_); |
| EXPECT_EQ(112U, header.header_size_); |
| EXPECT_EQ(0U, header.link_size_); |
| EXPECT_EQ(0U, header.link_off_); |
| EXPECT_EQ(15U, header.string_ids_size_); |
| EXPECT_EQ(112U, header.string_ids_off_); |
| EXPECT_EQ(7U, header.type_ids_size_); |
| EXPECT_EQ(172U, header.type_ids_off_); |
| EXPECT_EQ(2U, header.proto_ids_size_); |
| EXPECT_EQ(200U, header.proto_ids_off_); |
| EXPECT_EQ(1U, header.field_ids_size_); |
| EXPECT_EQ(224U, header.field_ids_off_); |
| EXPECT_EQ(3U, header.method_ids_size_); |
| EXPECT_EQ(232U, header.method_ids_off_); |
| EXPECT_EQ(2U, header.class_defs_size_); |
| EXPECT_EQ(256U, header.class_defs_off_); |
| EXPECT_EQ(584U, header.data_size_); |
| EXPECT_EQ(320U, header.data_off_); |
| } |
| |
| TEST_F(DexFileTest, ClassDefs) { |
| UniquePtr<const DexFile> raw(OpenTestDexFile("Nested")); |
| ASSERT_TRUE(raw.get() != NULL); |
| EXPECT_EQ(2U, raw->NumClassDefs()); |
| |
| const DexFile::ClassDef& c0 = raw->GetClassDef(0); |
| EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0)); |
| |
| const DexFile::ClassDef& c1 = raw->GetClassDef(1); |
| EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1)); |
| } |
| |
| TEST_F(DexFileTest, CreateMethodDescriptor) { |
| UniquePtr<const DexFile> raw(OpenTestDexFile("CreateMethodDescriptor")); |
| ASSERT_TRUE(raw.get() != NULL); |
| EXPECT_EQ(1U, raw->NumClassDefs()); |
| |
| const DexFile::ClassDef& class_def = raw->GetClassDef(0); |
| ASSERT_STREQ("LCreateMethodDescriptor;", raw->GetClassDescriptor(class_def)); |
| |
| const byte* class_data = raw->GetClassData(class_def); |
| ASSERT_TRUE(class_data != NULL); |
| DexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data); |
| |
| EXPECT_EQ(1u, header.direct_methods_size_); |
| |
| // Check the descriptor for the static initializer. |
| { |
| uint32_t last_idx = 0; |
| ASSERT_EQ(1U, header.direct_methods_size_); |
| DexFile::Method method; |
| raw->dexReadClassDataMethod(&class_data, &method, &last_idx); |
| const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_); |
| uint32_t proto_idx = method_id.proto_idx_; |
| const char* name = raw->dexStringById(method_id.name_idx_); |
| ASSERT_STREQ("<init>", name); |
| int32_t length; |
| std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length)); |
| ASSERT_EQ("()V", descriptor); |
| } |
| |
| // Check both virtual methods. |
| ASSERT_EQ(2U, header.virtual_methods_size_); |
| uint32_t last_idx = 0; |
| |
| { |
| DexFile::Method method; |
| raw->dexReadClassDataMethod(&class_data, &method, &last_idx); |
| const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_); |
| |
| const char* name = raw->dexStringById(method_id.name_idx_); |
| ASSERT_STREQ("m1", name); |
| |
| uint32_t proto_idx = method_id.proto_idx_; |
| int32_t length; |
| std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length)); |
| ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", descriptor); |
| } |
| |
| { |
| DexFile::Method method; |
| raw->dexReadClassDataMethod(&class_data, &method, &last_idx); |
| const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_); |
| |
| const char* name = raw->dexStringById(method_id.name_idx_); |
| ASSERT_STREQ("m2", name); |
| |
| uint32_t proto_idx = method_id.proto_idx_; |
| int32_t length; |
| std::string descriptor(raw->CreateMethodDescriptor(proto_idx, &length)); |
| ASSERT_EQ("(ZSC)LCreateMethodDescriptor;", descriptor); |
| } |
| } |
| |
| } // namespace art |