From: ehilsdal Date: Thu, 28 Aug 2003 15:11:12 +0000 (+0000) Subject: updated section 2 X-Git-Tag: V1_1_1~59 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f3929cad6a0e6d6973483dd23c7aea68b6e7fed1;p=aspectj.git updated section 2 --- diff --git a/docs/teaching/exercises/answers/Answer2a.java b/docs/teaching/exercises/answers/Answer2a.java index 12d00d976..9131d54ce 100644 --- a/docs/teaching/exercises/answers/Answer2a.java +++ b/docs/teaching/exercises/answers/Answer2a.java @@ -17,10 +17,8 @@ import figures.FigureElement; public aspect Answer2a { before(int newValue): set(int Point.*) && args(newValue) { - if (newValue < FigureElement.MIN_VALUE) { + if (newValue < 0) { throw new IllegalArgumentException("too small"); - } else if (newValue > FigureElement.MAX_VALUE) { - throw new IllegalArgumentException("too large"); } } } diff --git a/docs/teaching/exercises/answers/Answer2d.java b/docs/teaching/exercises/answers/Answer2d.java index 3d131ad6b..2d313134d 100644 --- a/docs/teaching/exercises/answers/Answer2d.java +++ b/docs/teaching/exercises/answers/Answer2d.java @@ -12,13 +12,13 @@ package answers; -import figures.SlothfulPoint; +import figures.*; aspect Answer2d { - after(int newValue, SlothfulPoint p) returning: - call(void setX(int)) && args(newValue) && target(p) { - if (newValue != p.getX()) { - throw new RuntimeException("setter didn't set"); - } + int around(int val): (set(int Point._x) || set(int Point._y)) + && args(val) { + if (val < 0) + val = 0; + return proceed(val); } } diff --git a/docs/teaching/exercises/answers/Answer2e.java b/docs/teaching/exercises/answers/Answer2e.java index 53245b4d0..43112ec89 100644 --- a/docs/teaching/exercises/answers/Answer2e.java +++ b/docs/teaching/exercises/answers/Answer2e.java @@ -14,11 +14,21 @@ package answers; import figures.*; -public aspect Answer2e { - pointcut checkpoint(Box box): - call(void move(int, int)) && target(box); +import java.awt.Rectangle; - after(Box box) returning: checkpoint(box) { - box.checkBoxness(); +aspect Answer2e { + void around(Point p, int dx, int dy): + target(fe) && call(void move(int, int)) && args(dx, dy) { + int preX = p.getX(); + int preY = p.getY(); + + proceed(p, dx, dy); + + int postX = p.getX(); + int postY = p.getY(); + + if ((postX != preX + dx) || (postY != preY + dy)) { + throw new IllegalStateException("point didn't move properly"); + } } } diff --git a/docs/teaching/exercises/answers/Answer2f.java b/docs/teaching/exercises/answers/Answer2f.java index 5e78dabfc..4431b2742 100644 --- a/docs/teaching/exercises/answers/Answer2f.java +++ b/docs/teaching/exercises/answers/Answer2f.java @@ -14,11 +14,19 @@ package answers; import figures.*; -public aspect Answer2f { - pointcut checkpoint(Box box): - target(box) && call(public * *(..)) && !within(Answer*); +import java.awt.Rectangle; - after(Box box) returning: checkpoint(box) { - box.checkBoxness(); +aspect Answer2f { + void around(FigureElement fe, int dx, int dy): + target(fe) && call(void move(int, int)) && args(dx, dy) { + + Rectangle preBounds = new Rectangle(fe.getBounds()); + proceed(fe, dx, dy); + + preBounds.translate(dx, dy); + + if (!preBounds.equals(fe.getBounds())) { + throw new IllegalStateException("bounds don't match move"); + } } } diff --git a/docs/teaching/exercises/answers/Answer2g.java b/docs/teaching/exercises/answers/Answer2g.java deleted file mode 100644 index edf87c3db..000000000 --- a/docs/teaching/exercises/answers/Answer2g.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation - * ******************************************************************/ - -package answers; - -import figures.*; - -aspect Answer2g { - int around(int val): (set(int Point._x) || set(int Point._y)) - && args(val) { - return proceed(trim(val)); - } - - private int trim(int val) { - return Math.max(Math.min(val, FigureElement.MAX_VALUE), - FigureElement.MIN_VALUE); - } -} diff --git a/docs/teaching/exercises/answers/Answer2h.java b/docs/teaching/exercises/answers/Answer2h.java deleted file mode 100644 index ae58fa6c0..000000000 --- a/docs/teaching/exercises/answers/Answer2h.java +++ /dev/null @@ -1,31 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation - * ******************************************************************/ - -package answers; - -import figures.*; - -import java.awt.Rectangle; - -aspect Answer2h { - void around(FigureElement fe, int dx, int dy): - target(fe) && call(void move(int, int)) && args(dx, dy) { - Rectangle preBounds = new Rectangle(fe.getBounds()); - proceed(fe, dx, dy); - - preBounds.translate(dx, dy); - - if (!preBounds.equals(fe.getBounds())) { - throw new IllegalStateException("bounds don't match move"); - } - } -} diff --git a/docs/teaching/exercises/index.html b/docs/teaching/exercises/index.html index 59c95f4ff..500915e99 100644 --- a/docs/teaching/exercises/index.html +++ b/docs/teaching/exercises/index.html @@ -78,6 +78,15 @@ duplicate some code.

a. Catch old tracing

+

Sample Exercise: The main point of this exercise +is to make sure your configuration works. We have provided the +answer to this exercise below, so XXX. You need not go through the +thought process of fixing this

+ +

Task: Signal a warning for calls to +System.out.println. +

+

The way that we are all taught to print "hello world" from Java is to use System.out.println(), so that is what we typically use for one-off debugging traces. It's a common mistake to leave @@ -135,8 +144,8 @@ users who bind System.out to a static field to save typing.

b. Mandate setters

-

Problem: Add warnings for assignments outside of setter methods. -

+

Task: Signal a warning for assignments outside +of setter methods.

Tools: set, withincode, signature void set*(..) @@ -157,30 +166,26 @@ aspect A {

where the pointcut picks out join points of private field sets outside of setter methods. "Outside", here, means that the code for -the assignment is outside the text of the setter (a setter is -a method that looks like "void set*(..)"), so check out the quick -reference for set and withincode primitive -pointcuts. )

+the assignment is outside the text of the setter.

Make sure your program still passes the JUnit test tests.Test before continuing, and that you see all of the following warning messages. Make sure you get 11 warnings from this. -Wait to fix them until the next exercise. -

+Wait to fix them until the next exercise.

c. Refine setters mandate

-

Problem: Allow assignmnents inside of constructors. +

Task: Allow assignmnents inside of constructors.

Tools: signature new(..)

-

Look at some of the warnings. Notice that a lot of them are from -within constructors. Actually, the common coding convention is that -no private field should be set outside of setter methods or -constructors. Modify your answer (in a new file) to signal an -actual error at compile time (rather than just a warning) when such an -illegal assignment expression exists.

+

Look at some of the warnings from the previous exercise. Notice +that a lot of them are from within constructors. Actually, the common +coding convention is that no private field should be set outside of +setter methods or constructors. Modify your answer (in a new +file) to signal an actual error at compile time (rather than just a +warning) when such an illegal assignment expression exists.

You'll want to add another withincode primitive pointcut to deal with the constructors. @@ -219,13 +224,16 @@ them.

a. Check a simple precondition

-

Problem: Pass tests.Test2a. -

+

Sample Exercise: The main point of this exercise +is to make sure your configuration works. We have provided the +answer to this exercise below, so XXX. You need not go through the +thought process of fixing this

-

Tools: args, before + +

Task: Pass tests.Test2a.

-

THERE IS AN ANSWER BELOW. LOOK AT IT. TYPE IT IN. +

Tools: args, before

Write an aspect to throw an IllegalArgumentException @@ -275,45 +283,33 @@ import figures.*; aspect Answer2a { before(int newValue): set(int Point.*) && args(newValue) { - if (newValue < FigureElement.MIN_VALUE) { + if (newValue < 0) { throw new IllegalArgumentException("too small"); - } else if (newValue > FigureElement.MAX_VALUE) { - throw new IllegalArgumentException("too large"); - } + } } }

b. Check another precondition

+

Task: Pass tests.Test2b.

+

Group is a FigureElement class that encapsulates groups of other figure elements. As such, only actual -figure element objects should be added to Group objects. Write -an aspect to throw an IllegalArgumentException whenever -Group.add() is called with a -null value. If you look at the source code for -tests/Test2b.java, you'll see an example of the desired behavior, -i.e.

+figure element objects should be added to Group objects. +Write an aspect to throw an IllegalArgumentException +whenever Group.add() is called with a null +value.

-
-    public void testNull() {
-        try {
-	    g.add(null);
-            fail("should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException ea) {
-        }
-    }
-
+

Look at tests/Test2b.java to see exactly what we're +testing for.

-

For each of these exercises, you'll find that the corresponding -test case provides that most concrete example of the desired behavior -for your aspect. Please avail yourself of this resource.

+

c. Check yet another precondition

-

With this aspect in place, your code should pass -tests.Test2b. -

+

Task: Pass tests.Test2c.

-

c. Check yet another precondition

+

Tools: target +

Another constraint on a well-formed group is that it should not contain itself as a member (though it may contain other groups). Write @@ -326,10 +322,71 @@ an attempt is made to call Group.add() on a call.

-

With this aspect in place, your code should pass -tests.Test2c. +XXX RENUMBER LATER + +

d. Assure input

+ +

Task: Pass tests.Test2g.

+

Tools: around advice +

+ +

Instead of throwing an exception when one of Point's +int fields are set to an out-of-bounds value, write an +aspect to trim the value into an in-bounds one. You'll want to use +around advice that exposes the new value of the field +assignment with an args pointcut, and +proceed with the trimmed value.

+ +

e. Check a postcondition

+ +

Task: Pass tests.Test2e +

+ +

Tools: around advice +

+ +

A postcondition of a Point's move +operation is that the Point's coordinates should change. +If a call to move move didn't actually move a point by the desired +offset, then the point is in an illegal state and so an +IllegalStateException should be thrown. +

+ +

Note that because we're dealing with how the coordinates change +during move, we need some way of getting access to the coordinates +both before and after the move, in one piece of advice.

+ +

f. Check another postcondition

+ +

Task: Pass tests.Test2f +

+ +

Tools: the Rectangle(Rectangle) +constructor, the Rectangle.translate(int, int) method. +

+ +

FigureElement objects have a getBounds() +method that returns a java.awt.Rectangle representing the +bounds of the object. An important postcondition of the general +move operation on a figure element is that the figure +element's bounds rectangle should move by the same amount as the +figure itself. Write an aspect to check for this postcondition -- +throw an IllegalStateException if it is violated.

+ +

Help Yourself by Helping Others

+ +

At this point, check the people to your left and right. If +they're stuck somewhere, see if you can help them.

+ + + +
+ + +

3. Logging

+

d. Check a simple postcondition

One of the simplest postconditions to check is that a setter @@ -352,6 +409,7 @@ when it returns normally, or both?

tests.Test2d.

+

e. Check invariant

There is a method on the Box class, void @@ -398,77 +456,7 @@ causes the VM to abort.)

Make sure to pass the JUnit test tests.Test2f before continuing.

- -

g. Assure input

- -

Instead of throwing an exception when one of Point's -int fields are set to an out-of-bounds value, write an -aspect to trim the value into an in-bounds one. You'll want to use -around advice that exposes the new value of the field -assignment with an args pointcut, and -proceed with the trimmed value. Becuase this is tricky, -type in the below aspect... the trick for this exercise is not to come -up with an answer, but to understand the answer.

- -

Make sure to pass the JUnit test tests.Test2g -before continuing.

- -

Answer: -

- -
-package answers;
-
-import figures.*;
-
-aspect Answer2g {
-    int around(int val):
-            (set(int Point._x) || set(int Point._y))
-            && args(val) {
-        return proceed(trim(val));
-    }
-
-    private int trim(int val) {
-        return Math.max(Math.min(val, FigureElement.MAX_VALUE),
-                        FigureElement.MIN_VALUE);
-    }
-}
-
- - -

h. Check another invariant

- -

FigureElement objects have a getBounds() -method that returns a java.awt.Rectangle representing the -bounds of the object. An important postcondition of the -move operation is that the figure element's bounds -rectangle should move by the same amount as the figure itself. Write -an aspect to check for this postcondition -- throw an -IllegalStateException if it is violated.

- -

Note that because we're dealing with how the bounds changes during -move, we need some way of getting access to the bounds both before -and after the move, in one piece of advice. Also, note that -you can create a copy of a figure element's bounds rectangle with -new Rectangle(fe.getBounds()), and you can move a bounds -rectangle rect with rect.translate(dx, -dy).

- -

Make sure to pass the JUnit test tests.Test2h -before continuing.

- - -

Help Yourself by Helping Others

- -

At this point, check the people to your left and right. If -they're stuck somewhere, see if you can help them.

- - - -
- - -

3. Logging

+==================================================

The crosscutting feature you will be adding in part (4) will be support for caching the bound objects of Group figure diff --git a/docs/teaching/exercises/tests/Test2a.java b/docs/teaching/exercises/tests/Test2a.java index 0b737020b..4bc6dd28a 100644 --- a/docs/teaching/exercises/tests/Test2a.java +++ b/docs/teaching/exercises/tests/Test2a.java @@ -16,18 +16,16 @@ import figures.*; import junit.framework.*; -public class Test2a extends Test { +public class Test2a extends TestCase { public Test2a(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test2a.class); } - public void setUp() { - super.setUp(); - } - public void testTooSmall() { + Point p1 = new Point(10, 100); try { p1.setX(-10); fail("should have thrown IllegalArgumentException"); @@ -35,17 +33,13 @@ public class Test2a extends Test { } } - - public void testTooBig() { - try { - p1.setY(1000); - fail("should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException ea) { - } + public void testNotTooSmall() { + Point p1 = new Point(10, 100); + p1.setX(0); } - public void testMove() { + Line l1 = new Line(new Point(10, 100), new Point(20, 200)); try { l1.move(-500, -500); fail("should have thrown IllegalArgumentException"); diff --git a/docs/teaching/exercises/tests/Test2b.java b/docs/teaching/exercises/tests/Test2b.java index e127b5cc4..822c8de74 100644 --- a/docs/teaching/exercises/tests/Test2b.java +++ b/docs/teaching/exercises/tests/Test2b.java @@ -16,22 +16,31 @@ import figures.*; import junit.framework.*; -public class Test2b extends Test { +public class Test2b extends TestCase { public Test2b(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test2b.class); } - public void setUp() { - super.setUp(); - } - public void testNull() { + Point p1 = new Point(10, 100); + Group g = new Group(p1); + try { g.add(null); fail("should have thrown IllegalArgumentException"); } catch (IllegalArgumentException ea) { } } + + public void testNonNull() { + Point p1 = new Point(10, 100); + Group g = new Group(p1); + Point p2 = new Point(20, 200); + + g.add(p2); + } + } diff --git a/docs/teaching/exercises/tests/Test2c.java b/docs/teaching/exercises/tests/Test2c.java index 153739fc0..01c4978e4 100644 --- a/docs/teaching/exercises/tests/Test2c.java +++ b/docs/teaching/exercises/tests/Test2c.java @@ -16,30 +16,31 @@ import figures.*; import junit.framework.*; -public class Test2c extends Test { +public class Test2c extends TestCase { public Test2c(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); + junit.textui.TestRunner.run(Test2b.class); junit.textui.TestRunner.run(Test2c.class); } - public void setUp() { - super.setUp(); - } + public void testSelf() { + Point p1 = new Point(10, 100); + Group g = new Group(p1); - public void testNull() { try { - g.add(null); + g.add(g); fail("should have thrown IllegalArgumentException"); } catch (IllegalArgumentException ea) { } } - public void testSelf() { - try { - g.add(g); - fail("should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException ea) { - } + public void testNotSelf() { + Point p1 = new Point(10, 100); + Group g1 = new Group(p1); + Group g2 = new Group(p1); + + g1.add(g2); } } diff --git a/docs/teaching/exercises/tests/Test2d.java b/docs/teaching/exercises/tests/Test2d.java index b8056fbf3..cc8d7f51c 100644 --- a/docs/teaching/exercises/tests/Test2d.java +++ b/docs/teaching/exercises/tests/Test2d.java @@ -16,22 +16,31 @@ import figures.*; import junit.framework.*; -public class Test2d extends Test { +public class Test2d extends TestCase { public Test2d(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test2d.class); } - public void setUp() { - super.setUp(); + public void testOutOfBounds() { + Point p1 = new Point(10, 100); + + p1.setX(-10); + p1.setY(-100); + + assertEquals(0, p1.getX()); + assertEquals(0, p1.getY()); } - public void testSetting() { - try { - sloth1.setX(10); - fail("should have thrown RuntimeException"); - } catch (RuntimeException ea) { - } + public void testInBounds() { + Point p1 = new Point(10, 100); + + p1.setX(30); + p1.setY(300); + + assertEquals(30, p1.getX()); + assertEquals(300, p1.getY()); } } diff --git a/docs/teaching/exercises/tests/Test2e.java b/docs/teaching/exercises/tests/Test2e.java index dfa456138..09ab65790 100644 --- a/docs/teaching/exercises/tests/Test2e.java +++ b/docs/teaching/exercises/tests/Test2e.java @@ -16,27 +16,24 @@ import figures.*; import junit.framework.*; -public class Test2e extends Test { +public class Test2e extends TestCase { public Test2e(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test2e.class); } - public void setUp() { - super.setUp(); - } - - public void testEasy() { - Box sq = new Box(0, 0, 10, 10); - sq.move(5,5); - assertEquals(sq.getP0().getX(), 5); - assertEquals(sq.getP0().getY(), 5); - + public void testSloth() { + Point sp = new SlothfulPoint(10, 10); try { - sq.getP0().setX(100); - sq.move(37, 1); + sp.move(10, 10); fail("should have thrown IllegalStateException"); } catch (IllegalStateException e) { } } + + public void testNonSloth() { + Point p1 = new Point(10, 100); + p1.move(3, 30); + } } diff --git a/docs/teaching/exercises/tests/Test2f.java b/docs/teaching/exercises/tests/Test2f.java index a11e16781..1b90d268a 100644 --- a/docs/teaching/exercises/tests/Test2f.java +++ b/docs/teaching/exercises/tests/Test2f.java @@ -20,23 +20,23 @@ public class Test2f extends Test { public Test2f(String name) { super(name); } public static void main(String[] args) { + junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test2f.class); } - public void setUp() { - super.setUp(); - } - - public void testEasy() { - Box sq = new Box(0, 0, 10, 10); - sq.move(5,5); - assertEquals(sq.getP0().getX(), 5); - assertEquals(sq.getP0().getY(), 5); - + public void testSloth() { + FigureElement fe = new SlothfulPoint(10, 10); try { - sq.getP0().setX(100); - sq.getP1(); + fe.move(10, 10); fail("should have thrown IllegalStateException"); } catch (IllegalStateException e) { } } + + public void testNonSloth() { + Point p1 = new Point(10, 100); + Point p2 = new Point(20, 200); + Line l1 = new Line(p1, p2); + + l1.move(3, 30); + } } diff --git a/docs/teaching/exercises/tests/Test2g.java b/docs/teaching/exercises/tests/Test2g.java deleted file mode 100644 index f4a7a1949..000000000 --- a/docs/teaching/exercises/tests/Test2g.java +++ /dev/null @@ -1,42 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation - * ******************************************************************/ - -package tests; - -import figures.*; - -import junit.framework.*; - -public class Test2g extends Test { - public Test2g(String name) { super(name); } - - public static void main(String[] args) { - junit.textui.TestRunner.run(Test2g.class); - } - - public void setUp() { - super.setUp(); - } - - public void testBounds() { - p1.setX(FigureElement.MAX_VALUE + 1); - assertEquals(FigureElement.MAX_VALUE, p1.getX()); - p1.setY(FigureElement.MIN_VALUE - 1); - assertEquals(FigureElement.MIN_VALUE, p1.getY()); - } - - public void testBox() { - Box s = new Box(50, 50, 20000, 20000); - assertEquals(FigureElement.MAX_VALUE, s.getP2().getX()); - assertEquals(FigureElement.MAX_VALUE, s.getP2().getY()); - } -} diff --git a/docs/teaching/exercises/tests/Test2h.java b/docs/teaching/exercises/tests/Test2h.java deleted file mode 100644 index 339322519..000000000 --- a/docs/teaching/exercises/tests/Test2h.java +++ /dev/null @@ -1,42 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation - * ******************************************************************/ - -package tests; - -import figures.*; - -import junit.framework.*; - -public class Test2h extends Test { - public Test2h(String name) { super(name); } - - public static void main(String[] args) { - junit.textui.TestRunner.run(Test2h.class); - } - - public void setUp() { - super.setUp(); - } - - public void testSloth() { - FigureElement fe = new SlothfulPoint(10, 10); - try { - fe.move(10, 10); - fail("should have thrown IllegalStateException"); - } catch (IllegalStateException e) { } - } - - public void movePoints() { - p1.move(30, 45); - p2.move(10, 33); - } -}