Archive for the ‘Linux’ Category

Automated UI Tests with Hudson on Debian

Thursday, April 2nd, 2009

At DFKI we are using Java, Maven2 and Hudson for a Continuous Integration System within the research project MEDICO .

Until now, this works really fine for console based JUnit tests. However, the test coverage of our source code is far from 100% (ashes on me!). This is why I decided to test from two “directions”:

  1. Bottom-up using JUnit tests for simple methods. These tests are easy to write and to maintain. In theory, the whole application works correctly if all methods work correctly. Thus, this requires that you have 100% test coverage for your code. This condition is far from being met by our code base.
  2. To come up with this, we decided to add Top-down tests. Using the Java UI test framework FEST we specified test scripts which perform certain operations on the application level. Each of these scripts define the expected behavior of the UI and the data presented on the screen. Examples are below.

It took me several hours to set this up. The following steps assume that you have already installed Debian Linux, Maven2, Hudson as described here.

Here are the necessary steps:

1. Install Xorg

On a Debian system, you just have to do an

apt-get install xorg

2. Configure Xorg

Since we do not care about any special support for the graphics card (in fact, I run all these services on VMWare instances) you can just use automatic configuration routines from Xorg to find a minimal server layout. Just type

Xorg -configure

This will create a “xorg.conf.something” in the current working directory. To use it, you just have to copy it to “/etc/X11/xorg.conf”.

3. Install an appropriate window manager

I also tried running Xorg completely without any window managers and with tinywm. This is certainly not a good idea since some of my UI tests require the program windows to run maximized. But window maximization seems to require certain functions from the window manager. With the latter two window managers, I got this error message:

“Platform does not support maximizing frames”

This problem was solved by installing ICEWM. On Debian, all you have to do is:

apt-get install icewm

No further configuration needed.

4. Make Xorg start before Tomcat

For this purpose I created a “/etc/init.d/xorg” file with the following content:

case $1 in
start)
startx &
sleep 15
export DISPLAY=:0.0
xhost localhost
;;
stop)
killall -9 xinit
;;
restart)
killall -9 xinit
sleep 5
startx &
sleep 5
xhost localhost
export DISPLAY=:0.0
;;
esac
exit 0

Link this file to /etc/rc2.d/S98xorg to have it started before tomcat. As you can see above, this also activates access to the Xserver for all applications running on the local server. This only makes sense for dedicated servers without any user accounts that could interfere with the UI tests.

5. Export DISPLAY variable to the Tomcat init file

Add this line to /etc/init.d/tomcat

export DISPLAY=:0.0

and make sure that you have no “java.awt.headless=true” parameters in any of the Tomcat or Catalina startup scripts.

6. Define a sample application

Somehow a “Hello World”, here is a very simple sample application:

public class FrameSample {

public static JFrame frame;

public static void main(String[] args) {
frame = new JFrame(“TestFrame”);
frame.setName(“TestFrame”);

JButton button = new JButton(“TestButton”);
button.setName(“TestButton”);

frame.add(button);
frame.pack();
frame.setVisible(true);
}
}

7. Define a UI test for it

A really minimalistic example, that only checks for the presence of the “TestButton” is shown below:

public class FrameSampleTest {

private FrameFixture window;

@Before
public void setUp() {
dfki.km.medico.uisample.FrameSample.main(new String[] {});
window = new FrameFixture(FrameSample.frame);
window.show(); // shows the frame to test

}

@Test
public void testButtonExists() {
window.maximize();
window.button(“TestButton”).requireEnabled();
}
}

Documentation about more complex tests can be found in the FEST wiki.

Sonar on Debian with Tomcat 6

Sunday, March 29th, 2009

After moving all MEDICO related code to Maven2 and adopting a Continuous Integration cycle for it, I decided to take the next step and perform automatic code Monitoring with Sonar. We had been doing code monitoring before with Hudson and different plugins for PMD, Checkstyle etc. But it turned out that accessing the resulting information via the Hudson interface is not convenient if you want to monitor the quality of several software projects over time.

This is where Sonar comes into play. Quoting from their website:

