http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ErrorArray.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ErrorArray.as 
b/mustella/src/main/flex/ErrorArray.as
new file mode 100644
index 0000000..b30d234
--- /dev/null
+++ b/mustella/src/main/flex/ErrorArray.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+    public class ErrorArray {
+        private var _parts:Array;
+
+        public function ErrorArray(parts:Array) {
+            _parts = parts;
+        }
+
+        public function get parts():Array {
+            return _parts;
+        }
+
+        /**
+         *  customize string representation
+         */
+        public function toString():String {
+            var s:String;
+            if (parts && parts.length > 0)
+                s = '"' + parts.join('"..."') + '"';
+            return s;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/EventSnifferRemote.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/EventSnifferRemote.as 
b/mustella/src/main/flex/EventSnifferRemote.as
new file mode 100644
index 0000000..f2fe2d2
--- /dev/null
+++ b/mustella/src/main/flex/EventSnifferRemote.as
@@ -0,0 +1,154 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package 
+{
+import flash.display.DisplayObject;
+import flash.events.Event;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.events.StatusEvent;
+import flash.net.LocalConnection;
+
+import mx.core.FlexGlobals;
+import mx.core.IFlexDisplayObject;
+import mx.core.IMXMLObject;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+[Mixin]
+/**
+ *  Traps most events and records them to SnifferRemoteClient.swf
+ */
+public class EventSnifferRemote
+{
+       public function EventSnifferRemote()
+       {
+       }
+
+       public static function init(root:Object):void
+       {
+               document = root;
+               if (document)
+                       document.addEventListener("applicationComplete", 
initHandler);
+                       
+               connection = new LocalConnection();
+               connection.allowDomain("*");
+               connection.addEventListener(StatusEvent.STATUS, statusHandler);
+               
+               commandconnection = new LocalConnection();
+               commandconnection.allowDomain("*");
+               commandconnection.client = EventSnifferRemote;
+               commandconnection.connect("_EventSnifferCommands");
+       }
+
+    // Turn on only if the SnifferRemoteClient app's checkbox
+    // for this item is checked.
+       private static function initHandler(event:Event):void
+       {
+        connection.send("_EventSniffer", "toggleSniffersEnabled");
+       }
+
+       private static function statusHandler(event:Event):void
+       {
+       }
+
+    /**
+     *  @private
+        *  The document containing a reference to this object
+     */
+    private static var document:Object;
+
+    /**
+     *  @private
+        *  The local connection to the remote client
+     */
+    private static var connection:LocalConnection;
+    private static var commandconnection:LocalConnection;
+
+       public static function enableSniffer():void
+       {
+        //trace("EventSnifferRemote enabled");
+
+               // hook UIComponent so we can see all events
+               UIComponent.dispatchEventHook = dispatchEventHook;
+               document.stage.addEventListener(MouseEvent.CLICK, uberListener, 
true);
+               document.stage.addEventListener(MouseEvent.DOUBLE_CLICK, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_DOWN, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_MOVE, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_OUT, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_OVER, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_UP, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_WHEEL, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.ROLL_OUT, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.ROLL_OVER, 
uberListener, true);
+               document.stage.addEventListener(KeyboardEvent.KEY_UP, 
uberListener, true);
+               document.stage.addEventListener(KeyboardEvent.KEY_DOWN, 
uberListener, true);
+               document.stage.addEventListener(FocusEvent.FOCUS_IN, 
uberListener, true);
+               document.stage.addEventListener(FocusEvent.FOCUS_OUT, 
uberListener, true);
+       }
+
+       public static function disableSniffer():void
+       {
+        //trace("EventSnifferRemote disabled");
+        
+               // unhook UIComponent so we can see all events
+               UIComponent.dispatchEventHook = null;
+               document.stage.removeEventListener(MouseEvent.CLICK, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.DOUBLE_CLICK, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_DOWN, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_MOVE, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_OUT, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_OVER, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_UP, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.ROLL_OUT, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.ROLL_OVER, 
uberListener, true);
+               document.stage.removeEventListener(KeyboardEvent.KEY_UP, 
uberListener, true);
+               document.stage.removeEventListener(KeyboardEvent.KEY_DOWN, 
uberListener, true);
+               document.stage.removeEventListener(FocusEvent.FOCUS_IN, 
uberListener, true);
+               document.stage.removeEventListener(FocusEvent.FOCUS_OUT, 
uberListener, true);
+       }
+
+       private static function uberListener(event:Event):void
+       {
+               dispatchEventHook(event, DisplayObject(event.target));
+       }
+
+       private static function dispatchEventHook(event:Event, 
target:DisplayObject):void
+       {
+           
+               // connection.send("_EventSniffer", "appendLog", "Event", 
target.toString(), event.type, event.toString());
+               
+               // This is the appendLog method in SnifferRemoteClient which 
will accept this:
+           // public function appendLog(dataSource:String = null, 
target:String=null, eventName:String = null, event:String = null):void
+
+           var info:Object = new Object();
+           
+           info.dataSource = "Event";
+           info.target = target.toString();
+           info.eventName = event.type;
+           info.event = event.toString();
+           
+           connection.send("_EventSniffer", "appendLog", info);
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExcludeFileLocation.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExcludeFileLocation.as 
b/mustella/src/main/flex/ExcludeFileLocation.as
new file mode 100644
index 0000000..ee5ce6f
--- /dev/null
+++ b/mustella/src/main/flex/ExcludeFileLocation.as
@@ -0,0 +1,226 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.events.Event;
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.system.Capabilities;
+
+[Mixin]
+/**
+ *  Location of a hash table of tests not to run. 
+ *  This mixin should find the excludes written to one of two locations.
+ *  Browsers runs are picky about where they find the excludes, so, we serve 
them 
+ *  up via http (in a sibling location to the tests). 
+ *  The file is one test per line of the form ScriptName$TestID
+ *  The location of the file is assumed to be c:/temp on windows, 
+ *  or /tmp on Unix. 
+ */
+public class ExcludeFileLocation
+{
+
+       private static var loader:URLLoader;
+
+       public static var url:String;
+       public static var mustellaTestDir:String;
+
+       public static var frontURL:String;
+       public static var domain:String;
+
+       public static var excludeFile:String;
+
+       /**
+        * tell UnitTester it should wait for this load to complete
+        */
+       UnitTester.waitForExcludes = true;
+
+
+       public static var _root:DisplayObject;
+
+
+       public static var triedBrowser:Boolean = false;
+       public static var triedNormal:Boolean  = false;
+
+       // we try the http spot, in case this is a browser run
+       public static function init(root:DisplayObject):void
+       {
+
+               trace ("Hello from excludes at: " + new Date());
+
+       _root = root;
+
+        // set up callback to load excludes after 
+        // UnitTester has initialized.
+        UnitTester.loadExcludeFile = loadExcludeFile;   
+
+    }
+
+    public static function loadExcludeFile():void
+    {
+        var os:String = Capabilities.os;
+        
+        
+        if (os.indexOf ("Windows") != -1) 
+        {
+            excludeFile = "ExcludeListWin.txt";
+        } else if (os.indexOf ("Mac") != -1) 
+        {
+            excludeFile = "ExcludeListMac.txt";
+        } else if (os.indexOf ("Linux") != -1) 
+        {
+            excludeFile = "ExcludeListLinux.txt";
+        } else 
+        {              
+            trace ("Excludes: bad: we didn't see an OS we liked: " + os);
+            excludeFile = "ExcludeListWin.txt";
+        }
+        
+        url = _root.loaderInfo.url;
+        
+        // allow application to override mustella test dir
+        if (!UnitTester.mustellaTestDir)
+            mustellaTestDir = url.substring (0, url.indexOf 
("mustella/tests")+14);
+        else
+            mustellaTestDir = UnitTester.mustellaTestDir;
+        
+        frontURL = url.substring (0, url.indexOf (":"));
+        
+        domain = url.substring (url.indexOf (":")+3);
+        domain = domain.substring (0, domain.indexOf ("/"));
+        
+        if (Capabilities.playerType == "PlugIn" || Capabilities.playerType == 
"ActiveX")
+        { 
+            loadTryBrowser();
+        } else
+        {
+            loadTryNormal();
+            
+        } 
+        
+    }
+
+    public static function loadTryBrowser():void
+       {
+               trace ("excludes loadTryBrowser at: " + new Date().toString());
+
+               triedBrowser = true;
+
+               var useFile:String = "http://localhost/"; + excludeFile;
+
+               trace ("try excludes from here: " + useFile);
+
+               var req:URLRequest = new URLRequest(useFile);
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler);
+               loader.addEventListener("securityError", errorHandler);
+               loader.addEventListener("ioError", errorHandler);
+               loader.load(req);
+
+       }
+
+       /// if it worked, all good
+       private static function completeHandler(event:Event):void
+       {
+               trace ("Excludes: from web server");
+               postProcessData(event);
+       }
+
+
+       /**
+        *  A non-browser will get its results from the /tmp location. 
+        *  It should be a failure to get here; we try the browser case first
+        *  because it throws a nasty seciry
+        *  
+        */
+       public static function errorHandler(event:Event):void
+       { 
+       
+               trace ("Exclude: in the web read error handler");
+        if (!triedNormal) 
+               {
+                       loadTryNormal();
+               }
+
+       }
+       public static function loadTryNormal():void
+       {
+
+               triedNormal = true;
+
+               trace ("excludes loadTryFile " + new Date().toString());
+
+               var useFile:String;
+
+               useFile = mustellaTestDir +"/" + excludeFile;
+
+               trace ("Exclude: try load from: " + useFile);
+
+        var req:URLRequest = new URLRequest(useFile);
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler2);
+               loader.addEventListener("ioError", errorHandler2);
+               loader.addEventListener("securityError", errorHandler2);
+               loader.load(req);
+
+       }
+
+       private static function errorHandler2(event:Event):void
+       {
+               trace ("Exclude: error in the exclude file load " +event);
+        if (!triedBrowser) 
+               {
+                       loadTryBrowser();
+               }
+
+       }
+
+
+       private static function completeHandler2(event:Event):void
+       {
+               trace ("Excludes: Reading from file system at "+mustellaTestDir 
);
+               postProcessData(event);
+       }
+       private static function postProcessData(event:Event):void
+       {
+               var data:String = loader.data;
+               // DOS end of line
+               var delimiter:RegExp = new RegExp("\r\n", "g");
+               data = data.replace(delimiter, ",");
+               // Unix end of line
+               delimiter = new RegExp("\n", "g");
+               data = data.replace(delimiter, ",");
+
+               UnitTester.excludeList = {};
+               var items:Array = data.split(",");
+               var n:int = items.length;
+               for (var i:int = 0; i < n; i++)
+               {
+                       var s:String = items[i];
+                       if (s.length)
+                               UnitTester.excludeList[s] = 1;
+               }
+               
+               UnitTester.waitForExcludes = false;
+               UnitTester.pre_startEventHandler(event);
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExcludeFileLocationApollo.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExcludeFileLocationApollo.as 
b/mustella/src/main/flex/ExcludeFileLocationApollo.as
new file mode 100644
index 0000000..56bb0a4
--- /dev/null
+++ b/mustella/src/main/flex/ExcludeFileLocationApollo.as
@@ -0,0 +1,300 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.events.Event;
+import flash.system.Capabilities;
+import flash.filesystem.File;
+
+[Mixin]
+/**
+ *  Location of a hash table of tests not to run. 
+ *  This mixin should find the excludes written to one of two locations.
+ *  Browsers runs are picky about where they find the excludes, so, we serve 
them 
+ *  up via http (in a sibling location to the tests). 
+ *  The file is one test per line of the form ScriptName$TestID
+ *  The location of the file is assumed to be c:/temp on windows, 
+ *  or /tmp on Unix. 
+ */
+public class ExcludeFileLocationApollo
+{
+
+       private static var loader:URLLoader;
+
+       private static var url:String;
+       private static var mustellaTestDir:String;
+
+       private static var frontURL:String;
+       private static var domain:String;
+
+       public static var excludeFile:String = "ExcludeList.txt";       
+
+       /**
+        * tell UnitTester it should wait for this load to complete
+        */
+       UnitTester.waitForExcludes = true;
+
+
+       public static var _root:DisplayObject;
+
+
+       public static var triedBrowser:Boolean = false;
+       public static var triedNormal:Boolean  = false;
+
+       // we try the http spot, in case this is a browser run
+       public static function init(root:DisplayObject):void
+       {
+
+               trace ("Hello from excludes at: " + new Date());
+
+        _root = root;
+            
+        // set up callback to load excludes after 
+        // UnitTester has initialized.
+        UnitTester.loadExcludeFile = loadExcludeFile;   
+        
+       }
+
+
+    public static function loadExcludeFile():void
+    {
+        var os:String = Capabilities.os;
+        
+        // This seems to be a timing issue which pops up on some machines.
+        if( UnitTester.cv == null ){
+            UnitTester.cv = new ConditionalValue();
+        }
+        
+        if( (UnitTester.cv.os != null) && (UnitTester.cv.os.toLowerCase() == 
DeviceNames.ANDROID.toLowerCase()) ){
+            mustellaTestDir = "..";
+            excludeFile = UnitTester.excludeFile;
+            trace("Doing Android style exclude.  Checking in " + 
mustellaTestDir + "/" + excludeFile);
+        }else if( (UnitTester.cv.os != null) && 
(UnitTester.cv.os.toLowerCase() == DeviceNames.IOS.toLowerCase()) ){
+            mustellaTestDir = File.documentsDirectory.url;
+            excludeFile = UnitTester.excludeFile;
+        }else if (os.indexOf ("QNX") > -1) {
+            mustellaTestDir = "..";
+            excludeFile = UnitTester.excludeFile;
+            trace("Doing QNX style exclude.  Checking in " + mustellaTestDir + 
"/" + excludeFile);
+        }
+        else{
+            
+            if (os.indexOf ("Windows") != -1) 
+            {
+                excludeFile = "ExcludeListWinAIR.txt";
+            } else if (os.indexOf ("Mac") != -1) 
+            {
+                excludeFile = "ExcludeListMacAIR.txt";
+            } else if (os.indexOf ("Linux") != -1) 
+            {
+                excludeFile = "ExcludeListLinux.txt";
+            } else 
+            {          
+                trace ("Excludes: bad: we didn't see an OS we liked: " + os);
+                excludeFile = "ExcludeListWin.txt";
+            }
+            
+            url = _root.loaderInfo.url;
+            
+            if (url.indexOf("app:")!=-1) 
+            {
+                ApolloFilePath.init (_root);
+                url = encodeURI2(ApolloFilePath.apolloAdjust(url));
+                trace ("Adjusting path for AIR to: " + url);
+                // url = adjustPath(url);
+            }
+            
+            // allow application to override mustella test dir
+            if (!UnitTester.mustellaTestDir)
+                mustellaTestDir = url.substring (0, url.indexOf 
("mustella/tests")+14);
+            else
+                mustellaTestDir = UnitTester.mustellaTestDir;
+            
+            frontURL = url.substring (0, url.indexOf (":"));
+            domain = url.substring (url.indexOf (":")+3);              
+            domain = domain.substring (0, domain.indexOf ("/"));
+        }
+        
+        loadTryNormal();
+        
+    }
+
+    private static function apolloAdjust(url:String):String
+       {
+
+               var swf:String = _root.loaderInfo.url;
+               var f:File = new File (swf);
+               // clean it up: 
+               var myPattern:RegExp = /\\/g; 
+               var path:String = f.nativePath;
+               path = path.replace (myPattern, "/");
+               path = path.replace (":", "|");
+               // yank off the swfs directory, which we're in
+               path = path.substr (0, path.lastIndexOf ("/")-1);
+               path = path.substr (0, path.lastIndexOf ("/"));
+
+               if (url.indexOf ("../")==0)
+                       url = url.substring (2);
+
+               if (url.indexOf ("/..")==0)
+               {
+                       url = url.substring (3);
+                       path = path.substr (0, path.lastIndexOf ("/"));
+               }
+
+               /// create the final url
+               path = path + url;
+
+               return "file:///" + path;
+       }
+
+       public static var adjustPath:Function = function(url:String):String { 
return url; };
+
+
+
+        private static function encodeURI2(s:String):String
+        {
+                var pos:int = s.lastIndexOf("/");
+                if (pos != -1)
+                {
+                        var fragment:String = s.substring(pos + 1);
+                        s = s.substring(0, pos + 1);
+                        fragment= encodeURIComponent(fragment);
+                        s = s + fragment;
+                }
+                return s;
+        }
+
+
+       public static function loadTryBrowser():void
+       {
+               trace ("excludes loadTryBrowser at: " + new Date().toString());
+
+               triedBrowser = true;
+
+               var currentOS:String = Capabilities.os;
+
+               var useFile:String = "http://localhost/"; + excludeFile;
+
+               trace ("try excludes from here: " + useFile);
+
+               var req:URLRequest = new URLRequest(useFile);
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler);
+               loader.addEventListener("securityError", errorHandler);
+               loader.addEventListener("ioError", errorHandler);
+               loader.load(req);
+
+       }
+
+       /// if it worked, all good
+       private static function completeHandler(event:Event):void
+       {
+               trace ("Excludes: from web server");
+               postProcessData(event);
+       }
+
+
+       /**
+        *  A non-browser will get its results from the /tmp location. 
+        *  It should be a failure to get here; we try the browser case first
+        *  because it throws a nasty seciry
+        *  
+        */
+       public static function errorHandler(event:Event):void
+       { 
+       
+               trace ("Exclude: in the web read error handler");
+               if (!triedNormal) 
+               {
+                       loadTryNormal();        
+
+               }
+
+       }
+       public static function loadTryNormal():void
+       {
+
+               triedNormal = true;
+
+               trace ("excludes loadTryFile " + new Date().toString());
+
+               var currentOS:String = Capabilities.os;
+
+               var useFile:String;
+
+               useFile = mustellaTestDir +"/" + excludeFile;
+
+               trace ("Exclude: try load from: " + useFile);
+
+               var req:URLRequest = new URLRequest(useFile);
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler2);
+               loader.addEventListener("ioError", errorHandler2);
+               loader.addEventListener("securityError", errorHandler2);
+               loader.load(req);
+
+       }
+
+       private static function errorHandler2(event:Event):void
+       {
+               trace ("Exclude: error in the exclude file load " +event);      
+               if (!triedBrowser) 
+               {
+                       loadTryBrowser();
+               }
+
+       }
+
+
+       private static function completeHandler2(event:Event):void
+       {
+               trace ("Excludes: Reading from file system at "+mustellaTestDir 
);
+               postProcessData(event);
+       }
+       private static function postProcessData(event:Event):void
+       {
+               var data:String = loader.data;
+               // DOS end of line
+               var delimiter:RegExp = new RegExp("\r\n", "g");
+               data = data.replace(delimiter, ",");
+               // Unix end of line
+               delimiter = new RegExp("\n", "g");
+               data = data.replace(delimiter, ",");
+
+               UnitTester.excludeList = new Object();
+               var items:Array = data.split(",");
+               var n:int = items.length;
+               for (var i:int = 0; i < n; i++)
+               {
+                       var s:String = items[i];
+                       if (s.length)
+                               UnitTester.excludeList[s] = 1;
+
+               }
+               
+               UnitTester.waitForExcludes = false;
+               UnitTester.pre_startEventHandler(event);
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExcludeList.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExcludeList.as 
b/mustella/src/main/flex/ExcludeList.as
new file mode 100644
index 0000000..bbc24ba
--- /dev/null
+++ b/mustella/src/main/flex/ExcludeList.as
@@ -0,0 +1,44 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run.
+ */
+public class ExcludeList 
+{
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  Table is of form: ScriptName$TestID: 1,
+        */
+       public static function init(root:DisplayObject):void
+       {
+               UnitTester.excludeList = {
+                       CBTester$myButtonTest1: 1,
+                       CBTester$myTest2: 1
+               };
+       }
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExcludeList.txt
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExcludeList.txt 
b/mustella/src/main/flex/ExcludeList.txt
new file mode 100644
index 0000000..fcf48fb
--- /dev/null
+++ b/mustella/src/main/flex/ExcludeList.txt
@@ -0,0 +1 @@
+CBTester$myButtonTest1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExcludeListTextFile.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExcludeListTextFile.as 
b/mustella/src/main/flex/ExcludeListTextFile.as
new file mode 100644
index 0000000..9ff27ba
--- /dev/null
+++ b/mustella/src/main/flex/ExcludeListTextFile.as
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.events.Event;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run, read from ExcludeList.txt
+ *  The file is one test per line of the form ScriptName$TestID
+ */
+public class ExcludeListTextFile
+{
+
+       private static var loader:URLLoader;
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  Table is of form: ScriptName$TestID: 1,
+        */
+       public static function init(root:DisplayObject):void
+       {
+               var req:URLRequest = new URLRequest("ExcludeList.txt");
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler);
+               loader.load(req);
+
+       }
+
+       private static function completeHandler(event:Event):void
+       {
+               var data:String = loader.data;
+               // DOS end of line
+               var delimiter:RegExp = new RegExp("\r\n", "g");
+               data = data.replace(delimiter, ",");
+               // Unix end of line
+               delimiter = new RegExp("\n", "g");
+               data = data.replace(delimiter, ",");
+
+               UnitTester.excludeList = new Object();
+               var items:Array = data.split(",");
+               var n:int = items.length;
+               for (var i:int = 0; i < n; i++)
+               {
+                       var s:String = items[i];
+                       if (s.length)
+                               UnitTester.excludeList[s] = 1;
+               }
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ExitWhenDone.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ExitWhenDone.as 
b/mustella/src/main/flex/ExitWhenDone.as
new file mode 100644
index 0000000..1ef9714
--- /dev/null
+++ b/mustella/src/main/flex/ExitWhenDone.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+COMPILE::SWF
+{
+import flash.display.DisplayObject;
+import flash.net.*;
+import flash.events.Event;
+}
+
+[Mixin]
+/**
+ *  A "marker" class that causes test scripts to write out
+ *  bitmaps to the urls instead of reading and comparing
+ *  so that baselines/reference-points can be created for
+ *  future comparing.
+ */
+public class ExitWhenDone
+{
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  The UnitTester waits for an event before starting
+        */
+    COMPILE::SWF
+       public static function init(root:DisplayObject):void
+       {
+               UnitTester.exitWhenDone = true;
+       }
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/FakeSoftKeyboard.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/FakeSoftKeyboard.as 
b/mustella/src/main/flex/FakeSoftKeyboard.as
new file mode 100644
index 0000000..6f7629e
--- /dev/null
+++ b/mustella/src/main/flex/FakeSoftKeyboard.as
@@ -0,0 +1,129 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.display.InteractiveObject;
+import flash.display.Sprite;
+import flash.events.FocusEvent;
+import flash.events.SoftKeyboardEvent;
+import flash.events.SoftKeyboardTrigger;
+import flash.geom.Rectangle;
+import flash.text.TextField;
+import flash.utils.getQualifiedClassName;
+
+import mx.core.mx_internal;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run.
+ */
+public class FakeSoftKeyboard 
+{
+
+       private static var kbdrect:QName = new QName(mx_internal, 
"_softKeyboardRect");
+       
+       public static var portraitHeight:Number = 200;
+       public static var landscapeHeight:Number = 150;
+       
+       /**
+        *  Mixin callback that checks if we're in the emulator
+        *  and tries to fake what would happen in terms of events
+        *  and sizing if you were on the device.  It doesn't actually
+        *  need a useful UI since to type, you should just use
+        *  DispatchKeyEvent
+        */
+       public static function init(root:DisplayObject):void
+       {
+               if (DeviceNames.getFromOS() == "")
+                       return; // not mac or win
+               
+               FakeSoftKeyboard.root = root;
+               
+               root.addEventListener(FocusEvent.FOCUS_IN, focusInHandler);
+               root.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);   
        
+       }
+
+       public static var kbd:Sprite;
+       public static var root:DisplayObject;
+       
+       public static function focusInHandler(event:FocusEvent):void
+       {
+               var comp:Object = event.target;
+               if (comp is TextField || comp is InteractiveObject)
+               {
+            var className: String = getQualifiedClassName(comp);
+                       if (!(comp.needsSoftKeyboard || 
className.indexOf("StyleableStageText") > 0 || 
className.indexOf("ScrollableStageText") > 0 ))
+                               return;
+                       
+                       if (!comp.dispatchEvent(new 
SoftKeyboardEvent(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, 
+                                                       true, true, 
event.relatedObject, SoftKeyboardTrigger.USER_TRIGGERED)))
+                       {
+                               root.stage.focus = null;
+                               return;
+                       }
+                       
+                       if (!kbd)
+                       {
+                               kbd = new Sprite();
+                               kbd.graphics.beginFill(0x808080);
+                               kbd.graphics.drawRect(0, 0, 10, 10);
+                               kbd.graphics.endFill();
+                       }
+                       
+                       // root is actually a systemManager
+                       if (kbd.parent == null)
+                               root["popUpChildren"].addChild(kbd);
+                       if (root.stage.stageHeight > root.stage.stageWidth)
+                       {
+                               kbd.height = portraitHeight;
+                               kbd.width = root.stage.stageWidth;
+                               kbd.y = root.stage.stageHeight - portraitHeight;
+                               root["document"][kbdrect] = new Rectangle(0, 
kbd.y, kbd.width, kbd.height);
+                       }
+                       else
+                       {
+                               kbd.height = landscapeHeight;
+                               kbd.width = root.stage.stageWidth;
+                               kbd.y = root.stage.stageHeight - 
landscapeHeight;
+                               root["document"][kbdrect] = new Rectangle(0, 
kbd.y, kbd.width, kbd.height);
+                       }
+                       trace("sent softKeyboardActivate from", comp);
+                       comp.dispatchEvent(new 
SoftKeyboardEvent(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, 
+                                                       true, false, 
event.relatedObject, SoftKeyboardTrigger.USER_TRIGGERED));
+               }
+       }
+
+       public static function focusOutHandler(event:FocusEvent):void
+       {
+               trace("fakesoftkeyboard focusOut", event.target, 
event.relatedObject, kbd);
+               if (kbd && kbd.parent)
+               {
+                       // root is actually a systemManager
+                       root["popUpChildren"].removeChild(kbd);
+                       root["document"][kbdrect] = new Rectangle(0, 0, 0, 0);
+                       trace("sent softKeyboardDeactivate from", event.target);
+                       event.target.dispatchEvent(new 
SoftKeyboardEvent(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, 
+                                                               true, false, 
event.relatedObject, SoftKeyboardTrigger.USER_TRIGGERED));
+               }
+       }
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/IncludeFileLocation.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/IncludeFileLocation.as 
b/mustella/src/main/flex/IncludeFileLocation.as
new file mode 100644
index 0000000..6517c27
--- /dev/null
+++ b/mustella/src/main/flex/IncludeFileLocation.as
@@ -0,0 +1,100 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.events.Event;
+import flash.system.Capabilities;
+import flash.system.Security;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run, read from IncludeList.txt
+ *  The file is one test per line of the form ScriptName$TestID
+ *  The location of the file is assumed to be c:/tmp on windows, 
+ *  or /tmp on Unix
+ */
+public class IncludeFileLocation
+{
+
+       private static var loader:URLLoader;
+
+       /**
+        * tell UnitTester it should wait for this load to complete
+        */
+       UnitTester.waitForIncludes = true;
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  Table is of form: ScriptName$TestID: 1,
+        */
+       public static function init(root:DisplayObject):void
+       {
+
+
+               var currentOS:String = Capabilities.os;
+
+               var useFile:String;
+
+               if (currentOS.indexOf ("Windows") != -1)
+               {
+                       useFile = "c:/tmp/IncludeList.txt";     
+               } else { 
+
+                       useFile = "/tmp/IncludeList.txt";
+                       if (Security.sandboxType == Security.APPLICATION)
+                               useFile = "file:///tmp/IncludeList.txt";
+
+               }
+
+
+               var req:URLRequest = new URLRequest(useFile);
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler);
+               loader.load(req);
+
+       }
+
+       private static function completeHandler(event:Event):void
+       {
+               var data:String = loader.data;
+               // DOS end of line
+               var delimiter:RegExp = new RegExp("\r\n", "g");
+               data = data.replace(delimiter, ",");
+               // Unix end of line
+               delimiter = new RegExp("\n", "g");
+               data = data.replace(delimiter, ",");
+
+               UnitTester.includeList = {};
+               var items:Array = data.split(",");
+               var n:int = items.length;
+               for (var i:int = 0; i < n; i++)
+               {
+                       var s:String = items[i];
+                       if (s.length)
+                               UnitTester.includeList[s] = 1;
+               }
+               UnitTester.waitForIncludes = false;
+               UnitTester.pre_startEventHandler(event);
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/IncludeList.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/IncludeList.as 
b/mustella/src/main/flex/IncludeList.as
new file mode 100644
index 0000000..1e91b1d
--- /dev/null
+++ b/mustella/src/main/flex/IncludeList.as
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run.
+ */
+public class IncludeList 
+{
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  Table is of form: ScriptName$TestID: 1,
+        */
+       public static function init(root:DisplayObject):void
+       {
+               UnitTester.includeList = {
+                       CBTester: 1,
+                       CBTester$myButtonTest1: 1,
+                       CBTester$myTest2: 1
+               };
+       }
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/IncludeList.txt
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/IncludeList.txt 
b/mustella/src/main/flex/IncludeList.txt
new file mode 100644
index 0000000..fcf48fb
--- /dev/null
+++ b/mustella/src/main/flex/IncludeList.txt
@@ -0,0 +1 @@
+CBTester$myButtonTest1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/IncludeListTextFile.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/IncludeListTextFile.as 
b/mustella/src/main/flex/IncludeListTextFile.as
new file mode 100644
index 0000000..7be8649
--- /dev/null
+++ b/mustella/src/main/flex/IncludeListTextFile.as
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.events.Event;
+
+[Mixin]
+/**
+ *  A hash table of tests not to run, read from IncludeList.txt
+ *  The file is one test per line of the form ScriptName$TestID
+ */
+public class IncludeListTextFile
+{
+
+       private static var loader:URLLoader;
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  Table is of form: ScriptName$TestID: 1,
+        */
+       public static function init(root:DisplayObject):void
+       {
+               var req:URLRequest = new URLRequest("IncludeList.txt");
+               loader = new URLLoader();
+               loader.addEventListener("complete", completeHandler);
+               loader.load(req);
+
+       }
+
+       private static function completeHandler(event:Event):void
+       {
+               var data:String = loader.data;
+               // DOS end of line
+               var delimiter:RegExp = new RegExp("\r\n", "g");
+               data = data.replace(delimiter, ",");
+               // Unix end of line
+               delimiter = new RegExp("\n", "g");
+               data = data.replace(delimiter, ",");
+
+               UnitTester.includeList = {};
+               var items:Array = data.split(",");
+               var n:int = items.length;
+               for (var i:int = 0; i < n; i++)
+               {
+                       var s:String = items[i];
+                       if (s.length)
+                               UnitTester.includeList[s] = 1;
+               }
+       }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/Localhost8080.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/Localhost8080.as 
b/mustella/src/main/flex/Localhost8080.as
new file mode 100644
index 0000000..5531550
--- /dev/null
+++ b/mustella/src/main/flex/Localhost8080.as
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.net.*;
+import flash.events.Event;
+
+[Mixin]
+/**
+ *  A "marker" class that causes test scripts to write out
+ *  bitmaps to the urls instead of reading and comparing
+ *  so that baselines/reference-points can be created for
+ *  future comparing.
+ */
+public class Localhost8080
+{
+
+       /**
+        *  Mixin callback that gets everything ready to go.
+        *  The UnitTester waits for an event before starting
+        */
+       public static function init(root:DisplayObject):void
+       {
+               UnitTester.portNumber = 8080;
+       }
+
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MobileConfig.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MobileConfig.as 
b/mustella/src/main/flex/MobileConfig.as
new file mode 100644
index 0000000..59764c5
--- /dev/null
+++ b/mustella/src/main/flex/MobileConfig.as
@@ -0,0 +1,30 @@
+package {
+import flash.display.DisplayObject;
+import flash.system.Capabilities;
+[Mixin]
+/**
+* By including this mixin via CompileMustellaSwfs, we
+* can set up some variables for UnitTester to use for
+* an Android run.
+*/
+public class MobileConfig
+{
+       public static function init(root:DisplayObject):void
+       {
+               if( UnitTester.cv == null ){
+                       UnitTester.cv = new ConditionalValue();
+               }
+               UnitTester.cv.device = "mac";
+               UnitTester.cv.os = "android";
+               UnitTester.cv.targetOS = "android";
+               UnitTester.cv.osVersion = "${os_version}";
+               UnitTester.cv.deviceDensity = Util.roundDeviceDensity( 
flash.system.Capabilities.screenDPI );
+               UnitTester.cv.screenDPI = flash.system.Capabilities.screenDPI;
+               //UnitTester.cv.deviceWidth = set by MultiResult;
+               //UnitTester.cv.deviceHeight = set by MultiResult;
+               //UnitTester.cv.color = this is not defined yet, but there are 
rumours it might be.
+               UnitTester.run_id = "-1";
+               UnitTester.excludeFile = "ExcludeList${os}.txt";
+       }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MouseSnifferRemote.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MouseSnifferRemote.as 
b/mustella/src/main/flex/MouseSnifferRemote.as
new file mode 100644
index 0000000..94f0bf2
--- /dev/null
+++ b/mustella/src/main/flex/MouseSnifferRemote.as
@@ -0,0 +1,282 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package 
+{
+import flash.display.DisplayObject;
+import flash.events.Event;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.events.StatusEvent;
+import flash.geom.Point;
+import flash.net.LocalConnection;
+import flash.utils.describeType;
+import flash.utils.getQualifiedClassName;
+
+import mx.core.IDeferredInstantiationUIComponent;
+import mx.core.IUIComponent;
+import mx.managers.SystemManager;
+
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+[Mixin]
+/**
+ *  Tries to show location and target path of mouse
+ */
+public class MouseSnifferRemote
+{
+       public function MouseSnifferRemote()
+       {
+       }
+
+       public static function init(root:Object):void
+       {
+               document = root;
+               connection = new LocalConnection();
+               connection.allowDomain("*");
+               connection.addEventListener(StatusEvent.STATUS, statusHandler);
+
+        // Turn on only if the SnifferRemoteClient app's checkbox
+        // for this item is checked.
+        connection.send("_MouseSniffer", "toggleSniffersEnabled");
+
+               mousecommandconnection = new LocalConnection();
+               mousecommandconnection.allowDomain("*");
+               mousecommandconnection.client = MouseSnifferRemote;
+               mousecommandconnection.connect("_MouseSnifferCommands");
+       }
+
+       private static function statusHandler(event:Event):void
+       {
+       }
+
+    /**
+     *  @private
+        *  The document containing a reference to this object
+     */
+    private static var document:Object;
+
+    /**
+     *  @private
+        *  The local connection to the remote client
+     */
+    private static var connection:LocalConnection;
+    private static var mousecommandconnection:LocalConnection;
+
+       public static function enableSniffer():void
+       {
+        //trace("MouseSnifferRemote enabled");     
+
+               document.stage.addEventListener(MouseEvent.CLICK, uberListener, 
true);
+               document.stage.addEventListener(MouseEvent.DOUBLE_CLICK, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_DOWN, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_MOVE, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_OUT, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_OVER, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_UP, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.MOUSE_WHEEL, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.ROLL_OUT, 
uberListener, true);
+               document.stage.addEventListener(MouseEvent.ROLL_OVER, 
uberListener, true);
+       }
+
+       public static function disableSniffer():void
+       {
+        //trace("MouseSnifferRemote disabled");            
+        
+               document.stage.removeEventListener(MouseEvent.CLICK, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.DOUBLE_CLICK, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_DOWN, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_MOVE, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_OUT, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_OVER, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_UP, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.ROLL_OUT, 
uberListener, true);
+               document.stage.removeEventListener(MouseEvent.ROLL_OVER, 
uberListener, true);
+       }
+
+       public static var propLists:Object = new Object();
+
+       private static function uberListener(event:MouseEvent):void
+       {
+               var target:String = findPath(event.target);
+               var pt:Point = new Point(event.stageX, event.stageY);
+               var obj:Object = document.document;
+               var s:String = target;
+               var dot:int = s.indexOf(".");
+           var info:Object = new Object();
+
+               if (dot != -1)
+               {
+                       var pieces:Array = s.split(".");
+                       for (var i:int = 0; i < pieces.length; i++)
+                       {
+                               s = pieces[i];
+                               if (s != null && s.indexOf("getChildAt(") == 0)
+                               {
+                                       s = s.substring(11);
+                                       s = s.substring(0, s.length - 1);
+                                       obj = obj.getChildAt(parseInt(s));
+                               }
+                               else
+                               {
+                                       if (obj!=null && s != null && s in obj)
+                                               obj = obj[s];
+                                       else
+                                       {
+                                               // couldn't find the piece so 
document chain is broken.
+                                               // Containers as item renderers 
break this
+                                               target = "";
+                                               for (var j:int = 0; j < i; j++)
+                                               {
+                                                       target += pieces[j];
+                                                       if (j < i - 1)
+                                                               target += "."
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               else if (s.length && s.indexOf(" ") == -1)
+                       obj = obj[s];
+
+               if (obj != null)
+                       pt = obj.globalToLocal(pt);
+
+               if (target == null || target == ""){
+                       //connection.send("_MouseSniffer", "appendLog", 
"Mouse", "stage: " + pt.x + "," + pt.y + "  stage: " + event.stageX + "," + 
event.stageY);
+
+           info.dataSource = "Mouse";
+           info.target = "stage: " + pt.x + "," + pt.y + "  stage: " + 
event.stageX + "," + event.stageY;
+           info.eventName = "";
+           info.event = "";
+
+           connection.send("_MouseSniffer", "appendLog", info);
+                       
+               }else{
+                       //connection.send("_MouseSniffer", "appendLog", 
"Mouse", target + " " + pt.x + "," + pt.y + "   stage: " + event.stageX + "," + 
event.stageY);
+           info.dataSource = "Mouse";
+           info.target = target + " " + pt.x + "," + pt.y + "   stage: " + 
event.stageX + "," + event.stageY;
+           info.eventName = "";
+           info.event = "";
+
+           connection.send("_MouseSniffer", "appendLog", info);
+
+               }
+       }
+
+       private static function findPath(target:Object, name:String = ""):String
+       {
+               var s:String = target.toString();
+               var dot:int = s.indexOf(".");
+               if (dot == -1)
+               {
+                       if (target == document.document || target.parent == 
document.document)
+                               return name;
+               }
+
+               while (target)
+               {
+                       if (target is IDeferredInstantiationUIComponent)
+                       {
+                               var targetName:String = target.id;
+                               // id of component in document
+                               if (target.id && target.id in target.document)
+                               {
+                                       if (target.document[target.id] is Array)
+                                       {
+                                               var arr:Array = 
target.document[target.id];
+                                               for (var i:int = 0; i < 
arr.length; i++)
+                                               {
+                                                       if (arr[i] == target)
+                                                       {
+                                                               targetName += 
"." + i;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       name = (name == "") ? targetName : 
targetName + "." + name;
+                                       return findPath(target.document, name);
+                               }
+                               // MXML component has id in parent document
+                               if (target.id && target.document == target)
+                               {
+                                       name = (name == "") ? target.id : 
target.id + "." + name;
+                                       return findPath(target.parent.document, 
name);
+                               }
+                       }
+                       if (target.parent == document.document)
+                               break;
+
+                       if (target.parent is SystemManager)
+                       {
+                               // must be a popup
+                               if (target is IUIComponent)
+                               {
+                                       s = findPropertyInOwner(target)
+                                       if (s)
+                                       {
+                                               name = (name == "") ? s : s + 
"." + name;
+                                               target = target.owner;
+                                               continue;
+                                       }
+                               }
+
+                               var index:int = 
document.document.systemManager.rawChildren.getChildIndex(target as 
DisplayObject);
+                               s = "systemManager.rawChildren.getChildAt(" + 
index + ")";
+                               name = (name == "") ? s : s + "." + name;
+                               return name;
+                       }
+                       target = target.parent;
+               }
+               return "no component with id under mouse";
+
+       }
+
+       private static function findPropertyInOwner(target:Object):String
+       {
+               var owner:Object = target.owner;
+               var className:String = getQualifiedClassName(owner);
+               var propList:XMLList = propLists[className];
+               if (!propList)
+               {
+                       var dt:XML = describeType(owner);
+                       propList = dt..accessor.(@type != "Number" && @type != 
"String" && @type != "int" && @type != "Boolean"
+                                       && @type != "Array" && @type != 
"Object" && @type != "Class" && @access != "writeonly") +
+                                       dt..variable.(@type != "Number" && 
@type != "String" && @type != "int" && @type != "Boolean"
+                                       && @type != "Array" && @type != 
"Object" && @type != "Class");
+                       propLists[className] = propList;
+               }
+               var n:int = propList.length();
+               for (var i:int = 0; i < n; i++)
+               {
+                       var propName:String = propList[i].@name.toString();
+                       if (owner[propName] == target)
+                               return propName;
+               }
+               return null;
+       }
+
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MultiResult.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MultiResult.as 
b/mustella/src/main/flex/MultiResult.as
new file mode 100644
index 0000000..6c92306
--- /dev/null
+++ b/mustella/src/main/flex/MultiResult.as
@@ -0,0 +1,193 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package
+{
+
+       import flash.display.*;
+       import mx.core.FlexGlobals;
+       import mx.core.mx_internal;
+       
+       use namespace mx_internal;
+       
+       [DefaultProperty("conditionalValues")]  
+       public class MultiResult
+       {
+               private var conditionalValues:Vector.<ConditionalValue>;
+
+               public function MultiResult(){
+               }
+
+               /**
+                *  Loop through the conditional values and process the ones 
which apply to our configuration.
+                *  Functionally, it should work like this:
+                *      1) Any number of mismatches will case a CV to be 
ignored.
+                *      2) Empty CVs will be ignored.
+                *  3) Among device matches, pick the best.
+                *  4) If no match yet, among the remaining, pick the one with 
the most matches.
+                *  5) If no match yet, the TestStep's is used.
+                *
+                * Called by determineResult() and CompareBitmap's execute().
+                **/
+               public function 
chooseCV(conditionalValues:Vector.<ConditionalValue>):ConditionalValue{
+                       var i:int;
+                       var cv:ConditionalValue;
+                       //var cvToUse:ConditionalValue = null;
+                       var cvUT:ConditionalValue = UnitTester.cv;
+                       
+                       var bestDeviceMatch:ConditionalValue = null;
+                       var bestNonDeviceMatch:ConditionalValue = null;
+                       
+                       var bestDeviceMatchCount:int = 0;               // # 
matches for the best match, among device matches
+                       var bestNonDeviceMatchCount:int = 0;    // # matches 
for the best match
+                       var numMatches:int = 0;
+                       
+                       // When running mobile on desktop, set some items in 
UnitTester's CV later
+                       if( cvUT.deviceWidth == -1 ){
+                               cvUT.deviceWidth = 
FlexGlobals.topLevelApplication.width;
+                       }
+
+                       if( cvUT.deviceHeight == -1 ){
+                               cvUT.deviceHeight = 
FlexGlobals.topLevelApplication.height;
+                       }
+
+                       //trace("MultiResult.chooseCV(): Actual test 
environment is: \n" + cvUT.toString());
+                       
+                       for(i = 0; i < conditionalValues.length; ++i){
+                               cv = conditionalValues[ i ];
+                               
+                               // This is an empty one; ignore it.
+                               if( cv.isDefault() ){
+                                       continue;
+                               }
+                               
+                               numMatches = countMatches( cv, cvUT );
+                               //trace("numMatches="+numMatches+" with "+cv);
+                               
+                               if( numMatches <= 0 ) // -1 is a mismatch, and 
0 is no matches.
+                                       continue;       
+                               
+                               if( cv.device && cvUT.device && (cv.device == 
cvUT.device) ){
+                                       
+                                       if( numMatches > bestDeviceMatchCount ){
+                                               bestDeviceMatchCount = 
numMatches;
+                                               bestDeviceMatch = cv;
+                                       }
+                               }else{
+                                       
+                                       if( numMatches > 
bestNonDeviceMatchCount ){
+                                               bestNonDeviceMatchCount = 
numMatches;
+                                               bestNonDeviceMatch = cv;
+                                       }
+                               }
+                       }
+
+                       /**
+                               if( bestDeviceMatch != null )
+                                       trace("MultiResult.chooseCV(): 
bestDeviceMatch:\n" + bestDeviceMatch.toString());
+                               else
+                                       trace("MultiResult.chooseCV(): 
bestDeviceMatch: null");
+
+                               if( bestNonDeviceMatch != null )                
                
+                                       trace("MultiResult.chooseCV(): 
bestNonDeviceMatch:\n" + bestNonDeviceMatch.toString());
+                               else
+                                       trace("MultiResult.chooseCV(): 
bestNonDeviceMatch: null");
+                       **/     
+                               
+                       if( bestDeviceMatch != null )
+                               return bestDeviceMatch;
+                       else if( bestNonDeviceMatch != null )
+                               return bestNonDeviceMatch;
+                       else
+                               return null;
+               }
+               
+               
+               /**
+               * Count the matches between two CVs.
+               * If a value is unset in either, it's not a match or a mismatch.
+               * Returns 0 if no matches.
+               * Returns -1 immediately if a mismatch occurs.
+               **/
+               private function countMatches( cv1:ConditionalValue, 
cv2:ConditionalValue ):int{
+                       var ret:int = 0;
+                       
+                       // if .targetOS has been set in cv2 (which is the 
baseline as specified by options)
+                       // use that for comparison otherwise use the normal .os
+                       var os:String = cv2.targetOS != null ? cv2.targetOS : 
cv2.os;
+                       
+                       if( (cv1.os != null) && (os != null) ){
+                               if( cv1.os != os )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.osVersion != null) && (cv2.osVersion != null) 
){
+                               if( cv1.osVersion != cv2.osVersion )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.screenDPI > -1) && (cv2.screenDPI > -1) ){
+                               if( cv1.screenDPI != cv2.screenDPI )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.deviceDensity > -1) && (cv2.deviceDensity > 
-1) ){
+                               if( cv1.deviceDensity != cv2.deviceDensity )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.deviceWidth > -1) && (cv2.deviceWidth > -1) ){
+                               if( cv1.deviceWidth != cv2.deviceWidth )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.deviceHeight > -1) && (cv2.deviceHeight > -1) 
){
+                               if( cv1.deviceHeight != cv2.deviceHeight )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.color > -1) && (cv2.color > -1) ){
+                               if( cv1.color != cv2.color )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       if( (cv1.device != null) && (cv2.device != null) ){
+                               if( cv1.device != cv2.device )
+                                       return -1;
+                               else
+                                       ++ret;
+                       }
+
+                       return ret;
+               }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MustellaLogEvent.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MustellaLogEvent.as 
b/mustella/src/main/flex/MustellaLogEvent.as
new file mode 100644
index 0000000..48bc5c6
--- /dev/null
+++ b/mustella/src/main/flex/MustellaLogEvent.as
@@ -0,0 +1,44 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.events.Event;
+
+/**
+ *  The event passed into any code being
+ *  run in a RunCode step.  It supplies
+ *  some useful references
+ */
+public class MustellaLogEvent extends Event
+{
+       public function MustellaLogEvent (type:String, msg:String)
+       {
+               super(type);
+               this.msg = msg;
+       }
+
+       /**
+        *  The msg to be logged
+        */
+       public var msg:String;
+
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MustellaPNGEncoder.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MustellaPNGEncoder.as 
b/mustella/src/main/flex/MustellaPNGEncoder.as
new file mode 100644
index 0000000..8aaa1ef
--- /dev/null
+++ b/mustella/src/main/flex/MustellaPNGEncoder.as
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * writes bitmaps into PNG format. 
+ * original author, Ely
+ */
+package  {
+
+       import flash.display.*;
+       import flash.geom.*;
+       import flash.utils.*;
+       import flash.net.*;
+       
+public class MustellaPNGEncoder {
+       
+       
+       private var _png:ByteArray;
+
+       // empty constructor
+       public function MustellaPNGEncoder () { 
+       }
+       
+       public function encode(img:BitmapData):ByteArray
+       {
+               var imgWidth:uint = img.width;
+               var imgHeight:uint = img.height;
+
+               var imgData:ByteArray = img.getPixels(new 
Rectangle(0,0,imgWidth,imgHeight));
+                               
+               _png = new ByteArray();
+               
+               _png.writeByte(137);
+               _png.writeByte(80);
+               _png.writeByte(78);
+               _png.writeByte(71);
+               _png.writeByte(13);
+               _png.writeByte(10);
+               _png.writeByte(26);
+               _png.writeByte(10);
+               
+               var IHDR:ByteArray = new ByteArray();
+               IHDR.writeInt(imgWidth);
+               IHDR.writeInt(imgHeight);
+               IHDR.writeByte(8); // color depth: 8 bpp
+               IHDR.writeByte(6); // color type: RGBA
+               IHDR.writeByte(0); // compression: ZLIB
+               IHDR.writeByte(0); // filter method
+               IHDR.writeByte(0); // not interlaced;
+               
+               writeChunk([0x49,0x48,0x44,0x52],IHDR);
+               
+               var IDAT:ByteArray= new ByteArray();
+               for(var i:uint=0;i<imgHeight;i++) {
+                       IDAT.writeByte(0);
+                       for(var j:uint=0;j<imgWidth;j++) {
+                               var p:uint = img.getPixel32(j,i);
+                               IDAT.writeByte((p>>16)&0xFF);
+                               IDAT.writeByte((p>> 8)&0xFF);
+                               IDAT.writeByte((p    )&0xFF);
+                               IDAT.writeByte((p>>24)&0xFF);
+                       }
+               }               
+               
+               IDAT.compress();
+               writeChunk([0x49,0x44,0x41,0x54],IDAT);
+
+
+
+               writeChunk([0x49,0x45,0x4E,0x44],null);
+               return _png;
+       }
+
+       public function dump():String
+       {
+               _png.position = 0;
+               var out:String ="";
+               for(var i:uint=0;i<_png.length;i++) {
+                       var code:String = "0123456789abcdef";
+                       var v:uint = _png.readUnsignedByte();
+                       out += code.charAt((v & 0xF0) >> 4);
+                       out += code.charAt(v & 0xF);
+                       out += " ";
+               }
+               return out;
+       }
+       private function writeChunk(type:Array,data:ByteArray):void
+       {
+               var len:uint = 0;
+               if(data != null)
+                       len = data.length; // data length
+               _png.writeUnsignedInt(len);
+
+               var p:uint = _png.position;
+
+               _png.writeByte(type[0]);
+               _png.writeByte(type[1]);
+               _png.writeByte(type[2]);
+               _png.writeByte(type[3]);
+               if(data != null)
+                       _png.writeBytes(data);
+               
+               var endP:uint = _png.position;
+               _png.position = p;
+               var c:uint = crc(_png,endP-p);
+               _png.position = endP;
+               _png.writeUnsignedInt(c);
+       }
+
+   /* Table of CRCs of all 8-bit messages. */
+   private static var crc_table:Array;
+   
+   /* Flag: has the table been computed? Initially false. */
+   private static var crc_table_computed:Boolean = false;
+   
+   /* Make the table for a fast CRC. */
+   private function make_crc_table():void
+   {
+     var c:uint;
+     var n:int;
+     var k:int;
+   
+        crc_table = [];
+        
+     for (n = 0; n < 256; n++) {
+       c = n;
+       for (k = 0; k < 8; k++) {
+         if (c & 1)
+           c = uint(uint(0xedb88320) ^ uint(c >>> 1));
+         else
+           c = uint(c >>> 1);
+       }
+       crc_table[n] = c;
+     }
+     crc_table_computed = true;
+   }
+   
+   /* Update a running CRC with the bytes buf[0..len-1]--the CRC
+      should be initialized to all 1's, and the transmitted value
+      is the 1's complement of the final running CRC (see the
+      crc() routine below)). */
+   
+   private function update_crc(crc:uint, buf:ByteArray,
+                            len:uint):uint
+   {
+     var c:uint = crc;
+     var n:int;
+       var v:uint;
+          
+     if (!crc_table_computed)
+       make_crc_table();
+     for (n = 0; n < len; n++) {
+       v = buf.readUnsignedByte();
+       c = uint(crc_table[(c ^ v) & uint(0xff)] ^ uint(c >>> 8));
+     }
+     return c;
+   }
+   
+   /* Return the CRC of the bytes buf[0..len-1]. */
+   private function crc(buf:ByteArray, len:uint):uint
+   {
+     var cc:uint = update_crc(uint(0xffffffff), buf, len);
+     return uint(cc ^ uint(0xffffffff));
+   }   
+       
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MustellaRealTimeLogger.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MustellaRealTimeLogger.as 
b/mustella/src/main/flex/MustellaRealTimeLogger.as
new file mode 100644
index 0000000..d009de7
--- /dev/null
+++ b/mustella/src/main/flex/MustellaRealTimeLogger.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package
+{
+       import flash.events.DataEvent;
+       import flash.net.XMLSocket;
+       
+       public class MustellaRealTimeLogger
+       {
+               private static var socketAvailable:Boolean = false;
+               private static var isInitialized:Boolean = false;
+        private static var xmlsock:XMLSocket = new XMLSocket();
+
+               public static function Init():void
+               {
+                   try
+                   {
+                   xmlsock.connect("127.0.0.1", 13000);
+                   //xmlsock.addEventListener(DataEvent.DATA, onData);
+
+               socketAvailable = true;
+               isInitialized = true;
+               }
+               catch(e:Error)
+               { 
+               } 
+               }
+
+        public function onData(event:DataEvent):void
+        {
+               //indata.text = event.text;
+        }
+
+        public static function sendData(xmlFormattedData:String):void
+        { 
+           if(!isInitialized)
+           {
+                   Init();     
+           } 
+               
+           xmlsock.send(xmlFormattedData + "\n");
+        }
+        
+        public static function Close():void
+        {
+            if((socketAvailable) && (isInitialized))
+            {
+               xmlsock.close();
+            }
+        }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/MustellaSandboxEvent.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/MustellaSandboxEvent.as 
b/mustella/src/main/flex/MustellaSandboxEvent.as
new file mode 100644
index 0000000..9ce8b0f
--- /dev/null
+++ b/mustella/src/main/flex/MustellaSandboxEvent.as
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.events.Event;
+
+/**
+ *  An event used as a message passed across security domain boundaries
+ */
+public class MustellaSandboxEvent extends Event
+{
+       public static const MUSTELLA_STARTED:String = "mustellaStarted";
+       public static const STRING_TO_OBJECT:String = "stringToObject";
+       public static const GET_BITMAP:String = "getBitmap";
+       public static const GET_EFFECTS:String = "getEffects";
+       public static const GET_OBJECTS_UNDER_POINT:String = 
"getObjectsUnderPoint";
+       public static const RESET_COMPONENT:String = "resetComponent";
+       public static const MOUSEXY:String = "mouseXY";
+       public static const GET_FOCUS:String = "getFocus";
+       public static const APP_READY:String = "appReady";
+
+       /**
+        *  
+        */
+       public function MustellaSandboxEvent(type:String)
+       {
+               super(type);
+       }
+
+       // the string to be parsed and turned into an object
+       public var string:String;
+
+       // the object returned.
+       public var obj:Object;
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/NoFail.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/NoFail.as b/mustella/src/main/flex/NoFail.as
new file mode 100644
index 0000000..3cf3793
--- /dev/null
+++ b/mustella/src/main/flex/NoFail.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+
+[Mixin]
+/**
+ *  Class to report no failures. 
+ *  allows tests to continue. Useful for bitmap replacement, etc
+ */
+public class NoFail
+{
+
+       /**
+        *  Set a flag to ignore all failures (and don't report them)
+        */
+       public static function init(root:DisplayObject):void
+       {
+               UnitTester.noFail = true;
+       }
+
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/ObjectSnifferRemote.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/ObjectSnifferRemote.as 
b/mustella/src/main/flex/ObjectSnifferRemote.as
new file mode 100644
index 0000000..272af28
--- /dev/null
+++ b/mustella/src/main/flex/ObjectSnifferRemote.as
@@ -0,0 +1,333 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package
+{
+import flash.display.BitmapData;
+import flash.display.DisplayObject;
+import flash.events.Event;
+import flash.events.MouseEvent;
+import flash.events.StatusEvent;
+import flash.geom.Matrix;
+import flash.geom.Point;
+import flash.net.LocalConnection;
+import flash.utils.getQualifiedClassName;
+
+import mx.managers.IFocusManagerComponent;
+import mx.managers.SystemManager;
+import mx.core.FlexGlobals;
+import mx.core.IFlexDisplayObject;
+import mx.core.IMXMLObject;
+import mx.core.UIComponent;
+// import mx.core.Container;
+import mx.utils.ObjectUtil;
+
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+[Mixin]
+/**
+ *  Displays object properties and values to SnifferRemoteClient
+ */
+public class ObjectSnifferRemote
+{
+       public function ObjectSnifferRemote()
+       {
+       }
+
+       public static function init(root:Object):void
+       {
+
+               _root = document = root;
+               if (document)
+                       document.addEventListener("applicationComplete", 
initHandler);
+               connection = new LocalConnection();
+               connection.allowDomain("*");
+               connection.addEventListener(StatusEvent.STATUS, statusHandler);
+
+               commandconnection = new LocalConnection();
+               commandconnection.allowDomain("*");
+               commandconnection.client = ObjectSnifferRemote;
+               commandconnection.connect("_ObjectSnifferCommands");
+       }
+
+       private static function initHandler(event:Event):void
+       {
+               //enableSniffer();
+       }
+
+       private static function statusHandler(event:Event):void
+       {
+       }
+
+    /**
+     *  @private
+        *  The document containing a reference to this object
+     */
+    private static var document:Object;
+       private static var _root:Object;
+
+    /**
+     *  @private
+        *  The local connection to the remote client
+     */
+    private static var connection:LocalConnection;
+    private static var commandconnection:LocalConnection;
+
+       private static var snifferEnabled:Boolean = true;
+
+       public static function enableSniffer():void
+       {
+               snifferEnabled = true;
+       }
+
+       public static function disableSniffer():void
+       {
+               snifferEnabled = false;
+       }
+
+       private static function appendLog(s:String):void
+       {
+               //connection.send("_ObjectSniffer", "appendLog", "Object", s);
+
+           var info:Object = new Object();
+           
+        info.dataSource = "Object";
+        info.target = s;
+        info.eventName = "";
+        info.event = "";
+
+        /**        
+        trace("ObjectSniffer is sending: ");
+        trace ("    info.dataSource: " + info.dataSource);
+        trace ("    info.target: " + info.target);
+        trace ("    info.eventName: " + info.eventName);
+        trace ("    info.event: " + info.event);
+        **/
+        
+        connection.send("_ObjectSniffer", "appendLog", info);
+       }
+
+       public static function dumpObject(s:String):void
+       {
+               if (!snifferEnabled)
+                       return;
+
+               var obj:* = stringToObject(s);
+               if (obj === null)
+               {
+                       appendLog(s + " = null");
+               }
+               else if (obj === undefined)
+               {
+                       appendLog(s + " = undefined");
+               }
+               else if (obj is String)
+               {
+                       appendLog(s + " = " + obj);
+               }
+               else if (obj is Boolean)
+               {
+                       appendLog(s + " = " + obj.toString());
+               }
+               else if (obj is uint)
+               {
+                       appendLog(s + " = " + obj.toString(10) + " (0x" + 
obj.toString(16).toUpperCase() + ")");
+               }
+               else if (obj is Number)
+               {
+                       appendLog(s + " = " + obj.toString());
+               }
+               else if (obj is XML || obj is XMLList)
+               {
+                       if (obj is XMLList && obj.length() == 1)
+                               appendLog(s + " = " + obj.toString());
+                       else if (obj is XMLList && obj.length() == 0)
+                               appendLog(s + " not found");
+                       else
+                               appendLog(s + " = " + obj.toXMLString());
+               }
+               else if (obj is Array)
+               {
+                       appendLog(s + " = Array");
+               }
+               else appendLog(s + " = " + getQualifiedClassName(obj));
+       }
+
+       public static function listProperties(s:String):void
+       {
+               document.document.callLater(listProperties_cb, [s]);
+       }
+
+       public static function listProperties_cb(s:String):void
+       {
+               if (!snifferEnabled)
+                       return;
+
+               var n:int;
+               var i:int;
+
+               var obj:* = stringToObject(s);
+               if (obj === null)
+               {
+                       appendLog(s + " is null, has no properties");
+               }
+               else if (obj === undefined)
+               {
+                       appendLog(s + " is undefined, has no properties");
+               }
+               else if (obj is String)
+               {
+                       appendLog(s + " is String, has no properties");
+               }
+               else if (obj is uint)
+               {
+                       appendLog(s + " is uint, has no properties");
+               }
+               else if (obj is uint)
+               {
+                       appendLog(s + " is int, has no properties");
+               }
+               else if (obj is Number)
+               {
+                       appendLog(s + " is Number, has no properties");
+               }
+               else if (obj is XML)
+               {
+                       appendLog(s);
+                       appendLog("  attributes:");
+                       var attrs:XMLList = obj.attributes();
+                       n = attrs.length();
+                       for (i = 0; i < n; i++)
+                       {
+                               appendLog("    " + attrs[i].name());
+                       }
+                       var children:XMLList = obj.children();
+                       n = children.length();
+                       var namesTable:Object = {};
+                       for (i = 0; i < n; i++)
+                       {
+                               namesTable[children[i].name()] = 1;
+                       }
+                       appendLog("  children:");
+                       for (var p:String in namesTable)
+                               appendLog("    " + p);
+               }
+               else if (obj is Array)
+               {
+                       appendLog(s + " is Array of length " + obj.length);
+               }
+               else 
+               {
+                       var info:Object = ObjectUtil.getClassInfo(obj, null, { 
includeReadOnly: true, includeTransient: true, uris: ["", "mx_internal"] } );
+                       appendLog(s + " = " + info.name);
+                       n = info.properties.length;
+                       for (i = 0; i < n; i++)
+                               appendLog("  " + info.properties[i]);
+               }
+
+       }
+
+       /**
+        *  direct copy of UnitTester's stringToObject, except that it doesn't 
handle "script"
+        *  take an expression, find the object.
+        *  handles mx_internal:propName
+        *  a.b.c
+        *  getChildAt()
+        */
+       public static function stringToObject(s:*):*
+       {
+               if (s == null || s == "")
+                       return _root["document"];
+
+               try
+               {
+                       var propName:* = s;
+                       if (s.indexOf("mx_internal:") == 0)
+                               propName = new QName("mx_internal", 
s.substring(12));
+                       if (s.indexOf("getChildAt(") == 0 && s.indexOf(".") == 
-1)
+                       {
+                               s = s.substring(11);
+                               s = s.substring(0, s.indexOf(")"));
+                               return 
_root["document"].getChildAt(parseInt(s));
+                       }
+                       return _root["document"][propName];
+               }
+               catch (e:Error)
+               {
+                       // maybe it is a class
+                       var dot:int;
+                       var cc:int = s.indexOf("::");
+                       var className:String = s;
+                       var obj:Object = _root["document"];
+                       if (cc > 0)
+                       {
+                               dot = s.indexOf(".", cc);
+                               if (dot >= 0)
+                               {
+                                       className = s.substring(0, dot);
+                                       s = s.substring(dot + 1);
+                               }
+                               else
+                                       s = "";
+                       }
+                       else
+                               dot = s.indexOf(".");
+
+                       try
+                       {
+                               obj = 
_root["info"]().currentDomain.getDefinition(className);           
+                       }
+                       catch (e:Error)
+                       {
+                               if (dot == -1)
+                                       return undefined;
+                       }
+                       if (dot == -1)
+                               return obj;
+
+                       var list:Array = s.split(".");
+                       while (list.length)
+                       {
+                               try 
+                               {
+                                       s = list.shift();
+                                       if (s.indexOf("mx_internal:") == 0)
+                                               s = new QName(mx_internal, 
s.substring(12));
+                                       if (s is String && 
s.indexOf("getChildAt(") == 0)
+                                       {
+                                               s = s.substring(11);
+                                               s = s.substring(0, 
s.indexOf(")"));
+                                               obj = 
obj.getChildAt(parseInt(s));
+                                       }
+                                       else
+                                               obj = obj[s];
+                               }
+                               catch (e:Error)
+                               {
+                                       return undefined;
+                               }
+                       }
+                       return obj;
+               }
+               return null;
+       }
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/27eb06f5/mustella/src/main/flex/Pause.as
----------------------------------------------------------------------
diff --git a/mustella/src/main/flex/Pause.as b/mustella/src/main/flex/Pause.as
new file mode 100644
index 0000000..13349d3
--- /dev/null
+++ b/mustella/src/main/flex/Pause.as
@@ -0,0 +1,66 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package {
+
+import flash.display.DisplayObject;
+import flash.utils.setTimeout;
+
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+/**
+ *  The test step that sets a property to some value
+ *  MXML attributes:
+ *  
+ *  waitTarget (optional)
+ *  waitEvent (optional)
+ *  timeout 
+ */
+public class Pause extends TestStep
+{
+    public var reason:String;
+    
+       override public function execute(root:DisplayObject, 
context:UnitTester, testCase:TestCase, testResult:TestResult):Boolean
+       {
+               this.root = root;
+               this.context = context;
+               this.testCase = testCase;
+               this.testResult = testResult;
+
+               setTimeout(stepComplete, timeout);
+               TestOutput.logResult(this.toString());
+
+               return false;
+       }
+
+       /**
+        *  customize string representation
+        */
+       override public function toString():String
+       {
+           var s:String = "Paused for " + timeout + "ms.";
+           
+           if(this.reason != null)
+               s = s + " Reason: " + this.reason;
+
+               return s;
+       }
+}
+
+}

Reply via email to