|
|
@@ -13,14 +13,14 @@ cases. They progress, as most users do in their adoption of AspectJ, |
|
|
|
from non-functional, development-only aspects to aspects which augment |
|
|
|
a deployed program with crosscutting features. </p> |
|
|
|
|
|
|
|
<p> We have made available a package that includes the tests, the base |
|
|
|
code, JUnit, and a distribution of AspectJ. All it needs is |
|
|
|
information about where Java lives (so set your JAVA_HOME environment |
|
|
|
variable). It assumes that you unzip it in c:\ (on Windows) or in |
|
|
|
your home directory (on Linux): If you put it somewhere else, edit |
|
|
|
setpaths or setpaths.bat, as appropriate. Once all this is done, run |
|
|
|
<code>setpaths.bat</code> or <code>source setpaths</code> to export |
|
|
|
some other needed environment variables. </p> |
|
|
|
<p> Before the tutorial we will make available a package that includes |
|
|
|
the tests, the base code, JUnit, and a distribution of AspectJ. All |
|
|
|
it needs is information about where Java lives (so set your JAVA_HOME |
|
|
|
environment variable). It assumes that you unzip it in c:\ (on |
|
|
|
Windows) or in your home directory (on Linux): If you put it somewhere |
|
|
|
else, edit setpaths or setpaths.bat, as appropriate. Once all this is |
|
|
|
done, run <code>setpaths.bat</code> or <code>source setpaths</code> to |
|
|
|
export some other needed environment variables. </p> |
|
|
|
|
|
|
|
<p> All the files in the program are listed in base.lst, including |
|
|
|
test cases and an empty answer aspect, |
|
|
@@ -72,16 +72,39 @@ you go from one exercise to the next, make sure to save your work in a |
|
|
|
file and go on to work in a different file, even if you plan to |
|
|
|
duplicate some code. </p> |
|
|
|
|
|
|
|
<h3>Environment</h3> |
|
|
|
|
|
|
|
<p> You may use whatever editor or environment you choose to work |
|
|
|
through these exercises. We provide a simple code-browser that can |
|
|
|
work well as an editor for these short exercises, in addition to |
|
|
|
providing better visualization of how aspects affect the system: </p> |
|
|
|
|
|
|
|
<blockquote><PRE> |
|
|
|
$ ajbrowser base.lst |
|
|
|
</PRE></blockquote> |
|
|
|
|
|
|
|
<p> With the browser you can edit code (including the |
|
|
|
<code>answers/Answer.java</code> file), and after saving hit the build |
|
|
|
button to start an ajc compile. We recommend you start up another |
|
|
|
shell, though, to run the JUnit tests (and don't forget to run the |
|
|
|
<code>setpaths</code> script when you open the new shell): You could |
|
|
|
set up the run button to run a test through the Options menu, but |
|
|
|
we've found this is fairly cumbersome. </p> |
|
|
|
|
|
|
|
|
|
|
|
<hr> |
|
|
|
<!-- page break --> |
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
<br style="page-break-after: always" /> |
|
|
|
<h2>1. Static Invariants</h2> |
|
|
|
|
|
|
|
<h3>a. Catch old tracing</h3> |
|
|
|
|
|
|
|
<p> <strong>Sample Exercise</strong>: 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 </p> |
|
|
|
is to make sure your configuration works. Type in the answer below |
|
|
|
into your answer file, make sure you get the desired compile-time |
|
|
|
error, remove the offending line, and make sure you pass the JUnit |
|
|
|
test. </p> |
|
|
|
|
|
|
|
<p> <strong>Task:</strong> Signal a warning for calls to |
|
|
|
<code>System.out.println</code>. |
|
|
@@ -100,10 +123,9 @@ trace in <code>SlothfulPoint</code>. |
|
|
|
|
|
|
|
<blockquote><PRE> |
|
|
|
$ ajc -argfile base.lst |
|
|
|
./figures/SlothfulPoint.java:29:9: illegal access to System.out |
|
|
|
System.out.println("Slothful moving"); |
|
|
|
^ |
|
|
|
1 errors |
|
|
|
./figures/SlothfulPoint.java:38 illegal access to System.out |
|
|
|
|
|
|
|
1 error |
|
|
|
</PRE></blockquote> |
|
|
|
|
|
|
|
<p> Remove the illegal tracing call. |
|
|
@@ -116,7 +138,7 @@ all exercises) before continuing. </p> |
|
|
|
<blockquote><PRE> |
|
|
|
$ java tests.Test |
|
|
|
.... |
|
|
|
Time: 0.076 |
|
|
|
Time: 0.03 |
|
|
|
|
|
|
|
OK (4 tests) |
|
|
|
</PRE></blockquote> |
|
|
@@ -215,20 +237,17 @@ the convention. Make sure your program still passes the JUnit test |
|
|
|
your left and right. If they're stuck somewhere, see if you can help |
|
|
|
them. </p> |
|
|
|
|
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
<hr /> |
|
|
|
|
|
|
|
<h2>2. Dynamic invariants</h2> |
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
<br style="page-break-after: always" /> |
|
|
|
<h2>2. Dynamic invariants</h2> |
|
|
|
|
|
|
|
<h3>a. Check a simple precondition</h3> |
|
|
|
|
|
|
|
<p> <strong>Sample Exercise</strong>: 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 </p> |
|
|
|
|
|
|
|
<p> <strong>Sample Exercise</strong>: We've provided the answer to |
|
|
|
this exercise below to get you started. </p> |
|
|
|
|
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test2a</code>. |
|
|
|
</p> |
|
|
@@ -283,7 +302,7 @@ import figures.*; |
|
|
|
|
|
|
|
aspect Answer2a { |
|
|
|
before(int newValue): set(int Point.*) && args(newValue) { |
|
|
|
if (newValue < 0) { |
|
|
|
if (newValue < 0) { |
|
|
|
throw new IllegalArgumentException("too small"); |
|
|
|
} |
|
|
|
} |
|
|
@@ -322,8 +341,6 @@ an attempt is made to call <code>Group.add()</code> on a |
|
|
|
call. |
|
|
|
</p> |
|
|
|
|
|
|
|
XXX RENUMBER LATER |
|
|
|
|
|
|
|
<h3>d. Assure input</h3> |
|
|
|
|
|
|
|
<p> <strong>Task: </strong> Pass <code>tests.Test2g</code>. |
|
|
@@ -380,83 +397,12 @@ throw an <code>IllegalStateException</code> if it is violated. </p> |
|
|
|
<p> At this point, check the people to your left and right. If |
|
|
|
they're stuck somewhere, see if you can help them. </p> |
|
|
|
|
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
<hr /> |
|
|
|
<!-- page break --> |
|
|
|
|
|
|
|
<h2>3. Logging</h2> |
|
|
|
|
|
|
|
<h3>d. Check a simple postcondition</h3> |
|
|
|
|
|
|
|
<p> One of the simplest postconditions to check is that a setter |
|
|
|
actually sets its value. Write an aspect that throws a |
|
|
|
<code>java.lang.RuntimeException</code> if, after calling |
|
|
|
<code>setX()</code> on <code>SlothfulPoint</code> objects, |
|
|
|
<code>getX()</code> doesn't return the new value. </p> |
|
|
|
|
|
|
|
<p> You'll want to use an <code>args</code> pointcut to expose the |
|
|
|
argument to <code>setX()</code> and a <code>target</code> pointcut to |
|
|
|
expose the <code>SlothfulPoint</code> object itself (so you can later |
|
|
|
call <code>getX()</code> on it). |
|
|
|
</p> |
|
|
|
|
|
|
|
<p> An interesting question to think about for discussion is whether |
|
|
|
this postcondition should apply when getX() throws an exception, or |
|
|
|
when it returns normally, or both? </p> |
|
|
|
|
|
|
|
<p> With this aspect in place, your code should pass |
|
|
|
<code>tests.Test2d</code>. |
|
|
|
</p> |
|
|
|
|
|
|
|
|
|
|
|
<h3>e. Check invariant</h3> |
|
|
|
|
|
|
|
<p> There is a method on the <code>Box</code> class, <code>void |
|
|
|
checkBoxness()</code>, that checks whether the four points making up a |
|
|
|
box are correctly positioned relative to each other (i.e., they form a |
|
|
|
rectangle). Write an aspect that will make sure that after every time |
|
|
|
the <code>void move(int, int)</code> method on <code>Box</code> is |
|
|
|
called, that you also call <code>Box.checkBoxness()</code> to ensure |
|
|
|
that the <code>move</code> didn't break this invariant. </p> |
|
|
|
|
|
|
|
<p> With this aspect in place, your code should pass |
|
|
|
<code>tests.Test2e</code>. |
|
|
|
</p> |
|
|
|
|
|
|
|
<h3>f. Refine your invariant</h3> |
|
|
|
|
|
|
|
<p> <code>move</code> is not the only interesting method on |
|
|
|
<code>Box</code>. It may be that a box gets malformed between calls |
|
|
|
to <code>move</code>. So instead of checking boxness only |
|
|
|
after the <code>move</code> method of <code>Box</code>, check |
|
|
|
after the call to every one of <code>Box</code>'s public methods. |
|
|
|
</p> |
|
|
|
|
|
|
|
<p> When testing this aspect, you may find yourself facing a |
|
|
|
<code>StackOverflowException</code>. If so, carefully look at your |
|
|
|
pointcuts. Needless to say, there should not be an infinite loop in |
|
|
|
your program. You might want to look at using a <code>within</code> |
|
|
|
pointcut for a filter. </p> |
|
|
|
|
|
|
|
<p> (You might even find that this test case aborts with no message, |
|
|
|
i.e., |
|
|
|
</p> |
|
|
|
|
|
|
|
<blockquote><pre> |
|
|
|
$ java tests.test2f |
|
|
|
. |
|
|
|
$ |
|
|
|
</pre></blockquote> |
|
|
|
|
|
|
|
<p> this is a bug in Sun's JVM where a particular stack overflow |
|
|
|
causes the VM to abort.) |
|
|
|
</p> |
|
|
|
|
|
|
|
<p> Make sure to pass the JUnit test <code>tests.Test2f</code> |
|
|
|
before continuing. </p> |
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
================================================== |
|
|
|
<br style="page-break-after: always" /> |
|
|
|
<h2>3. Tracing</h2> |
|
|
|
|
|
|
|
<p> The crosscutting feature you will be adding in part (4) will be |
|
|
|
support for caching the bound objects of <code>Group</code> figure |
|
|
@@ -465,7 +411,7 @@ it's useful to explore the system with some tracing aspects. </p> |
|
|
|
|
|
|
|
<h3>a. Simple logging</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test3a</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test3a</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>Log.log(String)</code>, |
|
|
|
<code>thisJoinPoint.toString()</code>, <code>execution</code>, |
|
|
@@ -479,7 +425,7 @@ and call <code>Log.log(String)</code></p> |
|
|
|
|
|
|
|
<h3>b. Simple logging</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test3b</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test3b</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>target</code> |
|
|
|
</p> |
|
|
@@ -487,7 +433,7 @@ and call <code>Log.log(String)</code></p> |
|
|
|
|
|
|
|
<h3>c. More specialized logging</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test3c</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test3c</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> |
|
|
|
</p> |
|
|
@@ -520,7 +466,7 @@ based on the type of a parameter to a method call. </em> </p> |
|
|
|
|
|
|
|
<h3>d. Logging extended to checking an invariant</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test3d</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test3d</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>inter-type field declaration</code> |
|
|
|
</p> |
|
|
@@ -530,7 +476,7 @@ based on the type of a parameter to a method call. </em> </p> |
|
|
|
|
|
|
|
<h3>e. Better error messages for 3d</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test3e</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test3e</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> |
|
|
|
</p> |
|
|
@@ -581,13 +527,12 @@ previous exercises, you'll be most of the way there. </em> </p> |
|
|
|
<p> At this point, check the people to your left and right. If |
|
|
|
they're stuck somewhere, see if you can help them. </p> |
|
|
|
|
|
|
|
<hr /> |
|
|
|
|
|
|
|
<!-- ============================== --> |
|
|
|
|
|
|
|
<hr /> |
|
|
|
|
|
|
|
<!-- page break --> |
|
|
|
<h3>4. Caching</h3> |
|
|
|
<br style="page-break-after: always" /> |
|
|
|
<h2>4. Caching</h2> |
|
|
|
|
|
|
|
<p> Computation of the bounding box of <code>Group</code> objects |
|
|
|
needs to deal with all aggregate parts of the group, and this |
|
|
@@ -602,7 +547,7 @@ handle those points contained in Lines and Boxes only if time permits. |
|
|
|
|
|
|
|
<h3>a. Make a constant override</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test4a</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test4a</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>around</code>, |
|
|
|
<code>FigureElement.MAX_BOUNDS</code> |
|
|
@@ -623,7 +568,7 @@ around advice intercepting the method. |
|
|
|
|
|
|
|
<h3>b. Make a constant cache</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test4b</code>. |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test4b</code>. |
|
|
|
</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>private Rectangle Group.mumble;</code> |
|
|
@@ -642,7 +587,7 @@ state for every <code>Group</code> object.</em> </p> |
|
|
|
|
|
|
|
<h3>c. Invalidate, part 1</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test4c</code>. |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test4c</code>. |
|
|
|
</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>before</code> |
|
|
@@ -656,7 +601,7 @@ Change your aspect so that it invalidates the cache whenever the |
|
|
|
|
|
|
|
<h3>d. Invalidate, part 2</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test4d</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test4d</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <code>your solution to 3c</code></p> |
|
|
|
|
|
|
@@ -670,7 +615,7 @@ where there you cared about method calls. </p> |
|
|
|
|
|
|
|
<h3>e. Invalidate, part 3</h3> |
|
|
|
|
|
|
|
<p> <strong>Problem:</strong> Pass <code>tests.Test4e</code>.</p> |
|
|
|
<p> <strong>Task:</strong> Pass <code>tests.Test4e</code>.</p> |
|
|
|
|
|
|
|
<p> <strong>Tools:</strong> <em>You're on you're own</em></p> |
|
|
|
|