diff options
Diffstat (limited to 'test/121-modifiers')
-rw-r--r-- | test/121-modifiers/build | 34 | ||||
-rw-r--r-- | test/121-modifiers/classes/A$B.class | bin | 0 -> 223 bytes | |||
-rw-r--r-- | test/121-modifiers/classes/A$C.class | bin | 0 -> 130 bytes | |||
-rw-r--r-- | test/121-modifiers/classes/A.class | bin | 0 -> 248 bytes | |||
-rw-r--r-- | test/121-modifiers/classes/Inf.class | bin | 0 -> 128 bytes | |||
-rw-r--r-- | test/121-modifiers/classes/Main.class | bin | 0 -> 3772 bytes | |||
-rw-r--r-- | test/121-modifiers/classes/NonInf.class | bin | 0 -> 1026 bytes | |||
-rw-r--r-- | test/121-modifiers/expected.txt | 0 | ||||
-rw-r--r-- | test/121-modifiers/info.txt | 1 | ||||
-rw-r--r-- | test/121-modifiers/src/Asm.java | 125 | ||||
-rw-r--r-- | test/121-modifiers/src/Inf.java | 21 | ||||
-rw-r--r-- | test/121-modifiers/src/Main.java | 211 | ||||
-rw-r--r-- | test/121-modifiers/src/NonInf.java | 72 |
13 files changed, 464 insertions, 0 deletions
diff --git a/test/121-modifiers/build b/test/121-modifiers/build new file mode 100644 index 0000000000..d73be86f95 --- /dev/null +++ b/test/121-modifiers/build @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright (C) 2014 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. + +# Stop if something fails. +set -e + +# The classes are pre-compiled and modified with ASM. +# +# To reproduce, compile the source files. Asm.java needs the ASM libraries (core and tree). Then +# run Asm.java, which produces Inf.out and NonInf.out. Rename these to class files and put them +# into the classes directory (this assumes the ASM libraries are names asm.jar and asm-tree.jar): +# +# javac Inf.java NonInf.java Main.java +# javac -cp asm.jar:asm-tree.jar:. Asm.java +# java -cp asm.jar:asm-tree.jar:. Asm +# mv Inf.out classes/Inf.class +# mv NonInf.out classes/NonInf.class +# mv Main.class A.class A\$B.class A\$C.class classes/ + +${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes +zip $TEST_NAME.jar classes.dex diff --git a/test/121-modifiers/classes/A$B.class b/test/121-modifiers/classes/A$B.class Binary files differnew file mode 100644 index 0000000000..bd7ebfe11d --- /dev/null +++ b/test/121-modifiers/classes/A$B.class diff --git a/test/121-modifiers/classes/A$C.class b/test/121-modifiers/classes/A$C.class Binary files differnew file mode 100644 index 0000000000..3ae872e356 --- /dev/null +++ b/test/121-modifiers/classes/A$C.class diff --git a/test/121-modifiers/classes/A.class b/test/121-modifiers/classes/A.class Binary files differnew file mode 100644 index 0000000000..d89d029796 --- /dev/null +++ b/test/121-modifiers/classes/A.class diff --git a/test/121-modifiers/classes/Inf.class b/test/121-modifiers/classes/Inf.class Binary files differnew file mode 100644 index 0000000000..e8dd68029d --- /dev/null +++ b/test/121-modifiers/classes/Inf.class diff --git a/test/121-modifiers/classes/Main.class b/test/121-modifiers/classes/Main.class Binary files differnew file mode 100644 index 0000000000..e044074269 --- /dev/null +++ b/test/121-modifiers/classes/Main.class diff --git a/test/121-modifiers/classes/NonInf.class b/test/121-modifiers/classes/NonInf.class Binary files differnew file mode 100644 index 0000000000..0f1e826fb7 --- /dev/null +++ b/test/121-modifiers/classes/NonInf.class diff --git a/test/121-modifiers/expected.txt b/test/121-modifiers/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/121-modifiers/expected.txt diff --git a/test/121-modifiers/info.txt b/test/121-modifiers/info.txt new file mode 100644 index 0000000000..943cbf8aba --- /dev/null +++ b/test/121-modifiers/info.txt @@ -0,0 +1 @@ +This is a test checking the modifier (access flags) handling of ART. diff --git a/test/121-modifiers/src/Asm.java b/test/121-modifiers/src/Asm.java new file mode 100644 index 0000000000..f120622120 --- /dev/null +++ b/test/121-modifiers/src/Asm.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2014 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 org.objectweb.asm.*; +import org.objectweb.asm.tree.*; +import java.io.*; +import java.util.*; + +public class Asm { + /* + + Overall class access flags: + + 0x0001 | // public + 0x0010 | // final + 0x0020 | // super + 0x0200 | // interface + 0x0400 | // abstract + 0x1000 | // synthetic + 0x2000 | // annotation + 0x4000 ; // enum + + */ + + public final static int INTERFACE_DEFINED_BITS = + 0x0001 | // public, may be set. + 0x0010 | // final, must not be set. + 0x0020 | // super, must not be set. + 0x0200 | // interface, must be set. + 0x0400 | // abstract, must be set. + 0x1000 | // synthetic, may be set. + 0x2000 | // annotation, may be set (annotation implies interface) + 0x4000 ; // enum, must not be set. + + public final static int CLASS_DEFINED_BITS = + 0x0001 | // public, may be set. + 0x0010 | // final, may be set. + 0x0020 | // super, may be set. + 0x0200 | // interface, must not be set. + 0x0400 | // abstract, may be set. + 0x1000 | // synthetic, may be set. + 0x2000 | // annotation, must not be set. + 0x4000 ; // enum, may be set. + + public final static int FIELD_DEFINED_BITS = + 0x0001 | // public + 0x0002 | // private + 0x0004 | // protected + 0x0008 | // static + 0x0010 | // final + 0x0040 | // volatile + 0x0080 | // transient + 0x1000 | // synthetic + 0x4000 ; // enum + + public final static int METHOD_DEFINED_BITS = + 0x0001 | // public + 0x0002 | // private + 0x0004 | // protected + 0x0008 | // static + 0x0010 | // final + 0x0020 | // synchronized + 0x0040 | // bridge + 0x0080 | // varargs + 0x0100 | // native + 0x0400 | // abstract + 0x0800 | // strictfp + 0x1000 ; // synthetic + + public static void main(String args[]) throws Exception { + modify("Inf"); + modify("NonInf"); + } + + private static void modify(String clazz) throws Exception { + ClassNode classNode = new ClassNode(); + ClassReader cr = new ClassReader(clazz); + cr.accept(classNode, 0); + + modify(classNode); + + ClassWriter cw = new ClassWriter(0); + classNode.accept(cw); + byte[] b = cw.toByteArray(); + OutputStream out = new FileOutputStream(clazz + ".out"); + out.write(b, 0, b.length); + out.close(); + } + + private static void modify(ClassNode classNode) throws Exception { + int classFlagsOr = 0xFFFF; + // Check whether classNode is an interface or class. + if ((classNode.access & Opcodes.ACC_INTERFACE) == 0) { + classFlagsOr ^= CLASS_DEFINED_BITS; + } else { + classFlagsOr ^= INTERFACE_DEFINED_BITS; + } + classNode.access |= classFlagsOr; + + // Fields. + int fieldFlagsOr = 0xFFFF ^ FIELD_DEFINED_BITS; + for (FieldNode fieldNode : (List<FieldNode>)classNode.fields) { + fieldNode.access |= fieldFlagsOr; + } + + // Methods. + int methodFlagsOr = 0xFFFF ^ METHOD_DEFINED_BITS; + for (MethodNode methodNode :(List<MethodNode>) classNode.methods) { + methodNode.access |= methodFlagsOr; + } + } +} diff --git a/test/121-modifiers/src/Inf.java b/test/121-modifiers/src/Inf.java new file mode 100644 index 0000000000..1dadae0e47 --- /dev/null +++ b/test/121-modifiers/src/Inf.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2014 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. + */ + +public interface Inf { + + public final int I = 0; + +}
\ No newline at end of file diff --git a/test/121-modifiers/src/Main.java b/test/121-modifiers/src/Main.java new file mode 100644 index 0000000000..e21b789cc7 --- /dev/null +++ b/test/121-modifiers/src/Main.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2014 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. + */ + +// These classes are to check the additional flags for inner classes. +class A { + private static class B { + } + protected static interface C { + } +} + +public class Main { + public final static int INTERFACE_DEFINED_BITS = + 0x0001 | // public, may be set. + 0x0002 | // private, may be flagged by inner class. + 0x0004 | // protected, may be flagged by inner class. + 0x0008 | // static, may be flagged by inner class. + 0x0010 | // final, must not be set. + 0x0020 | // super, must not be set. + 0x0200 | // interface, must be set. + 0x0400 | // abstract, must be set. + 0x1000 | // synthetic, may be set. + 0x2000 | // annotation, may be set (annotation implies interface) + 0x4000 ; // enum, must not be set. + + public final static int CLASS_DEFINED_BITS = + 0x0001 | // public, may be set. + 0x0002 | // private, may be flagged by inner class. + 0x0004 | // protected, may be flagged by inner class. + 0x0008 | // static, may be flagged by inner class. + 0x0010 | // final, may be set. + 0x0020 | // super, may be set. + 0x0200 | // interface, must not be set. + 0x0400 | // abstract, may be set. + 0x1000 | // synthetic, may be set. + 0x2000 | // annotation, must not be set. + 0x4000 ; // enum, may be set. + + public final static int FIELD_DEFINED_BITS = + 0x0001 | // public + 0x0002 | // private + 0x0004 | // protected + 0x0008 | // static + 0x0010 | // final + 0x0040 | // volatile + 0x0080 | // transient + 0x1000 | // synthetic + 0x4000 ; // enum + + public final static int METHOD_DEFINED_BITS = + 0x0001 | // public + 0x0002 | // private + 0x0004 | // protected + 0x0008 | // static + 0x0010 | // final + 0x0020 | // synchronized + 0x0040 | // bridge + 0x0080 | // varargs + 0x0100 | // native + 0x0400 | // abstract + 0x0800 | // strictfp + 0x1000 ; // synthetic + + public static void main(String args[]) throws Exception { + check("Inf"); + check("NonInf"); + check("A"); + check("A$B"); + } + + private static void check(String className) throws Exception { + Class<?> clazz = Class.forName(className); + if (className.equals("Inf")) { + if (!clazz.isInterface()) { + throw new RuntimeException("Expected an interface."); + } + int undefinedBits = 0xFFFF ^ INTERFACE_DEFINED_BITS; + if ((clazz.getModifiers() & undefinedBits) != 0) { + System.out.println("Clazz.getModifiers(): " + Integer.toBinaryString(clazz.getModifiers())); + System.out.println("INTERFACE_DEF_BITS: " + Integer.toBinaryString(INTERFACE_DEFINED_BITS)); + throw new RuntimeException("Undefined bits for an interface: " + className); + } + } else { + if (clazz.isInterface()) { + throw new RuntimeException("Expected a class."); + } + int undefinedBits = 0xFFFF ^ CLASS_DEFINED_BITS; + if ((clazz.getModifiers() & undefinedBits) != 0) { + System.out.println("Clazz.getModifiers(): " + Integer.toBinaryString(clazz.getModifiers())); + System.out.println("CLASS_DEF_BITS: " + Integer.toBinaryString(CLASS_DEFINED_BITS)); + throw new RuntimeException("Undefined bits for a class: " + className); + } + } + + // Check fields. + for (java.lang.reflect.Field f : clazz.getDeclaredFields()) { + String name = f.getName(); + int undefinedBits = 0xFFFF ^ FIELD_DEFINED_BITS; + if ((f.getModifiers() & undefinedBits) != 0) { + System.out.println("f.getModifiers(): " + Integer.toBinaryString(f.getModifiers())); + System.out.println("FIELD_DEF_BITS: " + Integer.toBinaryString(FIELD_DEFINED_BITS)); + throw new RuntimeException("Unexpected field bits: " + name); + } + if (name.equals("I")) { + // Interface field, just check generically. + } else { + // Check the name, see that the corresponding bit is set. + int bitmask = getFieldMask(name); + if ((bitmask & f.getModifiers()) == 0) { + throw new RuntimeException("Expected field bit not set."); + } + } + } + + // Check methods. + for (java.lang.reflect.Method m : clazz.getDeclaredMethods()) { + String name = m.getName(); + int undefinedBits = 0xFFFF ^ METHOD_DEFINED_BITS; + if ((m.getModifiers() & undefinedBits) != 0) { + System.out.println("m.getModifiers(): " + Integer.toBinaryString(m.getModifiers())); + System.out.println("METHOD_DEF_BITS: " + Integer.toBinaryString(METHOD_DEFINED_BITS)); + throw new RuntimeException("Unexpected method bits: " + name); + } + // Check the name, see that the corresponding bit is set. + int bitmask = getMethodMask(name); + if ((bitmask & m.getModifiers()) == 0) { + throw new RuntimeException("Expected method bit not set."); + } + } + } + + private static int getFieldMask(String name) { + int index = name.indexOf("Field"); + if (index > 0) { + String shortS = name.substring(0, index); + if (shortS.equals("public")) { + return 0x0001; + } + if (shortS.equals("private")) { + return 0x0002; + } + if (shortS.equals("protected")) { + return 0x0004; + } + if (shortS.equals("static")) { + return 0x0008; + } + if (shortS.equals("transient")) { + return 0x0080; + } + if (shortS.equals("volatile")) { + return 0x0040; + } + if (shortS.equals("final")) { + return 0x0010; + } + } + throw new RuntimeException("Unexpected field name " + name); + } + + private static int getMethodMask(String name) { + int index = name.indexOf("Method"); + if (index > 0) { + String shortS = name.substring(0, index); + if (shortS.equals("public")) { + return 0x0001; + } + if (shortS.equals("private")) { + return 0x0002; + } + if (shortS.equals("protected")) { + return 0x0004; + } + if (shortS.equals("static")) { + return 0x0008; + } + if (shortS.equals("synchronized")) { + return 0x0020; + } + if (shortS.equals("varargs")) { + return 0x0080; + } + if (shortS.equals("final")) { + return 0x0010; + } + if (shortS.equals("native")) { + return 0x0100; + } + if (shortS.equals("abstract")) { + return 0x0400; + } + if (shortS.equals("strictfp")) { + return 0x0800; + } + } + throw new RuntimeException("Unexpected method name " + name); + } +} diff --git a/test/121-modifiers/src/NonInf.java b/test/121-modifiers/src/NonInf.java new file mode 100644 index 0000000000..52e4882532 --- /dev/null +++ b/test/121-modifiers/src/NonInf.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 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. + */ + +public abstract class NonInf { + + public int publicField; + private int privateField; + protected int protectedField; + static int staticField; + transient int transientField; + volatile int volatileField; + final int finalField; + + public NonInf() { + publicField = 0; + privateField = 1; + protectedField = 2; + staticField = 3; + transientField = 4; + volatileField = 5; + finalField = 6; + } + + public native void nativeMethod(); + + private int privateMethod() { + return 0; + } + + protected int protectedMethod() { + return 0; + } + + public int publicMethod() { + return 0; + } + + public abstract int abstractMethod(); + + public synchronized int synchronizedMethod() { + return 0; + } + + public static int staticMethod() { + return 0; + } + + public strictfp double strictfpMethod() { + return 0.0; + } + + public int varargsMethod(Object... args) { + return 0; + } + + public final int finalMethod() { + return 0; + } +}
\ No newline at end of file |