Automated bug finding with git bisect and boost::test

Here we use boost::test to write test programs for our C++ code, and git as a distributed version control system to track revisions.

One day a test that used to pass stopped working so I decided to try git-bisect to identify the commit  that broke the test. This took me along a journey of shell scripting and git magic that I’d like to share.

First I chdir’d to /tmp and cloned the repo:
cd /tmp
git clone ~/my_repo
cd my_repo

Then I created a shell script that builds the test and runs it, and placed it in the root of the git repository. This is the script, aptly called my_script:
#!/bin/sh
rm -rf bin
cd src
bjam release -j3
cd ../test
bjam release TestModel -j3
cd ..
bin/test/gcc-4.9/release/TestModel --build_info=yes --log_level=test_suite --report_level=detailed
OUT=$?
if [ $OUT -eq 0 ];then
exit 0
else
exit 1
fi

The shell script checks the exit code of the boost::test executable, and if that is different from zero (some tests failed) it returns 1, or 0 if all is OK. This is based on the magic shell variable $? that returns the exit code of the last run command – a trick I always forget and that seems so difficult to find with a search engine.

Now I make the script executable:
chmod u+x my_script

Then I test it here where I am (the HEAD):
./my_script
echo $?

This returns 1, so the test is failing. Now we can start the git-bisect journey:
git bisect reset
git bisect start
git bisect bad

Next we look for a previous commit where the test used to pass; let’s rewind by 20 commits and try there:
git checkout HEAD~20
./my_script
echo $?

Now this passes, so let’s get back to HEAD and find the corresponding commit:
git checkout master
git log --pretty=oneline | head -n 21

The HEAD~20 has a hash of f6aabbe80766a9745447214a89c513de29cbbe70 so let’s mark that as a good one:
git bisect good f6aabbe80766a9745447214a89c513de29cbbe70

and now we’re ready to start:
git bisect run ./my_script

after some time git-bisect returns with:
3c9b0231c2dbef5a7c6a490c877116e2c5bd89c2 is the first bad commit

Done !

pixelstats trackingpixel
Posted in Howtos | Leave a comment

Third LIBPF app preview

This time we have dynamic pages and you can switch between 4 pseudo-servers (switching server changes the app skin). But of course no server is running yet so it’s all fakes (there is a fruit salat configurator you can play around with).

Here is a group photo of the app on our test gizmos:

app on gizmosFor a hands-on session straight into your own device, try this link.

pixelstats trackingpixel
Posted in UI | Leave a comment

Using jshint on debian testing

tl;dr: If you wish to use jshint on debian testing (jessie), do this:

sudo apt-get update
sudo apt-get install nodejs nodejs-legacy
sudo npm install jshint -g
jshint

Long story: this is difficult to get right if you read random posts around. There are flamewars from 2012 about node-js package being obsolete in Debian (not true as of today) and WNPP for jshint is stuck because the package contains some code licensed with a variant of the MIT license considered un-kosher by debian (still true).

pixelstats trackingpixel
Posted in Howtos | Leave a comment

Second LIBPF app preview

Hey we’re still in the early prototyping phase – it’s all static pages – but you asked for it, so here it is on the XCode simulator (iPhone 3.5 retina):

Random screenshots:

03
00
02
01For a hands-on session straight into your own device, try this link.

pixelstats trackingpixel
Posted in UI | Leave a comment

First try at webapp integration testing with capybara on debian

Capybara looks like a promising tecnology for integration testing of web applications, so we decided to give it a try on debian jessie workstation.

There are some howtos around based on rails or other ruby-specific stuff, but what is required for a first try (see KISS phylosophy = Keep it Simple Stupid) is to run one test interactively with irb (the Interactive Ruby Shell).
There is a ruby-capybara debian package, but it only comes with rack_test driver. It looks tricky to configure with other drivers, as per Debian Bug report #705739; also its popcon data with 9 submitters suggest it may not trendy.

The RubyGems package manager seems to do the job better, so let’s remove the ruby-capybara package, install ruby-dev (for the header files to compile ruby extensions)  and launch gem for capybara and the selenium webdriver:

sudo apt-get remove ruby-capybara
sudo apt-get install ruby-dev
sudo gem install capybara
sudo gem install selenium-webdriver

Now start irb and try this:

