Detecting Class-Recursion in AS3
This article has arisen because I found that every now and again while I was writing unit tests for my code, I would find myself coming across stack overflows caused by an infinite recursion of classes. The unit-testing framework didn’t provide a very helpful error message informing me what was going wrong. I decided if I could amend the framework so that it gave me a message which I could resolve easily. It turns out to be harder than it first appeared.
The Recursive Problem
It is unlikely that you would ever write a class like this:
class Recursive
{
public function Recursive()
{
new Recursive();
}
}
However, there is a context where it’s not as unlikely as you’d think. One of the more annoying aspects of test-driven development is the creation of test suites and test classes to reflect each of the packages in your source folder. By convention each package contains an AllTests test suite which adds all the tests within that package. Below is an example:
package mypackage
{
import asunit.framework.TestSuite;
import mypackage.subpackage.AllTests;
public class AllTests extends TestSuite
{
public function AllTests()
{
addTest(new mypackage.AllTests());
addTest(new ExampleTestCase());
}
}
}
If you spotted the deliberate mistake, award yourself ten points. mypackage.AllTests was supposed to add mypackage.subpackage.AllTests as a test suite, but it inadvertently added itself. This will cause a stack overflow in ASUnit. It will tell you that:
Could not create and run test suite: Error: Error #1023: Stack overflow occurred.
It’s accurate, but not massively informative. We can do better than that.
A Generic Solution
I wanted to approach the problem generically before applying any solution to the ASUnit framework. How, then, can you detect that a constructor method calls another instance of the same method?
In AS2 there was an arguments.caller object, which would have allowed me to access the referring method. describeType could be used to inspect the caller and the current method, and check whether they’re the same… unfortunately, arguments.caller is not supported in AS3, as the AS3 Language Reference explains.
However, it is still possible to discover information about the methods in the stack of currently-called elements: by creating (but not throwing) an error. As long as you are running Flash in the debug player, then you can inspect that stack trace created by the error, and determine the sequence of constructions.
Check out the github repository for this approach
The main class in this repository is the RecursionWatcher.as file. The workhorse method is the stackIndicatesRecursion method which takes a generated error and inspects the stack trace that it produces to determine whether class-recursion is taking place.
A Solution for ASUnit?
So far this I’ve created this solution generically in its own repository, and I haven’t tried to integrate it into ASUnit. Some issues need to be thought through:
- Should this sort of solution be integrated into the TestCase or TestSuite class?
- What are the speed implications of adding this? What sort of speed reduction is the extra functionality worth?
- Can the functionality be put into a class which decorates the TestCase, minimising the footprint of the core code changes?
I will be approaching integrating this work into the latest versions of ASUnit in the next few weeks, but I would like to guage whether this is the most appropriate course of action to take, and whether it’s even worth putting this sort of test into the framework. All comments welcome!
-
http://robertpenner.com/ Robert Penner
-
http://robertpenner.com Robert Penner
-
http://alecmce.com Anonymous
-
http://alecmce.com alec
-
http://twitter.com/retrogamer4ever retrogamer4ever
-
http://twitter.com/alecmce alecmce


