diff options
Diffstat (limited to 'test/common')
-rw-r--r-- | test/common/span.h | 365 |
1 files changed, 321 insertions, 44 deletions
diff --git a/test/common/span.h b/test/common/span.h index 6586d491ec..82b63a58d5 100644 --- a/test/common/span.h +++ b/test/common/span.h @@ -67,6 +67,9 @@ public: byte data[] = { 'h', 'e', 'l', 'l', 'o' }; Common::Span<byte> span(data, sizeof(data)); + // empty iterator should default construct OK + Common::Span<byte>::iterator defaultIt; + Common::Span<byte>::iterator it = span.begin(); Common::Span<byte>::iterator sameIt(it); @@ -126,6 +129,31 @@ public: } } + void test_span_iterator_integers() { + const byte data[] = { 0xFF, 1, 2, 3, 2, 1, 0xFF }; + Common::Span<const byte> span(data, sizeof(data)); + Common::Span<const byte>::const_iterator it = span.cbegin(); + + TS_ASSERT_EQUALS(it.getInt8(), -1); + TS_ASSERT_EQUALS(it.getUint8(), 255); + TS_ASSERT_EQUALS(it.getInt16BE(), -255); + TS_ASSERT_EQUALS(it.getUint16BE(), 65281U); + TS_ASSERT_EQUALS((it + 5).getInt16LE(), -255); + TS_ASSERT_EQUALS((it + 5).getUint16LE(), 65281U); + TS_ASSERT_EQUALS(it.getUint24LE(), 131583U); +#ifdef SCUMM_LITTLE_ENDIAN + TS_ASSERT_EQUALS((it + 3).getUint32(), 4278256131U); +#elif SCUMM_BIG_ENDIAN + TS_ASSERT_EQUALS(it.getUint32(), 4278256131U); +#else +#error No endianness detected +#endif + TS_ASSERT_EQUALS(it.getInt32BE(), -16711165); + TS_ASSERT_EQUALS(it.getUint32BE(), 4278256131U); + TS_ASSERT_EQUALS((it + 3).getInt32LE(), -16711165); + TS_ASSERT_EQUALS((it + 3).getUint32LE(), 4278256131U); + } + void test_span_iterator_ptr() { Foo foo[2]; foo[0].a = 1; @@ -179,6 +207,18 @@ public: TS_ASSERT_EQUALS((bool)owner, false); TS_ASSERT(owner->data() == nullptr); TS_ASSERT_EQUALS(owner2->data(), dataPtr); + + // tests destruction of held pointer by reassignment + owner2 = owner; + } + + { + char *data = new char[6]; + Common::strlcpy(data, "hello", 6); + const Common::SpanOwner<Common::Span<const char> > constOwner(Common::Span<const char>(data, 6)); + TS_ASSERT_EQUALS((*constOwner)[0], 'h'); + TS_ASSERT_EQUALS(constOwner->getUint8At(1), 'e'); + TS_ASSERT_EQUALS(constOwner[2], 'l'); } { @@ -203,26 +243,151 @@ public: } } + void test_span_owner_named_span() { + Common::SpanOwner<Common::NamedSpan<byte> > owner; + owner->allocate(3, "foo"); + owner[0] = 'a'; + owner[1] = 'b'; + owner[2] = 'c'; + for (int i = 0; i < 3; ++i) { + TS_ASSERT_EQUALS(owner->getUint8At(i), 'a' + i); + TS_ASSERT_EQUALS((*owner)[i], 'a' + i); + } + TS_ASSERT(owner->name() == "foo"); + + { + Common::SpanOwner<Common::NamedSpan<byte> > owner2; + TS_ASSERT(owner2->data() == nullptr); + owner2->allocateFromSpan(*owner); + TS_ASSERT(owner2->data() != nullptr); + TS_ASSERT_DIFFERS(owner->data(), owner2->data()); + TS_ASSERT(owner2->name() == "foo"); + + for (int i = 0; i < 3; ++i) { + TS_ASSERT_EQUALS(owner2->getUint8At(i), 'a' + i); + TS_ASSERT_EQUALS((*owner2)[i], 'a' + i); + } + + TS_ASSERT_EQUALS((bool)owner2, true); + owner2.release(); + TS_ASSERT_EQUALS((bool)owner2, false); + } + + { + Common::SpanOwner<Common::NamedSpan<byte> > owner2; + TS_ASSERT_EQUALS((bool)owner, true); + void *dataPtr = owner->data(); + owner2 = owner; + TS_ASSERT_EQUALS((bool)owner, false); + TS_ASSERT(owner->data() == nullptr); + TS_ASSERT_EQUALS(owner2->data(), dataPtr); + + // tests destruction of held pointer by reassignment + owner2 = owner; + } + + { + char *data = new char[6]; + Common::strlcpy(data, "hello", 6); + const Common::SpanOwner<Common::NamedSpan<const char> > constOwner(Common::NamedSpan<const char>(data, 6)); + TS_ASSERT_EQUALS((*constOwner)[0], 'h'); + TS_ASSERT_EQUALS(constOwner->getUint8At(1), 'e'); + TS_ASSERT_EQUALS(constOwner[2], 'l'); + } + + { + TS_ASSERT_EQUALS((bool)owner, false); + Common::SpanOwner<Common::NamedSpan<byte> > owner2(owner); + TS_ASSERT_EQUALS((bool)owner2, false); + } + + { + owner->allocate(1); + TS_ASSERT_EQUALS((bool)owner, true); + Common::SpanOwner<Common::NamedSpan<byte> > owner2(owner); + TS_ASSERT_EQUALS((bool)owner2, true); + TS_ASSERT_DIFFERS(owner->data(), owner2->data()); + } + + { + TS_ASSERT_EQUALS((bool)owner, true); + void *dataPtr = owner->data(); + TS_ASSERT_EQUALS(owner.release(), dataPtr); + TS_ASSERT_EQUALS((bool)owner, false); + } + } + + void test_span_allocate_from_stream() { + byte data[] = "hello"; + Common::MemoryReadStream stream(data, sizeof(data)); + Common::SpanOwner<Common::Span<byte> > owner; + owner->allocateFromStream(stream, 2); + TS_ASSERT(owner->data() != data); + TS_ASSERT_EQUALS(owner->size(), 2U); + TS_ASSERT_EQUALS(owner[0], 'h'); + TS_ASSERT_EQUALS(owner[1], 'e'); + owner.clear(); + TS_ASSERT(owner->data() == nullptr); + stream.seek(0, SEEK_SET); + + owner->allocateFromStream(stream); + TS_ASSERT(owner->data() != data); + TS_ASSERT_EQUALS(owner->size(), sizeof(data)); + TS_ASSERT_EQUALS(owner[0], 'h'); + TS_ASSERT_EQUALS(owner[1], 'e'); + TS_ASSERT_EQUALS(owner[2], 'l'); + TS_ASSERT_EQUALS(owner[3], 'l'); + TS_ASSERT_EQUALS(owner[4], 'o'); + + Common::SpanOwner<Common::NamedSpan<const byte> > owner2; + stream.seek(0, SEEK_SET); + owner2->allocateFromStream(stream, Common::kSpanMaxSize, "streamname"); + TS_ASSERT(owner2->data() != data); + TS_ASSERT_EQUALS(owner2->size(), sizeof(data)); + TS_ASSERT_EQUALS(owner2[0], 'h'); + TS_ASSERT_EQUALS(owner2[1], 'e'); + TS_ASSERT_EQUALS(owner2[2], 'l'); + TS_ASSERT_EQUALS(owner2[3], 'l'); + TS_ASSERT_EQUALS(owner2[4], 'o'); + TS_ASSERT_EQUALS(owner2->name(), "streamname"); + } + void test_span_byte() { - byte data[] = { 'h', 'e', 'l', 'l', 'o' }; - Common::Span<byte> span(data, sizeof(data)); + { + byte data[] = { 'h', 'e', 'l', 'l', 'o' }; + Common::Span<byte> span(data, sizeof(data)); + + TS_ASSERT_EQUALS(span.size(), sizeof(data)); + TS_ASSERT_EQUALS(span.byteSize(), sizeof(data)); - TS_ASSERT_EQUALS(span.size(), sizeof(data)); - TS_ASSERT_EQUALS(span.byteSize(), sizeof(data)); + Common::Span<byte> other(span); + TS_ASSERT_EQUALS(span, other); + other.clear(); + TS_ASSERT(span != other); - Common::Span<byte> other(span); - TS_ASSERT_EQUALS(span, other); - other.clear(); - TS_ASSERT(span != other); + TS_ASSERT_EQUALS(span[0], 'h'); + TS_ASSERT_EQUALS(span[1], 'e'); + span[1] = 'o'; + TS_ASSERT_EQUALS(span[1], 'o'); - TS_ASSERT_EQUALS(span[0], 'h'); - TS_ASSERT_EQUALS(span[1], 'e'); - span[1] = 'o'; - TS_ASSERT_EQUALS(span[1], 'o'); + TS_ASSERT((bool)span); + span.clear(); + TS_ASSERT(!(bool)span); + } + + { + byte data[] = { 'h', 'e', 'l', 'l', 'o' }; + const Common::Span<const byte> span(data, sizeof(data)); - TS_ASSERT((bool)span); - span.clear(); - TS_ASSERT(!(bool)span); + TS_ASSERT_EQUALS(span.size(), sizeof(data)); + TS_ASSERT_EQUALS(span.byteSize(), sizeof(data)); + + const Common::Span<const byte> other(span); + TS_ASSERT_EQUALS(span, other); + + TS_ASSERT_EQUALS(span[0], 'h'); + TS_ASSERT_EQUALS(span[1], 'e'); + } } void test_span_integers() { @@ -265,50 +430,107 @@ public: void test_span_unsafe_data() { char data[] = "hello"; Common::Span<char> span(data, sizeof(data)); - TS_ASSERT_EQUALS(span.getUnsafeDataAt(0, 6), data); + + char *ptr = span.getUnsafeDataAt(0, 6); + TS_ASSERT_EQUALS(ptr, data); + ptr = span.getUnsafeDataAt(0); + TS_ASSERT_EQUALS(ptr, data); + + const Common::Span<const char> span2(data, sizeof(data)); + const char *ptr2 = span2.getUnsafeDataAt(0, 6); + TS_ASSERT_EQUALS(ptr2, data); + ptr2 = span2.getUnsafeDataAt(0); + TS_ASSERT_EQUALS(ptr2, data); } void test_span_subspan() { - byte data[] = { 1, 2, 3, 4, 5, 6 }; - Common::Span<byte> span(data, sizeof(data)); + { + byte data[] = { 1, 2, 3, 4, 5, 6 }; + Common::Span<byte> span(data, sizeof(data)); + + TS_ASSERT_EQUALS(span.subspan(0).size(), sizeof(data) - 0); + TS_ASSERT_EQUALS(span.subspan(2).size(), sizeof(data) - 2); + TS_ASSERT_EQUALS(span.subspan(2, 2).size(), 2U); + TS_ASSERT_EQUALS(span.subspan<uint16>(0).size(), sizeof(data) / 2); + TS_ASSERT_EQUALS(span.subspan<uint16>(0).byteSize(), sizeof(data)); + TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).size(), 1U); + TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).byteSize(), 2U); + +#ifdef SCUMM_LITTLE_ENDIAN + TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 4 << 8 | 3); +#elif SCUMM_BIG_ENDIAN + TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 3 << 8 | 4); +#else +#error No endianness detected +#endif + + Common::Span<uint16> shortSpan = span.subspan<uint16>(0); + TS_ASSERT_EQUALS(shortSpan.byteSize(), span.byteSize()); + TS_ASSERT(shortSpan.size() != span.size()); + shortSpan[1] = 0xFFFF; + Common::Span<byte> byteSpan = shortSpan.subspan<byte>(1); + TS_ASSERT_EQUALS(byteSpan.size(), sizeof(data) - 1 * sizeof(uint16)); + TS_ASSERT_EQUALS(byteSpan[0], 0xFF); + TS_ASSERT_EQUALS(byteSpan[1], 0xFF); + } + + { + byte data[] = { 1, 2, 3, 4, 5, 6 }; + const Common::Span<const byte> span(data, sizeof(data)); - TS_ASSERT_EQUALS(span.subspan(0).size(), sizeof(data) - 0); - TS_ASSERT_EQUALS(span.subspan(2).size(), sizeof(data) - 2); - TS_ASSERT_EQUALS(span.subspan(2, 2).size(), 2U); - TS_ASSERT_EQUALS(span.subspan<uint16>(0).size(), sizeof(data) / 2); - TS_ASSERT_EQUALS(span.subspan<uint16>(0).byteSize(), sizeof(data)); - TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).size(), 1U); - TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).byteSize(), 2U); + TS_ASSERT_EQUALS(span.subspan(0).size(), sizeof(data) - 0); + TS_ASSERT_EQUALS(span.subspan(2).size(), sizeof(data) - 2); + TS_ASSERT_EQUALS(span.subspan(2, 2).size(), 2U); + TS_ASSERT_EQUALS(span.subspan<uint16>(0).size(), sizeof(data) / 2); + TS_ASSERT_EQUALS(span.subspan<uint16>(0).byteSize(), sizeof(data)); + TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).size(), 1U); + TS_ASSERT_EQUALS(span.subspan<uint16>(0, 2).byteSize(), 2U); #ifdef SCUMM_LITTLE_ENDIAN - TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 4 << 8 | 3); + TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 4 << 8 | 3); #elif SCUMM_BIG_ENDIAN - TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 3 << 8 | 4); + TS_ASSERT_EQUALS(span.subspan<uint16>(0)[1], 3 << 8 | 4); #else #error No endianness detected #endif - Common::Span<uint16> shortSpan = span.subspan<uint16>(0); - TS_ASSERT_EQUALS(shortSpan.byteSize(), span.byteSize()); - TS_ASSERT(shortSpan.size() != span.size()); - shortSpan[1] = 0xFFFF; - Common::Span<byte> byteSpan = shortSpan.subspan<byte>(1); - TS_ASSERT_EQUALS(byteSpan.size(), sizeof(data) - 1 * sizeof(uint16)); - TS_ASSERT_EQUALS(byteSpan[0], 0xFF); - TS_ASSERT_EQUALS(byteSpan[1], 0xFF); + const Common::Span<uint16> shortSpan = span.subspan<uint16>(0); + TS_ASSERT_EQUALS(shortSpan.byteSize(), span.byteSize()); + TS_ASSERT(shortSpan.size() != span.size()); + Common::Span<byte> byteSpan = shortSpan.subspan<byte>(1); + TS_ASSERT_EQUALS(byteSpan.size(), sizeof(data) - 1 * sizeof(uint16)); + TS_ASSERT_EQUALS(byteSpan[0], 3); + TS_ASSERT_EQUALS(byteSpan[1], 4); + } } void test_span_to_stream() { - const byte data[] = { 0, 1, 2, 3, 4, 5 }; + const byte data[] = { 0, 1, 2, 3 }; Common::Span<const byte> span(data, sizeof(data)); - Common::MemoryReadStream stream(span.toStream(1, 2)); - byte out; - TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); - TS_ASSERT_EQUALS(out, 1); - TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); - TS_ASSERT_EQUALS(out, 2); - TS_ASSERT_EQUALS(stream.read(&out, 1), 0U); + { + Common::MemoryReadStream stream(span.toStream(1, 2)); + byte out; + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 1); + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 2); + TS_ASSERT_EQUALS(stream.read(&out, 1), 0U); + } + + { + Common::MemoryReadStream stream = span.toStream(); + byte out; + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 0); + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 1); + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 2); + TS_ASSERT_EQUALS(stream.read(&out, 1), 1U); + TS_ASSERT_EQUALS(out, 3); + TS_ASSERT_EQUALS(stream.read(&out, 1), 0U); + } } void test_span_copying() { @@ -396,7 +618,7 @@ public: TS_ASSERT_EQUALS(span0 - span4, -2); } - void test_namedspan() { + void test_named_span() { byte data[6] = { 0, 1, 2, 3, 4, 5 }; Common::NamedSpan<byte> span(data, sizeof(data), "foo.data"); TS_ASSERT_EQUALS(span.name(), "foo.data"); @@ -430,7 +652,62 @@ public: TS_ASSERT_EQUALS(actual, expected); } + Common::NamedSpan<byte> span2; + span2 = span; + TS_ASSERT_EQUALS(span2, span); + Common::Span<byte> superclassInstance; superclassInstance = span; + TS_ASSERT_EQUALS(span, superclassInstance); + + Common::Span<byte> subclassInstance(superclassInstance); + TS_ASSERT_EQUALS(subclassInstance, superclassInstance); + + const Common::NamedSpan<const byte> constSpan(span); + + { + Common::NamedSpan<const byte> subspan = constSpan.subspan(2); + + expected = "Access violation reading foo.data: 23 + 45 > 4 (abs: 25 + 45 > 6)"; + actual = subspan.getValidationMessage(23, 45, Common::kValidateRead); + TS_ASSERT_EQUALS(actual, expected); + TS_ASSERT_EQUALS(subspan.sourceByteOffset(), 2U); + } + + { + Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data"); + expected = "Access violation reading new.data: -34 + -56 > 4 (abs: -32 + -56 > 6)"; + actual = subspan.getValidationMessage(-34, -56, Common::kValidateRead); + TS_ASSERT_EQUALS(actual, expected); + } + + { + Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data", 0); + expected = "Access violation reading new.data: -34 + -56 > 4 (abs: -34 + -56 > 4)"; + actual = subspan.getValidationMessage(-34, -56, Common::kValidateRead); + TS_ASSERT_EQUALS(actual, expected); + } + + { + Common::NamedSpan<const byte> subspan = constSpan.subspan(2, Common::kSpanMaxSize, "new.data", 0); + subspan.sourceByteOffset() = 2; + expected = "Access violation reading new.data: -34 + -56 > 4 (abs: -32 + -56 > 6)"; + actual = subspan.getValidationMessage(-34, -56, Common::kValidateRead); + TS_ASSERT_EQUALS(actual, expected); + } + + { + Common::MemoryReadStream *stream = new Common::MemoryReadStream(data, sizeof(data)); + Common::File file; + file.open(stream, "test.txt"); + Common::SpanOwner<Common::NamedSpan<const byte> > fileOwner; + fileOwner->allocateFromStream(file); + TS_ASSERT_EQUALS(fileOwner->size(), (uint)file.size()); + file.close(); + TS_ASSERT(fileOwner->name() == "test.txt"); + for (uint i = 0; i < fileOwner->size(); ++i) { + TS_ASSERT_EQUALS(fileOwner->getInt8At(i), data[i]); + } + } } }; |