sysdep.h moved to endianhelper.h for MsgPackStream

MsgPackStream integers fixed (unpack_upto_* removed, bad idea)
MsgPackStream::test_array added
This commit is contained in:
Isaikin Roman
2015-06-10 17:42:06 +03:00
parent 9e61498ca2
commit 318aa870cd
11 changed files with 199 additions and 221 deletions

View File

@ -1,5 +1,5 @@
set(qmsgpack_srcs msgpack.cpp msgpack_common.cpp stream.cpp private/pack_p.cpp private/unpack_p.cpp private/qt_types_p.cpp) set(qmsgpack_srcs msgpack.cpp msgpack_common.cpp stream.cpp private/pack_p.cpp private/unpack_p.cpp private/qt_types_p.cpp)
set(qmsgpack_headers msgpack.h stream.h msgpack_common.h msgpack_export.h) set(qmsgpack_headers msgpack.h stream.h msgpack_common.h msgpack_export.h endianhelper.h)
add_library(qmsgpack SHARED ${qmsgpack_srcs} ${qmsgpack_headers}) add_library(qmsgpack SHARED ${qmsgpack_srcs} ${qmsgpack_headers})

View File

@ -3,7 +3,6 @@
#include "private/unpack_p.h" #include "private/unpack_p.h"
#include "private/pack_p.h" #include "private/pack_p.h"
#include "private/qt_types_p.h" #include "private/qt_types_p.h"
#include "private/sysdep.h"
#include <QVector> #include <QVector>
QVariant MsgPack::unpack(const QByteArray &data) QVariant MsgPack::unpack(const QByteArray &data)

View File

@ -62,8 +62,8 @@ const quint8 FIXEX16 = 0xd8;
const quint8 STR8 = 0xd9; const quint8 STR8 = 0xd9;
const quint8 STR16 = 0xda; const quint8 STR16 = 0xda;
const quint8 STR32 = 0xdb; const quint8 STR32 = 0xdb;
const quint8 ARRAY8 = 0xdc; const quint8 ARRAY16 = 0xdc;
const quint8 ARRAY16 = 0xdd; const quint8 ARRAY32 = 0xdd;
const quint8 MAP16 = 0xde; const quint8 MAP16 = 0xde;
const quint8 MAP32 = 0xdf; const quint8 MAP32 = 0xdf;
const quint8 NEGATIVE_FIXINT = 0xe0; const quint8 NEGATIVE_FIXINT = 0xe0;

View File

@ -62,8 +62,8 @@ const quint8 FIXEX16 = 0xd8;
const quint8 STR8 = 0xd9; const quint8 STR8 = 0xd9;
const quint8 STR16 = 0xda; const quint8 STR16 = 0xda;
const quint8 STR32 = 0xdb; const quint8 STR32 = 0xdb;
const quint8 ARRAY8 = 0xdc; const quint8 ARRAY16 = 0xdc;
const quint8 ARRAY16 = 0xdd; const quint8 ARRAY32 = 0xdd;
const quint8 MAP16 = 0xde; const quint8 MAP16 = 0xde;
const quint8 MAP32 = 0xdf; const quint8 MAP32 = 0xdf;
const quint8 NEGATIVE_FIXINT = 0xe0; const quint8 NEGATIVE_FIXINT = 0xe0;

View File

@ -1,5 +1,5 @@
#include "pack_p.h" #include "pack_p.h"
#include "private/sysdep.h" #include "../endianhelper.h"
#include <QByteArray> #include <QByteArray>
#include <QDebug> #include <QDebug>

View File

@ -2,7 +2,7 @@
#include "pack_p.h" #include "pack_p.h"
#include "unpack_p.h" #include "unpack_p.h"
#include "stream.h" #include "stream.h"
#include "sysdep.h" #include "../endianhelper.h"
#include <QDebug> #include <QDebug>

View File

@ -1,5 +1,5 @@
#include "unpack_p.h" #include "unpack_p.h"
#include "sysdep.h" #include "../endianhelper.h"
#include <QByteArray> #include <QByteArray>
#include <QDebug> #include <QDebug>