require 'capybara/dsl'
Capybara.default_driver = :selenium
Capybara.app_host = 'http://bing.com'
Capybara.default_wait_time = 15
Capybara.visit '/'
Capybara.fill_in 'sb_form_q', :with => 'simevo'
Capybara.find('#sb_form_go').click

Mandatory screenshot:

capybara

pixelstats trackingpixel
Posted in Howtos, UI, Uncategorized | Leave a comment

LIBPF app preview

Work is underway to create a LIBPF mobile app. At the moment we have the storyboard:

P1100260and a very early prototype of the main page:

pixelstats trackingpixel
Posted in Uncategorized | Leave a comment

New LIBPF.com headquarters

Starting today LIBPF is temporarily based c/o Faktory Basement, a multi-purpose facility (club, music reharsal / recording and coworking) located in the now abandoned chemical site of Châtillon / Montefibre.

Nothing more adequate to the topic of process simulation than a post-industrial site !

Here are some snapshots:

Whole building viewEntranceThe roomThe coworkers

 

 

 

pixelstats trackingpixel
Posted in Uncategorized | Leave a comment

Debian Wheezy with KDE

The right way to install KDE on Debian Wheezy is to start the right installer by choosing “KDE desktop” under Alternate Desktop Environments under Advanced Options in the CD boot menu.
If you haven’t done that, you’ll end with Gnome. In this case here is the cure:

sudo apt-get autoremove --purge gnome*
sudo apt-get install kde-standard
pixelstats trackingpixel
Posted in Howtos, Uncategorized | Leave a comment

Apple OS X virtualization with VirtualBox

A long time ago virtualizing Apple OS X was forbidden by the End User License Agreement, with the exception of Server versions of the operating system. Consequently Oracle (the maintainer of VirtualBox) was not very supportive, and many replies on the end user forum for VirtualBox still point to the then default answer.

Countless hackers spent endless nights to work around this issue, and thousands of posts offer tricks and step-by-step guides that are now mostly obsolete. Also, many of these refer to the process of virtualizing OS X on non-Apple hardware, which is illegal (so called “hackintosh”).

Two years ago, with OS X Lion (10.7) Apple started allowing users to run up to two additional instances of OS X on the same machine without a need for extra licenses. It took some time to the VirtualBox developers to pick up this fact and enhance their support for OS X guests, but with VirtualBox 4.3 released on October 15th, 2013 things start to be useable.

More precisely the following is a report on running Apple Max OS X 10.7, 10.8 and 10.9 as guests under VirtualBox 4.3.2 on a 10.7 host.

To create 10.7 and 10.8 guests, you need to extract the InstallESD.dmg from the restore image or from the installer downloaded from the iTunes store. There are step-by-step guides around to do that. You do not need to patch the InstallESD.dmg in any way.

Just go ahead and create a new VM with the correct OS type (i.e. Mac OS X) and version (i.e. Mac OS X 10.7 Lion (64 bit) or Mac OS X 10.8 Mountain Lion (64 bit)). Pick up all the default options or change RAM and disk sizes, then attach the InstallESD.dmg file to the VM’s CD/DVD.

Before you launch it, if you like you can prepare for setting the VM screen resolution to 1440×900 by executing these commands in a terminal of the host:

VBoxManage setextradata "OSX_108" "CustomVideoMode1" "1440x900x32
VBoxManage setextradata "OSX_108" "GUI/CustomVideoMode1" "1440x900x32"
VBoxManage setextradata "OSX_108" VBoxInternal2/EfiGopMode 4
VBoxManage setextradata "OSX_108" VBoxInternal2/UgaHorizontalResolution 1440
VBoxManage setextradata "OSX_108" VBoxInternal2/UgaVerticalResolution 900

(these may well be quite redundant but they’re guaranteed to work).

The install process should be slower than on bare metal, but smooth with the exception of some occasional hangs on booting (just kill the VM and retry).

When you are done, remember to turn off energy saving (set timeout to “Never”) in the system preferences as recommended here.

To complete the procedure for setting the VM screen resolution to 1440×900, execute the command:

sudo vi /Library/Preferences/SystemConfiguration/com.apple.Boot.plist

in the guest operating system, and inside the

<dict>
...
</dict>

section insert:

<key>Graphics Mode</key>
<string>1920x1080x32</string>
<key>Kernel Flags</key>
<string>"Graphics Mode"="1920x1080x32"</string>

