summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/1945-proxy-method-arguments/expected.txt26
-rw-r--r--test/1945-proxy-method-arguments/get_args.cc113
-rw-r--r--test/1945-proxy-method-arguments/info.txt7
-rw-r--r--test/1945-proxy-method-arguments/src/Main.java149
-rwxr-xr-xtest/807-method-handle-and-mr/build (renamed from test/990-method-handle-and-mr/build)0
-rw-r--r--test/807-method-handle-and-mr/expected.txt (renamed from test/990-method-handle-and-mr/expected.txt)0
-rw-r--r--test/807-method-handle-and-mr/info.txt (renamed from test/990-method-handle-and-mr/info.txt)0
-rw-r--r--test/807-method-handle-and-mr/src/Main.java (renamed from test/990-method-handle-and-mr/src/Main.java)0
-rw-r--r--test/912-classes/src-art/art/Test912.java1
-rw-r--r--test/983-source-transform-verify/source_transform.cc100
-rw-r--r--test/983-source-transform-verify/source_transform.h4
-rw-r--r--test/983-source-transform-verify/source_transform_art.cc80
-rw-r--r--test/983-source-transform-verify/source_transform_slicer.cc41
-rw-r--r--test/983-source-transform-verify/src/art/Test983.java8
-rw-r--r--test/Android.bp70
-rwxr-xr-xtest/etc/run-test-jar2
-rw-r--r--test/knownfailures.json49
-rwxr-xr-xtest/testrunner/testrunner.py7
-rw-r--r--test/ti-agent/common_load.cc2
19 files changed, 522 insertions, 137 deletions
diff --git a/test/1945-proxy-method-arguments/expected.txt b/test/1945-proxy-method-arguments/expected.txt
new file mode 100644
index 0000000000..1824953202
--- /dev/null
+++ b/test/1945-proxy-method-arguments/expected.txt
@@ -0,0 +1,26 @@
+JNI_OnLoad called
+proxy: $Proxy0
+Proxy for interface TestInterface.method0
+ arg0: $Proxy0
+Proxy for interface TestInterface.method1
+ arg0: $Proxy0
+ arg1: java.lang.String "a"
+Proxy for interface TestInterface.method10
+ arg0: $Proxy0
+ arg1: java.lang.String "one"
+ arg2: java.lang.String "two"
+ arg3: java.lang.String "three"
+ arg4: java.lang.String "four"
+ arg5: java.lang.String "five"
+ arg6: java.lang.String "six"
+ arg7: java.lang.String "seven"
+ arg8: java.lang.String "eight"
+ arg9: java.lang.String "nine"
+ arg10: java.lang.String "ten"
+Proxy for interface TestInterface.method10Even
+ arg0: $Proxy0
+ arg2: java.lang.String "two"
+ arg4: java.lang.String "four"
+ arg6: java.lang.String "six"
+ arg8: java.lang.String "eight"
+ arg10: java.lang.String "ten"
diff --git a/test/1945-proxy-method-arguments/get_args.cc b/test/1945-proxy-method-arguments/get_args.cc
new file mode 100644
index 0000000000..211ae10ab0
--- /dev/null
+++ b/test/1945-proxy-method-arguments/get_args.cc
@@ -0,0 +1,113 @@
+/*
+ * 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 "arch/context.h"
+#include "art_method-inl.h"
+#include "jni.h"
+#include "oat_quick_method_header.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread.h"
+
+namespace art {
+
+namespace {
+
+// Visit a proxy method Quick frame at a given depth.
+class GetProxyQuickFrameVisitor FINAL : public StackVisitor {
+ public:
+ GetProxyQuickFrameVisitor(art::Thread* target, art::Context* ctx, size_t frame_depth)
+ REQUIRES_SHARED(art::Locks::mutator_lock_)
+ : art::StackVisitor(target, ctx, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+ cur_depth_(0u),
+ frame_depth_(frame_depth),
+ quick_frame_(nullptr) {}
+
+ bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (GetMethod()->IsRuntimeMethod()) {
+ return true;
+ }
+ if (cur_depth_ == frame_depth_) {
+ // Found frame.
+ ShadowFrame* shadow_frame = GetCurrentShadowFrame();
+ if (shadow_frame != nullptr) {
+ // Nothing to do.
+ } else {
+ VisitQuickFrameAtSearchedDepth();
+ }
+ return false;
+ } else {
+ ++cur_depth_;
+ return true;
+ }
+ }
+
+ void VisitQuickFrameAtSearchedDepth() REQUIRES_SHARED(Locks::mutator_lock_) {
+ quick_frame_ = GetCurrentQuickFrame();
+ CHECK(quick_frame_ != nullptr);
+ ArtMethod* method = *quick_frame_;
+ CHECK(method != nullptr);
+ CHECK(method->IsProxyMethod()) << method->PrettyMethod();
+ }
+
+ // Return the found Quick frame.
+ ArtMethod** GetQuickFrame() {
+ return quick_frame_;
+ }
+
+ private:
+ // The depth of the currently visited frame.
+ size_t cur_depth_;
+ // The depth of the currently searched frame.
+ size_t frame_depth_;
+ // The quick frame, if found.
+ ArtMethod** quick_frame_;
+ // Method name
+
+ DISALLOW_COPY_AND_ASSIGN(GetProxyQuickFrameVisitor);
+};
+
+extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(size_t arg_pos,
+ ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+jobject GetProxyReferenceArgument(size_t arg_pos, size_t proxy_method_frame_depth) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ std::unique_ptr<Context> context(Context::Create());
+
+ GetProxyQuickFrameVisitor visitor(self, context.get(), proxy_method_frame_depth);
+ visitor.WalkStack();
+ ArtMethod** quick_frame = visitor.GetQuickFrame();
+ CHECK(quick_frame != nullptr);
+
+ // Find reference argument in frame.
+ StackReference<mirror::Object>* ref_arg =
+ artQuickGetProxyReferenceArgumentAt(arg_pos, quick_frame);
+ CHECK(ref_arg != nullptr);
+ art::ObjPtr<mirror::Object> obj = ref_arg->AsMirrorPtr();
+
+ return obj.IsNull() ? nullptr : soa.AddLocalReference<jobject>(obj);
+}
+
+extern "C" JNIEXPORT jobject JNICALL Java_TestInvocationHandler_getArgument(
+ JNIEnv* env ATTRIBUTE_UNUSED, jobject thiz ATTRIBUTE_UNUSED, int arg_pos, int frame_depth) {
+ return GetProxyReferenceArgument(arg_pos, frame_depth);
+}
+
+} // namespace
+
+} // namespace art
diff --git a/test/1945-proxy-method-arguments/info.txt b/test/1945-proxy-method-arguments/info.txt
new file mode 100644
index 0000000000..15ccc44ac9
--- /dev/null
+++ b/test/1945-proxy-method-arguments/info.txt
@@ -0,0 +1,7 @@
+Test checking that reference arguments of proxy methods are visited as
+thread stack roots when visiting Quick frames roots (b/73149739).
+Previously, if the proxy method (direcly or indirectly) executed code
+accessing one of these reference arguments in the proxy method stack
+frame, it could end up with a stale reference, as the corresponding
+object may have been moved by the garbage collector, but the stack
+reference would not have been updated.
diff --git a/test/1945-proxy-method-arguments/src/Main.java b/test/1945-proxy-method-arguments/src/Main.java
new file mode 100644
index 0000000000..b04a661a4b
--- /dev/null
+++ b/test/1945-proxy-method-arguments/src/Main.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+interface TestInterface {
+ void method0();
+ void method1(String arg);
+ void method10(String arg1, String arg2, String arg3, String arg4, String arg5,
+ String arg6, String arg7, String arg8, String arg9, String arg10);
+ void method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5,
+ String arg6, long arg7, String arg8, double arg9, String arg10);
+}
+
+class TestInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) {
+ // Force garbage collection to try to make `proxy` move in memory
+ // (in the case of a moving garbage collector).
+ System.gc();
+
+ System.out.println("Proxy for " + TestInterface.class + "." + method.getName());
+ if (method.getName().equals("method0")) {
+ testMethod0(proxy, args);
+ } else if (method.getName().equals("method1")) {
+ testMethod1(proxy, args);
+ } else if (method.getName().equals("method10")) {
+ testMethod10(proxy, args);
+ } else if (method.getName().equals("method10Even")) {
+ testMethod10Even(proxy, args);
+ }
+ return null;
+ }
+
+ private void testMethod0(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ }
+
+ private void testMethod1(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument 1 from the proxy method frame ($Proxy0.method1 activation).
+ String arg1 = (String) getProxyMethodArgument(1);
+ System.out.println(" arg1: " + arg1.getClass().getName() + " \"" + arg1 + "\"");
+ Main.assertEquals(args[0], arg1);
+ }
+
+ private void testMethod10(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument `i` from the proxy method frame ($Proxy0.method10 activation).
+ for (int i = 0; i < 10; ++i) {
+ int arg_pos = i + 1;
+ String arg = (String) getProxyMethodArgument(arg_pos);
+ System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\"");
+ Main.assertEquals(args[i], arg);
+ }
+ }
+
+ private void testMethod10Even(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10Even
+ // activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument `i` from the proxy method frame ($Proxy0.method10Even activation).
+ for (int i = 1; i < 10; i += 2) {
+ int arg_pos = i + 1;
+ String arg = (String) getProxyMethodArgument(arg_pos);
+ System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\"");
+ Main.assertEquals(args[i], arg);
+ }
+ }
+
+ // Get reference argument at position `arg_pos` in proxy frame.
+ // This method should only be called from one of the
+ // `TestInvocationHandler.testMethod*` methods via `TestInvocationHandler.invoke`.
+ private Object getProxyMethodArgument(int arg_pos) {
+ // Find proxy frame in stack (from a testMethod* method).
+ //
+ // depth method
+ // ----------------------------------------------------------------------
+ // 0 TestInvocationHandler.getArgument (outermost frame)
+ // 1 TestInvocationHandler.getProxyMethodArgument
+ // 2 TestInvocationHandler.testMethod*
+ // 3 TestInvocationHandler.invoke
+ // 4 java.lang.reflect.Proxy.invoke
+ // -> 5 TestInterface.method* (proxy method)
+ // 6 Main.main (innermost frame)
+ //
+ int proxy_method_frame_depth = 5;
+ return getArgument(arg_pos, proxy_method_frame_depth);
+ }
+
+ // Get reference argument at position `arg_pos` in frame at depth `frame_depth`.
+ private native Object getArgument(int arg_pos, int frame_depth);
+}
+
+public class Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+
+ TestInvocationHandler invocationHandler = new TestInvocationHandler();
+ TestInterface proxy = (TestInterface) Proxy.newProxyInstance(
+ Main.class.getClassLoader(),
+ new Class<?>[] { TestInterface.class },
+ invocationHandler);
+ System.out.println("proxy: " + proxy.getClass().getName());
+
+ proxy.method0();
+ proxy.method1("a");
+ proxy.method10("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
+ proxy.method10Even((byte) 1, "two", (short) 3, "four", 5, "six", 7L, "eight", 9.0, "ten");
+ }
+
+ public static void assertEquals(Object expected, Object actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ public static void assertEquals(String expected, String actual) {
+ if (expected != actual) {
+ throw new Error("Expected \"" + expected + "\", got \"" + actual + "\"");
+ }
+ }
+}
diff --git a/test/990-method-handle-and-mr/build b/test/807-method-handle-and-mr/build
index 12a8e18d0b..12a8e18d0b 100755
--- a/test/990-method-handle-and-mr/build
+++ b/test/807-method-handle-and-mr/build
diff --git a/test/990-method-handle-and-mr/expected.txt b/test/807-method-handle-and-mr/expected.txt
index 8483fb5045..8483fb5045 100644
--- a/test/990-method-handle-and-mr/expected.txt
+++ b/test/807-method-handle-and-mr/expected.txt
diff --git a/test/990-method-handle-and-mr/info.txt b/test/807-method-handle-and-mr/info.txt
index 85a957ceea..85a957ceea 100644
--- a/test/990-method-handle-and-mr/info.txt
+++ b/test/807-method-handle-and-mr/info.txt
diff --git a/test/990-method-handle-and-mr/src/Main.java b/test/807-method-handle-and-mr/src/Main.java
index 739b8eb551..739b8eb551 100644
--- a/test/990-method-handle-and-mr/src/Main.java
+++ b/test/807-method-handle-and-mr/src/Main.java
diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java
index ddfadf3626..1a60185f49 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -398,6 +398,7 @@ public class Test912 {
public static double dummy = Math.random(); // So it can't be compile-time initialized.
}
+ @SuppressWarnings("RandomCast")
private static class TestForInitFail {
public static int dummy = ((int)Math.random())/0; // So it throws when initializing.
}
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index dfefce207b..9e65a9964c 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -14,30 +14,13 @@
* limitations under the License.
*/
-#include <inttypes.h>
+#include "source_transform.h"
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <vector>
+#include "jni.h"
#include "android-base/stringprintf.h"
-#include "jni.h"
#include "jvmti.h"
-
-#include "base/macros.h"
-#include "bytecode_utils.h"
-#include "dex/code_item_accessors-inl.h"
-#include "dex/art_dex_file_loader.h"
-#include "dex/dex_file.h"
-#include "dex/dex_file_loader.h"
-#include "dex/dex_instruction.h"
-#include "jit/jit.h"
-#include "native_stack_dump.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
-#include "thread_list.h"
+#include "scoped_local_ref.h"
// Test infrastructure
#include "jvmti_helper.h"
@@ -48,9 +31,18 @@ namespace Test983SourceTransformVerify {
constexpr bool kSkipInitialLoad = true;
+static void Println(JNIEnv* env, const char* msg) {
+ ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983"));
+ jmethodID println_method = env->GetStaticMethodID(test_klass.get(),
+ "doPrintln",
+ "(Ljava/lang/String;)V");
+ ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg));
+ env->CallStaticVoidMethod(test_klass.get(), println_method, data.get());
+}
+
// The hook we are using.
void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
- JNIEnv* jni_env ATTRIBUTE_UNUSED,
+ JNIEnv* env,
jclass class_being_redefined,
jobject loader ATTRIBUTE_UNUSED,
const char* name,
@@ -60,78 +52,24 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
jint* new_class_data_len ATTRIBUTE_UNUSED,
unsigned char** new_class_data ATTRIBUTE_UNUSED) {
if (kSkipInitialLoad && class_being_redefined == nullptr) {
- // Something got loaded concurrently. Just ignore it for now.
+ // Something got loaded concurrently. Just ignore it for now. To make sure the test is
+ // repeatable we only care about things that come from RetransformClasses.
return;
}
- std::cout << "Dex file hook for " << name << std::endl;
+ Println(env, android::base::StringPrintf("Dex file hook for %s", name).c_str());
if (IsJVM()) {
return;
}
- // Due to b/72402467 the class_data_len might just be an estimate.
- CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
- const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
- uint32_t header_file_size = header->file_size_;
- CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
- class_data_len = static_cast<jint>(header_file_size);
-
- const ArtDexFileLoader dex_file_loader;
- std::string error;
- std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
- class_data_len,
- "fake_location.dex",
- /*location_checksum*/ 0,
- /*oat_dex_file*/ nullptr,
- /*verify*/ true,
- /*verify_checksum*/ true,
- &error));
- if (dex.get() == nullptr) {
- std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
- return;
- }
- for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
- const DexFile::ClassDef& def = dex->GetClassDef(i);
- const uint8_t* data_item = dex->GetClassData(def);
- if (data_item == nullptr) {
- continue;
- }
- for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
- if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
- continue;
- }
- for (const DexInstructionPcPair& pair :
- art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
- const Instruction& inst = pair.Inst();
- int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
- if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
- (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
- std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
- << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
- << inst.DumpString(dex.get()) << std::endl;
- continue;
- }
- }
- }
- }
+ VerifyClassData(class_data_len, class_data);
}
// Get all capabilities except those related to retransformation.
-jint OnLoad(JavaVM* vm,
- char* options ATTRIBUTE_UNUSED,
- void* reserved ATTRIBUTE_UNUSED) {
- if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
- printf("Unable to get jvmti env!\n");
- return 1;
- }
- SetStandardCapabilities(jvmti_env);
+extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) {
jvmtiEventCallbacks cb;
memset(&cb, 0, sizeof(cb));
cb.ClassFileLoadHook = CheckDexFileHook;
- if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
- printf("Unable to set class file load hook cb!\n");
- return 1;
- }
- return 0;
+ JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
}
} // namespace Test983SourceTransformVerify
diff --git a/test/983-source-transform-verify/source_transform.h b/test/983-source-transform-verify/source_transform.h
index db9415aec1..2206498cc3 100644
--- a/test/983-source-transform-verify/source_transform.h
+++ b/test/983-source-transform-verify/source_transform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -22,7 +22,7 @@
namespace art {
namespace Test983SourceTransformVerify {
-jint OnLoad(JavaVM* vm, char* options, void* reserved);
+void VerifyClassData(jint class_data_len, const unsigned char* class_data);
} // namespace Test983SourceTransformVerify
} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc
new file mode 100644
index 0000000000..5353370ac6
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_art.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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 "source_transform.h"
+
+#include <inttypes.h>
+
+#include <memory>
+
+#include <android-base/logging.h>
+
+#include "dex/code_item_accessors-inl.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "dex/dex_instruction.h"
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ // Due to b/72402467 the class_data_len might just be an estimate.
+ CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
+ const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
+ uint32_t header_file_size = header->file_size_;
+ CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
+ class_data_len = static_cast<jint>(header_file_size);
+
+ const ArtDexFileLoader dex_file_loader;
+ std::string error;
+ std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
+ class_data_len,
+ "fake_location.dex",
+ /*location_checksum*/ 0,
+ /*oat_dex_file*/ nullptr,
+ /*verify*/ true,
+ /*verify_checksum*/ true,
+ &error));
+ CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error;
+ for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
+ const DexFile::ClassDef& def = dex->GetClassDef(i);
+ const uint8_t* data_item = dex->GetClassData(def);
+ if (data_item == nullptr) {
+ continue;
+ }
+ for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
+ if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
+ continue;
+ }
+ for (const DexInstructionPcPair& pair :
+ art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
+ const Instruction& inst = pair.Inst();
+ int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
+ if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
+ (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
+ LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
+ << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
+ << inst.DumpString(dex.get()) << std::endl;
+ }
+ }
+ }
+ }
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc
new file mode 100644
index 0000000000..abf32e752e
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_slicer.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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 "source_transform.h"
+
+#pragma clang diagnostic push
+// slicer defines its own CHECK. b/65422458
+#pragma push_macro("CHECK")
+#undef CHECK
+
+// Slicer's headers have code that triggers these warnings. b/65298177
+#pragma clang diagnostic ignored "-Wsign-compare"
+#include "reader.h"
+
+#pragma pop_macro("CHECK")
+#pragma clang diagnostic pop
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ dex::Reader reader(class_data, class_data_len);
+ reader.CreateFullIr(); // This will verify all bytecode.
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java
index faae96aef6..7dc47ab06a 100644
--- a/test/983-source-transform-verify/src/art/Test983.java
+++ b/test/983-source-transform-verify/src/art/Test983.java
@@ -27,7 +27,15 @@ public class Test983 {
doTest();
}
+ private native static void setupLoadHook();
+
+ /* called from JNI */
+ public static void doPrintln(String str) {
+ System.out.println(str);
+ }
+
public static void doTest() {
+ setupLoadHook();
Redefinition.enableCommonRetransformation(true);
Redefinition.doCommonClassRetransformation(Transform.class);
Redefinition.doCommonClassRetransformation(Object.class);
diff --git a/test/Android.bp b/test/Android.bp
index 5f39ffefa9..bf39ec4d9f 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -62,7 +62,7 @@ art_cc_defaults {
"libvixld-arm",
"libvixld-arm64",
"libart-gtest",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libicuuc",
@@ -114,7 +114,7 @@ art_cc_defaults {
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
],
static_libs: [
"libgtest",
@@ -151,7 +151,7 @@ art_cc_library {
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libbacktrace",
],
@@ -169,7 +169,6 @@ cc_defaults {
"art_defaults",
],
shared_libs: [
- "libdexfile",
"libbacktrace",
"libbase",
"libnativehelper",
@@ -180,7 +179,10 @@ art_cc_test_library {
name: "libartagent",
srcs: ["900-hello-plugin/load_unload.cc"],
defaults: ["libartagent-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -190,7 +192,10 @@ art_cc_test_library {
"art_debug_defaults",
"libartagent-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
art_cc_defaults {
@@ -238,6 +243,7 @@ art_cc_defaults {
"931-agent-thread/agent_thread.cc",
"933-misc-events/misc_events.cc",
"945-obsolete-native/obsolete_native.cc",
+ "983-source-transform-verify/source_transform.cc",
"984-obsolete-invoke/obsolete_invoke.cc",
"986-native-method-bind/native_bind.cc",
"987-agent-bind/agent_bind.cc",
@@ -288,20 +294,22 @@ art_cc_defaults {
"909-attach-agent/attach.cc",
"912-classes/classes_art.cc",
"936-search-onload/search_onload.cc",
- "983-source-transform-verify/source_transform.cc",
+ "983-source-transform-verify/source_transform_art.cc",
"1940-ddms-ext/ddm_ext.cc",
"1944-sudden-exit/sudden_exit.cc",
],
shared_libs: [
"libbase",
- "libdexfile",
],
}
art_cc_test_library {
name: "libtiagent",
defaults: ["libtiagent-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -310,24 +318,32 @@ art_cc_test_library {
"art_debug_defaults",
"libtiagent-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
-art_cc_test_library {
+cc_library_static {
name: "libctstiagent",
defaults: ["libtiagent-base-defaults"],
+ host_supported: false,
+ srcs: [
+ "983-source-transform-verify/source_transform_slicer.cc",
+ ],
whole_static_libs: [
- "libdexfile",
- "libz",
- "libziparchive",
+ "slicer",
+ "libz", // for slicer (using adler32).
],
static_libs: [
"libbase",
- "libcutils",
- "libutils",
],
- shared_libs: [
- "liblog",
+ header_libs: [
+ // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are
+ // many problems with how we export headers that are making doing this the 'right' way
+ // difficult.
+ // TODO: move those headers to art/ rather than under runtime.
+ "libart_runtime_headers",
],
export_include_dirs: ["ti-agent"],
}
@@ -367,11 +383,9 @@ cc_defaults {
"art_defaults",
],
srcs: [
- "common/runtime_state.cc",
- "common/stack_inspect.cc",
"004-JniTest/jni_test.cc",
- "004-SignalTest/signaltest.cc",
"004-ReferenceMap/stack_walk_refmap_jni.cc",
+ "004-SignalTest/signaltest.cc",
"004-StackWalk/stack_walk_jni.cc",
"004-ThreadStress/thread_stress.cc",
"004-UnsafeTest/unsafe_test.cc",
@@ -388,6 +402,7 @@ cc_defaults {
"154-gc-loop/heap_interface.cc",
"167-visit-locks/visit_locks.cc",
"169-threadgroup-jni/jni_daemon_thread.cc",
+ "1945-proxy-method-arguments/get_args.cc",
"203-multi-checkpoint/multi_checkpoint.cc",
"305-other-fault-handler/fault_handler.cc",
"454-get-vreg/get_vreg_jni.cc",
@@ -411,9 +426,10 @@ cc_defaults {
"667-jit-jni-stub/jit_jni_stub_test.cc",
"674-hiddenapi/hiddenapi.cc",
"708-jit-cache-churn/jit.cc",
+ "common/runtime_state.cc",
+ "common/stack_inspect.cc",
],
shared_libs: [
- "libdexfile",
"libbacktrace",
"libbase",
"libnativehelper",
@@ -423,7 +439,10 @@ cc_defaults {
art_cc_test_library {
name: "libarttest",
defaults: ["libarttest-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -432,7 +451,10 @@ art_cc_test_library {
"art_debug_defaults",
"libarttest-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
art_cc_test_library {
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index bb6ace1b06..b8427f491b 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -850,7 +850,7 @@ if [ "$HOST" = "n" ]; then
fi
# System libraries needed by libarttestd.so
- PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so
+ PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so
# Create a script with the command. The command can get longer than the longest
# allowed adb command and there is no way to get the exit status from a adb shell
diff --git a/test/knownfailures.json b/test/knownfailures.json
index b483b93e19..ddf9098c64 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -377,12 +377,6 @@
"variant": "jvmti-stress & jit | redefine-stress & jit"
},
{
- "test_patterns": ["674-hiddenapi"],
- "description": ["hiddenapi test is failing with redefine stress cdex"],
- "bug": "http://b/72610009",
- "variant": "redefine-stress & cdex-fast"
- },
- {
"test_patterns": ["616-cha"],
"description": ["The test assumes a boot image exists."],
"bug": "http://b/34193647",
@@ -423,21 +417,13 @@
"variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile"
},
{
- "tests": [
- "714-invoke-custom-lambda-metafactory",
- "950-redefine-intrinsic",
- "951-threaded-obsolete",
- "952-invoke-custom",
- "952-invoke-custom-kinds",
- "953-invoke-polymorphic-compiler",
- "954-invoke-polymorphic-verifier",
- "955-methodhandles-smali",
- "956-methodhandles",
- "957-methodhandle-transforms",
- "958-methodhandle-stackframe",
- "959-invoke-polymorphic-accessors",
- "979-const-method-handle",
- "990-method-handle-and-mr"
+ "test_patterns": [
+ ".*invoke-custom.*",
+ ".*invoke-polymorphic.*",
+ ".*methodhandle.*",
+ ".*method-handle.*",
+ ".*varhandle.*",
+ ".*var-handle.*"
],
"description": [
"Tests that use invoke-polymorphic/invoke-custom which is not yet supported by",
@@ -460,9 +446,22 @@
},
{
"tests": [
+ "132-daemon-locks-shutdown",
+ "607-daemon-stress",
+ "602-deoptimizeable",
+ "121-simple-suspend-check",
+ "083-compiler-regressions"
+ ],
+ "description": ["Tests that have failed on redefine stress for unknown reasons"],
+ "bug": "b/73177368",
+ "variant": "redefine-stress"
+ },
+ {
+ "tests": [
"097-duplicate-method",
"138-duplicate-classes-check2",
"159-app-image-fields",
+ "674-hiddenapi",
"649-vdex-duplicate-method",
"804-class-extends-itself",
"921-hello-failure"
@@ -481,6 +480,7 @@
"626-const-class-linking",
"629-vdex-speed",
"647-jni-get-field-id",
+ "674-hiddenapi",
"944-transform-classloaders"
],
"description": [
@@ -494,7 +494,7 @@
"004-ThreadStress"
],
"description": "The thread stress test just takes too long with field-stress",
- "variant": "jvmti-stress | field-stress | step-stress"
+ "variant": "jvmti-stress | field-stress | step-stress | redefine-stress"
},
{
"tests": [
@@ -653,11 +653,6 @@
"description": ["Test is designed to only check --compiler-filter=speed"]
},
{
- "test_patterns": [".*"],
- "description": ["Tests are timing out for weeks now, disable to fix."],
- "variant": "cdex-fast & redefine-stress"
- },
- {
"tests": "674-HelloWorld-Dm",
"variant": "target",
"description": ["Requires zip, which isn't available on device"]
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 3d173f5571..4329ad4863 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -110,6 +110,7 @@ test_count = 0
total_test_count = 0
verbose = False
dry_run = False
+ignore_skips = False
build = False
gdb = False
gdb_arg = ''
@@ -710,6 +711,8 @@ def is_test_disabled(test, variant_set):
return True
if test in env.EXTRA_DISABLED_TESTS:
return True
+ if ignore_skips:
+ return False
variants_list = DISABLED_TEST_CONTAINER.get(test, {})
for variants in variants_list:
variants_present = True
@@ -878,6 +881,7 @@ def get_default_threads(target):
def parse_option():
global verbose
global dry_run
+ global ignore_skips
global n_thread
global build
global gdb
@@ -897,6 +901,8 @@ def parse_option():
parser.add_argument('--dry-run', action='store_true', dest='dry_run')
parser.add_argument("--skip", action="append", dest="skips", default=[],
help="Skip the given test in all circumstances.")
+ parser.add_argument("--no-skips", dest="ignore_skips", action="store_true", default=False,
+ help="Don't skip any run-test configurations listed in knownfailures.json.")
parser.add_argument('--no-build-dependencies',
action='store_false', dest='build',
help="Don't build dependencies under any circumstances. This is the " +
@@ -935,6 +941,7 @@ def parse_option():
verbose = True
if options['n_thread']:
n_thread = max(1, options['n_thread'])
+ ignore_skips = options['ignore_skips']
if options['dry_run']:
dry_run = True
verbose = True
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 9a7352e479..bfd165db10 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -28,7 +28,6 @@
#include "901-hello-ti-agent/basics.h"
#include "909-attach-agent/attach.h"
#include "936-search-onload/search_onload.h"
-#include "983-source-transform-verify/source_transform.h"
#include "1919-vminit-thread-start-timing/vminit.h"
namespace art {
@@ -83,7 +82,6 @@ static AgentLib agents[] = {
{ "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr },
{ "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr },
{ "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
- { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr },
{ "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr },
};