Debugging Sailfish OS application power consumption

Lately my simple news feed reader, Ampiaiskala, got rejected from Jolla Store in Harbour Quality Assurance as it seemed that it was too power hungry while minimized. I was a bit surprised as 0.1 version was accepted and the functionality hadn't changed. So, it was time to get familiarized with PowerTOP and how to debug problems with power consumption.

First we need to install PowerTOP to Jolla and then just ran it via SSH over USB or WLAN while the app is minimized and screen is closed. After that it's about what all those numbers mean and where they come from.

Installing PowerTOP on Jolla

Steps to install PowerTOP from command line:

1. Add mer-tools repository:

$ ssu ar mer-tools

2. Refresh repository cache:

$ pkcon refresh

3. Install tool:

$ pkcon install powertop

4. Run tool:

$ devel-su powertop

Debugging power consumption

PowerTOP reports how much power each process uses and provides a list of all running processes which are waking up and how many times in a second (how many times each one sends a CPU interrupt). Only one process is monitored so it doesn't tell all about the system, e.g. when the process has interaction with audio or network.

After installing PowerTOP tool, usage is easy via SSH over USB or WLAN connection. Difference between these connections is that device does not suspend with PC USB connection enabled and with WLAN device goes to suspend if there's not any network traffic and display is turned off.

Connect to your phone e.g. with ssh nemo@192.168.1.58 and ran the PowerTOP as root: devel-su powertop. The command prompts you for the root password which you have given in Settings > System > Developer mode > SSH and root password.

Before starting to debug your app's power consumption it's useful to create a baseline by running PowerTOP after a cold startup, without opening any applications, and then run it a few more times throughout the day to get a comparison of different workloads.

Generate HTML page of PowerTOP results for baseline:

$ devel-su powertop --html=<filename>

After getting some baseline results it's just reading the numbers and figuring out if your application eats power or not. And if it is power hungry beast then figuring out why it does that.

Complementary to PowerTOP, there's Strace which lets you find out how a program is interacting with the operating system by monitoring system calls and signals. Just install it with $ pkcon install strace and ran it with strace -p or strace -ttT -p . It shows what your application does while it's expected to be idle. For example:

$ ps aux | grep ampiaiskala
$ devel-su strace -p 1301

The result looks something like this:

Don't ask me what all that means :)

Power consumption and Harbour QA testing

The reason I'm debugging my application for power usage is Jolla Harbour Quality Assurance which rejected my app with "It seems that app doesn't go to idle state when device does". The Quality Assurance procedure for power consumption is explained in Together being the following.

"Jolla's Harbour QA testing is mostly done with PC USB cable connection, application minimized to home screen and display is turned off. In this state application should not block suspend and wake ups should be minimal (< ~60, this is a reference value). A good practice is to take a "system state" before opening application and compare those results when application is minimized to home screen." "The phone suspend is blocked by wake locks and easy test for that is catting /sys/power/wake_lock file. The file should be empty normally if nothing from user space is not blocking suspend. If application is using e.g. audio, then file should include "mce_cpu_keepalive" string. Of course applications are allowed to do things in the background but that should be minimal for its own functionality. E.g are internet streaming."

After another Harbour QA rejection (2014-06-05) I asked in IRC from Jolla Sailor, nazanin, about the power consumption issue and what steps they are using so I could repeat them. The steps are the following:

  • First there are no apps open, lock the device, run powertop command
  • Wait for about 1 minute until the device status becomes stable
  • Unlock it, open the application you want to test, play around with it for a bit, until the number of wake ups reaches 300 or 400
  • Check if you already see the app in wakeup list in this status
  • Lock the device and observe how powertop updates
  • If after 1 minute or 2, the application drops down from the list, it's okay
  • If it doesn't, then wait more, for about 5-10 minutes
  • If you see the application is still there, that is when you can assume the test case is failed and application is causing power consumption

Possible reasons for excess power consumption

The procedure to figure out if your application is consuming power more than it should is relatively easy but finding out why it does that is a bit harder. Things like timers, animations, WebViews and using animated images are possible culprits and how the app behaves with none or bad network connectivity. I don't know there to be any good tips how to debug these issues other than going through your app, knowing what it does and figuring out possible issues.

