mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 06:24:41 +02:00
Fixes to, test for metadata streaming.
This commit is contained in:
parent
6d14ad6ab5
commit
eb95b01aa1
4 changed files with 97 additions and 31 deletions
|
@ -107,6 +107,14 @@ Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, QObject
|
||||||
_sharedObjectStreamer(*this) {
|
_sharedObjectStreamer(*this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitstream::addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject) {
|
||||||
|
_metaObjectSubstitutions.insert(className, metaObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bitstream::addTypeSubstitution(const QByteArray& typeName, int type) {
|
||||||
|
_typeStreamerSubstitutions.insert(typeName, getTypeStreamers().value(type));
|
||||||
|
}
|
||||||
|
|
||||||
const int LAST_BIT_POSITION = BITS_IN_BYTE - 1;
|
const int LAST_BIT_POSITION = BITS_IN_BYTE - 1;
|
||||||
|
|
||||||
Bitstream& Bitstream::write(const void* data, int bits, int offset) {
|
Bitstream& Bitstream::write(const void* data, int bits, int offset) {
|
||||||
|
@ -496,7 +504,10 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
||||||
objectReader = ObjectReader();
|
objectReader = ObjectReader();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
const QMetaObject* metaObject = getMetaObjects().value(className);
|
const QMetaObject* metaObject = _metaObjectSubstitutions.value(className);
|
||||||
|
if (!metaObject) {
|
||||||
|
metaObject = getMetaObjects().value(className);
|
||||||
|
}
|
||||||
if (!metaObject) {
|
if (!metaObject) {
|
||||||
qWarning() << "Unknown class name: " << className << "\n";
|
qWarning() << "Unknown class name: " << className << "\n";
|
||||||
}
|
}
|
||||||
|
@ -523,6 +534,7 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
||||||
// for hash metadata, check the names/types of the properties as well as the name hash against our own class
|
// for hash metadata, check the names/types of the properties as well as the name hash against our own class
|
||||||
if (_metadataType == HASH_METADATA) {
|
if (_metadataType == HASH_METADATA) {
|
||||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||||
|
bool matches = true;
|
||||||
if (metaObject) {
|
if (metaObject) {
|
||||||
int propertyIndex = 0;
|
int propertyIndex = 0;
|
||||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||||
|
@ -536,21 +548,20 @@ Bitstream& Bitstream::operator>(ObjectReader& objectReader) {
|
||||||
}
|
}
|
||||||
if (propertyIndex >= properties.size() ||
|
if (propertyIndex >= properties.size() ||
|
||||||
!properties.at(propertyIndex).getReader().matchesExactly(typeStreamer)) {
|
!properties.at(propertyIndex).getReader().matchesExactly(typeStreamer)) {
|
||||||
objectReader = ObjectReader(className, metaObject, properties);
|
matches = false;
|
||||||
return *this;
|
break;
|
||||||
}
|
}
|
||||||
hash.addData(property.name(), strlen(property.name()) + 1);
|
hash.addData(property.name(), strlen(property.name()) + 1);
|
||||||
propertyIndex++;
|
propertyIndex++;
|
||||||
}
|
}
|
||||||
if (propertyIndex != properties.size()) {
|
if (propertyIndex != properties.size()) {
|
||||||
objectReader = ObjectReader(className, metaObject, properties);
|
matches = false;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QByteArray localHashResult = hash.result();
|
QByteArray localHashResult = hash.result();
|
||||||
QByteArray remoteHashResult(localHashResult.size(), 0);
|
QByteArray remoteHashResult(localHashResult.size(), 0);
|
||||||
read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE);
|
read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE);
|
||||||
if (metaObject && localHashResult == remoteHashResult) {
|
if (metaObject && matches && localHashResult == remoteHashResult) {
|
||||||
objectReader = ObjectReader(className, metaObject, getPropertyReaders(metaObject));
|
objectReader = ObjectReader(className, metaObject, getPropertyReaders(metaObject));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -589,7 +600,10 @@ Bitstream& Bitstream::operator<(const TypeStreamer* streamer) {
|
||||||
Bitstream& Bitstream::operator>(TypeReader& reader) {
|
Bitstream& Bitstream::operator>(TypeReader& reader) {
|
||||||
QByteArray typeName;
|
QByteArray typeName;
|
||||||
*this >> typeName;
|
*this >> typeName;
|
||||||
const TypeStreamer* streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
const TypeStreamer* streamer = _typeStreamerSubstitutions.value(typeName);
|
||||||
|
if (!streamer) {
|
||||||
|
streamer = getTypeStreamers().value(QMetaType::type(typeName.constData()));
|
||||||
|
}
|
||||||
if (!streamer) {
|
if (!streamer) {
|
||||||
qWarning() << "Unknown type name: " << typeName << "\n";
|
qWarning() << "Unknown type name: " << typeName << "\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,12 @@ public:
|
||||||
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
|
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
|
||||||
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, QObject* parent = NULL);
|
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, QObject* parent = NULL);
|
||||||
|
|
||||||
|
/// Substitutes the supplied metaobject for the given class name's default mapping.
|
||||||
|
void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject);
|
||||||
|
|
||||||
|
/// Substitutes the supplied type for the given type name's default mapping.
|
||||||
|
void addTypeSubstitution(const QByteArray& typeName, int type);
|
||||||
|
|
||||||
/// Writes a set of bits to the underlying stream.
|
/// Writes a set of bits to the underlying stream.
|
||||||
/// \param bits the number of bits to write
|
/// \param bits the number of bits to write
|
||||||
/// \param offset the offset of the first bit
|
/// \param offset the offset of the first bit
|
||||||
|
@ -363,6 +369,9 @@ private:
|
||||||
|
|
||||||
WeakSharedObjectHash _weakSharedObjectHash;
|
WeakSharedObjectHash _weakSharedObjectHash;
|
||||||
|
|
||||||
|
QHash<QByteArray, const QMetaObject*> _metaObjectSubstitutions;
|
||||||
|
QHash<QByteArray, const TypeStreamer*> _typeStreamerSubstitutions;
|
||||||
|
|
||||||
static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
|
static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
|
||||||
static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
|
static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
|
||||||
static QHash<int, const TypeStreamer*>& getTypeStreamers();
|
static QHash<int, const TypeStreamer*>& getTypeStreamers();
|
||||||
|
|
|
@ -34,23 +34,65 @@ static int streamedBytesReceived = 0;
|
||||||
static int sharedObjectsCreated = 0;
|
static int sharedObjectsCreated = 0;
|
||||||
static int sharedObjectsDestroyed = 0;
|
static int sharedObjectsDestroyed = 0;
|
||||||
|
|
||||||
|
static QByteArray createRandomBytes(int minimumSize, int maximumSize) {
|
||||||
|
QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0);
|
||||||
|
for (int i = 0; i < bytes.size(); i++) {
|
||||||
|
bytes[i] = rand();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray createRandomBytes() {
|
||||||
|
const int MIN_BYTES = 4;
|
||||||
|
const int MAX_BYTES = 16;
|
||||||
|
return createRandomBytes(MIN_BYTES, MAX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
static bool testSerialization(Bitstream::MetadataType metadataType) {
|
static bool testSerialization(Bitstream::MetadataType metadataType) {
|
||||||
QByteArray array;
|
QByteArray array;
|
||||||
QDataStream outStream(&array, QIODevice::WriteOnly);
|
QDataStream outStream(&array, QIODevice::WriteOnly);
|
||||||
Bitstream out(outStream, metadataType);
|
Bitstream out(outStream, metadataType);
|
||||||
SharedObjectPointer testObjectWritten = new TestSharedObjectA(randFloat());
|
SharedObjectPointer testObjectWrittenA = new TestSharedObjectA(randFloat());
|
||||||
out << testObjectWritten;
|
out << testObjectWrittenA;
|
||||||
|
SharedObjectPointer testObjectWrittenB = new TestSharedObjectB(randFloat(), createRandomBytes());
|
||||||
|
out << testObjectWrittenB;
|
||||||
|
QByteArray endWritten = "end";
|
||||||
|
out << endWritten;
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
QDataStream inStream(array);
|
QDataStream inStream(array);
|
||||||
Bitstream in(inStream, metadataType);
|
Bitstream in(inStream, metadataType);
|
||||||
SharedObjectPointer testObjectRead;
|
in.addMetaObjectSubstitution("TestSharedObjectA", &TestSharedObjectB::staticMetaObject);
|
||||||
in >> testObjectRead;
|
in.addMetaObjectSubstitution("TestSharedObjectB", &TestSharedObjectA::staticMetaObject);
|
||||||
|
SharedObjectPointer testObjectReadA, testObjectReadB;
|
||||||
|
in >> testObjectReadA >> testObjectReadB;
|
||||||
|
|
||||||
if (!testObjectWritten->equals(testObjectRead)) {
|
if (!testObjectReadA || testObjectReadA->metaObject() != &TestSharedObjectB::staticMetaObject) {
|
||||||
QDebug debug = qDebug() << "Read/write mismatch";
|
qDebug() << "Wrong class for A" << testObjectReadA << metadataType;
|
||||||
testObjectWritten->dump(debug);
|
return true;
|
||||||
testObjectRead->dump(debug);
|
}
|
||||||
|
if (metadataType == Bitstream::FULL_METADATA && static_cast<TestSharedObjectA*>(testObjectWrittenA.data())->getFoo() !=
|
||||||
|
static_cast<TestSharedObjectB*>(testObjectReadA.data())->getFoo()) {
|
||||||
|
QDebug debug = qDebug() << "Failed to transfer shared field from A to B";
|
||||||
|
testObjectWrittenA->dump(debug);
|
||||||
|
testObjectReadA->dump(debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!testObjectReadB || testObjectReadB->metaObject() != &TestSharedObjectA::staticMetaObject) {
|
||||||
|
qDebug() << "Wrong class for B" << testObjectReadB << metadataType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (metadataType == Bitstream::FULL_METADATA && static_cast<TestSharedObjectB*>(testObjectWrittenB.data())->getFoo() !=
|
||||||
|
static_cast<TestSharedObjectA*>(testObjectReadB.data())->getFoo()) {
|
||||||
|
QDebug debug = qDebug() << "Failed to transfer shared field from B to A";
|
||||||
|
testObjectWrittenB->dump(debug);
|
||||||
|
testObjectReadB->dump(debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray endRead;
|
||||||
|
in >> endRead;
|
||||||
|
if (endWritten != endRead) {
|
||||||
|
qDebug() << "End tag mismatch." << endRead;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,20 +142,6 @@ bool MetavoxelTests::run() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray createRandomBytes(int minimumSize, int maximumSize) {
|
|
||||||
QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0);
|
|
||||||
for (int i = 0; i < bytes.size(); i++) {
|
|
||||||
bytes[i] = rand();
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QByteArray createRandomBytes() {
|
|
||||||
const int MIN_BYTES = 4;
|
|
||||||
const int MAX_BYTES = 16;
|
|
||||||
return createRandomBytes(MIN_BYTES, MAX_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SharedObjectPointer createRandomSharedObject() {
|
static SharedObjectPointer createRandomSharedObject() {
|
||||||
switch (randIntInRange(0, 2)) {
|
switch (randIntInRange(0, 2)) {
|
||||||
case 0: return new TestSharedObjectA(randFloat());
|
case 0: return new TestSharedObjectA(randFloat());
|
||||||
|
@ -354,7 +382,9 @@ void TestSharedObjectA::setFoo(float foo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TestSharedObjectB::TestSharedObjectB() {
|
TestSharedObjectB::TestSharedObjectB(float foo, const QByteArray& bar) :
|
||||||
|
_foo(foo),
|
||||||
|
_bar(bar) {
|
||||||
sharedObjectsCreated++;
|
sharedObjectsCreated++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,11 +89,24 @@ private:
|
||||||
/// Another simple shared object.
|
/// Another simple shared object.
|
||||||
class TestSharedObjectB : public SharedObject {
|
class TestSharedObjectB : public SharedObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(float foo READ getFoo WRITE setFoo)
|
||||||
|
Q_PROPERTY(QByteArray bar READ getBar WRITE setBar)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Q_INVOKABLE TestSharedObjectB();
|
Q_INVOKABLE TestSharedObjectB(float foo = 0.0f, const QByteArray& bar = QByteArray());
|
||||||
virtual ~TestSharedObjectB();
|
virtual ~TestSharedObjectB();
|
||||||
|
|
||||||
|
void setFoo(float foo) { _foo = foo; }
|
||||||
|
float getFoo() const { return _foo; }
|
||||||
|
|
||||||
|
void setBar(const QByteArray& bar) { _bar = bar; }
|
||||||
|
const QByteArray& getBar() const { return _bar; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
float _foo;
|
||||||
|
QByteArray _bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A simple test message.
|
/// A simple test message.
|
||||||
|
|
Loading…
Reference in a new issue