001: // $Id: ExtensionInsertionTest.java,v 1.3 2004/05/12 17:26:50 anicoara Exp $
002: // =====================================================================
003: //
004: // (history at end)
005: //
006:
007: package ch.ethz.prose;
008:
009: //used packages
010: import java.util.*;
011:
012: import junit.framework.*;
013: import ch.ethz.jvmai.MethodEntryJoinPoint;
014: import ch.ethz.prose.crosscut.*;
015: import ch.ethz.prose.engine.JoinPointRequest;
016: import ch.ethz.prose.filter.PointCutter;
017: import ch.ethz.prose.filter.Within;
018:
019: /**
020: * JUnit test for DefaultAspect,ProseSystem and Functional Crosscut.
021: *
022: * @version $Revision: 1.3 $
023: * @author Andrei Popovici
024: */
025:
026: public class ExtensionInsertionTest extends TestCase {
027:
028: static class TestClass {
029: public void hello(String stuff) {
030: int a = 1;
031: }
032:
033: public void byebye(String stuff, String stuf1) {
034: int b = 1;
035: }
036: }
037:
038: static class TestClassWithInt {
039: int receivedI = 0;
040:
041: public void hello(int i) {
042: receivedI = i;
043: }
044: }
045:
046: static class ModParExtension extends DefaultAspect {
047: Crosscut myCC1 = new MethodCut() {
048: public void METHOD_ARGS(TestClassWithInt receiver, int i) {
049: if (this JoinPoint() instanceof MethodEntryJoinPoint)
050: ((MethodEntryJoinPoint) this JoinPoint()).setArg(0,
051: new Integer(20));
052: }
053:
054: protected PointCutter pointCutter() {
055: return null;
056: }
057: };
058: }
059:
060: static class NonPubExtension extends DefaultAspect {
061: public boolean called = false;
062: Crosscut pc1 = new MethodCut() {
063: public void METHOD_ARGS(TestClass cls, String stuff,
064: REST params) {
065: called = true;
066: }
067:
068: protected PointCutter pointCutter() {
069: return null;
070: }
071: };
072: }
073:
074: public static class SimpleExtension extends DefaultAspect {
075: public static List lastArgumentCalls = new Vector();
076:
077: public static class Crosscut1 extends MethodCut {
078: public void METHOD_ARGS(TestClass cls, String stuff,
079: REST params) {
080: lastArgumentCalls.add("C1 received " + stuff);
081: }
082:
083: protected PointCutter pointCutter() {
084: return null;
085: }
086: }
087:
088: public static class Crosscut2 extends MethodCut {
089: public void METHOD_ARGS(ANY this Obj, String stuff,
090: String stuff1) {
091: lastArgumentCalls.add("C2 received " + stuff);
092: }
093:
094: protected PointCutter pointCutter() {
095: return Within.method("byebye");
096: }
097: }
098:
099: Crosscut1 c1 = new Crosscut1();
100: Crosscut2 c2 = new Crosscut2();
101: }
102:
103: static abstract class AbstractMethodCut extends MethodCut {
104: public abstract void METHOD_ARGS(TestClass t, REST r);
105:
106: protected PointCutter pointCutter() {
107: return Within.method("hello").OR(Within.method("byebye"));
108: }
109: };
110:
111: static boolean concVisited = false;
112: static Vector visitedBy = new Vector();
113:
114: static class ConcreteMethodCut1 extends AbstractMethodCut {
115: public void METHOD_ARGS(TestClass t, REST r) {
116: concVisited = true;
117: visitedBy.add(getOwner());
118: }
119: };
120:
121: static class ConcreteMethodCut2 extends ConcreteMethodCut1 {
122: protected PointCutter pointCutter() {
123: return Within.method("byebye").AND(super .pointCutter());
124: }
125: };
126:
127: static class ConcreteExtension extends DefaultAspect {
128: Crosscut c = new ConcreteMethodCut1();
129: };
130:
131: static class ConcreteExtension1 extends DefaultAspect {
132: Crosscut c = new ConcreteMethodCut2();
133: };
134:
135: TestClass testObject = null;
136: SimpleExtension testExtension = null;
137: NonPubExtension npExtension = null;
138: ConcreteExtension concExtension = null;
139: ConcreteExtension1 concExtension1 = null;
140:
141: /**
142: * Construct test with given name.
143: * @param name test name
144: */
145: public ExtensionInsertionTest(String name) {
146: super (name);
147: }
148:
149: /**
150: * Set up fixture.
151: */
152: protected void setUp() {
153: // System.err.println("setting up" + this);
154: try {
155: ProseSystem.startup();
156: } catch (Exception e) {
157: e.printStackTrace();
158: Assert.fail("ProseSystem.startup() failed.");
159: }
160: testExtension = new SimpleExtension();
161: npExtension = new NonPubExtension();
162: testObject = new TestClass();
163: concExtension = new ConcreteExtension();
164: concExtension1 = new ConcreteExtension1();
165: }
166:
167: protected void tearDown() {
168: try {
169: ProseSystem.teardown();
170: } catch (Exception e) {
171: e.printStackTrace();
172: }
173: }
174:
175: public void _testRegisterListener() throws Exception {
176: try {
177: Iterator i1 = testExtension.c1.createRequest().iterator();
178: while (i1.hasNext()) {
179: JoinPointRequest crtReq = (JoinPointRequest) (i1.next());
180:
181: ProseSystem.getAspectManager().getJoinPointManager()
182: .registerListener(testExtension.c1, crtReq);
183: }
184:
185: i1 = testExtension.c2.createRequest().iterator();
186: while (i1.hasNext()) {
187: JoinPointRequest crtReq = (JoinPointRequest) (i1.next());
188: ProseSystem.getAspectManager().getJoinPointManager()
189: .registerListener(testExtension.c1, crtReq);
190: }
191: } catch (Exception e) {
192: e.printStackTrace();
193: }
194: }
195:
196: /** this tests inserts our example extension and
197: * then calls 5 times each method of the example
198: * class. the first crosscut (C1) should receive
199: * 5 * 2 on behalf of hello and 5 *2 on behalf of
200: * byebye; the seccond crosscut would receive 5*2
201: * messages for byeye. We test that our crosscuts
202: * receive 30 messages.
203: */
204: public void testExtensionInsertion() throws Exception {
205: try {
206: ProseSystem.getAspectManager().insert(testExtension);
207:
208: for (int i = 0; i < 5; i++)
209: testObject.hello("hello invocation [ " + i + " ]");
210:
211: for (int i = 5; i < 10; i++)
212: testObject.byebye("byebye invocation [" + i + "]",
213: "foo");
214:
215: assertTrue("thirty notifications",
216: SimpleExtension.lastArgumentCalls.size() == 30);
217: ProseSystem.getAspectManager().withdraw(testExtension);
218: } catch (Throwable e) {
219: e.printStackTrace();
220: throw (Exception) e;
221: }
222: }
223:
224: /** Until recently, crosscuts had to be declared as public
225: * static local classes of extensions. This is no longer required.
226: * We test here that a real inner class is callable.
227: */
228: public void testInnerCrosscutInsertion() throws Exception {
229: ProseSystem.getAspectManager().insert(npExtension);
230: testObject.byebye("byebye", "invocation");
231: assertTrue("Inner class method called", npExtension.called);
232: ProseSystem.getAspectManager().withdraw(npExtension);
233: }
234:
235: /** This test checks whether after the call of the ProseSystem.teardown()
236: * method all joinpoints have been correctly cleaned up.
237: */
238: public void testTeardownQuality() {
239: ProseSystem.getAspectManager().insert(npExtension);
240: try {
241: ProseSystem.teardown();
242: } catch (SystemTeardownException e) {
243: Assert.fail("ProseSystem.teardown() failed");
244: }
245: testObject.byebye("byebye", "invocation");
246: assertTrue("Inner class method not called", !npExtension.called);
247: }
248:
249: public void testConcreteExtension() {
250: ProseSystem.getAspectManager().insert(concExtension);
251: concVisited = false;
252: testObject.hello("");
253: assertTrue("conc was visted by hello", concVisited);
254: concVisited = false;
255: testObject.byebye("", "");
256: assertTrue("conc was visted by bybye", concVisited);
257: }
258:
259: public void testConcreteExtension1() {
260: ProseSystem.getAspectManager().insert(concExtension1);
261: concVisited = false;
262: testObject.hello("");
263: assertTrue("conc was NOT visted by hello", !concVisited);
264: concVisited = false;
265: testObject.byebye("", "");
266: assertTrue("conc was visted by bybye", concVisited);
267: }
268:
269: public void testExtensionUniqueness() {
270: ConcreteExtension ce1 = new ConcreteExtension();
271: ce1.associateTo("first");
272: ConcreteExtension ce2 = new ConcreteExtension();
273: ce2.associateTo("first");
274:
275: ProseSystem.getAspectManager().insert(ce1);
276:
277: // FIXME: this crashes the VM!
278: // if (true) throw new Error();
279: try {
280: ProseSystem.getAspectManager().insert(ce2); // should fail
281: Assert
282: .fail("was able to insert second aspect with the same id");
283: } catch (Throwable e) {
284: // take a break
285: }
286: }
287:
288: public void testParamModification() {
289: ModParExtension mpe = new ModParExtension();
290: ProseSystem.getAspectManager().insert(mpe);
291: TestClassWithInt objWithInt = new TestClassWithInt();
292: try {
293: objWithInt.hello(10);
294: assertEquals("ModParExtension has doubled the value", 20,
295: objWithInt.receivedI);
296: } catch (ch.ethz.jvmai.InvalidIdException t) { /*invalid jFrameID JVMDI HotSwap*/
297: }
298: }
299:
300: public void testNotificationOrder() {
301: visitedBy = new Vector();
302: ConcreteExtension ce1 = new ConcreteExtension();
303: ce1.setPriority(1);
304: ce1.associateTo("first");
305: ConcreteExtension ce2 = new ConcreteExtension();
306: ce2.associateTo("second");
307: ce2.setPriority(2);
308:
309: ProseSystem.getAspectManager().insert(ce1);
310: ProseSystem.getAspectManager().insert(ce2);
311: testObject.byebye("", "");
312:
313: Vector firstOrderVisitedBy = visitedBy;
314: visitedBy = new Vector();
315: ProseSystem.getAspectManager().withdraw(ce1);
316: ProseSystem.getAspectManager().withdraw(ce2);
317:
318: ce1.setPriority(2);
319: ce2.setPriority(1);
320: ProseSystem.getAspectManager().insert(ce1);
321: ProseSystem.getAspectManager().insert(ce2);
322: testObject.byebye("", "");
323:
324: assertTrue("vectors differ in ordering", !firstOrderVisitedBy
325: .equals(visitedBy));
326: }
327:
328: /**
329: * Test suite.
330: * @return test instance
331: */
332: public static Test suite() {
333: return new TestSuite(ExtensionInsertionTest.class);
334: }
335:
336: }
337:
338: //======================================================================
339: //
340: // $Log: ExtensionInsertionTest.java,v $
341: // Revision 1.3 2004/05/12 17:26:50 anicoara
342: // Adapt Junit tests to 3.8.1 version and the new package structure
343: //
344: // Revision 1.1.1.1 2003/07/02 15:30:42 apopovic
345: // Imported from ETH Zurich
346: //
347: // Revision 1.2 2003/05/06 15:13:34 popovici
348: // aspectId renamed to 'associated object'
349: //
350: // Revision 1.1 2003/05/05 14:02:33 popovici
351: // renaming from runes to prose
352: //
353: // Revision 1.14 2003/04/30 14:50:10 popovici
354: // junit test for checking parameter modification added; tests for checking parameters modification (old) updated; they used to fail silently
355: //
356: // Revision 1.13 2003/04/29 12:41:07 popovici
357: // Feature added:
358: // - the 'setPriority' in class insertable allows now Aspects and Crosscuts to have a priority.
359: // Notitification is done from low int priorities to high int priorities.
360: // - the 'setAspectID' introduced to replace constuctor; used to be cumberstone for subclasses
361: //
362: // Revision 1.12 2003/04/27 13:08:40 popovici
363: // Specializers renamed to PointCutter
364: //
365: // Revision 1.11 2003/04/17 15:15:02 popovici
366: // Extension->Aspect renaming
367: //
368: // Revision 1.10 2003/04/17 13:54:34 popovici
369: // Refactorization of 'ExecutionS' into 'Within' and 'Executions'.
370: // Method names refer now to 'types'
371: //
372: // Revision 1.9 2003/04/17 12:49:38 popovici
373: // Refactoring of the crosscut package
374: // ExceptionCut renamed to ThrowCut
375: // McutSignature is now SignaturePattern
376: //
377: // Revision 1.8 2003/04/17 08:46:43 popovici
378: // Important functionality additions
379: // - Cflow specializers
380: // - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
381: // - Transactional capabilities
382: // - Total refactoring of Specializer evaluation, which permits fine-grained distinction
383: // between static and dynamic specializers.
384: // - Functionality pulled up in abstract classes
385: // - Uniformization of advice methods patterns and names
386: //
387: // Revision 1.7 2003/03/05 08:31:23 popovici
388: // Bug fix afeer import organization
389: //
390: // Revision 1.6 2003/03/04 18:36:07 popovici
391: // Organization of imprts
392: //
393: // Revision 1.5 2003/03/04 11:25:55 popovici
394: // Important refactorization step (march):
395: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
396: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
397: // structures
398: //
399: // Revision 1.4 2002/11/26 17:15:29 pschoch
400: // RootComponent now added (replaces RootComponent now added (replaces old ProseSystem)
401: // ProseSystem now owns and starts the Aspect interface.
402: // ProseSystem now containes a 'test' AspectManager
403: // AspectManager now owns the JoinPointManager.
404: // ExtensionManger can be 'connected' to the JVM, or disconnected. The
405: // JoinPointManager of a connected Ext.Mgr enables joinpoints; the
406: // JoinPointManger of a disconnected Ext.Mgr never enables join-points
407: // Documentation updated accordingly.
408: //
409: // Revision 1.3 2002/06/06 14:39:54 popovici
410: // Renamings: FunctionalCrosscut->MethodCut
411: // AllFields->SetCut
412: // SetCu.fieldModiticationAdvice -> SetCut.setAdvice
413: //
414: // Revision 1.2 2002/02/05 11:20:17 smarkwal
415: // modifications to test JVMAI-based implementation
416: //
417: // Revision 1.1.1.1 2001/11/29 18:13:30 popovici
418: // Sources from runes
419: //
420: // Revision 1.1.2.6 2001/06/01 12:17:12 popovici
421: // Methods 'hello' und 'byebye' now not-void.
422: //
423: // Revision 1.1.2.5 2001/03/23 12:32:23 popovici
424: // Minor correction in 'testTeardownQuality'. A call to the method
425: // to dispatch is now performed after teardown. The test used tu yield
426: // otherwise true by default.
427: //
428: // Revision 1.1.2.4 2001/02/22 16:56:06 popovici
429: // ProseSystem.setup replaced with startup; teardown introduced
430: // - test 'testTeardownQuality' introduced
431: //
432: // Revision 1.1.2.3 2001/02/07 12:03:41 popovici
433: // ProseSystem.insertExtension() now throws an exception. 'testInnerCrosscutInsert'
434: // adapted.
435: //
436: // Revision 1.1.2.2 2000/12/01 09:47:50 popovici
437: // Test 'testInnerCrosscutInsertion' added.
438: //
439: // Revision 1.1.2.1 2000/10/25 09:38:52 popovici
440: // Initial Revision
441: //
|