My own cases for Harbour QA rejections due power consumption have been with using SilicaWebview (QtWebKit) and keeping it open when the app is minimized and thus eating too much CPU and preventing the device go to sleep. The solution would be that you suspend the WebKit rendering or close the WebView. But that's easier said than done. After discussing this issue in IRC with couple of Sailors (nazanin, kontio) for now there's no good solution to suspend the WebKit as it doesn't provide an easy API to suspend rendering. If it's reasonable for user experience you can pop the WebView page when app is minimized. You can bind the action e.g. to CoverPage and use onStatusChanged signal and check for "status == PageStatus.Activating.

I came across this WebKit issue with Haikala and Ampiaiskala as they open WebKit view for reading the news feed item's web page. For those I modified my code to allow the user to close the web view from the pull down menu when user goes back to the feed list. After that they passed the Harbour QA. Couple of months ago there was a similar case on SailfishDevel mailing list.

With my imgur app, Sailimgur, it was again using WebKit for viewing imgur's gallery page but also there's animated images running while showing the gallery or image page in the app. The app was seen under wake-ups when it was showing an animated image like .gif. If the app wasn't showing some funny gifs from imgur it dropped down from the list after a while as it should. Understandable effect as the UI is running the gif which consumes power and prevents the device go to sleep.

The partial solution is to manually stop the animated images when the app is minimized but in my opinion that should be something that Sailfish OS should take care automatically. The other thing is the animated image running in the SilicaWebView where QtWebKit keeps running in the background and doesn't suspend automatically. You could send SIGSTOP to suspend it when minimized and then continue with SIGCONT from C++ but it's a bit hassle as you would need a monitoring process to manage that. And it's not known if that works or not.

In the end after considering the options the Sailors said that they accept my app in the current state, since WebKit doesn't provide an easy API to suspend rendering. But have to think about what I could do to limit wake-ups.

Maven plugin to generate HTML from Markdown

Writing documentation or user guide isn't the most interesting part of the software project but it's still needed to be done and important for the end users. There are many ways to achieve documentation but using Markdown is good way to make it easier. After that you just need to convert it to HTML and as I couldn't find a suitable Maven plugin to do that nicely I wrote one myself: markdown-page-generator-plugin.

Software developers are a bit lazy to write good and up to date documentation and as I needed to write the API documentation for the web application as separate HTML pages I got to know the issue first hand. I like writing documents but typing the API documentation as static HTML wasn't very effective or fun. Fortunately it was quite easy to do it with Markdown which allows you to write documentation using an easy-to-read, easy-to-write plain text format which you can then convert to HTML. After that the only problem was to enable easy HTML generation directly from Maven Lifecycle and thus was the "Markdown to HTML Page Generator Maven Plugin" developed.

Markdown to HTML Page Generator Maven Plugin

"Markdown to HTML Page Generator" is a simple Maven Plugin which reads the input directory for Markdown files with .md suffix and outputs HTML files to target directory. There are couple of configuration options to set the input/output directories and if you want to add header and footer files to make it structurally valid HTML. The plugin uses pegdown Markdown processor.

Source code

The plugin code can be found from GitHub: markdown-page-generator-plugin.

Usage

Check out the plugin's GitHub page for configuration options.

Using the plugin could be easier but as it isn't in Maven repository you have to e.g. add it as Maven project to same Eclipse workspace as your project and build it. After that add it as a plugin to your build and it's run automatically when processing sources. You can also run it from command line with "mvn com.ruleoftech:markdown-page-generator-plugin:generate".

Web application test automation with Robot Framework

Software quality has always been important but seems that lately it has become more generally acknowledged fact that quality assurance and testing aren't things to be left behind. With Java EE Web applications you have different ways to achieve test coverage and test that your application works with tools like JUnit, Mockito and DBUnit. But what about testing your web application with different browsers? One great way is to use Robot Framework which is a generic test automation framework and when combined with Selenium 2 it makes both writing your tests and running them quite intuitive.

Contents

Introduction

Robot Framework which is a generic test automation framework for acceptance testing and its tabular test data syntax is almost plain English and easy to understand. Its testing capabilities can be extended by test libraries implemented either with Python or Java, and users can create new higher-level keywords from existing ones using the same syntax that is used for creating test cases. Robot Framework itself is open source and released under Apache License 2.0, and most of the libraries and tools in the ecosystem are also open source. The development of the core framework is supported by Nokia Siemens Networks.

