File indexing completed on 2024-05-19 15:26:48

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include <QtTest/QtTest>
0008 
0009 #include <vector>
0010 #include "io/aep/riff.hpp"
0011 
0012 using namespace glaxnimate::io::aep;
0013 
0014 class TestCase: public QObject
0015 {
0016     Q_OBJECT
0017 
0018 private Q_SLOTS:
0019     void test_chunk_id()
0020     {
0021         ChunkId chunk = QByteArrayLiteral("rawr");
0022         QCOMPARE(chunk, "rawr");
0023         QVERIFY(chunk != "abcd");
0024     }
0025 
0026     void test_chunk_find()
0027     {
0028         RiffChunk parent{QByteArrayLiteral("rawr"), 0};
0029         parent.children.push_back(std::make_unique<RiffChunk>(RiffChunk{QByteArrayLiteral("itm1")}));
0030         parent.children.push_back(std::make_unique<RiffChunk>(RiffChunk{QByteArrayLiteral("itm3")}));
0031         parent.children.push_back(std::make_unique<RiffChunk>(RiffChunk{QByteArrayLiteral("rept"), 1}));
0032         parent.children.push_back(std::make_unique<RiffChunk>(RiffChunk{QByteArrayLiteral("rept"), 2}));
0033         parent.children.push_back(std::make_unique<RiffChunk>(RiffChunk{QByteArrayLiteral("itm2")}));
0034 
0035         auto it1 = parent.find("itm3");
0036         QVERIFY(it1 != parent.children.end());
0037         QCOMPARE((*it1)->header, "itm3");
0038         auto it2 = parent.find("rept", it1);
0039         QVERIFY(it2 != parent.children.end());
0040         QCOMPARE((*it2)->header, "rept");
0041         QCOMPARE(parent.child("itm3")->header, "itm3");
0042         QCOMPARE(parent.child("itm7"), nullptr);
0043 
0044         std::vector<const RiffChunk*> items(5);
0045         std::vector<const RiffChunk**> ptrs;
0046         for ( auto& p : items )
0047             ptrs.push_back(&p);
0048 
0049         parent.find_multiple(ptrs, {"rept", "itm1", "itm2", "itm3", "itm4"});
0050         QCOMPARE(items[0]->length, 1);
0051         QCOMPARE(items[1]->header, "itm1");
0052         QCOMPARE(items[2]->header, "itm2");
0053         QCOMPARE(items[3]->header, "itm3");
0054         QCOMPARE(items[4], nullptr);
0055     }
0056 
0057     void test_big_endian_u8()
0058     {
0059         auto endian = Endianness::Big();
0060         auto data = QByteArrayLiteral("\x69");
0061         auto value = 0x69;
0062         QCOMPARE(endian.read_uint<1>(data), value);
0063         QCOMPARE(endian.read_uint<std::uint8_t>(data), value);
0064     }
0065 
0066     void test_big_endian_u16()
0067     {
0068         auto endian = Endianness::Big();
0069         auto data = QByteArrayLiteral("\x13\x37");
0070         auto value = 0x1337;
0071         QCOMPARE(endian.read_uint<2>(data), value);
0072         QCOMPARE(endian.read_uint<std::uint16_t>(data), value);
0073     }
0074 
0075     void test_big_endian_u32()
0076     {
0077         auto endian = Endianness::Big();
0078         auto data = QByteArrayLiteral("\x13\x37\x04\x20");
0079         auto value = 0x13370420;
0080         QCOMPARE(endian.read_uint<4>(data), value);
0081         QCOMPARE(endian.read_uint<std::uint32_t>(data), value);
0082     }
0083 
0084     void test_big_endian_s8()
0085     {
0086         auto endian = Endianness::Big();
0087         auto data = QByteArrayLiteral("\x69");
0088         auto value = 0x69;
0089         QCOMPARE(endian.read_sint<1>(data), value);
0090         QCOMPARE(endian.read_sint<std::int8_t>(data), value);
0091     }
0092 
0093     void test_big_endian_s16()
0094     {
0095         auto endian = Endianness::Big();
0096         auto data = QByteArrayLiteral("\x13\x37");
0097         auto value = 0x1337;
0098         QCOMPARE(endian.read_sint<2>(data), value);
0099         QCOMPARE(endian.read_sint<std::uint16_t>(data), value);
0100     }
0101 
0102     void test_big_endian_s32()
0103     {
0104         auto endian = Endianness::Big();
0105         auto data = QByteArrayLiteral("\x13\x37\x04\x20");
0106         auto value = 0x13370420;
0107         QCOMPARE(endian.read_sint<4>(data), value);
0108         QCOMPARE(endian.read_sint<std::int32_t>(data), value);
0109     }
0110 
0111 
0112     void test_big_endian_s8_neg()
0113     {
0114         auto endian = Endianness::Big();
0115         auto data = QByteArrayLiteral("\x97");
0116         auto value = -0x69;
0117         QCOMPARE(endian.read_sint<1>(data), value);
0118         QCOMPARE(endian.read_sint<std::int8_t>(data), value);
0119     }
0120 
0121     void test_big_endian_s16_neg()
0122     {
0123         auto endian = Endianness::Big();
0124         auto data = QByteArrayLiteral("\xff\x97");
0125         auto value = -0x69;
0126         QCOMPARE(std::int16_t(std::uint16_t(0xff97)), value);
0127         QCOMPARE(endian.read_sint<2>(data), value);
0128         QCOMPARE(endian.read_sint<std::int16_t>(data), value);
0129     }
0130 
0131     void test_big_endian_s32_neg()
0132     {
0133         auto endian = Endianness::Big();
0134         auto data = QByteArrayLiteral("\xff\xff\xff\x97");
0135         auto value = -0x69;
0136         QCOMPARE(endian.read_sint<4>(data), value);
0137         QCOMPARE(endian.read_sint<std::int32_t>(data), value);
0138     }
0139 
0140 
0141     void test_little_endian_u8()
0142     {
0143         auto endian = Endianness::Little();
0144         auto data = QByteArrayLiteral("\x69");
0145         auto value = 0x69;
0146         QCOMPARE(endian.read_uint<1>(data), value);
0147         QCOMPARE(endian.read_uint<std::uint8_t>(data), value);
0148     }
0149 
0150     void test_little_endian_u16()
0151     {
0152         auto endian = Endianness::Little();
0153         auto data = QByteArrayLiteral("\x37\x13");
0154         auto value = 0x1337;
0155         QCOMPARE(endian.read_uint<2>(data), value);
0156         QCOMPARE(endian.read_uint<std::uint16_t>(data), value);
0157     }
0158 
0159     void test_little_endian_u32()
0160     {
0161         auto endian = Endianness::Little();
0162         auto data = QByteArrayLiteral("\x20\x04\x37\x13");
0163         auto value = 0x13370420;
0164         QCOMPARE(endian.read_uint<4>(data), value);
0165         QCOMPARE(endian.read_uint<std::uint32_t>(data), value);
0166     }
0167 
0168     void test_little_endian_s8()
0169     {
0170         auto endian = Endianness::Little();
0171         auto data = QByteArrayLiteral("\x69");
0172         auto value = 0x69;
0173         QCOMPARE(endian.read_sint<1>(data), value);
0174         QCOMPARE(endian.read_sint<std::int8_t>(data), value);
0175     }
0176 
0177     void test_little_endian_s16()
0178     {
0179         auto endian = Endianness::Little();
0180         auto data = QByteArrayLiteral("\x37\x13");
0181         auto value = 0x1337;
0182         QCOMPARE(endian.read_sint<2>(data), value);
0183         QCOMPARE(endian.read_sint<std::uint16_t>(data), value);
0184     }
0185 
0186     void test_little_endian_s32()
0187     {
0188         auto endian = Endianness::Little();
0189         auto data = QByteArrayLiteral("\x20\x04\x37\x13");
0190         auto value = 0x13370420;
0191         QCOMPARE(endian.read_sint<4>(data), value);
0192         QCOMPARE(endian.read_sint<std::int32_t>(data), value);
0193     }
0194 
0195 
0196     void test_little_endian_s8_neg()
0197     {
0198         auto endian = Endianness::Little();
0199         auto data = QByteArrayLiteral("\x97");
0200         auto value = -0x69;
0201         QCOMPARE(endian.read_sint<1>(data), value);
0202         QCOMPARE(endian.read_sint<std::int8_t>(data), value);
0203     }
0204 
0205     void test_little_endian_s16_neg()
0206     {
0207         auto endian = Endianness::Little();
0208         auto data = QByteArrayLiteral("\x97\xff");
0209         auto value = -0x69;
0210         QCOMPARE(std::int16_t(std::uint16_t(0xff97)), value);
0211         QCOMPARE(endian.read_sint<2>(data), value);
0212         QCOMPARE(endian.read_sint<std::int16_t>(data), value);
0213     }
0214 
0215     void test_little_endian_s32_neg()
0216     {
0217         auto endian = Endianness::Little();
0218         auto data = QByteArrayLiteral("\x97\xff\xff\xff");
0219         auto value = -0x69;
0220         QCOMPARE(endian.read_sint<4>(data), value);
0221         QCOMPARE(endian.read_sint<std::int32_t>(data), value);
0222     }
0223 
0224     void test_big_endian_f32()
0225     {
0226         auto endian = Endianness::Big();
0227         QCOMPARE(endian.read_float32(QByteArrayLiteral("\x3f\x80\x00\x00")), 1.f);
0228         QCOMPARE(endian.read_float32(QByteArrayLiteral("\x44\xa7\x20\x00")), 1337.f);
0229         QCOMPARE(endian.read_float32(QByteArrayLiteral("\xc2\x8a\x00\x00")), -69.f);
0230     }
0231 
0232     void test_big_endian_f64()
0233     {
0234         auto endian = Endianness::Big();
0235         QCOMPARE(endian.read_float64(QByteArrayLiteral("\x3f\xf0\x00\x00\x00\x00\x00\x00")), 1.);
0236         QCOMPARE(endian.read_float64(QByteArrayLiteral("\x40\x94\xe4\x00\x00\x00\x00\x00")), 1337.);
0237         QCOMPARE(endian.read_float64(QByteArrayLiteral("\xc0\x51\x40\x00\x00\x00\x00\x00")), -69.);
0238     }
0239 
0240     void test_rifx_reader_root()
0241     {
0242         QByteArray arr = QByteArrayLiteral(
0243             "RIFX\x00\x00\x00\x04rawr"
0244         );
0245         QBuffer file(&arr);
0246         file.open(QIODevice::ReadOnly);
0247         RiffReader reader;
0248         auto chunk = reader.parse(&file);
0249         QCOMPARE(chunk.header, "RIFX");
0250         QCOMPARE(chunk.length, 4);
0251         QCOMPARE(chunk.subheader, "rawr");
0252         QCOMPARE(chunk.data().size(), 0);
0253         QCOMPARE(chunk.children.size(), 0);
0254     }
0255 
0256     void test_rifx_reader_chunk()
0257     {
0258         QByteArray arr = QByteArrayLiteral(
0259             "RIFX\x00\x00\x00\x28rawrawoo\0\0\0\4\1\2\3\4awoo\0\0\0\3\1\2\3\0awoo\0\0\0\4\1\2\3\4"
0260         );
0261         QBuffer file(&arr);
0262         file.open(QIODevice::ReadOnly);
0263         RiffReader reader;
0264         auto chunk = reader.parse(&file);
0265         QCOMPARE(chunk.header, "RIFX");
0266         QCOMPARE(chunk.length, 40);
0267         QCOMPARE(chunk.subheader, "rawr");
0268         QCOMPARE(chunk.data().size(), 0);
0269         QCOMPARE(chunk.children.size(), 3);
0270 
0271         auto child = chunk.children[0].get();
0272         QCOMPARE(child->header, "awoo");
0273         QCOMPARE(child->length, 4);
0274         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0275         QCOMPARE(child->children.size(), 0);
0276 
0277         child = chunk.children[1].get();
0278         QCOMPARE(child->header, "awoo");
0279         QCOMPARE(child->length, 3);
0280         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3"));
0281         QCOMPARE(child->children.size(), 0);
0282 
0283         child = chunk.children[2].get();
0284         QCOMPARE(child->header, "awoo");
0285         QCOMPARE(child->length, 4);
0286         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0287         QCOMPARE(child->children.size(), 0);
0288     }
0289 
0290 
0291     void test_rifx_reader_list()
0292     {
0293         QByteArray arr = QByteArrayLiteral(
0294             "RIFX\x00\x00\x00\x34rawrLIST\0\0\0\x28listawoo\0\0\0\4\1\2\3\4awoo\0\0\0\3\1\2\3\0awoo\0\0\0\4\1\2\3\4"
0295         );
0296         QBuffer file(&arr);
0297         file.open(QIODevice::ReadOnly);
0298         RiffReader reader;
0299         auto chunk = reader.parse(&file);
0300         QCOMPARE(chunk.header, "RIFX");
0301         QCOMPARE(chunk.length, 52);
0302         QCOMPARE(chunk.subheader, "rawr");
0303         QCOMPARE(chunk.data().size(), 0);
0304         QCOMPARE(chunk.children.size(), 1);
0305 
0306         auto list = chunk.children[0].get();
0307         QCOMPARE(list->header, "LIST");
0308         QCOMPARE(list->subheader, "list");
0309         QCOMPARE(list->length, 40);
0310         QCOMPARE(list->data().size(), 0);
0311         QCOMPARE(list->children.size(), 3);
0312 
0313         auto child = list->children[0].get();
0314         QCOMPARE(child->header, "awoo");
0315         QCOMPARE(child->length, 4);
0316         QCOMPARE(child->data().size(), 4);
0317         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0318         QCOMPARE(child->children.size(), 0);
0319 
0320         child = list->children[1].get();
0321         QCOMPARE(child->header, "awoo");
0322         QCOMPARE(child->length, 3);
0323         QCOMPARE(child->data().size(), 3);
0324         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3"));
0325         QCOMPARE(child->children.size(), 0);
0326 
0327         child = list->children[2].get();
0328         QCOMPARE(child->header, "awoo");
0329         QCOMPARE(child->length, 4);
0330         QCOMPARE(child->data().size(), 4);
0331         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0332         QCOMPARE(child->children.size(), 0);
0333     }
0334 
0335     void test_riff_reader_list()
0336     {
0337         QByteArray arr = QByteArrayLiteral(
0338             "RIFF\x34\x00\x00\x00rawrLIST\x28\0\0\0listawoo\4\0\0\0\1\2\3\4awoo\3\0\0\0\1\2\3\0awoo\4\0\0\0\1\2\3\4"
0339         );
0340         QBuffer file(&arr);
0341         file.open(QIODevice::ReadOnly);
0342         RiffReader reader;
0343         auto chunk = reader.parse(&file);
0344         QCOMPARE(chunk.header, "RIFF");
0345         QCOMPARE(chunk.length, 52);
0346         QCOMPARE(chunk.subheader, "rawr");
0347         QCOMPARE(chunk.data().size(), 0);
0348         QCOMPARE(chunk.children.size(), 1);
0349 
0350         auto list = chunk.children[0].get();
0351         QCOMPARE(list->header, "LIST");
0352         QCOMPARE(list->subheader, "list");
0353         QCOMPARE(list->length, 40);
0354         QCOMPARE(list->data().size(), 0);
0355         QCOMPARE(list->children.size(), 3);
0356 
0357         auto child = list->children[0].get();
0358         QCOMPARE(child->header, "awoo");
0359         QCOMPARE(child->length, 4);
0360         QCOMPARE(child->data().size(), 4);
0361         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0362         QCOMPARE(child->children.size(), 0);
0363 
0364         child = list->children[1].get();
0365         QCOMPARE(child->header, "awoo");
0366         QCOMPARE(child->length, 3);
0367         QCOMPARE(child->data().size(), 3);
0368         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3"));
0369         QCOMPARE(child->children.size(), 0);
0370 
0371         child = list->children[2].get();
0372         QCOMPARE(child->header, "awoo");
0373         QCOMPARE(child->length, 4);
0374         QCOMPARE(child->data().size(), 4);
0375         QCOMPARE(child->data().read(), QByteArrayLiteral("\1\2\3\4"));
0376         QCOMPARE(child->children.size(), 0);
0377     }
0378 
0379     void test_flags()
0380     {
0381         Flags flag(0b1000'0100'0010'0001);
0382         QCOMPARE(flag.get(1, 7), true);
0383         QCOMPARE(flag.get(1, 6), false);
0384         QCOMPARE(flag.get(1, 5), false);
0385         QCOMPARE(flag.get(1, 4), false);
0386         QCOMPARE(flag.get(1, 3), false);
0387         QCOMPARE(flag.get(1, 2), true);
0388         QCOMPARE(flag.get(1, 1), false);
0389         QCOMPARE(flag.get(1, 0), false);
0390 
0391         QCOMPARE(flag.get(0, 7), false);
0392         QCOMPARE(flag.get(0, 6), false);
0393         QCOMPARE(flag.get(0, 5), true);
0394         QCOMPARE(flag.get(0, 4), false);
0395         QCOMPARE(flag.get(0, 3), false);
0396         QCOMPARE(flag.get(0, 2), false);
0397         QCOMPARE(flag.get(0, 1), false);
0398         QCOMPARE(flag.get(0, 0), true);
0399     }
0400 };
0401 
0402 QTEST_GUILESS_MAIN(TestCase)
0403 #include "test_riff.moc"
0404