“Sonar enables to collect, analyze and report metrics on source code. Sonar not only offers consolidated reporting on and across projects throughout time, but it becomes the central place to manage code quality.”

Sonar 1238344318231

Since Sonar does not officially support deployment in Tomcat 6, the rest of this post explains how to install Sonar on Debian Linux running Apache Tomcat version 6.0.18 and JDK 1.6.0_07-b06.

1. Preparing the WAR file

Prepare the WAR file accroding to the Sonar Full Installation Guide.

2. Before Deployment

With the standard Tomcat 6 setup you will run into java.lang.OutOfMemoryError Exceptions for the PermGen space. These look like that in the “catalina.<date>.log” file:

SEVERE: An exception or error occurred in the container during the request processing

java.lang.OutOfMemoryError: PermGen space

at java.lang.Throwable.getStackTraceElement(Native Method)

at java.lang.Throwable.getOurStackTrace(Throwable.java:591)

at java.lang.Throwable.printStackTrace(Throwable.java:510)

at java.util.logging.SimpleFormatter.format(SimpleFormatter.java:72)

at org.apache.juli.FileHandler.publish(FileHandler.java:129)

at java.util.logging.Logger.log(Logger.java:472)

at java.util.logging.Logger.doLog(Logger.java:494)

at java.util.logging.Logger.logp(Logger.java:694)

at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:167)

at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:135)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:274)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)

at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:419)

at org.apache.coyote.ajp.AjpAprProtocol$AjpConnectionHandler.process(AjpAprProtocol.java:378)

at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1509)

at java.lang.Thread.run(Thread.java:619)

Apparently, not even the deployment of Sonar worked. Thus, you have to change your “catalina.sh” according to this article. Search for the JAVA_OPTS variable and add these parameters:

JAVA_OPTS=”-Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m

-XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC”

The article cited above also suggests to add “-Djava.awt.headless=true” but that is not applicable for my case since I am running an X-Server on the same machine to perform automated UI tests.

3. Deployment

Now you can deploy your WAR file, e.g., via the Tomcat Manager application or just moving the “sonar.war” file to the webapps directory of you Tomcat installation.

4. Database Setup

After logging into Sonar for the first time, it asks for the Database Setup.

I created just the default integrated database. Performing this step took several seconds, but then Sonar was up and running!

5. First login

Just a hint (I had to look that up): The default password for user “admin” is “admin”.

After changing this password, you might run into 500 Internal Server errors. As Olivier from the Sonar developers pointed out, this is a known issue: SONAR-514. All you have to do is delete all session cookies and login again.

Installing Hudson on Debian

Wednesday, January 28th, 2009

This post describes how to setup the continuous integration tool Hudson on a Debian Linux system.

1. Update your /etc/apt/sources.list.

You definitely need the non-free components which include the official Sun Java packages. Therefore you should have a line like the follwing in your /etc/apt/sources.list:

deb http://ftp.de.debian.org/debian/ etch main non-free contrib

2. Install JRE and JDK 1.6

On a root shell, type:

apt-get install sun-java6-jre sun-java6-jdk

3. Configure Debian to use exactly this version as the system-wide default

On a root shell, type:

update-alternatives -–config java
update-alternatives -–config javac

4. Install Tomcat

On a root shell, type:

apt-get install tomcat5.5 tomcat5.5-admin tomcat5.5-webapps

5. Make Tomcat listen on port 8080

The default for Tomcat on Debian is to start on port 8180. We want it to start on port 8080. Thus, you need to change your /etc/tomcat5.5/server.xml. In the section

<Connector port=”8180″ maxHttpHeaderSize=”8192″
maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″
enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true” />
you have to replace “8180″ by “8080″.

6. Disable Tomcat’s security mechanism

Hudson brings it’s own security management system. The Tomcat security mechanism for wepapps block the startup of Hudson and have to be in /etc/default/tomcat5.5 disabled. Search for “TOMCAT5_SECURITY” and change the line to make it look like this:

TOMCAT5_SECURITY=no

Instead, you should configure Hudsons internal security management system.

7. Setup a home directory for Hudson

In a root shell, type:

mkdir /home/hudson

chown tomcat55:nogroup /home/hudson