The matter with 10.9 is different because VirtualBox does not seem to be able to start the VM from the unpatched InstallESD.dmg, even if the correct OS version is chosen (Mac OS X 10.9 Mavericks (64 bit)). The method I used was to clone a 10.8 VM and launch the installer from there.

Mandatory screenshot:

bbb

pixelstats trackingpixel
Posted in Howtos, Uncategorized | Leave a comment

Doing RPC in 2013

Some history

18 years ago I bought a book titled “Power programming with RPC”; I was surprised to see that the 1992 book is still available now ! After reading it, at the time I was really excited about RPC (Remote Procedure Call) which is indeed a useful thing to have.

But I was also very confused about how to actually implement it. Many solutions have been proposed over the years, from Sun’s Open Network Computing (ONC) which is the technology presented in that book: CORBA (who still remembers about that ?), Microsoft DCOM and .NET, SOAP, XML-RPC, JSON-RPC, Java RMI (Remote Method Invocation), the Internet Communications Engine (ICE), Autobahn

None of these seem to fit my requirements:

  • portability: it should work with almost any combination of client-server choosen among HTML5 browser, browser OS, mobile OS (just to name three of them: Android, iOS, WP8), desktop OS (just to name three of them: Windows, Max OS X, Linux)
  • patent-free
  • open source, non-pure-GPL, C++ implementations available
  • defaulting to a low-overhead, zero-configuration protocol when the RPC is invoked between a client and a server which run locally as separate processes on the same device.

In exchange for those, I can live without discovery and an Interface Description Language (IDL).

Enter Qt and QJsonRpc

But wait, since RPC is basically calling remote procedures on a server by sending over strings, Qt’s meta object system is a good basis to build on: it is portable, it has reflection to pick up the method to call from the string, it provides signals-slots to implement call-backs, it has a variant type. Qt also provides interexchangable QTcpSocket for two-way connections over the network and QLocalSocket for local connections (QLocalSocket uses a named pipe on Windows and a local domain socket on Unix).

While musing about those facts, I stumbled upon QJsonRpc, a Qt implementation of the JSON-RPC protocol available here. It is compatible with both Qt4 and Qt5, and it is licensed under the LGPLv2.1. It is developed by devonit, an innovative firm which BTW has just introduced a smart new device which plugs into the HDMI port of any monitor and transforms it into a thin client.

There is not much documentation around on QJsonRpc so to understand what this thing does, let’s try it out – here is how I did on Debian wheezy with Qt4 and on jessie with Qt5;  to set-up on a fresh install of Debian jessie, do this:

sudo apt-get install qtbase5-dev g++

Then:

wget https://bitbucket.org/devonit/qjsonrpc/get/81c851a5c77a.zip
unzip 81c851a5c77a.zip
cd devonit-qjsonrpc-81c851a5c77a/

If you are using Qt4, issue:

qmake

whereas on jessie to use Qt5, do:

/usr/lib/i386-linux-gnu/qt5/bin/qmake)

Then:

make
cd tests/manual
cat > ./localserver/runserver
#!/bin/bash
/lib/ld-linux.so.2 --library-path ../../src ./localserver/server
^D
chmod u+x ./localserver/runserver
cat > ./qjsonrpc/runqjsonrpc
#!/bin/bash
/lib/ld-linux.so.2 --library-path ../../src ./qjsonrpc/qjsonrpc $@
^D
chmod u+x ./qjsonrpc/runqjsonrpc
cat > ./localclient/runclient
#!/bin/bash
/lib/ld-linux.so.2 --library-path ../../src ./localclient/localclient
^D
chmod u+x ./localclient/runclient

Now start the local server:

./localserver/runserver

then open a new console and start the local client:

./localclient/runclient

The local client will print this:

response received: QJsonRpcMessage(type=QJsonRpcMessage::Response, id=1, result=QVariant(, ) )
response received: QJsonRpcMessage(type=QJsonRpcMessage::Response, id=2, result=QVariant(, ) )
response received: QJsonRpcMessage(type=QJsonRpcMessage::Response, id=3, result=QVariant(, ) )
response received: QJsonRpcMessage(type=QJsonRpcMessage::Response, id=4, result=QVariant(QString, "Hello matt") )

whereas the localserver will print this:

