domingo, 17 de septiembre de 2017

Including a Jenkins link in the crashlytics report

I've been implementing some mobile application automatic tests using appium (appium.io). We also use Jenkins (https://jenkikns.io) as continuous integration tool. We compile and test the applications as Jenkins jobs. The apps include crashlytics (https://try.crashlytics.com/) to send a report everytime the application crashes. We are thinking it would be good to know the crash report was generated by a jenkins job and have a link to the offending job, so we can access all the logs that are stored as Jenkins artifacts. This how we do it. First we obtain the job url via Jenkins environment variables. This is the python code:

jenkins_url = os.environ ("JENKINS_URL") + "/job/" + os.environ ("JOB_NAME") + \
          "/" + os.environ ("BUILD_NUMBER")
Then we instruct appium to pass this url as an environment varaible to the application as desired capabilities. iOS

args = { "args": [], "env" : { "JENKINS_URL": jenkins_url }}
desired_caps["processArguments"] = json.dumps (args)
Android

desired_caps ["optionalIntentArguments"] = '--es "android.intent.extra.JENKINS_URL" ' +  '"' + \
        jenkins_url + '"'
Then, we read the value of the variable inside application code and set it as a crashlytics key. swift (iOS):

       NSString *jenkinsUrl = environment  [@"JENKINS_URL"];
       if  (jenkinsUrl) {
            [CrashlyticsKit setObjectValue:jenkinsUrl forKey:@"JENKINS_URL"];
       }
Java (android):

Intent intent = getIntent ();
String jenkins_url = intent.getStringExtra ("android.intent.extra.JENKINS_URL");

if (jenkins_url != null) {
    Crashlytics.setString ("JENKINS_URL", jenkins_url);
}

viernes, 10 de febrero de 2017

Using two irtrans USB devices in one Ubuntu PC.

IRTrans is a little USB device to capture and send IR commands (like a remote control).

The irtrans USB device documentation states that "Individual control of multiple external transmitters is not possible". The reason for that is the provided irtrans server (irserver64) listen to two predefined ports (21000 for the irtrans protocol and 8765 for the lirc protocol). When the second server tries to bind to any of these ports it fails because the ports are already taken.

There is a workaround for this problem using docker containers. The simple idea is, we launch two servers in two separated containers and we configure these with a different IP address.

The first thing we need to do is to install docker in our Ubuntu computer. See here how to do that.

The we need to create our container. In an empty directory we copy:
  •  the irserver64 file. 
  •  the remotes/ directory, containing a number of files with the keypresses of the remotes we want to simulate. 
  • a file called Dockerfile with the following content: 


FROM ubuntu:16.04

RUN mkdir /irtrans
RUN mkdir /irtrans/remotes

COPY irserver64 /irtrans
COPY remotes/file.rem /irtrans/remotes

WORKDIR /irtrans
ENTRYPOINT ["./irserver64"]
From this directory we can compile our container with (irtrans.1 is an arbitrary name we give to our container):

dockebuild -t irtrans.1 .
Then we need to create our docker network.

docker network create --subnet=172.18.0.0/16 mynet123=
And now we can run two containers in different ip addresses. Remember to give the container access to the serial port:

docker run --net mynet123 --ip 172.18.0.22 --device=/dev/ttyUSB0 irtrans.1 /dev/ttyUSB0
docker run --net mynet123 --ip 172.18.0.23 --device=/dev/ttyUSB2 irtrans.1 /dev/ttyUSB2

domingo, 8 de enero de 2017

Qtest + google mock

The problem we are trying to solve is using google mocks with qtest. Since we don't use google test we need to replace the default event listener so we can fail the test with qt macros. We overwrite the OnTestPartResult. Then we create a macro to initialize all our tests the same way. unittest.h:
/**
 * \file
 * \brief Generic definitions for unit tests.
 */

#ifndef __UNIT_TESTS_H__
#define __UNIT_TESTS_H__

#include 
#include "gmock/gmock.h"

