001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.ta.instrumentation.test;
022:
023: import java.lang.reflect.Field;
024: import java.lang.reflect.InvocationTargetException;
025: import java.lang.reflect.Method;
026: import java.lang.reflect.Modifier;
027: import java.net.URL;
028:
029: import com.db4o.ObjectContainer;
030: import com.db4o.activation.Activator;
031: import com.db4o.instrumentation.*;
032: import com.db4o.instrumentation.core.*;
033: import com.db4o.instrumentation.filter.*;
034: import com.db4o.instrumentation.main.*;
035: import com.db4o.ta.Activatable;
036: import com.db4o.ta.instrumentation.InjectTransparentActivationEdit;
037: import com.db4o.ta.instrumentation.TransparentActivationInstrumentationConstants;
038:
039: import db4ounit.*;
040:
041: public class TransparentActivationClassLoaderTestCase implements
042: TestLifeCycle {
043:
044: private static final Class ORIG_CLASS = ToBeInstrumented.class;
045: private static final String CLASS_NAME = ORIG_CLASS.getName();
046: private static final Class SUB_CLASS = ToBeInstrumentedSub.class;
047: private static final String SUB_CLASS_NAME = SUB_CLASS.getName();
048: private static final Class FA_CLASS = ToBeInstrumentedWithFieldAccess.class;
049: private static final String FA_CLASS_NAME = FA_CLASS.getName();
050: private static final Class NI_CLASS = NotToBeInstrumented.class;
051: private static final String NI_CLASS_NAME = NI_CLASS.getName();
052: private static final Class CNI_CLASS = CanNotBeInstrumented.class;
053: private static final String CNI_CLASS_NAME = CNI_CLASS.getName();
054:
055: private ClassLoader _loader;
056:
057: public void testSelectedClassIsInstrumented() throws Exception {
058: Class clazz = _loader.loadClass(CLASS_NAME);
059: Assert.areEqual(CLASS_NAME, clazz.getName());
060: Assert.areNotSame(ORIG_CLASS, clazz);
061: assertActivatableInterface(clazz);
062: assertActivatorField(clazz);
063: assertBindMethod(clazz);
064: assertActivateMethod(clazz);
065: assertMethodInstrumentation(clazz, "foo", true);
066: assertMethodInstrumentation(clazz, "bar", true);
067: assertMethodInstrumentation(clazz, "baz", true);
068: assertMethodInstrumentation(clazz, "boo", true);
069: }
070:
071: public void testSubClassIsInstrumented() throws Exception {
072: Class clazz = _loader.loadClass(SUB_CLASS_NAME);
073: Assert.areEqual(SUB_CLASS_NAME, clazz.getName());
074: Assert.areNotSame(SUB_CLASS, clazz);
075: assertNoActivatorField(clazz);
076: assertNoMethod(
077: clazz,
078: TransparentActivationInstrumentationConstants.BIND_METHOD_NAME,
079: new Class[] { ObjectContainer.class });
080: assertNoMethod(
081: clazz,
082: TransparentActivationInstrumentationConstants.ACTIVATE_METHOD_NAME,
083: new Class[] {});
084: assertMethodInstrumentation(clazz, "fooSub", true);
085: assertMethodInstrumentation(clazz, "barSub", true);
086: assertMethodInstrumentation(clazz, "bazSub", true);
087: assertMethodInstrumentation(clazz, "booSub", true);
088: }
089:
090: public void testFieldAccessIsInstrumented() throws Exception {
091: Class clazz = _loader.loadClass(FA_CLASS_NAME);
092: final Activatable objOne = (Activatable) clazz.newInstance();
093: final Activatable objTwo = (Activatable) clazz.newInstance();
094: MockActivator ocOne = new MockActivator();
095: objOne.bind(ocOne);
096: MockActivator ocTwo = new MockActivator();
097: objTwo.bind(ocTwo);
098: final Method method = clazz.getDeclaredMethod("compareID",
099: new Class[] { clazz });
100: method.setAccessible(true);
101: method.invoke(objOne, new Object[] { objTwo });
102: Assert.areEqual(1, ocOne.count());
103: Assert.areEqual(1, ocTwo.count());
104: }
105:
106: public void testInterObjectFieldAccessIsInstrumented()
107: throws Exception {
108: Class iClazz = _loader.loadClass(CLASS_NAME);
109: Class niClazz = _loader.loadClass(NI_CLASS_NAME);
110: final Activatable iObj = (Activatable) iClazz.newInstance();
111: final Object niObj = niClazz.newInstance();
112: MockActivator act = new MockActivator();
113: iObj.bind(act);
114: final Method method = niClazz.getDeclaredMethod(
115: "accessToBeInstrumented", new Class[] { iClazz });
116: method.setAccessible(true);
117: method.invoke(niObj, new Object[] { iObj });
118: Assert.areEqual(1, act.count());
119: }
120:
121: private void assertActivatableInterface(Class clazz) {
122: Assert.isTrue(Activatable.class.isAssignableFrom(clazz));
123: }
124:
125: private void assertActivatorField(Class clazz)
126: throws NoSuchFieldException {
127: Field activatorField = clazz
128: .getDeclaredField(TransparentActivationInstrumentationConstants.ACTIVATOR_FIELD_NAME);
129: Assert.areEqual(Activator.class, activatorField.getType());
130: assertFieldModifier(activatorField, Modifier.PRIVATE);
131: assertFieldModifier(activatorField, Modifier.TRANSIENT);
132: }
133:
134: private void assertNoActivatorField(final Class clazz) {
135: Assert.expect(NoSuchFieldException.class, new CodeBlock() {
136: public void run() throws Throwable {
137: clazz
138: .getDeclaredField(TransparentActivationInstrumentationConstants.ACTIVATOR_FIELD_NAME);
139: }
140: });
141: }
142:
143: private void assertBindMethod(Class clazz) throws Exception {
144: final Field activatorField = clazz
145: .getDeclaredField(TransparentActivationInstrumentationConstants.ACTIVATOR_FIELD_NAME);
146: final Method bindMethod = clazz
147: .getDeclaredMethod(
148: TransparentActivationInstrumentationConstants.BIND_METHOD_NAME,
149: new Class[] { Activator.class });
150: Assert
151: .isTrue((bindMethod.getModifiers() & Modifier.PUBLIC) > 0);
152:
153: activatorField.setAccessible(true);
154: final Object obj = clazz.newInstance();
155: Assert.isNull(activatorField.get(obj));
156:
157: MockActivator oc = new MockActivator();
158: Assert.areEqual(0, oc.count());
159:
160: bindMethod.invoke(obj, new Object[] { oc });
161: Object activator = activatorField.get(obj);
162: Assert.isNotNull(activator);
163:
164: try {
165: bindMethod.invoke(obj, new Object[] { oc });
166: Assert.fail();
167: } catch (InvocationTargetException x) {
168: Assert.isInstanceOf(IllegalStateException.class, x
169: .getTargetException());
170: }
171:
172: MockActivator otherOc = new MockActivator();
173: try {
174: bindMethod.invoke(obj, new Object[] { otherOc });
175: Assert.fail();
176: } catch (InvocationTargetException exc) {
177: Assert.isInstanceOf(IllegalStateException.class, exc
178: .getTargetException());
179: }
180: Assert.areEqual(0, oc.count());
181: Assert.areEqual(0, otherOc.count());
182: }
183:
184: private void assertNoMethod(final Class clazz,
185: final String methodName, final Class[] paramTypes)
186: throws Exception {
187: Assert.expect(NoSuchMethodException.class, new CodeBlock() {
188: public void run() throws Throwable {
189: clazz.getDeclaredMethod(methodName, paramTypes);
190: }
191: });
192: }
193:
194: private void assertActivateMethod(Class clazz) throws Exception {
195: final Method activateMethod = clazz
196: .getDeclaredMethod(
197: TransparentActivationInstrumentationConstants.ACTIVATE_METHOD_NAME,
198: new Class[] {});
199: activateMethod.setAccessible(true);
200: Assert
201: .isTrue((activateMethod.getModifiers() & Modifier.PUBLIC) > 0);
202: final Activatable obj = (Activatable) clazz.newInstance();
203: MockActivator activator = new MockActivator();
204: obj.bind(activator);
205: activateMethod.invoke(obj, new Object[] {});
206: activateMethod.invoke(obj, new Object[] {});
207: Assert.areEqual(2, activator.count());
208: }
209:
210: private void assertMethodInstrumentation(Class clazz,
211: String methodName, boolean expectInstrumentation)
212: throws Exception {
213: final Activatable obj = (Activatable) clazz.newInstance();
214: MockActivator oc = new MockActivator();
215: obj.bind(oc);
216: final Method method = clazz.getDeclaredMethod(methodName,
217: new Class[] {});
218: method.setAccessible(true);
219: method.invoke(obj, new Object[] {});
220: if (expectInstrumentation) {
221: Assert.areEqual(1, oc.count());
222: } else {
223: Assert.areEqual(0, oc.count());
224: }
225: }
226:
227: private void assertFieldModifier(Field activatorField, int modifier) {
228: Assert.isTrue((activatorField.getModifiers() & modifier) > 0);
229: }
230:
231: public void testOtherClassIsNotInstrumented() throws Exception {
232: Class clazz = _loader.loadClass(NI_CLASS_NAME);
233: Assert.areEqual(NI_CLASS_NAME, clazz.getName());
234: Assert.areNotSame(NI_CLASS, clazz);
235: Assert.isFalse(Activatable.class.isAssignableFrom(clazz));
236: }
237:
238: public void testCanNotBeInstrumented() throws Exception {
239: Assert.expect(IllegalArgumentException.class, new CodeBlock() {
240: public void run() throws Throwable {
241: _loader.loadClass(CNI_CLASS_NAME);
242: }
243: });
244: }
245:
246: public void setUp() throws Exception {
247: ClassLoader baseLoader = ORIG_CLASS.getClassLoader();
248: URL[] urls = {};
249: ClassFilter filter = new ByNameClassFilter(new String[] {
250: CLASS_NAME, SUB_CLASS_NAME, FA_CLASS_NAME,
251: CNI_CLASS_NAME });
252: _loader = new BloatInstrumentingClassLoader(urls, baseLoader,
253: new AcceptAllClassesFilter(),
254: new InjectTransparentActivationEdit(filter));
255: }
256:
257: public void tearDown() throws Exception {
258: }
259:
260: public static void main(String[] args) {
261: new TestRunner(TransparentActivationClassLoaderTestCase.class)
262: .run();
263: }
264: }
|