28 września 2012

Konstruktor a SetUp (Google Test)

Chciałem się dowiedzieć jak właściwie działa metoda SetUp(), dla klas testów w konfrontacji z konstruktorem takiej klasy.
#include <gmock/gmock.h>
#include <stdio.h>

using namespace ::testing;

class SimpleTest : public Test
{
public:
    SimpleTest() {
        std::cout << "Constructor()" << std::endl;
    }

    void SetUp() {
        std::cout << "SetUp()" << std::endl;
    }

    void TearDown() {
         std::cout << "TearDown()" << std::endl;
    }

    ~SimpleTest() {
        std::cout << "Destructor()" << std::endl;
    }
};

TEST_F(SimpleTest, test1)
{
    std::cout << "test1 " << std::endl;
}

TEST_F(SimpleTest, test2)
{
    std::cout << "test2 " << std::endl;
}

int main(int argc, char *argv[])
{
    ::testing::InitGoogleMock(&argc, argv);
    return RUN_ALL_TESTS();
}
Najwyraźniej każde makro TEST_F, tworzy klasę dziedziczącą z naszej klasy testującej. SetUp() oraz Constructor() wołane są za każdym razem przed rozpoczęciem testu. Odpowiednio TearDown() oraz Destructor(), także wołane są na końcu każdego testu.
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from SimpleTest
[ RUN      ] SimpleTest.test1
Constructor()
SetUp()
test1 
TearDown()
Destructor()
[       OK ] SimpleTest.test1 (0 ms)
[ RUN      ] SimpleTest.test2
Constructor()
SetUp()
test2 
TearDown()
Destructor()
[       OK ] SimpleTest.test2 (0 ms)
[----------] 2 tests from SimpleTest (1 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (4 ms total)
[  PASSED  ] 2 tests.

GoogleTest/Mock instalacja

Piekło zamarzło, nie udało mi się zainstalować narzędzi "Google Mock" i "Google Test" z repozytorium Ubuntu ("google-mock", "libgtest-dev"). Tzn. udało się, ale nijak nie zrozumiałem jak z linkować to co dostałem z moim projektem/testem. Według nich powinienem zadziałać skryptem (gtest-config), tylko gdzie go można znaleźć...?
g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
g++ $(gtest-config --ldflags --libs) -o foo foo.o
W ramach kompilacji chciałem przeprowadzić standardowe budowanie ze skryptów make. Wpierw okazało się, że autoconf/make(?) nie jest już wspierany (albo odradzany), i że powianiem skorzystać z CMake. Tak też uczyniłem, lecz to co zostało wyplute, nijak nie chciało współgrać z linkerem.

Skończyło się ręcznym kompilowaniu bibliotek. Wpierw ustawiłem sobie kilka zmiennych środowiskowych, żeby było bardziej przejrzyście.
export GMOCK_DIR=~/Downloads/gmock-1.6.0/
export GTEST_DIR=~/Downloads/gmock-1.6.0/gtest/
export GMOCK_INCLUDE=~/Downloads/gmock-1.6.0/include/
export GTEST_INCLUDE=~/Downloads/gmock-1.6.0/gtest/include/
export GMOCK_LIB=~/Downloads/gmock-1.6.0
Kompilacja do statycznych bibliotek
g++ -I${GTEST_INCLUDE} -I${GTEST_DIR} -I${GMOCK_INCLUDE} \
    -I${GMOCK_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
g++ -I${GTEST_INCLUDE} -I${GTEST_DIR} -I${GMOCK_INCLUDE} \
    -I${GMOCK_DIR} -c ${GMOCK_DIR}/src/gmock-all.cc
ar -rv libgmock.a gtest-all.o gmock-all.o
Prosty test:
#include <gtest/gtest.h>

using namespace testing;

int main()
{
    EXPECT_EQ(1, 2);
    return 0;
}
I wreszcie kompilacja testu:
g++ -I${GTEST_INCLUDE} -I${GMOCK_INCLUDE} \
    main.cpp ${GMOCK_LIB}/libgmock.a -lpthread -o main
Oraz wynik:
$ ./main 
main.cpp:7: Failure
Value of: 2
Expected: 1

Zasada Pareto

http://pl.wikipedia.org/wiki/Zasada_Pareto



Drugą cześć zasady sobie dopowiedziałem. A tymczasem Hello Google Chart Tools.

19 września 2012

FL like Flame

Ciekawa analiza serwera C&C obsługującego Flame-a:
http://www.securelist.com/en/blog/750/Full_Analysis_of_Flame_s_Command_Control_servers

Zauważyłem, że dla initialization vector (IV) została wybrana nielosowa wartość (co jest generalnie zalecane).
IV: 12345678
Zazwyczaj w systemach kryptograficznych wszyscy drżą, o każdy detal, który mógłby osłabić całość. Tutaj nie ma to żadnego znaczenia, skoro ten klucz już ktoś odczytał. Ponadto w trybie CBC, klucz ten nie musi być utrzymywany w tajemnicy.

Druga sprawa, to złamanie hasła za-hashowanego za pomocą MD5.
Password hash (MD5): 27934e96d90d06818674b98bec7230fa

(ok, cracked: 900gage!@#)
Nie jest to obecnie zalecana metoda tworzenie funkcji skrótu. Jak widać dość skomplikowane 10 literowe, zostało odkryte, choć nie ma informacji, czy czy to dzięki słabościom MD5, czy może era tak krótkich haseł już minęła.

Takie tam ... dzień bez, zawiści, dniem straconym ;)

17 września 2012

Kopiowanie kluczy mapy

Szukałem ładnego sposobu na wydobycie kluczy z mapy, tak by nie tworzyć pętli for iterującej po mapie i przepisującej wartość it->first do jakiegoś kontenera. Na szczęście okazało się, że biblioteka boost oferuje gotowy przykład:
http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/adaptors/reference/map_keys.html

Jest to zastosowanie wzorca projektowego "adapter". Wykorzystuje on i przekształca istniejący interfejs w taki jakiego oczekuje klient. Tutaj Range iterator zostaje owrapowany w ten sposób, że nowy iterator, zwraca to czego oczekujemy.
#include <boost/range/adaptor/map.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <map>
#include <vector>

int main()
{
    std::map<std::string, int> m;
    m["first"] = 301;
    m["second"] = 302;
    m["third"] = 54;

    std::vector<std::string> v;
    boost::push_back(v, m | boost::adaptors::reversed
                          | boost::adaptors::map_keys);

    boost::push_back(v,
                     boost::adaptors::keys(
                         boost::adaptors::reverse(m)));

    BOOST_FOREACH(std::string& s, v)
    {
        std::cout << s << std::endl;
    }

    return 0;
}
Istnieją dwa sposoby na stworzenia adaptera, pierwsza z wykorzystaniem operator|(), druga to skorzystanie z metod. Wygląda na to, że kolejność nakładanie adapterów nie ma znaczenia. Ale to trzeba doczytać, albo przetestować jeszcze.

Dodatkowo wszystkie klucze wpisuje w odwrotnej kolejności. A oto wynik
third
second
first
third
second
first

15 września 2012

Boost.Tuple jako klucz mapy

Ostatnio próbowałem wykorzystać obiekt krotki, jako klucz std::map. Jak się okazało kompilator zaprotestował
#include <string>
#include <map>
#include <boost/tuple/tuple.hpp>

int main()
{
    std::map<boost::tuple<int, bool, std::string>, int> m;

    boost::tuple<int, bool, std::string> key(2, false, "asdf");
    m[key] = 44;

    return 0;
}
Protest - kompilator skarży się, że boost::tuple (nasz klucz) nie posiada operatora less.
/usr/include/c++/4.6/bits/stl_function.h:236:22: error: no match for ‘operator<’ in ‘__x < __y’
Po zbadaniu problemu okazało się, że trzeba do-includować poniższą linijkę.
#include <boost/tuple/tuple_comparison.hpp>

14 września 2012

Boost.Foreach

Często w książkach można spotkać konstrukcję pętli for, której zadaniem jest prze-iterowanie po jakimś kontenerze. Wtedy warunek zakończenia pętli wygląda najczęściej tak:
it != v.end()
Jeżeli jednak nasz kod z pętli nie usuwa, dodaje, przemieszcza (?) obiektów w kontenerze, można pokusić się o bardziej optymalne rozwiązanie, bowiem metoda end(), będzie wołana na początku każdego rozpoczęcia pętli.
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>

template <typename T>
class Vec : public std::vector<T>
{
public:
    typename std::vector<T>::iterator begin()
    {
        std::cout << "begin()" << std::endl;
        return std::vector<T>::begin();
    }
    typename std::vector<T>::iterator end()
    {
        std::cout << "end()" << std::endl;
        return std::vector<T>::end();
    }
};

int main()
{
    Vec<int> v;
    v.push_back(10);
    v.push_back(45);
    v.push_back(6);

    for (Vec<int>::iterator it = v.begin(); it != v.end(); ++it)
    {
        std::cout << "value: " << *it << std::endl;
    }

    return 0;
}
Wynik
begin()
end()
value: 10
end()
value: 45
end()
value: 6
end()
Wypadało by więc, zapisać sobie na boku wartość zwracaną przez end i z takiej wartości korzystać podczas sprawdzania warunku końca pętli. Minus - kod strasznie puchnie - rozwiązanie BOOST_FOREACH()
int main()
{
    Vec<int> v;
    v.push_back(10);
    v.push_back(45);
    v.push_back(6);

    BOOST_FOREACH(int i, v)
    {
        std::cout << "value " << i << std::endl;
    }

    return 0;
}

A oto wynik - z jednym wołaniem metody end()
begin()
end()
value 10
value 45
value 6