namespace unittests {

/**
 * \brief A class to replace qtest default event listener. 
 * 
 * The relevant thing here is the OnTestPartResult method. We need to change it
 * to fail the tests, at qtest level, when the expectations fail.
 *
 * This function gets called when we call the destructor of the mocks or the
 * ::testing::Mock::VerifyAndClearExpectations function.
 */
class GoogleTestEventListener : public ::testing::EmptyTestEventListener {
   virtual void OnTestStart(const ::testing::TestInfo&) {
   }

   virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result) {
        if (test_part_result.failed()) {
            QFAIL(
                QString("mock objects failed with '%1' at %2:%3")
                    .arg(QString(test_part_result.summary()))
                    .arg(test_part_result.file_name())
                    .arg(test_part_result.line_number())
                    .toLatin1().constData()
            );
        }
   }

   // Called after a test ends.
   virtual void OnTestEnd(const ::testing::TestInfo&) {
   }
};

} // namespace unittests

/**
 * \def INIT_GOOGLE_MOCKS (argc, argv)
 * \brief A macro that defines the unit test initialization. 
 *
 * We define the initialization process in one place.
 * This only really needed when using google mocks expectations.i.e. if your
 * test uses EXPECT_CALL.
 */
#define INIT_GOOGLE_MOCKS(argc, argv) { \
      ::testing::InitGoogleTest (&(argc), (argv)); \
      ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();  \
      delete listeners.Release(listeners.default_result_printer());\
      listeners.Append(new unittests::GoogleTestEventListener); }

#endif // __UNIT_TESTS_H__
And now an example on how to use it. First we have a class called classToTest. classToTest.h:
#ifndef __CLASS_TO_TEST__
#define __CLASS_TO_TEST__

#include "dependency.h"

class ClassToTest 
{
public:
    ClassToTest (Dependency *dep);
    ~ClassToTest ();

    int function1 (int param);
private:
    Dependency * _dependency;
};

#endif //__CLASS_TO_TEST__
classToTest.cpp:
#include "classToTest.h"

ClassToTest::ClassToTest (Dependency *dep)
{
    _dependency = dep;
}

ClassToTest::~ClassToTest ()
{
}

int ClassToTest::function1 (int param)
{
    return (_dependency->getValue (param));
}
The class uses the following dependency. dependency.h:
#ifndef __DEPENDENCY_H__
#define __DEPENDENCY_H__

class Dependency 
{
public:
    virtual int getValue (int inValue) = 0;

};

#endif // __DEPENDENCY_H__
This is how the test looks like: MyTest.h:
#ifndef __SECOND_TEST_H__
#define __SECOND_TEST_H__

#include 

class MyTest: public QObject
{
    Q_OBJECT
private slots:
    void test1 ();
};

#endif //__SECOND_TEST_H__
MyTest.cpp:
#include "classToTest.h"
#include "unittests.h"
#include "MyTest.h"
#include "gmock/gmock.h"

class MockDependency: public Dependency 
{
public:
    MOCK_METHOD1 (getValue, int (int inValue));
};

void MyTest::test1 ()
{
    MockDependency dep;

    EXPECT_CALL (dep, getValue (13))
        .Times (1)
        .WillOnce(::testing::Return(7));

    ClassToTest C (&dep);

    QCOMPARE (C.function1 (13), 7);
}

int main (int argc, char **argv)
{
    INIT_GOOGLE_MOCKS (argc, argv);

    MyTest *theTest = new MyTest ();
    return (QTest::qExec (theTest, argc, argv));
    delete theTest;
}
Finally, I've included the cmake/ctest script in case you want to compile the example. CMakeLists.txt:
cmake_minimum_required (VERSION 2.8.11)

enable_testing ()
project (ppral CXX)

add_subdirectory (googletest-master/googlemock)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package (Qt5Core REQUIRED)
find_package (Qt5Test REQUIRED)

# Add the include directories for the Qt 5 Widgets module to
# the compile lines.
include_directories(${Qt5Core_INCLUDE_DIRS} )
include_directories(googletest-master/googlemock/include)
include_directories(googletest-master/googletest/include)
# Add compiler flags for building executables (-fPIE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS} ")

qt5_wrap_cpp (classToTest.cpp classToTest.h Dependecy.h unittests.h
 MyTest.h MyTest.cpp)

add_executable (MyTest classToTest.cpp classToTest.h MyTest.h
    MyTest.cpp unittests.h dependency.h)