Robot Framework doesn't do any specific testing activity but instead it acts as a front end for libraries like Selenium2Library. Selenium2Library is a web testing library for Robot Framework that leverages the Selenium 2 (WebDriver) libraries from the Selenium project. In practice it starts the browser (eg. IE, Firefox, Chrome) and runs the tests against it natively as a user would. There's no need to manually click through the user interface.

Robot Framework has good documentation and by going through the "Web testing with Robot Framework and Selenium2Library" demo you see how it's used in web testing, get introduction to test data syntax, how tests are executed, and how logs and reports look like. For more detailed view about Robot Framework's features you can read the User Guide.

Installing test tools

The "Web testing with Robot Framework and Selenium2Library" demo is good starting point for getting to know Robot Framework but it more or less skips the details of setting up the system and as the installation instructions are a bit too verbose here is an example how to install and use Robot Framework and Selenium 2 in 64-bit Windows 7.

Python installation

First we need Python as a precondition to run Robot Framework and we install Python version 2.7.x as Robot Framework is currently not compatible with Python 3.x. From the Python download page select Python 2.7.9 Windows X86-64 Installer.

For using the RIDE editor we also need wxPython. From the download page select wxPython2.8-win64-unicode-py27 for 64-bit Python 2.7.

Next we need to set up the PATH environment variable in Windows if you didn't setup it when you installed Python.

Open Start > Settings > Control Panel > System > Advanced > Environment Variables
Select System variables > PATH > Edit and add e.g. ;\Python27;C:\Python27\Scripts at the end of the value.
Exit the dialog with OK to save the changes.

Starting from Python 2.7.9, the standard Windows installer by default installs and activates pip.

Robot Framework and Selenium2Library installation

In practice it is easiest to install Robot Framework and Selenium2Library along with its dependencies using pip package manager. Once you have pip installed, all you need to do is running these commands in your Command Prompt:

1. pip install robotframework
2. pip install robotframework-selenium2library

It's good to notice that pip has a "feature" that unless a specific version is given, they install the latest possible version even if that is an alpha or beta release. A workaround is giving the version explicitly. like pip install robotframework==2.7.7

RIDE installation

RIDE is a light-weight and intuitive editor for Robot Framework test case files. It can be installed by using Windows installer (select robotframework-ride-1.1.win-amd64.exe) or with pip using:

pip install robotframework-ride

The Windows installer does a shortcut to the desktop and you can start it from Command Prompt with command ride.py.

Now you have everything you need to create and execute Robot Framework tests.

Executing Robot Framework tests

As described in WebDemo running tests requires the demo application located under demoapp directory to be running. It can be started by executing it from the command line:

python demoapp/server.py

After the demo application is started, it is be available at http://localhost:7272 and it needs to be running while executing the automated tests. It can be shut down by using Ctrl-C.

In Robot Framework each file contains one or more tests and is treated as a test suite. Every directory that contains a test suite file or directory is also a test suite. When Robot Framework is executed on a directory it will go through all files and directories of the correct kind except those that start with an underscore character.

WebDemo's test cases are located in login_tests directory and to execute them all type in your Command Prompt:

pybot login_tests

Running the tests opens a browser window which Selenium 2 is driving natively as a user would and you can see the interactions.
When the test is finished executing four files will have been generated: report.html, log.html and output.xml. On failed tests selenium takes screenshots which are named like selenium-screenshot-1.png. The browser can also be run on a remote machine using the Selenium Server.

You can also run an individual test case file and use various command line options (see pybot --help) supported by Robot Framework:

pybot login_tests/valid_login.txt
pybot --test InvalidUserName --loglevel DEBUG login_tests

If you selected Firefox as your browser and get an error like "Type Error: environment can only contain strings" that's a bug in Selenium's Firefox profile. You can fix it with a "monkey patch" to C:\Python27\Lib\site-packages\selenium\webdriver\firefox\firefox_profile.py.

Using different browsers

The browser that is used is controlled by ${BROWSER} variable defined in resource.txt resource file. Firefox browser is used by default, but that can be easily overridden from the command line.

pybot --variable BROWSER:Chrome login_tests
pybot --variable BROWSER:IE login_tests

Browsers like Chrome and Internet Explorer require separate Internet Explorer Driver and Chrome Driver to be installed before they can be used. InternetExplorerDriver can be downloaded from Selenium project and ChromeDriver from Chromium project. Just place them both somewhere in your PATH.

