mas01mj@732: package asunit.framework { mas01mj@732: mas01mj@732: import asunit.errors.AbstractError; mas01mj@732: mas01mj@732: import flash.errors.IllegalOperationError; mas01mj@732: import flash.events.*; mas01mj@732: import flash.net.URLLoader; mas01mj@732: import flash.utils.getTimer; mas01mj@732: mas01mj@732: /** mas01mj@732: * Extend this class if you have a TestCase that requires the mas01mj@732: * asynchronous load of external data. mas01mj@732: */ mas01mj@732: public class AsynchronousTestCase extends TestCase implements Test { mas01mj@732: mas01mj@732: protected static const DEFAULT_REMOTE_TIMEOUT:int = 30000; mas01mj@732: private static const INVALID_TIME:int = -1; mas01mj@732: mas01mj@732: private var _ioErrorExpected:Boolean; mas01mj@732: private var _remoteDuration:int; mas01mj@732: private var _remoteStartTime:int; mas01mj@732: private var _remoteTimeout:int; mas01mj@732: private var _securityErrorExpected:Boolean; mas01mj@732: mas01mj@732: public function AsynchronousTestCase(testMethod:String = null) { mas01mj@732: super(testMethod); mas01mj@732: _remoteStartTime = INVALID_TIME; mas01mj@732: mas01mj@732: // set defaults for user-configurable properties: mas01mj@732: _remoteTimeout = DEFAULT_REMOTE_TIMEOUT; mas01mj@732: _ioErrorExpected = false; mas01mj@732: _securityErrorExpected = false; mas01mj@732: } mas01mj@732: mas01mj@732: public function get remoteDuration():int { mas01mj@732: return _remoteDuration; mas01mj@732: } mas01mj@732: mas01mj@732: public function remoteDurationIsValid():Boolean { mas01mj@732: return _remoteDuration != INVALID_TIME; mas01mj@732: } mas01mj@732: mas01mj@732: // see testRemoteDuration() below mas01mj@732: public function set remoteTimeout(ms:int):void { mas01mj@732: _remoteTimeout = ms; mas01mj@732: } mas01mj@732: mas01mj@732: public function set ioErrorExpected(yn:Boolean):void { mas01mj@732: _ioErrorExpected = yn; mas01mj@732: } mas01mj@732: mas01mj@732: public function set securityErrorExpected(yn:Boolean):void { mas01mj@732: _securityErrorExpected = yn; mas01mj@732: } mas01mj@732: mas01mj@732: // use this method in overriding run() if you are using a URLLoader: mas01mj@732: protected function configureListeners(loader:URLLoader):void { mas01mj@732: loader.addEventListener(Event.COMPLETE, completeHandler); mas01mj@732: loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler); mas01mj@732: loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); mas01mj@732: loader.addEventListener(Event.OPEN, openHandler); mas01mj@732: loader.addEventListener(ProgressEvent.PROGRESS, progressHandler); mas01mj@732: loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); mas01mj@732: } mas01mj@732: mas01mj@732: // in a subclass, you should override this method and call super.run() at the end mas01mj@732: public override function run():void { mas01mj@732: if ((this as Object).constructor == AsynchronousTestCase) mas01mj@732: { mas01mj@732: throw new AbstractError("run() method must be overridden in class derived from AsynchronousTestCase"); mas01mj@732: } mas01mj@732: mas01mj@732: startRemoteDuration(); mas01mj@732: } mas01mj@732: mas01mj@732: private final function startRemoteDuration():void { mas01mj@732: _remoteStartTime = getTimer(); mas01mj@732: } mas01mj@732: mas01mj@732: private final function setRemoteDuration():void { mas01mj@732: if (_remoteStartTime == INVALID_TIME) { mas01mj@732: // I guess you overrode run() in a subclass without calling super.run() mas01mj@732: _remoteDuration = INVALID_TIME; mas01mj@732: } mas01mj@732: else { mas01mj@732: _remoteDuration = getTimer() - _remoteStartTime; mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: protected final function completeHandler(event:Event):void { mas01mj@732: setRemoteDuration(); mas01mj@732: setDataSource(event); mas01mj@732: // call super.run() to execute test methods: mas01mj@732: runTests(); mas01mj@732: } mas01mj@732: mas01mj@732: // override this method to put a copy of the data into a member reference mas01mj@732: protected function setDataSource(event:Event):void { mas01mj@732: throw new AbstractError("setDataSource must be overridden in class derived from AsynchronousTestCase"); mas01mj@732: } mas01mj@732: mas01mj@732: // this method gives derived classes access to TestCase.run() mas01mj@732: protected final function runTests():void { mas01mj@732: super.run(); mas01mj@732: } mas01mj@732: mas01mj@732: // TODO: add support for failing status events... mas01mj@732: protected function httpStatusHandler(event:HTTPStatusEvent):void { mas01mj@732: // I believe this is useless except in AIR. mas01mj@732: } mas01mj@732: mas01mj@732: protected final function ioErrorHandler(event:IOErrorEvent):void { mas01mj@732: result.startTest(this); mas01mj@732: if (_ioErrorExpected == false) mas01mj@732: { mas01mj@732: // access is authorized and we didn't get in: log the error mas01mj@732: result.addError(this, new IllegalOperationError(event.text)); mas01mj@732: } mas01mj@732: setRemoteDuration(); mas01mj@732: testRemoteDuration(); mas01mj@732: dispatchEvent(new Event(Event.COMPLETE)); mas01mj@732: } mas01mj@732: mas01mj@732: protected function openHandler(event:Event):void { mas01mj@732: } mas01mj@732: mas01mj@732: protected function progressHandler(event:ProgressEvent):void { mas01mj@732: } mas01mj@732: mas01mj@732: protected final function securityErrorHandler(event:SecurityErrorEvent):void { mas01mj@732: result.startTest(this); mas01mj@732: if (_securityErrorExpected == false) mas01mj@732: { mas01mj@732: // access is authorized and we didn't get in: log the error mas01mj@732: result.addError(this, new IllegalOperationError(event.text)); mas01mj@732: } mas01mj@732: setRemoteDuration(); mas01mj@732: testRemoteDuration(); mas01mj@732: dispatchEvent(new Event(Event.COMPLETE)); mas01mj@732: } mas01mj@732: mas01mj@732: public function testRemoteDuration():void { mas01mj@732: if (!remoteDurationIsValid()) mas01mj@732: { mas01mj@732: return; mas01mj@732: } mas01mj@732: if (_remoteDuration > _remoteTimeout) mas01mj@732: { mas01mj@732: result.addError(this, new IllegalOperationError("remote communication took too long: " + _remoteDuration/1000 + " seconds.\n" + this.toString())); mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: public function testUnauthorizedAccess():void { mas01mj@732: if (_securityErrorExpected || _ioErrorExpected) mas01mj@732: { mas01mj@732: fail("unauthorized access permitted (expected no access)\n" + this.toString()); mas01mj@732: } mas01mj@732: } mas01mj@732: mas01mj@732: } mas01mj@732: }