void TestService::testMethod() called
void TestService::testMethodWithParams(const QString&, bool, double) called with parameters:
first: "one"
second: false
third: 10
void TestService::testMethodWithVariantParams(const QString&, bool, double, const QVariant&) called with variant parameters:
first: "one"
second: false
third: 10
fourth: QVariant(double, 2.5)
QString TestService::testMethodWithParamsAndReturnValue(const QString&) called

To better understand what is going on, look into the code ! For example the key client-side code for the last request is (let’s skip error handling for ease of understanding):

QJsonRpcSocket *m_client = new QJsonRpcSocket(socket, this);
QJsonRpcServiceReply *reply = m_client->invokeRemoteMethod("agent.testMethod");
reply = m_client->invokeRemoteMethod("agent.testMethodWithParamsAndReturnValue", "matt");
connect(reply, SIGNAL(finished()), this, SLOT(processResponse()));

and the call-back:

void LocalClient::processResponse() {
  QJsonRpcServiceReply *reply = static_cast<QJsonRpcServiceReply *>(sender());
  qDebug() << "response received: " << reply->response();
}

whereas the key server-side code is:

TestService service;
QJsonRpcLocalServer rpcServer;
rpcServer.addService(&service);
rpcServer.listen(serviceName);

and the server-side implementation of the testMethodWithParamsAndReturnValue method:

QString TestService::testMethodWithParamsAndReturnValue(const QString &name) {
  return QString("Hello %1").arg(name);
}

Now shut down the client by hitting ^C in the client console, then launch the command-line client:

./qjsonrpc/runqjsonrpc testservice agent.testMethod

this will print:

QVariant(, )

or on Qt5:

QVariant(Invalid)

whereas

./qjsonrpc/runqjsonrpc testservice agent.testMethodWithParamsAndReturnValue matt

will print:

QVariant(QString, "Hello matt")

The command-line interface is only able to connect to a local server, but as to the server / client, there is also a demo over TCP on port 5555.
If we diff the localclient (using Qt’s QLocalSocket) and the tcpclient (using QTcpSocket), there are very few differences, the main one is:

< QLocalSocket *socket = new QLocalSocket(this);
< socket->connectToServer(serviceName);
---
> QTcpSocket *socket = new QTcpSocket(this);
> socket->connectToHost(QHostAddress::LocalHost, 5555);

where serviceName is a QString obtained by calling QDir::absoluteFilePath on the file /tmp/testservice.

Diffing the server also shows very few differences, the main one is:

< if (!rpcServer.listen(serviceName)) {
---
> if (!rpcServer.listen(QHostAddress::LocalHost, 5555)) {

and the testservice implementation is actually the same !

Enter Websockets and QWebSockets

Now connecting over a WAN over port 5555 with a custom protocol calls for firewall troubles. Your IT people will complain they have to open new ports and your customer’s antivirus will harass them. Also no other application on earth will talk to your server.

Better use Websockets, a web technology providing full-duplex communications channels over a single TCP connection over port 80, configured as an upgrade to the HTTP protocol, and compatible with a number of browsers (Google Chrome, Internet Explorer, Firefox, Safari and Opera) which can act as clients if you develop an HTML5 interface.

And lo ! I stumbled upon QWebSockets, a pure Qt implementation of client and server WebSockets; it has no other dependencies that Qt5 and it is licensed under LGPL v2.1. One painful limitation is that it currently lacks the WSS protocol (the secure version of the ws:// protocol); but since it’s open-source, maybe somebody will care to implement it !

Here is how I tried it out on Debian jessie with Qt5:

wget https://codeload.github.com/KurtPattyn/QWebSockets/legacy.tar.gz/master
tar xzf KurtPattyn-QWebSockets-v0.9.0-97-g2f6831e.tar.gz
cd KurtPattyn-QWebSockets-2f6831e
/usr/lib/i386-linux-gnu/qt5/bin/qmake
make

now let’s test the provided example:

cd examples
./echoserver/echoserver

prints:

Echoserver listening on port 1234

then in a new console:

./echoclient/echoclient

prints:

Websocket connected
Message received: "Hello, world!"

Both libraries are LGPL licensed, so it would be great to set up a QJsonRpcWebServer based on the QJsonRpcTcpServer from QJsonRpc, to use the QWebSocketServer from QWebSockets in place of Qt’s builtin QTcpServer.

pixelstats trackingpixel
Posted in Philosophy, Uncategorized | 3 Comments