View File

@ -1,9 +1,6 @@
#include "stream.h" #include "stream.h"
#include <QBuffer> #include <QBuffer>
#include "private/sysdep.h"
#include "private/pack_p.h" #include "private/pack_p.h"
#include "msgpack_common.h"
#include <limits>
#include <QDebug> #include <QDebug>
#undef CHECK_STREAM_PRECOND #undef CHECK_STREAM_PRECOND
@ -103,12 +100,10 @@ MsgPackStream &MsgPackStream::operator>>(bool &b)
MsgPackStream &MsgPackStream::operator >>(quint8 &u8) MsgPackStream &MsgPackStream::operator >>(quint8 &u8)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; quint64 u64;
if (dev->read((char *)&p, 1) != 1) { if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint8>::max())
setStatus(ReadPastEnd); u8 = u64;
return *this; else
}
if (!unpack_upto_quint8(u8, &p))
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -116,12 +111,10 @@ MsgPackStream &MsgPackStream::operator >>(quint8 &u8)
MsgPackStream &MsgPackStream::operator>>(quint16 &u16) MsgPackStream &MsgPackStream::operator>>(quint16 &u16)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; quint64 u64;
if (dev->read((char *)&p, 1) != 1) { if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint16>::max())
setStatus(ReadPastEnd); u16 = u64;
return *this; else
}
if (!unpack_upto_quint16(u16, &p))
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -129,12 +122,10 @@ MsgPackStream &MsgPackStream::operator>>(quint16 &u16)
MsgPackStream &MsgPackStream::operator>>(quint32 &u32) MsgPackStream &MsgPackStream::operator>>(quint32 &u32)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; quint64 u64;
if (dev->read((char *)&p, 1) != 1) { if (unpack_ulonglong(u64) && u64 <= std::numeric_limits<quint32>::max())
setStatus(ReadPastEnd); u32 = u64;
return *this; else
}
if (!unpack_upto_quint32(u32, &p))
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -142,25 +133,20 @@ MsgPackStream &MsgPackStream::operator>>(quint32 &u32)
MsgPackStream &MsgPackStream::operator>>(quint64 &u64) MsgPackStream &MsgPackStream::operator>>(quint64 &u64)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; unpack_ulonglong(u64);
if (dev->read((char *)&p, 1) != 1) {
setStatus(ReadPastEnd);
return *this;
}
if (!unpack_upto_quint64(u64, &p))
setStatus(ReadCorruptData);
return *this; return *this;
} }
MsgPackStream &MsgPackStream::operator>>(qint8 &i8) MsgPackStream &MsgPackStream::operator>>(qint8 &i8)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; qint64 i64;
if (dev->read((char *)&p, 1) != 1) { if (!unpack_longlong(i64))
setStatus(ReadPastEnd);
return *this; return *this;
} if (i64 >= std::numeric_limits<qint8>::min() &&
if (!unpack_upto_qint8(i8, &p)) i64 <= std::numeric_limits<qint8>::max())
i8 = i64;
else
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -168,12 +154,13 @@ MsgPackStream &MsgPackStream::operator>>(qint8 &i8)
MsgPackStream &MsgPackStream::operator>>(qint16 &i16) MsgPackStream &MsgPackStream::operator>>(qint16 &i16)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; qint64 i64;
if (dev->read((char *)&p, 1) != 1) { if (!unpack_longlong(i64))
setStatus(ReadPastEnd);
return *this; return *this;
} if (i64 >= std::numeric_limits<qint16>::min() &&
if (!unpack_upto_qint16(i16, &p)) i64 <= std::numeric_limits<qint16>::max())
i16 = i64;
else
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -181,12 +168,13 @@ MsgPackStream &MsgPackStream::operator>>(qint16 &i16)
MsgPackStream &MsgPackStream::operator>>(qint32 &i32) MsgPackStream &MsgPackStream::operator>>(qint32 &i32)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; qint64 i64;
if (dev->read((char *)&p, 1) != 1) { if (!unpack_longlong(i64))
setStatus(ReadPastEnd);
return *this; return *this;
} if (i64 >= std::numeric_limits<qint32>::min() &&
if (!unpack_upto_qint32(i32, &p)) i64 <= std::numeric_limits<qint32>::max())
i32 = i64;
else
setStatus(ReadCorruptData); setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -194,13 +182,7 @@ MsgPackStream &MsgPackStream::operator>>(qint32 &i32)
MsgPackStream &MsgPackStream::operator>>(qint64 &i64) MsgPackStream &MsgPackStream::operator>>(qint64 &i64)
{ {
CHECK_STREAM_PRECOND(*this); CHECK_STREAM_PRECOND(*this);
quint8 p; unpack_longlong(i64);
if (dev->read((char *)&p, 1) != 1) {
setStatus(ReadPastEnd);
return *this;
}
if (!unpack_upto_qint64(i64, &p))
setStatus(ReadCorruptData);
return *this; return *this;
} }
@ -330,6 +312,12 @@ MsgPackStream &MsgPackStream::operator>>(QByteArray &array)
return *this; return *this;
} }
bool MsgPackStream::readBytes(char *data, uint len)
{
CHECK_STREAM_PRECOND(false);
return dev->read(data, len) == len;
}
MsgPackStream &MsgPackStream::operator<<(bool b) MsgPackStream &MsgPackStream::operator<<(bool b)
{ {
CHECK_STREAM_WRITE_PRECOND(*this); CHECK_STREAM_WRITE_PRECOND(*this);
@ -444,169 +432,94 @@ MsgPackStream &MsgPackStream::operator<<(QByteArray array)
bool MsgPackStream::writeBytes(const char *data, uint len) bool MsgPackStream::writeBytes(const char *data, uint len)
{ {
CHECK_STREAM_WRITE_PRECOND(*this); CHECK_STREAM_WRITE_PRECOND(false);
if (dev->write(data, len) != len) if (dev->write(data, len) != len)
setStatus(WriteFailed); setStatus(WriteFailed);
return *this; return true;
} }
bool MsgPackStream::unpack_upto_quint8(quint8 &u8, quint8 *p) bool MsgPackStream::unpack_longlong(qint64 &i64)
{ {
if (*p <= MsgPack::FirstByte::POSITIVE_FIXINT) { quint8 p[9];
u8 = *p; if (dev->read((char *)p, 1) != 1) {
} else if (*p == MsgPack::FirstByte::UINT8) { setStatus(ReadPastEnd);
if (dev->read((char* )&u8, 1) != 1)
return false;
} else {
return false; return false;
} }
return true;
}
bool MsgPackStream::unpack_upto_quint16(quint16 &u16, quint8 *p) if (p[0] <= 127) {// positive fixint 0x00 - 0x7f
{ i64 = p[0];
if (*p == MsgPack::FirstByte::UINT16) {
quint8 d[2];
if (dev->read((char *)d, 2) != 2)
return false;
u16 = _msgpack_load16(quint16, d);
} else {
quint8 u8;
bool ok = unpack_upto_quint8(u8, p);
u16 = u8;
return ok;
}
return true;
}
bool MsgPackStream::unpack_upto_quint32(quint32 &u32, quint8 *p)
{
if (*p == MsgPack::FirstByte::UINT32) {
quint8 d[4];
if (dev->read((char *)d, 4) != 4)
return false;
u32 = _msgpack_load32(quint32, d);
return true; return true;
} else { } else if (*p >= 0xe0) { // negative fixint 0xe0 - 0xff
quint16 u16; i64 = (qint8)p[0];
bool ok = unpack_upto_quint16(u16, p);
u32 = u16;
return ok;
}
return true;
}
bool MsgPackStream::unpack_upto_quint64(quint64 &u64, quint8 *p)
{
if (*p == MsgPack::FirstByte::UINT64) {
quint8 d[8];
if (dev->read((char *)d, 8) != 8) {
return false;
}
u64 = _msgpack_load64(quint64, d);
return true; return true;
} else {
quint32 u32;
bool ok = unpack_upto_quint32(u32, p);
u64 = u32;
return ok;
} }
}
bool MsgPackStream::unpack_upto_qint8(qint8 &i8, quint8 *p) static int typeLengths[] = {1, 2, 4, 8, 1, 2, 4, 8};
{ int typeLength = typeLengths[p[0] - MsgPack::FirstByte::UINT8];
if (*p >= MsgPack::FirstByte::NEGATIVE_FIXINT) { if (dev->read((char *)p + 1, typeLength) != typeLength) {
i8 = *p; setStatus(ReadPastEnd);
} else if (*p == MsgPack::FirstByte::INT8) { return false;
if (dev->read((char *)&i8, 1) != 1) { }
if (p[0] == MsgPack::FirstByte::UINT8) {
i64 = p[1];
} else if (p[0] == MsgPack::FirstByte::INT8) {
i64 = (qint8)p[1];
} else if (p[0] == MsgPack::FirstByte::UINT16) {
i64 = _msgpack_load16(quint16, p + 1);
} else if (p[0] == MsgPack::FirstByte::INT16) {
i64 = _msgpack_load16(qint16, p + 1);
} else if (p[0] == MsgPack::FirstByte::UINT32) {
i64 = _msgpack_load32(quint32, p + 1);
} else if (p[0] == MsgPack::FirstByte::INT32) {
i64 = _msgpack_load32(qint32, p + 1);
} else if (p[0] == MsgPack::FirstByte::UINT64) {
quint64 u64;
u64 = _msgpack_load64(quint64, p + 1);
if (u64 > std::numeric_limits<qint64>::max()) {
setStatus(ReadCorruptData);
return false; return false;
} }
} else { i64 = u64;
quint8 u8; } else if (p[0] == MsgPack::FirstByte::INT64) {
bool ok = unpack_upto_quint8(u8, p); i64 = _msgpack_load64(qint64, p + 1);
if (u8 > std::numeric_limits<qint8>::max())
return false;
else
i8 = u8;
return ok;
} }
return true; return true;
} }
bool MsgPackStream::unpack_upto_qint16(qint16 &i16, quint8 *p) bool MsgPackStream::unpack_ulonglong(quint64 &u64)
{ {
if (*p == MsgPack::FirstByte::INT16) { quint8 p[9];
quint8 d[2]; if (dev->read((char *)p, 1) != 1) {
if (dev->read((char *)d, 2) != 2) { setStatus(ReadPastEnd);
return false; return false;
}
i16 = _msgpack_load16(qint16, d);
} else {
qint8 i8;
bool ok = unpack_upto_qint8(i8, p);
if (ok) {
i16 = i8;
} else {
quint16 u16;
bool ok = unpack_upto_quint16(u16, p);
if (u16 > std::numeric_limits<qint16>::max())
return false;
else
i16 = u16;
return ok;
}
} }
return true;
}
bool MsgPackStream::unpack_upto_qint32(qint32 &i32, quint8 *p) if (p[0] <= 127) {// positive fixint 0x00 - 0x7f
{ u64 = p[0];
if(*p == MsgPack::FirstByte::INT32) {
quint8 d[4];
if (dev->read((char *)d, 4) != 4) {
return false;
}
i32 = _msgpack_load32(qint32, d);
} else {
qint16 i16;
bool ok = unpack_upto_qint16(i16, p);
if (ok) {
i32 = i16;
} else {
quint32 u32;
bool ok = unpack_upto_quint32(u32, p);
if (u32 > std::numeric_limits<qint32>::max())
return false;
else
i32 = u32;
return ok;
}
}
return true;
}
bool MsgPackStream::unpack_upto_qint64(qint64 &i64, quint8 *p)
{
if(*p == MsgPack::FirstByte::INT64) {
quint8 d[8];
if (dev->read((char *)d, 8) != 8)
return false;
i64 = _msgpack_load64(qint64, d);
return true; return true;
} else { } else if (*p >= 0xe0) { // negative fixint 0xe0 - 0xff
qint32 i32; return false;
bool ok = unpack_upto_qint32(i32, p);
if (ok) {
i64 = i32;
} else {
quint64 u64;
bool ok = unpack_upto_quint64(u64, p);
if (u64 > std::numeric_limits<qint64>::max())
return false;
else
i64 = u64;
return ok;
}
} }
return true;
static int typeLengths[] = {1, 2, 4, 8, 1, 2, 4, 8};
int typeLength = typeLengths[p[0] - MsgPack::FirstByte::UINT8];
if (dev->read((char *)p + 1, typeLength) != typeLength) {
setStatus(ReadPastEnd);
return false;
}
if (p[0] == MsgPack::FirstByte::UINT8) {
u64 = p[1];
return true;
} else if (p[0] == MsgPack::FirstByte::UINT16) {
u64 = _msgpack_load16(quint64, p + 1);
return true;
} else if (p[0] == MsgPack::FirstByte::UINT32) {
u64 = _msgpack_load32(quint64, p + 1);
return true;
} else if (p[0] == MsgPack::FirstByte::UINT64) {
u64 = _msgpack_load64(quint64, p + 1);
return true;
}
setStatus(ReadCorruptData);
return false;
} }

View File

@ -1,7 +1,9 @@
#ifndef STREAM_H #ifndef STREAM_H
#define STREAM_H #define STREAM_H
#include <QIODevice> #include <QIODevice>
#include <limits.h> #include <limits>
#include "msgpack_common.h"
#include "endianhelper.h"
class MsgPackStream class MsgPackStream
{ {
@ -34,6 +36,7 @@ public:
MsgPackStream &operator>>(double &d); MsgPackStream &operator>>(double &d);
MsgPackStream &operator>>(QString &str); MsgPackStream &operator>>(QString &str);
MsgPackStream &operator>>(QByteArray &array); MsgPackStream &operator>>(QByteArray &array);
bool readBytes(char *data, uint len);
MsgPackStream &operator<<(bool b); MsgPackStream &operator<<(bool b);
MsgPackStream &operator<<(quint32 u32); MsgPackStream &operator<<(quint32 u32);
@ -47,20 +50,13 @@ public:
MsgPackStream &operator<<(QByteArray array); MsgPackStream &operator<<(QByteArray array);
bool writeBytes(const char *data, uint len); bool writeBytes(const char *data, uint len);
private: private:
QIODevice *dev; QIODevice *dev;
bool owndev; bool owndev;
Status q_status; Status q_status;
bool unpack_upto_quint8(quint8 &u8, quint8 *p); bool unpack_longlong(qint64 &i64);
bool unpack_upto_quint16(quint16 &u16, quint8 *p); bool unpack_ulonglong(quint64 &u64);
bool unpack_upto_quint32(quint32 &u32, quint8 *p);
bool unpack_upto_quint64(quint64 &u64, quint8 *p);
bool unpack_upto_qint8(qint8 &i8, quint8 *p);
bool unpack_upto_qint16(qint16 &i16, quint8 *p);
bool unpack_upto_qint32(qint32 &i32, quint8 *p);
bool unpack_upto_qint64(qint64 &i64, quint8 *p);
}; };
template <typename T> template <typename T>
@ -69,19 +65,19 @@ MsgPackStream& operator<<(MsgPackStream& s, const QList<T> &list)
quint32 len = list.size(); quint32 len = list.size();
quint8 p[5]; quint8 p[5];
if (len <= 15) { if (len <= 15) {
p[0] = 0x90 | len; p[0] = MsgPack::FirstByte::FIXARRAY | len;
s.writeBytes(p, 1); s.writeBytes((const char *)p, 1);
} else if (len <= std::numeric_limits<quint16>::max()) { } else if (len <= std::numeric_limits<quint16>::max()) {
p[0] = 0xdc; p[0] = MsgPack::FirstByte::ARRAY16;
_msgpack_store16(p + 1, len); _msgpack_store16(p + 1, len);
s.writeBytes(p, 3); s.writeBytes((const char *)p, 3);
} else { } else {
p[0] = 0xdd; p[0] = MsgPack::FirstByte::ARRAY32;
_msgpack_store32(p + 1, len); _msgpack_store32(p + 1, len);
s.writeBytes(p, 5); s.writeBytes((const char *)p, 5);
} }
if (s.status() != MsgPackStream::Ok) if (s.status() != MsgPackStream::Ok)
return *this; return s;
for (int i = 0; i < list.size(); ++i) for (int i = 0; i < list.size(); ++i)
s << list[i]; s << list[i];
return s; return s;
@ -91,9 +87,19 @@ template <typename T>
MsgPackStream& operator>>(MsgPackStream& s, QList<T> &list) MsgPackStream& operator>>(MsgPackStream& s, QList<T> &list)
{ {
list.clear(); list.clear();
quint32 size; quint8 p[5];
s >> size; quint32 len;
for (quint32 i = 0; i < size; ++i) { s.readBytes((char *)p, 1);
if (p[0] >= 0x90 && p[0] <= 0x9f) {
len = p[0] & 0xf;
} else if (p[0] == MsgPack::FirstByte::ARRAY16) {
s.readBytes((char *)p + 1, 2);
len = _msgpack_load16(quint16, p + 1);
} else if (p[0] == MsgPack::FirstByte::ARRAY32) {
s.readBytes((char *)p + 1, 4);
len = _msgpack_load32(quint32, p + 1);
}
for (quint32 i = 0; i < len; ++i) {
T t; T t;
s >> t; s >> t;
list.append(t); list.append(t);

View File

@ -17,6 +17,7 @@ private Q_SLOTS:
void test_float(); void test_float();
void test_double(); void test_double();
void test_bin(); void test_bin();
void test_array();
}; };
void StreamTest::test_unpack_integers() void StreamTest::test_unpack_integers()
@ -307,5 +308,64 @@ void StreamTest::test_bin()
QVERIFY(stream.status() == MsgPackStream::Ok); QVERIFY(stream.status() == MsgPackStream::Ok);
} }
void StreamTest::test_array()
{
{
QList<qint64> list;
list << 0 << 127 << -1 << -31 << 128 << 255 << -33 << -128 << 256;
list << 65535 << -129 << -32768 << 65536;
list << -32769 << (qint32)-2147483648;
list << (qint64)-2147483649;
list << std::numeric_limits<qint64>::min();
QByteArray packed;
{
MsgPackStream stream(&packed, QIODevice::WriteOnly);
stream << list;
QVERIFY(stream.status() == MsgPackStream::Ok);
}
QVariantList list2 = MsgPack::unpack(packed).toList();
QVERIFY(list.size() == list2.size());
for (int i = 0; i < list.size(); ++i)
QVERIFY(list[i] == list2[i]);
packed = MsgPack::pack(list2);
MsgPackStream stream(packed);
QList<qint64> list3;
stream >> list3;
QVERIFY(stream.status() == MsgPackStream::Ok);
QVERIFY(list2.size() == list3.size());
for (int i = 0; i < list2.size(); ++i)
QVERIFY(list2[i] == list3[i]);
}
{
QList<quint64> list;
list << 6;
list << std::numeric_limits<quint64>::min();
list << std::numeric_limits<quint64>::max();
list << -4;
QByteArray packed;
{
MsgPackStream stream(&packed, QIODevice::WriteOnly);
stream << list;
QVERIFY(stream.status() == MsgPackStream::Ok);
}
QVariantList list2 = MsgPack::unpack(packed).toList();
QVERIFY(list.size() == list2.size());
for (int i = 0; i < list.size(); ++i)
QVERIFY(list[i] == list2[i]);
packed = MsgPack::pack(list2);
MsgPackStream stream(packed);
QList<quint64> list3;
stream >> list3;
QVERIFY(stream.status() == MsgPackStream::Ok);
QVERIFY(list2.size() == list3.size());
for (int i = 0; i < list2.size(); ++i)
QVERIFY(list2[i] == list3[i]);
}
}
QTEST_APPLESS_MAIN(StreamTest) QTEST_APPLESS_MAIN(StreamTest)
#include "stream_test.moc" #include "stream_test.moc"