diff options
author | 2018-02-21 13:20:31 -0800 | |
---|---|---|
committer | 2018-02-21 13:51:15 -0800 | |
commit | b2ec9f5c128673c43f776cbe12c8eeb0a6884ebb (patch) | |
tree | 724022162a4f3de021cebab32ee5ac67ec860f32 | |
parent | f13343eb8b2738e2812fd7bd9d5592f529e93c21 (diff) |
Remove duplication, split tests
The code move to libdexfile/dex/descriptors_names.cc apparently did not
remove the original code from runtime/utils.cc. Fix that duplication
and all the header mentions needed. Also, split the test files to go
along with the new locations for the code to be tested.
Bug: 22322814
Test: make -j 50 checkbuild
make -j 50 test-art-host-gtest
flash & boot marlin
Change-Id: Ie734672c4bca2c647d8016291f910b5608674545
39 files changed, 347 insertions, 657 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 40a5370ec7..a20313374c 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -23,6 +23,7 @@ #include "base/enums.h" #include "class_linker.h" #include "compiled_method-inl.h" +#include "dex/descriptors_names.h" #include "dex/quick_compiler_callbacks.h" #include "dex/verification_results.h" #include "driver/compiler_driver.h" diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index fb428b8d9a..a6681ec1ef 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -42,6 +42,7 @@ #include "compiler.h" #include "compiler_callbacks.h" #include "compiler_driver-inl.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" #include "dex/dex_instruction-inl.h" diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc index 28e68c94df..2e315b5d12 100644 --- a/compiler/driver/dex_compilation_unit.cc +++ b/compiler/driver/dex_compilation_unit.cc @@ -17,6 +17,7 @@ #include "dex_compilation_unit.h" #include "dex/code_item_accessors-inl.h" +#include "dex/descriptors_names.h" #include "mirror/dex_cache.h" #include "utils.h" diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index bbf8c26d59..5ff31cead5 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -27,6 +27,7 @@ #include "code_generator.h" #include "data_type-inl.h" #include "dead_code_elimination.h" +#include "dex/descriptors_names.h" #include "disassembler.h" #include "inliner.h" #include "licm.h" diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index b5c5e4566d..37d1317e32 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -59,6 +59,7 @@ #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dexlayout.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/quick_compiler_callbacks.h" #include "dex/verification_results.h" diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index e841811861..159a4a5ec2 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -35,6 +35,7 @@ #include "base/logging.h" // For VLOG_IS_ON. #include "dex/art_dex_file_loader.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_layout.h" #include "dex/dex_file_loader.h" diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp index 382a46aeec..180831537f 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -110,6 +110,7 @@ art_cc_test { "dex/code_item_accessors_test.cc", "dex/compact_dex_file_test.cc", "dex/compact_offset_table_test.cc", + "dex/descriptors_names_test.cc", "dex/dex_file_loader_test.cc", "dex/dex_file_verifier_test.cc", "dex/dex_instruction_test.cc", diff --git a/libdexfile/dex/descriptors_names_test.cc b/libdexfile/dex/descriptors_names_test.cc new file mode 100644 index 0000000000..90eba28636 --- /dev/null +++ b/libdexfile/dex/descriptors_names_test.cc @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2011 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 "descriptors_names.h" + +#include "gtest/gtest.h" + +namespace art { + +class DescriptorsNamesTest : public testing::Test {}; + +TEST_F(DescriptorsNamesTest, PrettyDescriptor_ArrayReferences) { + EXPECT_EQ("java.lang.Class[]", PrettyDescriptor("[Ljava/lang/Class;")); + EXPECT_EQ("java.lang.Class[][]", PrettyDescriptor("[[Ljava/lang/Class;")); +} + +TEST_F(DescriptorsNamesTest, PrettyDescriptor_ScalarReferences) { + EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava.lang.String;")); + EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava/lang/String;")); +} + +TEST_F(DescriptorsNamesTest, PrettyDescriptor_Primitive) { + EXPECT_EQ("boolean", PrettyDescriptor(Primitive::kPrimBoolean)); + EXPECT_EQ("byte", PrettyDescriptor(Primitive::kPrimByte)); + EXPECT_EQ("char", PrettyDescriptor(Primitive::kPrimChar)); + EXPECT_EQ("short", PrettyDescriptor(Primitive::kPrimShort)); + EXPECT_EQ("int", PrettyDescriptor(Primitive::kPrimInt)); + EXPECT_EQ("float", PrettyDescriptor(Primitive::kPrimFloat)); + EXPECT_EQ("long", PrettyDescriptor(Primitive::kPrimLong)); + EXPECT_EQ("double", PrettyDescriptor(Primitive::kPrimDouble)); + EXPECT_EQ("void", PrettyDescriptor(Primitive::kPrimVoid)); +} + +TEST_F(DescriptorsNamesTest, PrettyDescriptor_PrimitiveArrays) { + EXPECT_EQ("boolean[]", PrettyDescriptor("[Z")); + EXPECT_EQ("boolean[][]", PrettyDescriptor("[[Z")); + EXPECT_EQ("byte[]", PrettyDescriptor("[B")); + EXPECT_EQ("byte[][]", PrettyDescriptor("[[B")); + EXPECT_EQ("char[]", PrettyDescriptor("[C")); + EXPECT_EQ("char[][]", PrettyDescriptor("[[C")); + EXPECT_EQ("double[]", PrettyDescriptor("[D")); + EXPECT_EQ("double[][]", PrettyDescriptor("[[D")); + EXPECT_EQ("float[]", PrettyDescriptor("[F")); + EXPECT_EQ("float[][]", PrettyDescriptor("[[F")); + EXPECT_EQ("int[]", PrettyDescriptor("[I")); + EXPECT_EQ("int[][]", PrettyDescriptor("[[I")); + EXPECT_EQ("long[]", PrettyDescriptor("[J")); + EXPECT_EQ("long[][]", PrettyDescriptor("[[J")); + EXPECT_EQ("short[]", PrettyDescriptor("[S")); + EXPECT_EQ("short[][]", PrettyDescriptor("[[S")); +} + +TEST_F(DescriptorsNamesTest, PrettyDescriptor_PrimitiveScalars) { + EXPECT_EQ("boolean", PrettyDescriptor("Z")); + EXPECT_EQ("byte", PrettyDescriptor("B")); + EXPECT_EQ("char", PrettyDescriptor("C")); + EXPECT_EQ("double", PrettyDescriptor("D")); + EXPECT_EQ("float", PrettyDescriptor("F")); + EXPECT_EQ("int", PrettyDescriptor("I")); + EXPECT_EQ("long", PrettyDescriptor("J")); + EXPECT_EQ("short", PrettyDescriptor("S")); +} + +TEST_F(DescriptorsNamesTest, MangleForJni) { + EXPECT_EQ("hello_00024world", MangleForJni("hello$world")); + EXPECT_EQ("hello_000a9world", MangleForJni("hello\xc2\xa9world")); + EXPECT_EQ("hello_1world", MangleForJni("hello_world")); + EXPECT_EQ("Ljava_lang_String_2", MangleForJni("Ljava/lang/String;")); + EXPECT_EQ("_3C", MangleForJni("[C")); +} + +TEST_F(DescriptorsNamesTest, IsValidDescriptor) { + std::vector<uint8_t> descriptor( + { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, ';', 0x00 }); + EXPECT_TRUE(IsValidDescriptor(reinterpret_cast<char*>(&descriptor[0]))); + + std::vector<uint8_t> unpaired_surrogate( + { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, ';', 0x00 }); + EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate[0]))); + + std::vector<uint8_t> unpaired_surrogate_at_end( + { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0x00 }); + EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate_at_end[0]))); + + std::vector<uint8_t> invalid_surrogate( + { 'L', 'a', '/', 'b', '$', 0xed, 0xb0, 0x80, ';', 0x00 }); + EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&invalid_surrogate[0]))); + + std::vector<uint8_t> unpaired_surrogate_with_multibyte_sequence( + { 'L', 'a', '/', 'b', '$', 0xed, 0xb0, 0x80, 0xf0, 0x9f, 0x8f, 0xa0, ';', 0x00 }); + EXPECT_FALSE( + IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate_with_multibyte_sequence[0]))); +} + +} // namespace art diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 82bb88a5d5..f91f6e3b74 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -43,6 +43,7 @@ #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dex/code_item_accessors-inl.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_instruction-inl.h" #include "disassembler.h" diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc index 1dd1a4afc0..6359814615 100644 --- a/profman/profile_assistant_test.cc +++ b/profman/profile_assistant_test.cc @@ -20,6 +20,7 @@ #include "art_method-inl.h" #include "base/unix_file/fd_file.h" #include "common_runtime_test.h" +#include "dex/descriptors_names.h" #include "exec_utils.h" #include "jit/profile_compilation_info.h" #include "linear_alloc.h" diff --git a/runtime/Android.bp b/runtime/Android.bp index 1ac770fd06..86cdc8b6b1 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -544,6 +544,7 @@ art_cc_test { "base/bit_struct_test.cc", "base/bit_utils_test.cc", "base/bit_vector_test.cc", + "base/file_utils_test.cc", "base/hash_set_test.cc", "base/hex_dump_test.cc", "base/histogram_test.cc", @@ -566,6 +567,7 @@ art_cc_test { "entrypoints/math_entrypoints_test.cc", "entrypoints/quick/quick_trampoline_entrypoints_test.cc", "entrypoints_order_test.cc", + "exec_utils_test.cc", "gc/accounting/card_table_test.cc", "gc/accounting/mod_union_table_test.cc", "gc/accounting/space_bitmap_test.cc", diff --git a/runtime/art_field.cc b/runtime/art_field.cc index dbba2b0918..3f70958cff 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -18,6 +18,7 @@ #include "art_field-inl.h" #include "class_linker-inl.h" +#include "dex/descriptors_names.h" #include "gc/accounting/card_table-inl.h" #include "handle_scope.h" #include "mirror/class-inl.h" diff --git a/runtime/art_method.cc b/runtime/art_method.cc index efdf5991ec..bbc60072b6 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -25,6 +25,7 @@ #include "base/stringpiece.h" #include "class_linker-inl.h" #include "debugger.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" #include "dex/dex_instruction.h" diff --git a/runtime/base/file_magic.cc b/runtime/base/file_magic.cc index e668699a0b..2b9bed0397 100644 --- a/runtime/base/file_magic.cc +++ b/runtime/base/file_magic.cc @@ -24,7 +24,6 @@ #include <android-base/stringprintf.h> #include "base/unix_file/fd_file.h" -#include "dex/dex_file.h" namespace art { diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc index 58990f344b..dd3f8d5b3c 100644 --- a/runtime/base/file_utils.cc +++ b/runtime/base/file_utils.cc @@ -45,15 +45,12 @@ #include "android-base/stringprintf.h" #include "android-base/strings.h" +#include "base/bit_utils.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" -#include "dex/dex_file-inl.h" #include "dex/dex_file_loader.h" -#include "dex/dex_instruction.h" -#include "dex/utf-inl.h" -#include "oat_quick_method_header.h" +#include "globals.h" #include "os.h" -#include "scoped_thread_state_change-inl.h" #if defined(__APPLE__) #include <crt_externs.h> diff --git a/runtime/base/file_utils_test.cc b/runtime/base/file_utils_test.cc new file mode 100644 index 0000000000..cf6e34d1ea --- /dev/null +++ b/runtime/base/file_utils_test.cc @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2011 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 "base/file_utils.h" + +#include <libgen.h> +#include <stdlib.h> + +#include "base/stl_util.h" +#include "common_runtime_test.h" + +namespace art { + +class FileUtilsTest : public CommonRuntimeTest {}; + +TEST_F(FileUtilsTest, GetDalvikCacheFilename) { + std::string name; + std::string error; + + EXPECT_TRUE(GetDalvikCacheFilename("/system/app/Foo.apk", "/foo", &name, &error)) << error; + EXPECT_EQ("/foo/system@app@Foo.apk@classes.dex", name); + + EXPECT_TRUE(GetDalvikCacheFilename("/data/app/foo-1.apk", "/foo", &name, &error)) << error; + EXPECT_EQ("/foo/data@app@foo-1.apk@classes.dex", name); + + EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/core.jar", "/foo", &name, &error)) << error; + EXPECT_EQ("/foo/system@framework@core.jar@classes.dex", name); + + EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.art", "/foo", &name, &error)) << error; + EXPECT_EQ("/foo/system@framework@boot.art", name); + + EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.oat", "/foo", &name, &error)) << error; + EXPECT_EQ("/foo/system@framework@boot.oat", name); +} + +TEST_F(FileUtilsTest, GetDalvikCache) { + EXPECT_STREQ("", GetDalvikCache("should-not-exist123").c_str()); + + EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".").c_str()); +} + + +TEST_F(FileUtilsTest, GetSystemImageFilename) { + EXPECT_STREQ("/system/framework/arm/boot.art", + GetSystemImageFilename("/system/framework/boot.art", InstructionSet::kArm).c_str()); +} + +TEST_F(FileUtilsTest, GetAndroidRootSafe) { + std::string error_msg; + + // We don't expect null returns for most cases, so don't check and let std::string crash. + + // CommonRuntimeTest sets ANDROID_ROOT, so expect this to be the same. + std::string android_root = GetAndroidRootSafe(&error_msg); + std::string android_root_env = getenv("ANDROID_ROOT"); + EXPECT_EQ(android_root, android_root_env); + + // Set ANDROID_ROOT to something else (but the directory must exist). So use dirname. + char* root_dup = strdup(android_root_env.c_str()); + char* dir = dirname(root_dup); + ASSERT_EQ(0, setenv("ANDROID_ROOT", dir, 1 /* overwrite */)); + std::string android_root2 = GetAndroidRootSafe(&error_msg); + EXPECT_STREQ(dir, android_root2.c_str()); + free(root_dup); + + // Set a bogus value for ANDROID_ROOT. This should be an error. + ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", 1 /* overwrite */)); + EXPECT_TRUE(GetAndroidRootSafe(&error_msg) == nullptr); + + // Unset ANDROID_ROOT and see that it still returns something (as libart code is running). + ASSERT_EQ(0, unsetenv("ANDROID_ROOT")); + std::string android_root3 = GetAndroidRootSafe(&error_msg); + // This should be the same as the other root (modulo realpath), otherwise the test setup is + // broken. + UniqueCPtr<char> real_root(realpath(android_root.c_str(), nullptr)); + UniqueCPtr<char> real_root3(realpath(android_root3.c_str(), nullptr)); + EXPECT_STREQ(real_root.get(), real_root3.get()); + + + // Reset ANDROID_ROOT, as other things may depend on it. + ASSERT_EQ(0, setenv("ANDROID_ROOT", android_root_env.c_str(), 1 /* overwrite */)); +} + +} // namespace art diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc index 90eb74c75c..78d54292d1 100644 --- a/runtime/base/logging.cc +++ b/runtime/base/logging.cc @@ -22,7 +22,6 @@ #include "aborting.h" #include "mutex.h" -#include "thread-current-inl.h" #include "utils.h" // Headers for LogMessage::LogLine. diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 02580cc03f..900ce0eac3 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -31,6 +31,7 @@ #include "base/time_utils.h" #include "class_linker-inl.h" #include "class_linker.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "gc/space/space.h" #include "java_vm_ext.h" diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 63d47e6869..9c0cceeb4b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -50,6 +50,7 @@ #include "class_table-inl.h" #include "compiler_callbacks.h" #include "debugger.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" #include "dex/dex_file_loader.h" diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 61ad725b79..602e094e39 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -33,6 +33,7 @@ #include "base/time_utils.h" #include "class_linker-inl.h" #include "class_linker.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" #include "dex/dex_file_types.h" diff --git a/runtime/exec_utils_test.cc b/runtime/exec_utils_test.cc new file mode 100644 index 0000000000..68edfa8b72 --- /dev/null +++ b/runtime/exec_utils_test.cc @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 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 "exec_utils.h" + +#include "base/file_utils.h" +#include "base/memory_tool.h" +#include "common_runtime_test.h" + +namespace art { + +std::string PrettyArguments(const char* signature); +std::string PrettyReturnType(const char* signature); + +class ExecUtilsTest : public CommonRuntimeTest {}; + +TEST_F(ExecUtilsTest, ExecSuccess) { + std::vector<std::string> command; + if (kIsTargetBuild) { + std::string android_root(GetAndroidRoot()); + command.push_back(android_root + "/bin/id"); + } else { + command.push_back("/usr/bin/id"); + } + std::string error_msg; + if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { + // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. + EXPECT_TRUE(Exec(command, &error_msg)); + } + EXPECT_EQ(0U, error_msg.size()) << error_msg; +} + +TEST_F(ExecUtilsTest, ExecError) { + // This will lead to error messages in the log. + ScopedLogSeverity sls(LogSeverity::FATAL); + + std::vector<std::string> command; + command.push_back("bogus"); + std::string error_msg; + if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { + // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. + EXPECT_FALSE(Exec(command, &error_msg)); + EXPECT_FALSE(error_msg.empty()); + } +} + +TEST_F(ExecUtilsTest, EnvSnapshotAdditionsAreNotVisible) { + static constexpr const char* kModifiedVariable = "EXEC_SHOULD_NOT_EXPORT_THIS"; + static constexpr int kOverwrite = 1; + // Set an variable in the current environment. + EXPECT_EQ(setenv(kModifiedVariable, "NEVER", kOverwrite), 0); + // Test that it is not exported. + std::vector<std::string> command; + if (kIsTargetBuild) { + std::string android_root(GetAndroidRoot()); + command.push_back(android_root + "/bin/printenv"); + } else { + command.push_back("/usr/bin/printenv"); + } + command.push_back(kModifiedVariable); + std::string error_msg; + if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { + // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. + EXPECT_FALSE(Exec(command, &error_msg)); + EXPECT_NE(0U, error_msg.size()) << error_msg; + } +} + +TEST_F(ExecUtilsTest, EnvSnapshotDeletionsAreNotVisible) { + static constexpr const char* kDeletedVariable = "PATH"; + static constexpr int kOverwrite = 1; + // Save the variable's value. + const char* save_value = getenv(kDeletedVariable); + EXPECT_NE(save_value, nullptr); + // Delete the variable. + EXPECT_EQ(unsetenv(kDeletedVariable), 0); + // Test that it is not exported. + std::vector<std::string> command; + if (kIsTargetBuild) { + std::string android_root(GetAndroidRoot()); + command.push_back(android_root + "/bin/printenv"); + } else { + command.push_back("/usr/bin/printenv"); + } + command.push_back(kDeletedVariable); + std::string error_msg; + if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { + // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. + EXPECT_TRUE(Exec(command, &error_msg)); + EXPECT_EQ(0U, error_msg.size()) << error_msg; + } + // Restore the variable's value. + EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0); +} + +} // namespace art diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index f8dd8293ca..a0b58ef29e 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -35,6 +35,7 @@ #include "base/macros.h" #include "class_linker.h" #include "common_throws.h" +#include "dex/descriptors_names.h" #include "entrypoints/entrypoint_utils-inl.h" #include "gc/reference_processor.h" #include "handle_scope-inl.h" diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index 0986005e4b..fd435627bf 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -24,6 +24,7 @@ #include "base/memory_tool.h" #include "class_linker.h" #include "common_runtime_test.h" +#include "dex/descriptors_names.h" #include "dex/dex_instruction.h" #include "handle.h" #include "handle_scope-inl.h" diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 5d730ce0b0..7a09391056 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -25,6 +25,7 @@ #include "class_ext.h" #include "class_linker-inl.h" #include "class_loader.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" #include "dex_cache.h" diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 3765d0af59..f274cfc2fa 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -24,6 +24,7 @@ #include "class-inl.h" #include "class.h" #include "class_linker-inl.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "gc/accounting/card_table-inl.h" #include "gc/heap.h" diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc index cad84ceecb..6208a962e5 100644 --- a/runtime/mirror/string.cc +++ b/runtime/mirror/string.cc @@ -21,6 +21,7 @@ #include "base/array_ref.h" #include "base/stl_util.h" #include "class-inl.h" +#include "dex/descriptors_names.h" #include "dex/utf-inl.h" #include "gc/accounting/card_table-inl.h" #include "gc_root-inl.h" diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index b49209c4cf..dd7b34ae21 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -28,6 +28,7 @@ #include "common_throws.h" #include "compiler_filter.h" #include "dex/art_dex_file_loader.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_loader.h" #include "jit/debugger_interface.h" diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index e518553292..38a4a3bfb0 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -23,6 +23,7 @@ #include "base/enums.h" #include "class_linker-inl.h" #include "common_throws.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" #include "dex/utf.h" diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index 6eebff4aca..3a0d76032e 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -17,6 +17,7 @@ #include "java_lang_VMClassLoader.h" #include "class_linker.h" +#include "dex/descriptors_names.h" #include "dex/dex_file_loader.h" #include "jni_internal.h" #include "mirror/class_loader.h" diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h index 62ce9e9509..6edb12f4c5 100644 --- a/runtime/reflection-inl.h +++ b/runtime/reflection-inl.h @@ -22,6 +22,7 @@ #include "android-base/stringprintf.h" #include "common_throws.h" +#include "dex/descriptors_names.h" #include "jvalue-inl.h" #include "mirror/object-inl.h" #include "obj_ptr-inl.h" diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc index 7794872c83..7b36c7368e 100644 --- a/runtime/reflection_test.cc +++ b/runtime/reflection_test.cc @@ -22,6 +22,7 @@ #include "art_method-inl.h" #include "base/enums.h" #include "common_compiler_test.h" +#include "dex/descriptors_names.h" #include "java_vm_ext.h" #include "jni_internal.h" #include "nativehelper/scoped_local_ref.h" diff --git a/runtime/thread.cc b/runtime/thread.cc index 1de7b20737..4cdf015478 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -47,6 +47,7 @@ #include "base/to_str.h" #include "class_linker-inl.h" #include "debugger.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" #include "dex/dex_file_types.h" diff --git a/runtime/trace.cc b/runtime/trace.cc index f9d22df543..bdc6757c89 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -31,6 +31,7 @@ #include "class_linker.h" #include "common_throws.h" #include "debugger.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "entrypoints/quick/quick_entrypoints.h" #include "gc/scoped_gc_critical_section.h" diff --git a/runtime/utils.cc b/runtime/utils.cc index 393b18e1b3..7246c3d279 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -72,59 +72,6 @@ std::string GetThreadName(pid_t tid) { return result; } -void AppendPrettyDescriptor(const char* descriptor, std::string* result) { - // Count the number of '['s to get the dimensionality. - const char* c = descriptor; - size_t dim = 0; - while (*c == '[') { - dim++; - c++; - } - - // Reference or primitive? - if (*c == 'L') { - // "[[La/b/C;" -> "a.b.C[][]". - c++; // Skip the 'L'. - } else { - // "[[B" -> "byte[][]". - // To make life easier, we make primitives look like unqualified - // reference types. - switch (*c) { - case 'B': c = "byte;"; break; - case 'C': c = "char;"; break; - case 'D': c = "double;"; break; - case 'F': c = "float;"; break; - case 'I': c = "int;"; break; - case 'J': c = "long;"; break; - case 'S': c = "short;"; break; - case 'Z': c = "boolean;"; break; - case 'V': c = "void;"; break; // Used when decoding return types. - default: result->append(descriptor); return; - } - } - - // At this point, 'c' is a string of the form "fully/qualified/Type;" - // or "primitive;". Rewrite the type with '.' instead of '/': - const char* p = c; - while (*p != ';') { - char ch = *p++; - if (ch == '/') { - ch = '.'; - } - result->push_back(ch); - } - // ...and replace the semicolon with 'dim' "[]" pairs: - for (size_t i = 0; i < dim; ++i) { - result->append("[]"); - } -} - -std::string PrettyDescriptor(const char* descriptor) { - std::string result; - AppendPrettyDescriptor(descriptor, &result); - return result; -} - std::string PrettySize(int64_t byte_count) { // The byte thresholds at which we display amounts. A byte count is displayed // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1]. @@ -151,330 +98,6 @@ std::string PrettySize(int64_t byte_count) { negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]); } -std::string GetJniShortName(const std::string& class_descriptor, const std::string& method) { - // Remove the leading 'L' and trailing ';'... - std::string class_name(class_descriptor); - CHECK_EQ(class_name[0], 'L') << class_name; - CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name; - class_name.erase(0, 1); - class_name.erase(class_name.size() - 1, 1); - - std::string short_name; - short_name += "Java_"; - short_name += MangleForJni(class_name); - short_name += "_"; - short_name += MangleForJni(method); - return short_name; -} - -// See http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp615 for the full rules. -std::string MangleForJni(const std::string& s) { - std::string result; - size_t char_count = CountModifiedUtf8Chars(s.c_str()); - const char* cp = &s[0]; - for (size_t i = 0; i < char_count; ++i) { - uint32_t ch = GetUtf16FromUtf8(&cp); - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) { - result.push_back(ch); - } else if (ch == '.' || ch == '/') { - result += "_"; - } else if (ch == '_') { - result += "_1"; - } else if (ch == ';') { - result += "_2"; - } else if (ch == '[') { - result += "_3"; - } else { - const uint16_t leading = GetLeadingUtf16Char(ch); - const uint32_t trailing = GetTrailingUtf16Char(ch); - - StringAppendF(&result, "_0%04x", leading); - if (trailing != 0) { - StringAppendF(&result, "_0%04x", trailing); - } - } - } - return result; -} - -std::string DotToDescriptor(const char* class_name) { - std::string descriptor(class_name); - std::replace(descriptor.begin(), descriptor.end(), '.', '/'); - if (descriptor.length() > 0 && descriptor[0] != '[') { - descriptor = "L" + descriptor + ";"; - } - return descriptor; -} - -std::string DescriptorToDot(const char* descriptor) { - size_t length = strlen(descriptor); - if (length > 1) { - if (descriptor[0] == 'L' && descriptor[length - 1] == ';') { - // Descriptors have the leading 'L' and trailing ';' stripped. - std::string result(descriptor + 1, length - 2); - std::replace(result.begin(), result.end(), '/', '.'); - return result; - } else { - // For arrays the 'L' and ';' remain intact. - std::string result(descriptor); - std::replace(result.begin(), result.end(), '/', '.'); - return result; - } - } - // Do nothing for non-class/array descriptors. - return descriptor; -} - -std::string DescriptorToName(const char* descriptor) { - size_t length = strlen(descriptor); - if (descriptor[0] == 'L' && descriptor[length - 1] == ';') { - std::string result(descriptor + 1, length - 2); - return result; - } - return descriptor; -} - -// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii. -uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = { - 0x00000000, // 00..1f low control characters; nothing valid - 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-' - 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_' - 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z' -}; - -// Helper for IsValidPartOfMemberNameUtf8(); do not call directly. -bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) { - /* - * It's a multibyte encoded character. Decode it and analyze. We - * accept anything that isn't (a) an improperly encoded low value, - * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high - * control character, or (e) a high space, layout, or special - * character (U+00a0, U+2000..U+200f, U+2028..U+202f, - * U+fff0..U+ffff). This is all specified in the dex format - * document. - */ - - const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr); - const uint16_t leading = GetLeadingUtf16Char(pair); - - // We have a surrogate pair resulting from a valid 4 byte UTF sequence. - // No further checks are necessary because 4 byte sequences span code - // points [U+10000, U+1FFFFF], which are valid codepoints in a dex - // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of - // the surrogate halves are valid and well formed in this instance. - if (GetTrailingUtf16Char(pair) != 0) { - return true; - } - - - // We've encountered a one, two or three byte UTF-8 sequence. The - // three byte UTF-8 sequence could be one half of a surrogate pair. - switch (leading >> 8) { - case 0x00: - // It's only valid if it's above the ISO-8859-1 high space (0xa0). - return (leading > 0x00a0); - case 0xd8: - case 0xd9: - case 0xda: - case 0xdb: - { - // We found a three byte sequence encoding one half of a surrogate. - // Look for the other half. - const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr); - const uint16_t trailing = GetLeadingUtf16Char(pair2); - - return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff); - } - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - // It's a trailing surrogate, which is not valid at this point. - return false; - case 0x20: - case 0xff: - // It's in the range that has spaces, controls, and specials. - switch (leading & 0xfff8) { - case 0x2000: - case 0x2008: - case 0x2028: - case 0xfff0: - case 0xfff8: - return false; - } - return true; - default: - return true; - } - - UNREACHABLE(); -} - -/* Return whether the pointed-at modified-UTF-8 encoded character is - * valid as part of a member name, updating the pointer to point past - * the consumed character. This will consume two encoded UTF-16 code - * points if the character is encoded as a surrogate pair. Also, if - * this function returns false, then the given pointer may only have - * been partially advanced. - */ -static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) { - uint8_t c = (uint8_t) **pUtf8Ptr; - if (LIKELY(c <= 0x7f)) { - // It's low-ascii, so check the table. - uint32_t wordIdx = c >> 5; - uint32_t bitIdx = c & 0x1f; - (*pUtf8Ptr)++; - return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0; - } - - // It's a multibyte encoded character. Call a non-inline function - // for the heavy lifting. - return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr); -} - -bool IsValidMemberName(const char* s) { - bool angle_name = false; - - switch (*s) { - case '\0': - // The empty string is not a valid name. - return false; - case '<': - angle_name = true; - s++; - break; - } - - while (true) { - switch (*s) { - case '\0': - return !angle_name; - case '>': - return angle_name && s[1] == '\0'; - } - - if (!IsValidPartOfMemberNameUtf8(&s)) { - return false; - } - } -} - -enum ClassNameType { kName, kDescriptor }; -template<ClassNameType kType, char kSeparator> -static bool IsValidClassName(const char* s) { - int arrayCount = 0; - while (*s == '[') { - arrayCount++; - s++; - } - - if (arrayCount > 255) { - // Arrays may have no more than 255 dimensions. - return false; - } - - ClassNameType type = kType; - if (type != kDescriptor && arrayCount != 0) { - /* - * If we're looking at an array of some sort, then it doesn't - * matter if what is being asked for is a class name; the - * format looks the same as a type descriptor in that case, so - * treat it as such. - */ - type = kDescriptor; - } - - if (type == kDescriptor) { - /* - * We are looking for a descriptor. Either validate it as a - * single-character primitive type, or continue on to check the - * embedded class name (bracketed by "L" and ";"). - */ - switch (*(s++)) { - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - case 'Z': - // These are all single-character descriptors for primitive types. - return (*s == '\0'); - case 'V': - // Non-array void is valid, but you can't have an array of void. - return (arrayCount == 0) && (*s == '\0'); - case 'L': - // Class name: Break out and continue below. - break; - default: - // Oddball descriptor character. - return false; - } - } - - /* - * We just consumed the 'L' that introduces a class name as part - * of a type descriptor, or we are looking for an unadorned class - * name. - */ - - bool sepOrFirst = true; // first character or just encountered a separator. - for (;;) { - uint8_t c = (uint8_t) *s; - switch (c) { - case '\0': - /* - * Premature end for a type descriptor, but valid for - * a class name as long as we haven't encountered an - * empty component (including the degenerate case of - * the empty string ""). - */ - return (type == kName) && !sepOrFirst; - case ';': - /* - * Invalid character for a class name, but the - * legitimate end of a type descriptor. In the latter - * case, make sure that this is the end of the string - * and that it doesn't end with an empty component - * (including the degenerate case of "L;"). - */ - return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0'); - case '/': - case '.': - if (c != kSeparator) { - // The wrong separator character. - return false; - } - if (sepOrFirst) { - // Separator at start or two separators in a row. - return false; - } - sepOrFirst = true; - s++; - break; - default: - if (!IsValidPartOfMemberNameUtf8(&s)) { - return false; - } - sepOrFirst = false; - break; - } - } -} - -bool IsValidBinaryClassName(const char* s) { - return IsValidClassName<kName, '.'>(s); -} - -bool IsValidJniClassName(const char* s) { - return IsValidClassName<kName, '/'>(s); -} - -bool IsValidDescriptor(const char* s) { - return IsValidClassName<kDescriptor, '/'>(s); -} - void Split(const std::string& s, char separator, std::vector<std::string>* result) { const char* p = s.data(); const char* end = p + s.size(); @@ -541,10 +164,6 @@ void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) *task_cpu = strtoull(fields[36].c_str(), nullptr, 10); } -std::string PrettyDescriptor(Primitive::Type type) { - return PrettyDescriptor(Primitive::Descriptor(type)); -} - static void ParseStringAfterChar(const std::string& s, char c, std::string* parsed_value, diff --git a/runtime/utils.h b/runtime/utils.h index 443b0cc398..7dc8f354e4 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -67,44 +67,9 @@ static inline uint32_t PointerToLowMemUInt32(const void* p) { return intp & 0xFFFFFFFFU; } -// Used to implement PrettyClass, PrettyField, PrettyMethod, and PrettyTypeOf, -// one of which is probably more useful to you. -// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int", -// "[[I" would be "int[][]", "[Ljava/lang/String;" would be -// "java.lang.String[]", and so forth. -void AppendPrettyDescriptor(const char* descriptor, std::string* result); -std::string PrettyDescriptor(const char* descriptor); -std::string PrettyDescriptor(Primitive::Type type); - // Returns a human-readable size string such as "1MB". std::string PrettySize(int64_t size_in_bytes); -// Performs JNI name mangling as described in section 11.3 "Linking Native Methods" -// of the JNI spec. -std::string MangleForJni(const std::string& s); - -std::string GetJniShortName(const std::string& class_name, const std::string& method_name); - -// Turn "java.lang.String" into "Ljava/lang/String;". -std::string DotToDescriptor(const char* class_name); - -// Turn "Ljava/lang/String;" into "java.lang.String" using the conventions of -// java.lang.Class.getName(). -std::string DescriptorToDot(const char* descriptor); - -// Turn "Ljava/lang/String;" into "java/lang/String" using the opposite conventions of -// java.lang.Class.getName(). -std::string DescriptorToName(const char* descriptor); - -// Tests for whether 's' is a valid class name in the three common forms: -bool IsValidBinaryClassName(const char* s); // "java.lang.String" -bool IsValidJniClassName(const char* s); // "java/lang/String" -bool IsValidDescriptor(const char* s); // "Ljava/lang/String;" - -// Returns whether the given string is a valid field or method name, -// additionally allowing names that begin with '<' and end with '>'. -bool IsValidMemberName(const char* s); - // Splits a string using the given separator character into a vector of // strings. Empty strings will be omitted. void Split(const std::string& s, char separator, std::vector<std::string>* result); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index 1dc46871ac..e67e93f9c5 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -37,63 +37,8 @@ namespace art { -std::string PrettyArguments(const char* signature); -std::string PrettyReturnType(const char* signature); - class UtilsTest : public CommonRuntimeTest {}; -TEST_F(UtilsTest, PrettyDescriptor_ArrayReferences) { - EXPECT_EQ("java.lang.Class[]", PrettyDescriptor("[Ljava/lang/Class;")); - EXPECT_EQ("java.lang.Class[][]", PrettyDescriptor("[[Ljava/lang/Class;")); -} - -TEST_F(UtilsTest, PrettyDescriptor_ScalarReferences) { - EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava.lang.String;")); - EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava/lang/String;")); -} - -TEST_F(UtilsTest, PrettyDescriptor_Primitive) { - EXPECT_EQ("boolean", PrettyDescriptor(Primitive::kPrimBoolean)); - EXPECT_EQ("byte", PrettyDescriptor(Primitive::kPrimByte)); - EXPECT_EQ("char", PrettyDescriptor(Primitive::kPrimChar)); - EXPECT_EQ("short", PrettyDescriptor(Primitive::kPrimShort)); - EXPECT_EQ("int", PrettyDescriptor(Primitive::kPrimInt)); - EXPECT_EQ("float", PrettyDescriptor(Primitive::kPrimFloat)); - EXPECT_EQ("long", PrettyDescriptor(Primitive::kPrimLong)); - EXPECT_EQ("double", PrettyDescriptor(Primitive::kPrimDouble)); - EXPECT_EQ("void", PrettyDescriptor(Primitive::kPrimVoid)); -} - -TEST_F(UtilsTest, PrettyDescriptor_PrimitiveArrays) { - EXPECT_EQ("boolean[]", PrettyDescriptor("[Z")); - EXPECT_EQ("boolean[][]", PrettyDescriptor("[[Z")); - EXPECT_EQ("byte[]", PrettyDescriptor("[B")); - EXPECT_EQ("byte[][]", PrettyDescriptor("[[B")); - EXPECT_EQ("char[]", PrettyDescriptor("[C")); - EXPECT_EQ("char[][]", PrettyDescriptor("[[C")); - EXPECT_EQ("double[]", PrettyDescriptor("[D")); - EXPECT_EQ("double[][]", PrettyDescriptor("[[D")); - EXPECT_EQ("float[]", PrettyDescriptor("[F")); - EXPECT_EQ("float[][]", PrettyDescriptor("[[F")); - EXPECT_EQ("int[]", PrettyDescriptor("[I")); - EXPECT_EQ("int[][]", PrettyDescriptor("[[I")); - EXPECT_EQ("long[]", PrettyDescriptor("[J")); - EXPECT_EQ("long[][]", PrettyDescriptor("[[J")); - EXPECT_EQ("short[]", PrettyDescriptor("[S")); - EXPECT_EQ("short[][]", PrettyDescriptor("[[S")); -} - -TEST_F(UtilsTest, PrettyDescriptor_PrimitiveScalars) { - EXPECT_EQ("boolean", PrettyDescriptor("Z")); - EXPECT_EQ("byte", PrettyDescriptor("B")); - EXPECT_EQ("char", PrettyDescriptor("C")); - EXPECT_EQ("double", PrettyDescriptor("D")); - EXPECT_EQ("float", PrettyDescriptor("F")); - EXPECT_EQ("int", PrettyDescriptor("I")); - EXPECT_EQ("long", PrettyDescriptor("J")); - EXPECT_EQ("short", PrettyDescriptor("S")); -} - TEST_F(UtilsTest, PrettyTypeOf) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", mirror::Object::PrettyTypeOf(nullptr)); @@ -163,15 +108,6 @@ TEST_F(UtilsTest, PrettySize) { EXPECT_EQ("512B", PrettySize(512)); } -TEST_F(UtilsTest, MangleForJni) { - ScopedObjectAccess soa(Thread::Current()); - EXPECT_EQ("hello_00024world", MangleForJni("hello$world")); - EXPECT_EQ("hello_000a9world", MangleForJni("hello\xc2\xa9world")); - EXPECT_EQ("hello_1world", MangleForJni("hello_world")); - EXPECT_EQ("Ljava_lang_String_2", MangleForJni("Ljava/lang/String;")); - EXPECT_EQ("_3C", MangleForJni("[C")); -} - TEST_F(UtilsTest, JniShortName_JniLongName) { ScopedObjectAccess soa(Thread::Current()); mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;"); @@ -263,140 +199,6 @@ TEST_F(UtilsTest, Split) { EXPECT_EQ(expected, actual); } -TEST_F(UtilsTest, GetDalvikCacheFilename) { - std::string name; - std::string error; - - EXPECT_TRUE(GetDalvikCacheFilename("/system/app/Foo.apk", "/foo", &name, &error)) << error; - EXPECT_EQ("/foo/system@app@Foo.apk@classes.dex", name); - - EXPECT_TRUE(GetDalvikCacheFilename("/data/app/foo-1.apk", "/foo", &name, &error)) << error; - EXPECT_EQ("/foo/data@app@foo-1.apk@classes.dex", name); - - EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/core.jar", "/foo", &name, &error)) << error; - EXPECT_EQ("/foo/system@framework@core.jar@classes.dex", name); - - EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.art", "/foo", &name, &error)) << error; - EXPECT_EQ("/foo/system@framework@boot.art", name); - - EXPECT_TRUE(GetDalvikCacheFilename("/system/framework/boot.oat", "/foo", &name, &error)) << error; - EXPECT_EQ("/foo/system@framework@boot.oat", name); -} - -TEST_F(UtilsTest, GetDalvikCache) { - EXPECT_STREQ("", GetDalvikCache("should-not-exist123").c_str()); - - EXPECT_STREQ((android_data_ + "/dalvik-cache/.").c_str(), GetDalvikCache(".").c_str()); -} - - -TEST_F(UtilsTest, GetSystemImageFilename) { - EXPECT_STREQ("/system/framework/arm/boot.art", - GetSystemImageFilename("/system/framework/boot.art", InstructionSet::kArm).c_str()); -} - -TEST_F(UtilsTest, ExecSuccess) { - std::vector<std::string> command; - if (kIsTargetBuild) { - std::string android_root(GetAndroidRoot()); - command.push_back(android_root + "/bin/id"); - } else { - command.push_back("/usr/bin/id"); - } - std::string error_msg; - if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { - // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. - EXPECT_TRUE(Exec(command, &error_msg)); - } - EXPECT_EQ(0U, error_msg.size()) << error_msg; -} - -TEST_F(UtilsTest, ExecError) { - // This will lead to error messages in the log. - ScopedLogSeverity sls(LogSeverity::FATAL); - - std::vector<std::string> command; - command.push_back("bogus"); - std::string error_msg; - if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { - // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. - EXPECT_FALSE(Exec(command, &error_msg)); - EXPECT_FALSE(error_msg.empty()); - } -} - -TEST_F(UtilsTest, EnvSnapshotAdditionsAreNotVisible) { - static constexpr const char* kModifiedVariable = "EXEC_SHOULD_NOT_EXPORT_THIS"; - static constexpr int kOverwrite = 1; - // Set an variable in the current environment. - EXPECT_EQ(setenv(kModifiedVariable, "NEVER", kOverwrite), 0); - // Test that it is not exported. - std::vector<std::string> command; - if (kIsTargetBuild) { - std::string android_root(GetAndroidRoot()); - command.push_back(android_root + "/bin/printenv"); - } else { - command.push_back("/usr/bin/printenv"); - } - command.push_back(kModifiedVariable); - std::string error_msg; - if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { - // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. - EXPECT_FALSE(Exec(command, &error_msg)); - EXPECT_NE(0U, error_msg.size()) << error_msg; - } -} - -TEST_F(UtilsTest, EnvSnapshotDeletionsAreNotVisible) { - static constexpr const char* kDeletedVariable = "PATH"; - static constexpr int kOverwrite = 1; - // Save the variable's value. - const char* save_value = getenv(kDeletedVariable); - EXPECT_NE(save_value, nullptr); - // Delete the variable. - EXPECT_EQ(unsetenv(kDeletedVariable), 0); - // Test that it is not exported. - std::vector<std::string> command; - if (kIsTargetBuild) { - std::string android_root(GetAndroidRoot()); - command.push_back(android_root + "/bin/printenv"); - } else { - command.push_back("/usr/bin/printenv"); - } - command.push_back(kDeletedVariable); - std::string error_msg; - if (!(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) { - // Running on valgrind fails due to some memory that leaks in thread alternate signal stacks. - EXPECT_TRUE(Exec(command, &error_msg)); - EXPECT_EQ(0U, error_msg.size()) << error_msg; - } - // Restore the variable's value. - EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0); -} - -TEST_F(UtilsTest, IsValidDescriptor) { - std::vector<uint8_t> descriptor( - { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, ';', 0x00 }); - EXPECT_TRUE(IsValidDescriptor(reinterpret_cast<char*>(&descriptor[0]))); - - std::vector<uint8_t> unpaired_surrogate( - { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, ';', 0x00 }); - EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate[0]))); - - std::vector<uint8_t> unpaired_surrogate_at_end( - { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0x00 }); - EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate_at_end[0]))); - - std::vector<uint8_t> invalid_surrogate( - { 'L', 'a', '/', 'b', '$', 0xed, 0xb0, 0x80, ';', 0x00 }); - EXPECT_FALSE(IsValidDescriptor(reinterpret_cast<char*>(&invalid_surrogate[0]))); - - std::vector<uint8_t> unpaired_surrogate_with_multibyte_sequence( - { 'L', 'a', '/', 'b', '$', 0xed, 0xb0, 0x80, 0xf0, 0x9f, 0x8f, 0xa0, ';', 0x00 }); - EXPECT_FALSE( - IsValidDescriptor(reinterpret_cast<char*>(&unpaired_surrogate_with_multibyte_sequence[0]))); -} - TEST_F(UtilsTest, ArrayCount) { int i[64]; EXPECT_EQ(ArrayCount(i), 64u); @@ -416,40 +218,4 @@ TEST_F(UtilsTest, BoundsCheckedCast) { EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer + 57, buffer, buffer_end), nullptr); } -TEST_F(UtilsTest, GetAndroidRootSafe) { - std::string error_msg; - - // We don't expect null returns for most cases, so don't check and let std::string crash. - - // CommonRuntimeTest sets ANDROID_ROOT, so expect this to be the same. - std::string android_root = GetAndroidRootSafe(&error_msg); - std::string android_root_env = getenv("ANDROID_ROOT"); - EXPECT_EQ(android_root, android_root_env); - - // Set ANDROID_ROOT to something else (but the directory must exist). So use dirname. - char* root_dup = strdup(android_root_env.c_str()); - char* dir = dirname(root_dup); - ASSERT_EQ(0, setenv("ANDROID_ROOT", dir, 1 /* overwrite */)); - std::string android_root2 = GetAndroidRootSafe(&error_msg); - EXPECT_STREQ(dir, android_root2.c_str()); - free(root_dup); - - // Set a bogus value for ANDROID_ROOT. This should be an error. - ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", 1 /* overwrite */)); - EXPECT_TRUE(GetAndroidRootSafe(&error_msg) == nullptr); - - // Unset ANDROID_ROOT and see that it still returns something (as libart code is running). - ASSERT_EQ(0, unsetenv("ANDROID_ROOT")); - std::string android_root3 = GetAndroidRootSafe(&error_msg); - // This should be the same as the other root (modulo realpath), otherwise the test setup is - // broken. - UniqueCPtr<char> real_root(realpath(android_root.c_str(), nullptr)); - UniqueCPtr<char> real_root3(realpath(android_root3.c_str(), nullptr)); - EXPECT_STREQ(real_root.get(), real_root3.get()); - - - // Reset ANDROID_ROOT, as other things may depend on it. - ASSERT_EQ(0, setenv("ANDROID_ROOT", android_root_env.c_str(), 1 /* overwrite */)); -} - } // namespace art diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 66e578f312..9a393ea1c5 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -31,6 +31,7 @@ #include "base/time_utils.h" #include "class_linker.h" #include "compiler_callbacks.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_exception_helpers.h" #include "dex/dex_instruction-inl.h" diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 7ebdd90fc0..e7864a28a0 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -22,6 +22,7 @@ #include "base/bit_vector-inl.h" #include "base/casts.h" #include "class_linker-inl.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "method_verifier.h" #include "mirror/class-inl.h" diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 30aefede20..87fc60bd23 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -25,6 +25,7 @@ #include "base/scoped_arena_allocator.h" #include "base/stl_util.h" #include "class_linker-inl.h" +#include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" |