target_link_libraries (MyTest ${Qt5Core_LIBRARIES} ${Qt5Test_LIBRARIES} 
    gmock gtest)
add_test (NAME MyTest COMMAND MyTest) 

sábado, 25 de abril de 2015

wxPython double slider widget to enter a range.

I had this problem to enter a range of times in a wxPython application. After some research I could not found a widget that does what I need. The closest I could get was a Slider with SL_SELRANGE
style. Unfortunatelly this option is only available in Windows.

So I decide to create a small widget with two sliders to select the maximum and minimum time. If the minimum goes over the maximum the maximum is updated and viceversa. The selected values are updated as labels.





This is the code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

class RangeSlider (wx.Panel):
    MAX_VALUE = 1000

    def __init__ (self, parent, minTime, maxTime):
        super(RangeSlider, self).__init__(parent, wx.ID_ANY)

        self.minTime = minTime
        self.maxTime = maxTime

        sizer = wx.FlexGridSizer (rows=2, cols = 3, vgap = 5, hgap = 5)
        self.sldMax = wx.Slider(self, value=RangeSlider.MAX_VALUE, minValue=0,
                maxValue=self.MAX_VALUE,
                style=wx.SL_HORIZONTAL )
        self.sldMin = wx.Slider (self, value=0, minValue=0,
                maxValue=self.MAX_VALUE,
                style =wx.SL_HORIZONTAL )

        self.sldMax.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        self.sldMin.Bind (wx.EVT_SCROLL, self.OnSliderScroll2)

        self.txtMax = wx.StaticText(self, label= self.formatTime (self.maxTime))
        self.txtMin = wx.StaticText(self, label=self.formatTime (self.minTime))

        lab1 = wx.StaticText (self, label="Min " + self.formatTime (self.minTime))
        lab2 = wx.StaticText (self, label="Max " + self.formatTime (self.maxTime))

        sizer.Add (lab1, 0, wx.LEFT, 10)
        sizer.Add (self.sldMax, 1, wx.EXPAND)
        sizer.Add (lab2, 0, wx.RIGHT, 10)
        sizer.Add (self.txtMin, 1, wx.ALIGN_CENTER)
        sizer.Add (self.sldMin, 1, wx.EXPAND)
        sizer.Add (self.txtMax, 1, wx.ALIGN_CENTER)
        sizer.AddGrowableCol (1, 1)

        self.SetSizer (sizer)

    def formatTime (self, t):
        return "%02d:%02d:%02d" % (t / 3600, (t%3600)/60, t%60)

    def formatValue (self, v):
        t = v * (self.maxTime - self.minTime) / 1000
        return self.formatTime (t)


    def OnSliderScroll(self, e):

        val = self.sldMax.GetValue()

        valMin = self.sldMin.GetValue ()
        if valMin > val:
            self.sldMin.SetValue (val)
            self.txtMin.SetLabel (self.formatValue(val))

        self.txtMax.SetLabel(self.formatValue(val))

    def OnSliderScroll2 (self, e):
        val = self.sldMin.GetValue()

        valMax = self.sldMax.GetValue ()
        if valMax < val:
            self.sldMax.SetValue (val)
            self.txtMax.SetLabel (self.formatValue(val))

        self.txtMin.SetLabel(self.formatValue(val))


class Example(wx.Frame):

    def __init__(self, parent, minTime, maxTime):
        """ The time is seconds """
        super(Example, self).__init__(parent, wx.ID_ANY)


        self.InitUI(minTime, maxTime)


    def InitUI(self, minTime, maxTime):

        rangeSlider = RangeSlider (self,minTime, maxTime)

        self.SetTitle('RangeSlider')
        self.Centre()
        self.Show(True)

def main():

    ex = wx.App()
    Example(None, 0, 7200)
    ex.MainLoop()

if __name__ == '__main__':
    main()



jueves, 9 de abril de 2015

Timedoctor Visualizer. An application to analyze timedoctor files.

Recently I needed to analyze some linux execution tasks and interrupt traces and I could not find a tool to do what I wanted so I created my own.

The timedoctor files show the begining and end time of each task executed by a CPU. This is a quite usefull tool to analyze errors in embedded systems, like deadlock, priority inversions...

