diff options
author | Xavier Ducrohet <xav@android.com> | 2010-10-22 14:48:17 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-10-27 09:55:58 -0700 |
commit | 4f291d33e14e62b3301acc056a82fe206c74835f (patch) | |
tree | cc6d5b0297f4c755c2e2cee64189633007096636 /tools/layoutlib/bridge/tests | |
parent | 5da5438e4101ab3c499797f90cc3d9403e075a5a (diff) | |
download | frameworks_base-4f291d33e14e62b3301acc056a82fe206c74835f.zip frameworks_base-4f291d33e14e62b3301acc056a82fe206c74835f.tar.gz frameworks_base-4f291d33e14e62b3301acc056a82fe206c74835f.tar.bz2 |
Reimplement the native matrix method using the new delegate way.
Instead of renaming the old Matrix class into _Original_Matrix
and have layoutlib provide a full new implementation of Matrix,
we keep the old one by only modifying it to implement the native
methods which calls out to a new Matrix_Delegate class.
The goal is to not have to maintain the java portion in
sync between the framework and the layoutlib version.
Change-Id: I3e1aefffbae45e91b75331c0c6ff2260323deacd
Diffstat (limited to 'tools/layoutlib/bridge/tests')
-rw-r--r-- | tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java new file mode 100644 index 0000000..6eed8ba --- /dev/null +++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.layoutlib.bridge; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; +import com.android.tools.layoutlib.create.CreateInfo; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import junit.framework.TestCase; + +/** + * Tests that native delegate classes implement all the required methods. + * + * This looks at {@link CreateInfo#DELEGATE_CLASS_NATIVES} to get the list of classes that + * have their native methods reimplemented through a delegate. + * + * Since the reimplemented methods are not native anymore, we look for the annotation + * {@link LayoutlibDelegate}, and look for a matching method in the delegate (named the same + * as the modified class with _Delegate added as a suffix). + * If the original native method is not static, then we make sure the delegate method also + * include the original class as first parameter (to access "this"). + * + */ +public class TestNativeDelegate extends TestCase { + + public void testNativeDelegates() { + + final String[] classes = CreateInfo.DELEGATE_CLASS_NATIVES; + final int count = classes.length; + for (int i = 0 ; i < count ; i++) { + loadAndCompareClasses(classes[i], classes[i] + "_Delegate"); + } + } + + private void loadAndCompareClasses(String originalClassName, String delegateClassName) { + // load the classes + try { + ClassLoader classLoader = TestNativeDelegate.class.getClassLoader(); + Class<?> originalClass = classLoader.loadClass(originalClassName); + Class<?> delegateClass = classLoader.loadClass(delegateClassName); + + compare(originalClass, delegateClass); + } catch (ClassNotFoundException e) { + fail("Failed to load class: " + e.getMessage()); + } catch (SecurityException e) { + fail("Failed to load class: " + e.getMessage()); + } + } + + private void compare(Class<?> originalClass, Class<?> delegateClass) throws SecurityException { + Method[] originalMethods = originalClass.getDeclaredMethods(); + + for (Method originalMethod : originalMethods) { + // look for methods that were native: they have the LayoutlibDelegate annotation + if (originalMethod.getAnnotation(LayoutlibDelegate.class) == null) { + continue; + } + + // get the signature. + Class<?>[] parameters = originalMethod.getParameterTypes(); + + // if the method is not static, then the class is added as the first parameter + // (for "this") + if ((originalMethod.getModifiers() & Modifier.STATIC) == 0) { + + Class<?>[] newParameters = new Class<?>[parameters.length + 1]; + newParameters[0] = originalClass; + System.arraycopy(parameters, 0, newParameters, 1, parameters.length); + parameters = newParameters; + } + + try { + // try to load the method with the given parameter types. + delegateClass.getMethod(originalMethod.getName(), parameters); + } catch (NoSuchMethodException e) { + // compute a full class name that's long but not too long. + StringBuilder sb = new StringBuilder(originalMethod.getName() + "("); + for (int j = 0; j < parameters.length; j++) { + Class<?> theClass = parameters[j]; + sb.append(theClass.getName()); + int dimensions = 0; + while (theClass.isArray()) { + dimensions++; + theClass = theClass.getComponentType(); + } + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + if (j < (parameters.length - 1)) { + sb.append(","); + } + } + sb.append(")"); + + fail(String.format("Missing %1$s.%2$s", delegateClass.getName(), sb.toString())); + } + } + } +} |