8. Set Hudson’s home directory environment variable

Open /etc/init.d/tomcat5.5 and add this line:

export HUDSON_HOME=/home/hudson

9. Deploy the hudson.war via the Tomcat Manager

After this step, you should be able to log into Hudson via Web browser and start configuring via the web interface.

10. Install Maven2

On a root shell, type:

apt-get install maven2

Setup your MAVEN_HOME environment variable. Open /etc/init.d/tomcat5.5 and add this line:

export MAVEN_HOME=/usr/share/maven2/

Create a Maven2 home directory for Hudson. This has to be located in /usr/share/tomcat5.5/.m2. Execute the following commands on a root shell:

mkdir /usr/share/tomcat5.5/.m2

chown tomcat55:nogroup /usr/share/tomcat5.5/.m2

11. Install ant and junit

On a root shell, type:

apt-get install ant ant-optional junit

Setup your ANT_HOME environment variable. Open /etc/init.d/tomcat5.5 and add this line:

export ANT_HOME=/usr/share/ant

12. Install SVN access plugin for Hudson

Open via http://localhost:8081/hudson/pluginManager/available in a web browser and choose SVNCompat14 Plugin for installation. Please note: For me, the install stopped with this exception at the first time:

javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591) at …

But at the second try it ran through.

Web-based auto-updating photo frame

Thursday, January 1st, 2009

We have a big archive with all our digital images starting from back in the 1990s. Up till now we just store and backup the photos there but hardly ever look at them. I have been looking for a Wifi equipped digital photo frame which allows to access these images but have not found anything which has a reasonable size and access to arbitrary data sources.

After deciding for a completely web-based dual-monitor terminal for our kitchen table I spent some time today to enable it to also display photos, e.g. during our coffee breaks or when we have guest who do not necessarily see my emails.

I’ve created a Bash script which collects randomly a configurable number of photos, resizes them and puts them in a directory that is shared on our local webserver. You can download it from here: refresh_slideshow_photos.sh The script runs for a couple of minutes on our old Pentium II, but that could be done once per night or so.

The images are display using Johannes Knabe’s great PHP script for dynamic picture galleries. We had that feature on yesterday’s New Year’s Eve party and even the girls had to admit that this is a nice thing. ;-)

The whole thing is totally free of maintenance. Whenever you put new photos onto the server, they will show up sooner or later. Since the frontend is web-based, the application can be run simultaneously on multiple machines which can be located anywhere where you have (internet via dyndns.org) access to the server.

Starting your computer via Bluetooth

Tuesday, December 30th, 2008

Goal

My breakfast terminal should be switched on and off not only based on a time schedule but also on the information if I am at home. This turned out to be a requirement over Christmas break when the terminal was shut down by crontab entries automatically during my normal office hours when I am not at home.

Solution

Use the Bluetooth signal of my mobile phone to discover whether I am at home or not. Our Linux server runs 24/7 anyway and does the Bluetooth scan for my mobile.

Step 1: What’s my Bluetooth MAC?

Discover the Bluetooth MAC address of my mobile using hcitool.

$ hcitool scan
Scanning …
00:18:13:18:BE:B3       W810i

Alternatively, you could also use btscanner.

Step 2: Configure a monitoring daemon

First, I was trying bluemon which is available as a Debian package to monitor the Bluetooth airspace around our appartment. But it turned out that at least with my mobile (a Sony Ericson W810i) I get frequent connected/disconnected messages. This happens even when the mobile is not moved around and the link quality is good.

Instead, I switched to sdptool which comes with the Bluez, collection of Bluetooth utilities for Linux. But even with this tool, my mobile is sometimes not detected when I am executing a command like

sdptool browse 00:18:13:18:BE:B3

I’ve played around a little and it seems like after invoking it a couple of times, the mobile is detected properly if available.

Step 3: Booting the terminal

As described before the terminal is started via Wake on LAN by our server. All I had to do was to add support to check for the availability of my mobile whenever the terminal is to be booted or shut down.

You can also have a look on the Bash script I wrote for this. It is merely a collection of ugly hacks, so use at your own risk: check_mobile.sh