The tool has two main windows the first one shows the existing tasks in one file and allows to sort, select and deselect each of them. More than one file can be analyzed at the same time.

The other windows allows to visualize the time of execution of the selected tasks in the time. The window allows to pan, zoom and save an image with the graph.

The application was implemented in python and it uses wxPython for the user interface and matplotlib for the plots. I've made it run on Linux, Windows and Mac. The tool can be downloaded from here:

http://github.com/rgonzalez72/tdv

lunes, 6 de abril de 2015

Managing id tags in mp3 files with eyed3.

This is a problem I solved some time ago but after updating to the lastest library I discovered the interface has changed. Setting the tags is quite straightforward following the instructions in here: http://eyed3.nicfit.net/. It wasn't so easy for me to figure out how to attach and image to an mp3 file.
This is the solution I found:

import eyed3

audiofile = eyed3.load (fileName)
if audiofile.tag == None:
    audiofile.tag = eyed3.id3.Tag ()
    audiofile.file_info = eyed3.id3.FileInfo (fileName)


audiofile.tag.artist = artist
audiofile.tag.title = unicode (title)
audiofile.tag.genre = unicode (genre)
img_fp = open (file_path, "rb")

# The type of image, the content of the jpg file, mime type, description
audiofile.tag.images.set(eyed3.id3.frames.ImageFrame.FRONT_COVER,
                img_fp.read(), "image/jpeg", u" ")
audiofile.tag.save (filename=fileName, version=eyed3.id3.ID3_V2_3)

domingo, 15 de marzo de 2015

Heads up Omaha. An artificial inteligence example.

This entry describes the implementation of the Bot I entered to the "Heads up Omaha" competition (http://theaigames.com/competitions/heads-up-omaha). This is basically a competion between IA robots playing poker (Omaha). I was a bit surprised to make to the semifinals considering the little efford I put on it so I decided to explain the simple solution I found.

 I put the code in here:
 https://github.com/rgonzalez72/omaha

This is how I did it step by step. I wrote the bot using object oriented python.

Basic classes 

I created a number of classes to deal with the poker card. They are Suit, Height, Card, Hand and Maze. These classes are simple enough and they don't require further explanation.

Hand evaluation

The class Evaluate performs the evaluation of the hands. I copied the evaluation functions from the "getting started" code of the competion. The trick here is representing every hand and the rank as a 32 bit map in a way they can be compared. This is done in the eval5 function.

There is another function called eval9 that calculates the best score considering the four card in the hand and the five on the table  according to the Omaha rules. That is why we need the getCouples and getTrios functions in the Hand class.

Probabilities calculation 

This section describes how the probabilities of my hand is calculated. We'll I don't, I just estimate them after running a number of random games and counting the winning and losing hands. This is done in the calProbabilies function.

Fuzzy logic implementation

We have all the basic poker functionallity implemented so far. What we need now is to define the strategy. I decided to use fuzzy logic for the simple reason that I had never used it before and wanted to become familiar with it. First I was considering using some library but I could not be sure the library would be available in the competition servers so I implemented my basic fuzzy logic module.
The module defines fuzzy variables and operators. The variables can be triangles or trapezoids. The inputSet and outputSet classes are arrays of variables.

Fuzzy logic rules

Finally, with all the elements described, we can't define the rules that make our program "intelligent".

Type of game 

The first set of input rules we define is the number of chips in the pot that can be FEW, AVERAGE, LOTS. Depending on the number of chips we change the way we play that can be SUICIDAL, AGGRESIVE, CAUTIOUS and CONSERVATIVE. The rules are defined in GameTypeCalculator.

This strategy proved to be not too good and was later dropped the Bot is always AGGRESIVE.

ActionCalculator

The action calculator uses two inputSet: the game type and the hand probability. The hand probability can be VERY GOOD, GOOD, REGULAR and BAD. The goodness of the hand based on the probability is different in the phases of the game, that is why we have defined different ranges for pre-flop, flop, turn and river. The output set is the action: FOLD, CALL, RAISE MIN, RAISE MED, RAISE MAX. Please see ActionCalculator class and its children for details.

And that is, the rest of code is used to deal with the Bot interface. We've implemented a reasonable poker player in 1200 lines of code.