With Internet Explorer Driver you can get an error like "'Unexpected error launching Internet Explorer. Protected Mode settings are not the same for all zones. Enable Protected Mode must be set to the same value (enabled or disabled) for all zones.'". As it reads in the driver's configuration you must set the Protected Mode settings for each zone to be the same value. To set the Protected Mode settings in Internet Explorer, choose "Internet Options..." from the Tools menu, and click on the Security tab. For each zone, there will be a check box at the bottom of the tab labeled "Enable Protected Mode".

Reading the results

After the tests have run there are couple of result files to read: report.html and log.html.

The report.html shows the results of your tests and its background is green when all tests have passed and red if any have failed. It also shows "Test Statistics" for how many tests have passed and failed. "Test Details" shows how long the test took to run and, if it failed, what the fail message was.

The log.html gives you more detailed information about why some test fails if the fail message doesn't make it obvious. It also gives a detailed view of the execution of each of the tests.

Summary

From the short experience I have played with Robot Framework it seems to be powerful tool for designing and executing tests and good way to improve your application's overall quality.

Next it's time to get to know the Robot Framework syntax better, write some tests and run Selenium Server. Also the Maven plugin and RobotFramework-EclipseIDE plugin looks interesting.

References

Robot Framework documentation
Robot Framework User Guide
Web testing with Robot Framework and Selenium2Library demo
RIDE: light-weight and intuitive editor for Robot Framework test case files

Using the WebLogic Maven Plug-In for Deployment

Using the WebLogic Maven plug-In for deployment is much easier and quicker than going through the WebLogic Server's AdminServer and Oracle Documentation provides good examples how to do it.

In short, generating WebLogic Maven Plug-In contains following steps:

1. Build the plug-in JAR file using the WebLogic JarBuilder Tool (wljarbuilder) under MW_HOME/wlserver_10.3/server/lib/ with the following command:

java -jar wljarbuilder.jar -profile weblogic-maven-plugin

2. Extract the pom.xml file from weblogic-maven-plugin.jar under the MW_HOME/wlserver_10.3/server/lib directory, and then copy the pom.xml file to MW_HOME/wlserver_10.3/server/lib.

jar xvf MW_HOME/wlserver_10.3/server/lib/weblogic-maven-plugin.jar META-INF/maven/com.oracle.weblogic/weblogic-maven-plugin/pom.xml
 
in Linux:	
cp META-INF/maven/com.oracle.weblogic/weblogic-maven-plugin/pom.xml MW_HOME/wlserver_10.3/server/lib
 
or in Windows:
copy META-INF/maven/com.oracle.weblogic/weblogic-maven-plugin/pom.xml MW_HOME/wlserver_10.3/server/lib

3. Provision the weblogic-maven-plugin.jar in your local Maven repository with the following command.

mvn install:install-file -Dfile=MW_HOME/wlserver_10.3/server/lib/weblogic-maven-plugin.jar -DpomFile=pom.xml

4. Done.

The Maven plug-in can be used e.g. from application's POM file and be bound to some phase of the Maven life cycle. For example it can be bound to "install" phase and every time you run the "mvn install" command, the deployment plug-in is also called. In my opinion better way to use the plug-in is to add it as a profile so you can call it just when you want with command like "mvn clean install -Pdeploy-wls".

Maven Project pom.xml File

<profile>
	<id>deploy-wls</id>
	<build>
		<plugins> 
			<plugin> 
				<groupId>com.oracle.weblogic</groupId>
				<artifactId>weblogic-maven-plugin</artifactId> 
				<version>10.3.6.0</version> 
				<configuration> 
					<adminurl>t3://localhost:7001</adminurl>
					<user>weblogic</user> 
					<password>weblogic123</password> 
					<upload>true</upload> 
					<targets>myServer</targets>
					<action>deploy</action> 
					<remote>false</remote> 
					<verbose>true</verbose> 
					<source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source> 
					<name>${project.build.finalName}</name> 
				</configuration> 
				<executions> 
					<execution> 
						<phase>install</phase> 
						<goals> 
							<goal>deploy</goal> 
						</goals> 
					</execution> 
				</executions> 
			</plugin> 
		</plugins> 
	</build>
</profile>

The user credentials in the POM file are provided as clear-text but for more security you can use secure configuration authentication mechanism which stores the user name and password in encrypted form in an external file, and then uses it to supply the user credentials with which to connect to the WebLogic Server domain, along with the key that was used to encrypt the file.