Boost сериализация и QString

Время от времени кому то в голову приходит мысль использовать boost сериализацию в проектах с Qt. Тут встает вопрос как быть со строками, т.к. хочется просматривать  и редактировать.

Просто приведу пример кода без объяснений, думаю что все и так знают как можно работать с юникодом

namespace boost
{
    namespace serialization
    {

        template<class Archive>
        inline void save(Archive& ar, const QString& s,
                const unsigned int /*version*/)
        {
            auto ba = s.toUtf8();
            std::string str(ba.data(), ba.size());

            ar << make_nvp("QString", str);
        }

        template<class Archive>
        inline void load(Archive& ar, QString& s,
                const unsigned int /*version*/)
        {
            std::string str;
            ar >> make_nvp("QString", str);
            QByteArray ba(&str[0], str.size());
            s.append(ba);
        }

        template<class Archive>
        inline void serialize(Archive& ar, QString& s,
                const unsigned int file_version)
        {
            boost::serialization::split_free(ar, s, file_version);
        }
    }
}

Qt+GTest функциональное тестирование сетевых компонентов

Для тех кто не знает, что такое GTest отправляю на wiki: Google C++ Testing Framework(рус.). И путь вас не смущает, что это библиотека для модульного тестирования.

Использование фреймворка семейства xUnit, для функционального тестирования пришло в голову, когда реализовывал REST интерфейс к конфигурации Service Quality Management, в разработке которой я принимаю участие(на момент написания заметки). Это приложение на PHP с использованием SLIM, json-schema. PHPUnit использовался для автоматизированного тестирования функциональности. Косвенно тестировалась работа с базой, которая не тестируется при модульном тестировании. Все медленные операции(дисковые, взаимодействие с базой данной), а так же ненадежные операции(обрыв сети) заменяются специальной прослойкой и  mock-объектами.

Заканчиваю отступление и перехожу к теме. Сейчас развлекаюсь с MBaaS(mobile backend as a service) решением от QuickBlox. Что бы быть уверенным, что делаю все правильно, а так же для изучения поведения, стал писать тесты.

Еще одно отступление. В соответствие с книгой «Непрерывная интеграция: улучшение качества программного обеспечения и снижение риска» вместе с модульными тестами, можно размещать любые другие автоматические тесты, и если эти тесты довольно долго выполняются, то следует их выполнять по расписанию.

При использования Qt+GTest иногда требуется использовать свой код запуска тестов, т.к. внутри Qt используются то ли синглетоны, то ли статические переменные, которые должны быть инициализированы.

#include <QtCore/QCoreApplication>

#include "gtest/gtest.h"

int main(int argc, char** argv)
{
	QCoreApplication app(argc, argv);
	::testing::InitGoogleTest(&argc, argv);
	 return RUN_ALL_TESTS();
}

Дальше используется привычное сочетание с QEventLoop(для него и нужен был инстанс QXXXApplication)
Пример запуска сессии:

#include "Auth.h"
#include "QBloxGlobal.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop>

#include "gtest/gtest.h"

using namespace QBlox;

TEST(Auth, startSession)
{
	Auth auth(QBLOX_API_SERVER, QBLOX_AUTH_KEY, QBLOX_AUT_SECRET, QBLOX_APP_ID);

	auth.startSession();

	QEventLoop loop;
	QObject::connect(&auth, &Auth::sessionStarted,
			&loop, &QEventLoop::quit);
	loop.exec();
	const auto token = auth.token();

	ASSERT_FALSE(token.isEmpty());
}

libmemcached & C++

LibMemcached один из клиентов реализующий протокол сервера кэширования в памяти memcached, который используется в распределенной базе данных MemcacheDB.

Memcached/MemcacheDB это хранилища типа ключ-значение, поэтому MemcacheDB является NoSQL базой данных.

LibMemcached предоставляет api как для Си, так и Cи++.

Api для C++ представлен в виде класса memcache::Memcache, который подключается через заголовочный файл

#include <libmemcached/memcached.hpp>

Небольшая ремарка по представлению ключ-значение. Ключ представлен обычной строкой(std::string), значение представляется в виде последовательности символов

Описание некоторых методов классов:

  • Memcache (const std::string &config) конструктор, на вход строка конфигурации;
  • Memcache (const std::string &hostname, in_port_t port) конструктор, на вход подается хост и порт сервера memcached/db;
  • bool error (std::string &error_message) const, bool error () const получение информации об ошибке;
  • bool setBehavior (memcached_behavior_t flag, uint64_t data) установить поведение, к примеру setBehavior(MEMCACHED_BEHAVIOR_NO_BLOCK,1);
  • uint64_t getBehavior (memcached_behavior_t flag) получить поведение;
  • bool configure (const std::string &configuration) задать конфигурацию;
  • bool addServer (const std::string &server_name, in_port_t port) добавить сервер;
  • bool add (const std::string &key, const std::vector<char> &value) добавить пару ключ-значение, если такой ключ уже имеется возвращает false;
  • bool replace (const std::string &key, const std::vector< char > &value) заменяет значение по ключу, этот метод успешен только тогда, когда есть объект на сервере;
  • bool set (const std::string &key, const std::vector<char> &value, time_t expiration, uint32_t flags) добавляет или перезаписывает значение по ключу. expiration вроде как определяет время жизни, flags дополнительные флаги;
  • bool set (const std::string &key, const char *value, const size_t value_length, time_t expiration, uint32_t flags) то же самое, но вместо вектора передается const chat*;
  • bool get (const std::string &key, std::vector<char> &ret_val) получить значение по ключу. Если значения нет, возвращает false;