From 322214405bf43684dbbde2fce549b2dad53fb04a Mon Sep 17 00:00:00 2001 From: Alex Light Date: Tue, 20 Dec 2016 08:55:35 -0800 Subject: [PATCH] Create test for field access in obsolete methods. Test: ./test/run-test --host 918 Change-Id: Idf27a0a713e12876e35de5c24bf5d12984881927 --- test/918-obsolete-fields/build | 17 +++ test/918-obsolete-fields/expected.txt | 21 ++++ test/918-obsolete-fields/info.txt | 1 + test/918-obsolete-fields/run | 19 ++++ test/918-obsolete-fields/src/Main.java | 157 ++++++++++++++++++++++++++++ test/918-obsolete-fields/src/Transform.java | 47 +++++++++ test/Android.run-test.mk | 1 + test/ti-agent/common_load.cc | 1 + 8 files changed, 264 insertions(+) create mode 100755 test/918-obsolete-fields/build create mode 100644 test/918-obsolete-fields/expected.txt create mode 100644 test/918-obsolete-fields/info.txt create mode 100755 test/918-obsolete-fields/run create mode 100644 test/918-obsolete-fields/src/Main.java create mode 100644 test/918-obsolete-fields/src/Transform.java diff --git a/test/918-obsolete-fields/build b/test/918-obsolete-fields/build new file mode 100755 index 000000000..898e2e54a --- /dev/null +++ b/test/918-obsolete-fields/build @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Copyright 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. +# 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. + +./default-build "$@" --experimental agents diff --git a/test/918-obsolete-fields/expected.txt b/test/918-obsolete-fields/expected.txt new file mode 100644 index 000000000..4caefc620 --- /dev/null +++ b/test/918-obsolete-fields/expected.txt @@ -0,0 +1,21 @@ +Pre Start private method call +hello - private +Post Start private method call +Not doing anything here +Pre Finish private method call +goodbye - private +Post Finish private method call +Pre Start private method call +hello - private +Post Start private method call +transforming calling function +Pre Finish private method call +Goodbye - private - Transformed +Post Finish private method call +pre Start private method call - Transformed +Hello - private - Transformed +post Start private method call - Transformed +Not doing anything here +pre Finish private method call - Transformed +Goodbye - private - Transformed +post Finish private method call - Transformed diff --git a/test/918-obsolete-fields/info.txt b/test/918-obsolete-fields/info.txt new file mode 100644 index 000000000..97739cabb --- /dev/null +++ b/test/918-obsolete-fields/info.txt @@ -0,0 +1 @@ +Tests obsolete method field access support diff --git a/test/918-obsolete-fields/run b/test/918-obsolete-fields/run new file mode 100755 index 000000000..4379349cb --- /dev/null +++ b/test/918-obsolete-fields/run @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright 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. +# 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. + +./default-run "$@" --experimental agents \ + --experimental runtime-plugins \ + --jvmti diff --git a/test/918-obsolete-fields/src/Main.java b/test/918-obsolete-fields/src/Main.java new file mode 100644 index 000000000..a746032eb --- /dev/null +++ b/test/918-obsolete-fields/src/Main.java @@ -0,0 +1,157 @@ +/* + * 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. + * 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.util.function.Consumer; +import java.util.Base64; + +public class Main { + + // import java.util.function.Consumer; + // + // class Transform { + // private Consumer reporter; + // public Transform(Consumer reporter) { + // this.reporter = reporter; + // } + // + // private void Start() { + // reporter.accept("Hello - private - Transformed"); + // } + // + // private void Finish() { + // reporter.accept("Goodbye - private - Transformed"); + // } + // + // public void sayHi(Runnable r) { + // reporter.accept("pre Start private method call - Transformed"); + // Start(); + // reporter.accept("post Start private method call - Transformed"); + // r.run(); + // reporter.accept("pre Finish private method call - Transformed"); + // Finish(); + // reporter.accept("post Finish private method call - Transformed"); + // } + // } + private static final byte[] CLASS_BYTES = Base64.getDecoder().decode( + "yv66vgAAADQANAoADgAfCQANACAIACELACIAIwgAJAgAJQoADQAmCAAnCwAoACkIACoKAA0AKwgA" + + "LAcALQcALgEACHJlcG9ydGVyAQAdTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjsBAAlTaWdu" + + "YXR1cmUBADFMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xhbmcvU3RyaW5nOz47" + + "AQAGPGluaXQ+AQAgKExqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7KVYBAARDb2RlAQAPTGlu" + + "ZU51bWJlclRhYmxlAQA0KExqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI8TGphdmEvbGFuZy9T" + + "dHJpbmc7PjspVgEABVN0YXJ0AQADKClWAQAGRmluaXNoAQAFc2F5SGkBABcoTGphdmEvbGFuZy9S" + + "dW5uYWJsZTspVgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwAEwAZDAAPABABAB1IZWxs" + + "byAtIHByaXZhdGUgLSBUcmFuc2Zvcm1lZAcALwwAMAAxAQAfR29vZGJ5ZSAtIHByaXZhdGUgLSBU" + + "cmFuc2Zvcm1lZAEAK3ByZSBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQM" + + "ABgAGQEALHBvc3QgU3RhcnQgcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkBwAyDAAz" + + "ABkBACxwcmUgRmluaXNoIHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAwAGgAZAQAt" + + "cG9zdCBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkAQAJVHJhbnNmb3Jt" + + "AQAQamF2YS9sYW5nL09iamVjdAEAG2phdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcgEABmFjY2Vw" + + "dAEAFShMamF2YS9sYW5nL09iamVjdDspVgEAEmphdmEvbGFuZy9SdW5uYWJsZQEAA3J1bgAgAA0A" + + "DgAAAAEAAgAPABAAAQARAAAAAgASAAQAAQATABQAAgAVAAAAKgACAAIAAAAKKrcAASortQACsQAA" + + "AAEAFgAAAA4AAwAAABUABAAWAAkAFwARAAAAAgAXAAIAGAAZAAEAFQAAACgAAgABAAAADCq0AAIS" + + "A7kABAIAsQAAAAEAFgAAAAoAAgAAABoACwAbAAIAGgAZAAEAFQAAACgAAgABAAAADCq0AAISBbkA" + + "BAIAsQAAAAEAFgAAAAoAAgAAAB4ACwAfAAEAGwAcAAEAFQAAAG8AAgACAAAAOyq0AAISBrkABAIA" + + "KrcAByq0AAISCLkABAIAK7kACQEAKrQAAhIKuQAEAgAqtwALKrQAAhIMuQAEAgCxAAAAAQAWAAAA" + + "IgAIAAAAIgALACMADwAkABoAJQAgACYAKwAnAC8AKAA6ACkAAQAdAAAAAgAe"); + private static final byte[] DEX_BYTES = Base64.getDecoder().decode( + "ZGV4CjAzNQAw/b59wCwTlSVDmuhPEezuK3oe0rtT4ujMBQAAcAAAAHhWNBIAAAAAAAAAAAgFAAAd" + + "AAAAcAAAAAYAAADkAAAABAAAAPwAAAABAAAALAEAAAcAAAA0AQAAAQAAAGwBAABABAAAjAEAAJoC" + + "AACdAgAAoAIAAKgCAACsAgAAsgIAALoCAADbAgAA+gIAAAcDAAAmAwAAOgMAAFADAABkAwAAggMA" + + "AKEDAACoAwAAuAMAALsDAAC/AwAAxwMAANsDAAAKBAAAOAQAAGYEAACTBAAAnQQAAKIEAACpBAAA" + + "CAAAAAkAAAAKAAAACwAAAA4AAAARAAAAEQAAAAUAAAAAAAAAEgAAAAUAAACEAgAAEgAAAAUAAACM" + + "AgAAEgAAAAUAAACUAgAAAAAEABkAAAAAAAMAAgAAAAAAAAAFAAAAAAAAAA8AAAAAAAIAGwAAAAIA" + + "AAACAAAAAwAAABoAAAAEAAEAEwAAAAAAAAAAAAAAAgAAAAAAAAAQAAAAZAIAAO8EAAAAAAAAAQAA" + + "ANEEAAABAAAA3wQAAAIAAgABAAAAsAQAAAYAAABwEAQAAABbAQAADgADAAEAAgAAALgEAAAJAAAA" + + "VCAAABsBBgAAAHIgBgAQAA4AAAADAAEAAgAAAL4EAAAJAAAAVCAAABsBBwAAAHIgBgAQAA4AAAAE" + + "AAIAAgAAAMQEAAAqAAAAVCAAABsBGAAAAHIgBgAQAHAQAgACAFQgAAAbARYAAAByIAYAEAByEAUA" + + "AwBUIAAAGwEXAAAAciAGABAAcBABAAIAVCAAABsBFQAAAHIgBgAQAA4AAAAAAAEAAAABAAAAAAAA" + + "AAAAAACMAQAAAAAAAJQBAAABAAAAAgAAAAEAAAADAAAAAQAAAAQAASgAATwABjxpbml0PgACPjsA" + + "BD47KVYABkZpbmlzaAAfR29vZGJ5ZSAtIHByaXZhdGUgLSBUcmFuc2Zvcm1lZAAdSGVsbG8gLSBw" + + "cml2YXRlIC0gVHJhbnNmb3JtZWQAC0xUcmFuc2Zvcm07AB1MZGFsdmlrL2Fubm90YXRpb24vU2ln" + + "bmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5nL1J1bm5hYmxlOwASTGphdmEv" + + "bGFuZy9TdHJpbmc7ABxMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAB1MamF2YS91dGlsL2Z1" + + "bmN0aW9uL0NvbnN1bWVyOwAFU3RhcnQADlRyYW5zZm9ybS5qYXZhAAFWAAJWTAAGYWNjZXB0ABJl" + + "bWl0dGVyOiBqYWNrLTQuMTkALXBvc3QgRmluaXNoIHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFu" + + "c2Zvcm1lZAAscG9zdCBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQALHBy" + + "ZSBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkACtwcmUgU3RhcnQgcHJp" + + "dmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkAAhyZXBvcnRlcgADcnVuAAVzYXlIaQAFdmFs" + + "dWUAFQEABw48LQAeAAcOhwAaAAcOhwAiAQAHDoc8hzyHPIcAAgEBHBwEFw0XARcMFwMCAQEcHAUX" + + "ABcNFwEXDBcEAAEDAQACAIGABJwDAQK4AwEC3AMDAYAEABAAAAAAAAAAAQAAAAAAAAABAAAAHQAA" + + "AHAAAAACAAAABgAAAOQAAAADAAAABAAAAPwAAAAEAAAAAQAAACwBAAAFAAAABwAAADQBAAAGAAAA" + + "AQAAAGwBAAADEAAAAgAAAIwBAAABIAAABAAAAJwBAAAGIAAAAQAAAGQCAAABEAAAAwAAAIQCAAAC" + + "IAAAHQAAAJoCAAADIAAABAAAALAEAAAEIAAAAgAAANEEAAAAIAAAAQAAAO8EAAAAEAAAAQAAAAgF" + + "AAA="); + + // A class that we can use to keep track of the output of this test. + private static class TestWatcher implements Consumer { + private StringBuilder sb; + public TestWatcher() { + sb = new StringBuilder(); + } + + @Override + public void accept(String s) { + sb.append(s); + sb.append('\n'); + } + + public String getOutput() { + return sb.toString(); + } + + public void clear() { + sb = new StringBuilder(); + } + } + + public static void main(String[] args) { + System.loadLibrary(args[1]); + TestWatcher w = new TestWatcher(); + doTest(new Transform(w), w); + } + + // TODO Workaround to (1) inability to ensure that current_method is not put into a register by + // the JIT and/or (2) inability to deoptimize frames near runtime functions. + // TODO Fix one/both of these issues. + public static void doCall(Runnable r) { + r.run(); + } + + private static boolean interpreting = true; + private static boolean retry = false; + + public static void doTest(Transform t, TestWatcher w) { + Runnable do_redefinition = () -> { + w.accept("transforming calling function"); + doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES); + }; + // This just prints something out to show we are running the Runnable. + Runnable say_nothing = () -> { w.accept("Not doing anything here"); }; + + // Try and redefine. + t.sayHi(say_nothing); + t.sayHi(do_redefinition); + t.sayHi(say_nothing); + + // Print output of last run. + System.out.print(w.getOutput()); + } + + // Transforms the class + private static native void doCommonClassRedefinition(Class target, + byte[] classfile, + byte[] dexfile); +} diff --git a/test/918-obsolete-fields/src/Transform.java b/test/918-obsolete-fields/src/Transform.java new file mode 100644 index 000000000..abd1d19b6 --- /dev/null +++ b/test/918-obsolete-fields/src/Transform.java @@ -0,0 +1,47 @@ +/* + * 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. + * 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.util.function.Consumer; + +class Transform { + private Consumer reporter; + public Transform(Consumer reporter) { + this.reporter = reporter; + } + + private void Start() { + reporter.accept("hello - private"); + } + + private void Finish() { + reporter.accept("goodbye - private"); + } + + public void sayHi(Runnable r) { + reporter.accept("Pre Start private method call"); + Start(); + reporter.accept("Post Start private method call"); + // TODO Revist with b/33616143 + // TODO Uncomment this + // r.run(); + // TODO This is a very temporary fix until we get either deoptimization near runtime frames + // working, forcing current method to be always read from the stack or both working. + Main.doCall(r); + reporter.accept("Pre Finish private method call"); + Finish(); + reporter.accept("Post Finish private method call"); + } +} diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 56f7ed796..474e95d9f 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -288,6 +288,7 @@ TEST_ART_BROKEN_TARGET_TESTS += \ 915-obsolete-2 \ 916-obsolete-jit \ 917-fields-transformation \ + 918-obsolete-fields \ ifneq (,$(filter target,$(TARGET_TYPES))) ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \ diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 79c17d744..33619b9fd 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -70,6 +70,7 @@ AgentLib agents[] = { { "915-obsolete-2", common_redefine::OnLoad, nullptr }, { "916-obsolete-jit", common_redefine::OnLoad, nullptr }, { "917-fields-transformation", common_redefine::OnLoad, nullptr }, + { "918-obsolete-fields", common_redefine::OnLoad, nullptr }, }; static AgentLib* FindAgent(char* name) { -- 2.11.0