diff options
Diffstat (limited to 'startop/view_compiler/dex_builder_test.cc')
-rw-r--r-- | startop/view_compiler/dex_builder_test.cc | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/startop/view_compiler/dex_builder_test.cc b/startop/view_compiler/dex_builder_test.cc new file mode 100644 index 000000000000..61c86b4091b3 --- /dev/null +++ b/startop/view_compiler/dex_builder_test.cc @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dex_builder.h" + +#include "dex/art_dex_file_loader.h" +#include "dex/dex_file.h" +#include "gtest/gtest.h" + +using namespace startop::dex; + +// Takes a DexBuilder, encodes it into an in-memory DEX file, verifies the resulting DEX file and +// returns whether the verification was successful. +bool EncodeAndVerify(DexBuilder* dex_file) { + slicer::MemView image{dex_file->CreateImage()}; + + art::ArtDexFileLoader loader; + std::string error_msg; + std::unique_ptr<const art::DexFile> loaded_dex_file{loader.Open(image.ptr<const uint8_t>(), + image.size(), + /*location=*/"", + /*location_checksum=*/0, + /*oat_dex_file=*/nullptr, + /*verify=*/true, + /*verify_checksum=*/false, + &error_msg)}; + return loaded_dex_file != nullptr; +} + +// Write out and verify a DEX file that corresponds to: +// +// package dextest; +// public class DexTest { +// public static void foo() {} +// } +TEST(DexBuilderTest, VerifyDexWithClassMethod) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + auto method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Void()})}; + method.BuildReturn(); + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} + +// Makes sure a bad DEX class fails to verify. +TEST(DexBuilderTest, VerifyBadDexWithClassMethod) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + // This method has the error, because methods cannot take Void() as a parameter. + auto method{ + cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Void(), TypeDescriptor::Void()})}; + method.BuildReturn(); + method.Encode(); + + EXPECT_FALSE(EncodeAndVerify(&dex_file)); +} + +// Write out and verify a DEX file that corresponds to: +// +// package dextest; +// public class DexTest { +// public static int foo() { return 5; } +// } +TEST(DexBuilderTest, VerifyDexReturn5) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + auto method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int()})}; + auto r = method.MakeRegister(); + method.BuildConst4(r, 5); + method.BuildReturn(r); + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} + +// Write out and verify a DEX file that corresponds to: +// +// package dextest; +// public class DexTest { +// public static int foo(int x) { return x; } +// } +TEST(DexBuilderTest, VerifyDexReturnIntParam) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + auto method{ + cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})}; + method.BuildReturn(Value::Parameter(0)); + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} + +// Write out and verify a DEX file that corresponds to: +// +// package dextest; +// public class DexTest { +// public static int foo(String s) { return s.length(); } +// } +TEST(DexBuilderTest, VerifyDexCallStringLength) { + DexBuilder dex_file; + + auto cbuilder{dex_file.MakeClass("dextest.DexTest")}; + + MethodBuilder method{cbuilder.CreateMethod( + "foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::FromClassname("java.lang.String")})}; + + Value result = method.MakeRegister(); + + MethodDeclData string_length = + dex_file.GetOrDeclareMethod(TypeDescriptor::FromClassname("java.lang.String"), + "length", + Prototype{TypeDescriptor::Int()}); + + method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0))); + method.BuildReturn(result); + + method.Encode(); + + EXPECT_TRUE(EncodeAndVerify(&dex_file)); +} |