Repository: flex-utilities Updated Branches: refs/heads/develop b2f1e508a -> b8f6cf5ef
code coverage and tracing profiler prototype donated by Adobe Systems Inc. Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/7794f18d Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/7794f18d Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/7794f18d Branch: refs/heads/develop Commit: 7794f18d49b0c403083e27cfa120b9b6558aef9b Parents: b2f1e50 Author: Alex Harui <[email protected]> Authored: Fri Apr 25 16:48:52 2014 -0700 Committer: Alex Harui <[email protected]> Committed: Fri Apr 25 16:48:52 2014 -0700 ---------------------------------------------------------------------- CodeCoverage/CodeCoveragePreloadSWF.as | 81 ++++++++ CodeCoverage/CodeCoverageServer-app.xml | 265 ++++++++++++++++++++++++ CodeCoverage/CodeCoverageServer.mxml | 295 +++++++++++++++++++++++++++ 3 files changed, 641 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/7794f18d/CodeCoverage/CodeCoveragePreloadSWF.as ---------------------------------------------------------------------- diff --git a/CodeCoverage/CodeCoveragePreloadSWF.as b/CodeCoverage/CodeCoveragePreloadSWF.as new file mode 100644 index 0000000..a8200d1 --- /dev/null +++ b/CodeCoverage/CodeCoveragePreloadSWF.as @@ -0,0 +1,81 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.Sprite; + import flash.events.StatusEvent; + import flash.net.LocalConnection; + import flash.trace.Trace; + import flash.utils.getTimer; + + public class CodeCoveragePreloadSWF extends Sprite + { + public function CodeCoveragePreloadSWF() + { + Trace.setLevel(Trace.METHODS_AND_LINES, Trace.LISTENER); + Trace.setListener(callback); + lc = new LocalConnection(); + lc.addEventListener(StatusEvent.STATUS, onStatus); + lc.send("_CodeCoverageLC", "reset"); + } + + private var lc:LocalConnection; + + private var stringMap:Object = {}; + private var stringIndex:int = 0; + + private function onStatus(event:StatusEvent):void + { + } + + private var ids:String = ""; + private var lines:String = ""; + private var lastTime:Number = 0; + + public function callback(file_name:String, linenum:int, method_name:String, method_args:String):void + { + if (linenum > 0) + { + // trace(file_name, linenum); + if (!stringMap.hasOwnProperty(file_name)) + { + lc.send("_CodeCoverageLC", "newString", file_name); + stringMap[file_name] = stringIndex.toString(); + stringIndex++; + } + var id:String = stringMap[file_name]; + var line:String = linenum.toString(); + if (ids.length > 0) + { + ids += " "; + lines += " "; + } + ids += id; + lines += line; + if (ids.length > 20000 || lines.length > 20000 || (lastTime > 0 && getTimer() - lastTime > 500)) + { + lc.send("_CodeCoverageLC", "debugline", ids, lines); + ids = ""; + lines = ""; + } + lastTime = getTimer(); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/7794f18d/CodeCoverage/CodeCoverageServer-app.xml ---------------------------------------------------------------------- diff --git a/CodeCoverage/CodeCoverageServer-app.xml b/CodeCoverage/CodeCoverageServer-app.xml new file mode 100644 index 0000000..2c7d9b2 --- /dev/null +++ b/CodeCoverage/CodeCoverageServer-app.xml @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!-- + +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. + +--> +<application xmlns="http://ns.adobe.com/air/application/3.4"> + +<!-- Adobe AIR Application Descriptor File Template. + + Specifies parameters for identifying, installing, and launching AIR applications. + + xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/3.4 + The last segment of the namespace specifies the version + of the AIR runtime required for this application to run. + + minimumPatchLevel - The minimum patch level of the AIR runtime required to run + the application. Optional. +--> + + <!-- A universally unique application identifier. Must be unique across all AIR applications. + Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. --> + <id>CodeCoverageServer</id> + + <!-- Used as the filename for the application. Required. --> + <filename>CodeCoverageServer</filename> + + <!-- The name that is displayed in the AIR application installer. + May have multiple values for each language. See samples or xsd schema file. Optional. --> + <name>CodeCoverageServer</name> + + <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. + Values can also be 1-part or 2-part. It is not necessary to have a 3-part value. + An updated version of application must have a versionNumber value higher than the previous version. Required for namespace >= 2.5 . --> + <versionNumber>0.0.0</versionNumber> + + <!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. --> + <!-- <versionLabel></versionLabel> --> + + <!-- Description, displayed in the AIR application installer. + May have multiple values for each language. See samples or xsd schema file. Optional. --> + <!-- <description></description> --> + + <!-- Copyright information. Optional --> + <!-- <copyright></copyright> --> + + <!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 --> + <!-- <publisherID></publisherID> --> + + <!-- Settings for the application's initial window. Required. --> + <initialWindow> + <!-- The main SWF or HTML file of the application. Required. --> + <!-- Note: In Flash Builder, the SWF reference is set automatically. --> + <content>[This value will be overwritten by Flash Builder in the output app.xml]</content> + + <!-- The title of the main window. Optional. --> + <!-- <title></title> --> + + <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> + <!-- <systemChrome></systemChrome> --> + + <!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. --> + <!-- <transparent></transparent> --> + + <!-- Whether the window is initially visible. Optional. Default false. --> + <!-- <visible></visible> --> + + <!-- Whether the user can minimize the window. Optional. Default true. --> + <!-- <minimizable></minimizable> --> + + <!-- Whether the user can maximize the window. Optional. Default true. --> + <!-- <maximizable></maximizable> --> + + <!-- Whether the user can resize the window. Optional. Default true. --> + <!-- <resizable></resizable> --> + + <!-- The window's initial width in pixels. Optional. --> + <!-- <width></width> --> + + <!-- The window's initial height in pixels. Optional. --> + <!-- <height></height> --> + + <!-- The window's initial x position. Optional. --> + <!-- <x></x> --> + + <!-- The window's initial y position. Optional. --> + <!-- <y></y> --> + + <!-- The window's minimum size, specified as a width/height pair in pixels, such as "400 200". Optional. --> + <!-- <minSize></minSize> --> + + <!-- The window's initial maximum size, specified as a width/height pair in pixels, such as "1600 1200". Optional. --> + <!-- <maxSize></maxSize> --> + + <!-- The aspect ratio of the app ("portrait" or "landscape" or "any"). Optional. Mobile only. Default is the natural orientation of the device --> + + <!-- <aspectRatio></aspectRatio> --> + + <!-- Whether the app will begin auto-orienting on launch. Optional. Mobile only. Default false --> + + <!-- <autoOrients></autoOrients> --> + + <!-- Whether the app launches in full screen. Optional. Mobile only. Default false --> + + <!-- <fullScreen></fullScreen> --> + + <!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto --> + + <!-- <renderMode></renderMode> --> + + <!-- Whether the default direct mode rendering context allocates storage for depth and stencil buffers. Optional. Default false. --> + <!-- <depthAndStencil></depthAndStencil> --> + + <!-- Whether or not to pan when a soft keyboard is raised or lowered (either "pan" or "none"). Optional. Defaults "pan." --> + <!-- <softKeyboardBehavior></softKeyboardBehavior> --> + + <autoOrients>false</autoOrients> + <fullScreen>false</fullScreen> + <visible>false</visible> + </initialWindow> + + <!-- We recommend omitting the supportedProfiles element, --> + <!-- which in turn permits your application to be deployed to all --> + <!-- devices supported by AIR. If you wish to restrict deployment --> + <!-- (i.e., to only mobile devices) then add this element and list --> + <!-- only the profiles which your application does support. --> + <!-- <supportedProfiles>desktop extendedDesktop mobileDevice extendedMobileDevice</supportedProfiles> --> + + <!-- Languages supported by application --> + <!-- Only these languages can be specified --> + <!-- <supportedLanguages>en de cs es fr it ja ko nl pl pt ru sv tr zh</supportedLanguages> --> + + <!-- The subpath of the standard default installation location to use. Optional. --> + <!-- <installFolder></installFolder> --> + + <!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. --> + <!-- <programMenuFolder></programMenuFolder> --> + + <!-- The icon the system uses for the application. For at least one resolution, + specify the path to a PNG file included in the AIR package. Optional. --> + <!-- <icon> + <image16x16></image16x16> + <image29x29></image29x29> + <image32x32></image32x32> + <image36x36></image36x36> + <image48x48></image48x48> + <image50x50></image50x50> + <image57x57></image57x57> + <image58x58></image58x58> + <image72x72></image72x72> + <image100x100></image100x100> + <image114x114></image114x114> + <image128x128></image128x128> + <image144x144></image144x144> + <image512x512></image512x512> + <image1024x1024></image1024x1024> + </icon> --> + + <!-- Whether the application handles the update when a user double-clicks an update version + of the AIR file (true), or the default AIR application installer handles the update (false). + Optional. Default false. --> + <!-- <customUpdateUI></customUpdateUI> --> + + <!-- Whether the application can be launched when the user clicks a link in a web browser. + Optional. Default false. --> + <!-- <allowBrowserInvocation></allowBrowserInvocation> --> + + <!-- Listing of file types for which the application can register. Optional. --> + <!-- <fileTypes> --> + + <!-- Defines one file type. Optional. --> + <!-- <fileType> --> + + <!-- The name that the system displays for the registered file type. Required. --> + <!-- <name></name> --> + + <!-- The extension to register. Required. --> + <!-- <extension></extension> --> + + <!-- The description of the file type. Optional. --> + <!-- <description></description> --> + + <!-- The MIME content type. --> + <!-- <contentType></contentType> --> + + <!-- The icon to display for the file type. Optional. --> + <!-- <icon> + <image16x16></image16x16> + <image32x32></image32x32> + <image48x48></image48x48> + <image128x128></image128x128> + </icon> --> + + <!-- </fileType> --> + <!-- </fileTypes> --> + + <!-- iOS specific capabilities --> + <!-- <iPhone> --> + <!-- A list of plist key/value pairs to be added to the application Info.plist --> + <!-- <InfoAdditions> + <![CDATA[ + <key>UIDeviceFamily</key> + <array> + <string>1</string> + <string>2</string> + </array> + <key>UIStatusBarStyle</key> + <string>UIStatusBarStyleBlackOpaque</string> + <key>UIRequiresPersistentWiFi</key> + <string>YES</string> + ]]> + </InfoAdditions> --> + <!-- A list of plist key/value pairs to be added to the application Entitlements.plist --> + <!-- <Entitlements> + <![CDATA[ + <key>keychain-access-groups</key> + <array> + <string></string> + <string></string> + </array> + ]]> + </Entitlements> --> + <!-- Display Resolution for the app (either "standard" or "high"). Optional. Default "standard" --> + <!-- <requestedDisplayResolution></requestedDisplayResolution> --> + <!-- </iPhone> --> + + <!-- Specify Android specific tags that get passed to AndroidManifest.xml file. --> + <!--<android> --> + <!-- <manifestAdditions> + <![CDATA[ + <manifest android:installLocation="auto"> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/> + <application android:enabled="true"> + <activity android:excludeFromRecents="false"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + </application> + </manifest> + ]]> + </manifestAdditions> --> + <!-- Color depth for the app (either "32bit" or "16bit"). Optional. Default 16bit before namespace 3.0, 32bit after --> + <!-- <colorDepth></colorDepth> --> + <!-- </android> --> + <!-- End of the schema for adding the android specific tags in AndroidManifest.xml file --> + +</application> http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/7794f18d/CodeCoverage/CodeCoverageServer.mxml ---------------------------------------------------------------------- diff --git a/CodeCoverage/CodeCoverageServer.mxml b/CodeCoverage/CodeCoverageServer.mxml new file mode 100644 index 0000000..54d903c --- /dev/null +++ b/CodeCoverage/CodeCoverageServer.mxml @@ -0,0 +1,295 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + +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. + +--> +<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" + xmlns:s="library://ns.adobe.com/flex/spark" + xmlns:mx="library://ns.adobe.com/flex/mx" + applicationComplete="setupLC()" + enterFrame="updateStuff()" close="closeHandler(event)" + > + <fx:Declarations> + <!-- Place non-visual elements (e.g., services, value objects) here --> + </fx:Declarations> + <!-- preloadSWF=/Users/aharui/CodeCoveragePreloadSWF.swf --> + <fx:Script> + <![CDATA[ + import mx.controls.Alert; + + private var lc:LocalConnection; + private var file:File; + private var fs:FileStream; + + private var stringMap:Array = []; + private var lineMap:Array = []; + + private var so:SharedObject; + + private function setupLC():void + { + lc = new LocalConnection(); + lc.client = this; + lc.allowDomain('*'); + lc.connect("_CodeCoverageLC"); + + file = File.userDirectory; + file = file.resolvePath("codecoverage.txt"); + fs = new FileStream(); + fs.open(file, FileMode.APPEND); + + so = SharedObject.getLocal("CodeCoverageServer"); + if (so.data.mmcfg) + mmPath.text = so.data.mmcfg; + else + mmPath.text = File.userDirectory.nativePath + File.separator + "mm.cfg"; + + if (so.data.swfpath) + swfPath.text = so.data.swfpath; + else + swfPath.text = File.userDirectory.nativePath + File.separator + "CodeCoveragePreloadSWF.swf"; + + applyConfig(); + } + + private var mmFile:File; + + private function search():void + { + mmFile = new File(File.userDirectory.nativePath); + mmFile.browseForOpen("Path to mm.cfg"); + mmFile.addEventListener(Event.SELECT, selectHandler); + } + + private function selectHandler(event:Event):void + { + mmPath.text = mmFile.nativePath; + } + + private var swfFile:File; + + private function searchSWF():void + { + swfFile = new File(File.userDirectory.nativePath); + swfFile.browseForOpen("Path to CodeCoveragePreloadSWF.swf"); + swfFile.addEventListener(Event.SELECT, selectSWFHandler); + } + + private function selectSWFHandler(event:Event):void + { + swfPath.text = swfFile.nativePath; + } + + private function saveConfig():void + { + so.data.mmcfg = mmPath.text; + so.data.swfpath = swfPath.text; + + applyConfig(); + } + + private const PRELOAD_SWF:String = "preloadSWF="; + private function applyConfig():void + { + if (mmPath.text.length == 0) + return; + if (!mmFile) + mmFile = new File(); + + mmFile.nativePath = mmPath.text; + if (!mmFile.exists) + { + Alert.show("mm.cfg not found", "Error"); + return; + } + + if (!swfFile) + swfFile = new File(); + + swfFile.nativePath = swfPath.text; + if (!swfFile.exists) + { + Alert.show("CodeCoveragePreloadSWF.swf not found", "Error"); + return; + } + + var fs:FileStream = new FileStream(); + fs.open(mmFile, FileMode.UPDATE); + var text:String = fs.readUTFBytes(fs.bytesAvailable); + var lineSep:String = "\r\n"; + if (text.indexOf(lineSep) == -1) + { + lineSep = "\r"; + if (text.indexOf(lineSep) == -1) + { + lineSep = "\n"; + } + } + var lines:Array = text.split(lineSep); + var n:int = lines.length; + for (var i:int = 0; i < n; i++) + { + if (lines[i].indexOf(PRELOAD_SWF) != -1) + { + lines.splice(i, 1); + i--; + n-- + } + } + if (lines[n - 1].length == 0) + lines.pop(); + lines.push(PRELOAD_SWF + swfFile.nativePath); + lines.push(""); + text = lines.join(lineSep); + fs.position = 0; + fs.truncate(); + fs.writeUTFBytes(text); + fs.close(); + } + + private var count:int = 0; + + public function reset():void + { + if (stringMap.length > 0) + { + // codecoverpreloadswf is first one + var s:String = stringMap[0]; + stringMap = [s]; + lineMap = [{}]; + } + else + { + stringMap = []; + lineMap = [{}]; + } + } + + public function newString(file_name:String):void + { + stringMap.push(file_name); + lineMap.push({}); + //trace(file_name); + } + + private var s:String = ""; + + public function debugline(string_ids:String, linenums:String):void + { + var ids:Array = string_ids.split(" "); + var lines:Array = linenums.split(" "); + var n:int = ids.length; + for (var i:int = 0; i < n; i++) + { + ++count; + if (stringMap[ids[i]] == undefined) + s += ids[i] + ':' + rightJustify(lines[i]) + "\n"; + else if (lineMap[ids[i]][lines[i]] == undefined) + { + lineMap[ids[i]][lines[i]] = 1; + s += '"' + stringMap[ids[i]] + '":' + rightJustify(lines[i]) + "\n"; + } + } + } + + private var padding:String = " "; + + private function rightJustify(num:String):String + { + var i:int = 8 - num.length; + var pad:String = padding.substr(0, i); + return pad + num; + } + + private function updateStuff():void + { + if (count > 0) + { + fs.writeUTFBytes(s); + s = ""; + numlines.text = count.toString(); + } + } + + protected function closeHandler(event:Event):void + { + mmFile.nativePath = mmPath.text; + if (!mmFile.exists) + { + Alert.show("mm.cfg not found", "Error"); + return; + } + swfFile.nativePath = swfPath.text; + if (!swfFile.exists) + { + Alert.show("CodeCoveragePreloadSWF.swf not found", "Error"); + return; + } + + var fs:FileStream = new FileStream(); + fs.open(mmFile, FileMode.UPDATE); + var text:String = fs.readUTFBytes(fs.bytesAvailable); + var lineSep:String = "\r\n"; + if (text.indexOf(lineSep) == -1) + { + lineSep = "\r"; + if (text.indexOf(lineSep) == -1) + { + lineSep = "\n"; + } + } + var lines:Array = text.split(lineSep); + var n:int = lines.length; + for (var i:int = 0; i < n; i++) + { + if (lines[i].indexOf(PRELOAD_SWF) != -1) + { + lines.splice(i, 1); + i--; + n--; + } + } + if (lines[n - 1].length > 0) + lines.push(""); + text = lines.join(lineSep); + fs.position = 0; + fs.truncate(); + fs.writeUTFBytes(text); + fs.close(); + } + + ]]> + </fx:Script> + <s:layout> + <s:VerticalLayout /> + </s:layout> + <s:HGroup width="100%"> + <s:Label text="Path to mm.cfg: " /> + <s:TextInput id="mmPath" width="100%" /> + <s:Button label="Search..." click="search()" /> + </s:HGroup> + <s:HGroup width="100%"> + <s:Label text="Path to CodeCoveragePreloadSWF.swf: " /> + <s:TextInput id="swfPath" width="100%" /> + <s:Button label="Search..." click="searchSWF()" /> + </s:HGroup> + <s:Button label="Save Configuration" click="saveConfig()" /> + <s:HGroup> + <s:Label text="Num Lines:" /> + <s:Label id="numlines" /> + </s:HGroup> +</s:WindowedApplication>
