/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/base/memory.h" #include "third_party/catch/include/catch.hpp" #include "third_party/fmt/include/fmt/format.h" #include "xenia/base/clock.h" #include namespace xe { namespace base { namespace test { TEST_CASE("copy_128_aligned", "[copy_and_swap]") { alignas(128) uint8_t src[256], dest[256]; for (uint8_t i = 0; i < 255; ++i) { src[i] = 255 - i; } std::memset(dest, 0, sizeof(dest)); copy_128_aligned(dest, src, 1); REQUIRE(std::memcmp(dest, src, 128)); REQUIRE(dest[128] == 0); std::memset(dest, 0, sizeof(dest)); copy_128_aligned(dest, src, 2); REQUIRE(std::memcmp(dest, src, 256)); std::memset(dest, 0, sizeof(dest)); copy_128_aligned(dest, src + 1, 1); REQUIRE(std::memcmp(dest, src + 1, 128)); } TEST_CASE("copy_and_swap_16_aligned", "[copy_and_swap]") { alignas(16) uint16_t a = 0x1111, b = 0xABCD; copy_and_swap_16_aligned(&a, &b, 1); REQUIRE(a == 0xCDAB); REQUIRE(b == 0xABCD); alignas(16) uint16_t c[] = {0x0000, 0x0000, 0x0000, 0x0000}; alignas(16) uint16_t d[] = {0x0123, 0x4567, 0x89AB, 0xCDEF}; copy_and_swap_16_aligned(c, d, 1); REQUIRE(c[0] == 0x2301); REQUIRE(c[1] == 0x0000); REQUIRE(c[2] == 0x0000); REQUIRE(c[3] == 0x0000); copy_and_swap_16_aligned(c, d, 3); REQUIRE(c[0] == 0x2301); REQUIRE(c[1] == 0x6745); REQUIRE(c[2] == 0xAB89); REQUIRE(c[3] == 0x0000); copy_and_swap_16_aligned(c, d, 4); REQUIRE(c[0] == 0x2301); REQUIRE(c[1] == 0x6745); REQUIRE(c[2] == 0xAB89); REQUIRE(c[3] == 0xEFCD); alignas(16) uint64_t e; copy_and_swap_16_aligned(&e, d, 4); REQUIRE(e == 0xEFCDAB8967452301); alignas(16) char f[85] = {0x00}; alignas(16) char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_16_aligned(f, g, 42); REQUIRE(std::strcmp(f, "hTsii s a58b ty eolgns rtni.g..I 't susppsodet oebl " "noeg rhtnas atdnra dlagimnne.t") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_16_aligned(f, g + 16, 34); REQUIRE(std::strcmp(f, " eolgns rtni.g..I 't susppsodet oebl " "noeg rhtnas atdnra dlagimnne.t") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_16_aligned(f, g + 32, 26); REQUIRE(std::strcmp(f, "I 't susppsodet oebl " "noeg rhtnas atdnra dlagimnne.t") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_16_aligned(f, g + 64, 10); REQUIRE(std::strcmp(f, "s atdnra dlagimnne.t") == 0); } TEST_CASE("copy_and_swap_16_unaligned", "[copy_and_swap]") { uint16_t a = 0x1111, b = 0xABCD; copy_and_swap_16_unaligned(&a, &b, 1); REQUIRE(a == 0xCDAB); REQUIRE(b == 0xABCD); uint16_t c[] = {0x0000, 0x0000, 0x0000, 0x0000}; uint16_t d[] = {0x0123, 0x4567, 0x89AB, 0xCDEF}; copy_and_swap_16_unaligned(c, d, 1); REQUIRE(c[0] == 0x2301); REQUIRE(c[1] == 0x0000); REQUIRE(c[2] == 0x0000); REQUIRE(c[3] == 0x0000); copy_and_swap_16_unaligned(c, d, 4); REQUIRE(c[0] == 0x2301); REQUIRE(c[1] == 0x6745); REQUIRE(c[2] == 0xAB89); REQUIRE(c[3] == 0xEFCD); { constexpr size_t count = 100; std::array src{}; std::array dst{}; for (size_t i = 0; i < src.size(); ++i) { src[i] = static_cast(i) + 1; // no zero in array } copy_and_swap_16_unaligned(dst.data(), src.data(), count); for (size_t i = 0; i < src.size(); i += 2) { // Check src is untouched REQUIRE(static_cast(src[i + 0]) == i + 1); REQUIRE(static_cast(src[i + 1]) == i + 2); // Check swapped bytes REQUIRE(static_cast(dst[i]) == static_cast(src[i + 1])); REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i])); } } uint64_t e; copy_and_swap_16_unaligned(&e, d, 4); REQUIRE(e == 0xEFCDAB8967452301); char f[85] = {0x00}; char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_16_unaligned(f, g, 42); REQUIRE(std::strcmp(f, "hTsii s a58b ty eolgns rtni.g..I 't susppsodet oebl " "noeg rhtnas atdnra dlagimnne.t") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_16_unaligned(f, g + 1, 41); REQUIRE(std::strcmp(f, "ih ssia 8 5ybetl no gtsirgn.. .tIs's puopes dotb " "eolgnret ah ntsnaaddra ilngemtn") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_16_unaligned(f, g + 2, 41); REQUIRE(std::strcmp(f, "sii s a58b ty eolgns rtni.g..I 't susppsodet oebl " "noeg rhtnas atdnra dlagimnne.t") == 0); } TEST_CASE("copy_and_swap_32_aligned", "[copy_and_swap]") { alignas(32) uint32_t a = 0x11111111, b = 0x89ABCDEF; copy_and_swap_32_aligned(&a, &b, 1); REQUIRE(a == 0xEFCDAB89); REQUIRE(b == 0x89ABCDEF); alignas(32) uint32_t c[] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; alignas(32) uint32_t d[] = {0x01234567, 0x89ABCDEF, 0xE887EEED, 0xD8514199}; copy_and_swap_32_aligned(c, d, 1); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0x00000000); REQUIRE(c[2] == 0x00000000); REQUIRE(c[3] == 0x00000000); copy_and_swap_32_aligned(c, d, 3); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0xEFCDAB89); REQUIRE(c[2] == 0xEDEE87E8); REQUIRE(c[3] == 0x00000000); copy_and_swap_32_aligned(c, d, 4); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0xEFCDAB89); REQUIRE(c[2] == 0xEDEE87E8); REQUIRE(c[3] == 0x994151D8); alignas(32) uint64_t e; copy_and_swap_32_aligned(&e, d, 2); REQUIRE(e == 0xEFCDAB8967452301); alignas(32) char f[85] = {0x00}; alignas(32) char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_32_aligned(f, g, 21); REQUIRE(std::strcmp(f, "sihT si 58 atyb ol es gnnirt...g'tI us ssoppt deeb " "onol regnahtats radnla dmngi.tne") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_aligned(f, g + 16, 17); REQUIRE(std::strcmp(f, "ol es gnnirt...g'tI us ssoppt deeb " "onol regnahtats radnla dmngi.tne") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_aligned(f, g + 32, 13); REQUIRE(std::strcmp(f, "'tI us ssoppt deeb " "onol regnahtats radnla dmngi.tne") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_aligned(f, g + 64, 5); REQUIRE(std::strcmp(f, "ats radnla dmngi.tne") == 0); } TEST_CASE("copy_and_swap_32_unaligned", "[copy_and_swap]") { uint32_t a = 0x11111111, b = 0x89ABCDEF; copy_and_swap_32_unaligned(&a, &b, 1); REQUIRE(a == 0xEFCDAB89); REQUIRE(b == 0x89ABCDEF); uint32_t c[] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; uint32_t d[] = {0x01234567, 0x89ABCDEF, 0xE887EEED, 0xD8514199}; copy_and_swap_32_unaligned(c, d, 1); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0x00000000); REQUIRE(c[2] == 0x00000000); REQUIRE(c[3] == 0x00000000); copy_and_swap_32_unaligned(c, d, 3); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0xEFCDAB89); REQUIRE(c[2] == 0xEDEE87E8); REQUIRE(c[3] == 0x00000000); copy_and_swap_32_unaligned(c, d, 4); REQUIRE(c[0] == 0x67452301); REQUIRE(c[1] == 0xEFCDAB89); REQUIRE(c[2] == 0xEDEE87E8); REQUIRE(c[3] == 0x994151D8); { constexpr size_t count = 17; std::array src{}; std::array dst{}; for (size_t i = 0; i < src.size(); ++i) { src[i] = static_cast(i) + 1; // no zero in array } copy_and_swap_32_unaligned(dst.data(), src.data(), count); for (size_t i = 0; i < src.size(); i += 4) { // Check src is untouched REQUIRE(static_cast(src[i + 0]) == i + 1); REQUIRE(static_cast(src[i + 1]) == i + 2); REQUIRE(static_cast(src[i + 2]) == i + 3); REQUIRE(static_cast(src[i + 3]) == i + 4); // Check swapped bytes REQUIRE(static_cast(dst[i + 0]) == static_cast(src[i + 3])); REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i + 2])); REQUIRE(static_cast(dst[i + 2]) == static_cast(src[i + 1])); REQUIRE(static_cast(dst[i + 3]) == static_cast(src[i + 0])); } } uint64_t e; copy_and_swap_32_unaligned(&e, d, 2); REQUIRE(e == 0xEFCDAB8967452301); char f[85] = {0x00}; char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_32_unaligned(f, g, 21); REQUIRE(std::strcmp(f, "sihT si 58 atyb ol es gnnirt...g'tI us ssoppt deeb " "onol regnahtats radnla dmngi.tne") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_unaligned(f, g + 1, 20); REQUIRE(std::strcmp(f, " siha si 58 etybnol ts ggnir ...s'tIpus esopot d eb " "gnolt re nahnatsdradila emng") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_unaligned(f, g + 2, 20); REQUIRE(std::strcmp(f, "i si a sb 58 etygnolrts .gniI .. s'tppusdeso ot l " "ebegnoht rs nadnat dragilanemn") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_unaligned(f, g + 3, 20); REQUIRE(std::strcmp(f, "si s8 a yb 5l et gnoirts..gntI .s s'oppu desb otol " "eregnaht ts nadnaa drngiltnem") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_32_unaligned(f, g + 4, 20); REQUIRE(std::strcmp(f, " si 58 atyb ol es gnnirt...g'tI us ssoppt deeb onol " "regnahtats radnla dmngi.tne") == 0); } TEST_CASE("copy_and_swap_64_aligned", "[copy_and_swap]") { alignas(64) uint64_t a = 0x1111111111111111, b = 0x0123456789ABCDEF; copy_and_swap_64_aligned(&a, &b, 1); REQUIRE(a == 0xEFCDAB8967452301); REQUIRE(b == 0x0123456789ABCDEF); alignas(64) uint64_t c[] = {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}; alignas(64) uint64_t d[] = {0x0123456789ABCDEF, 0xE887EEEDD8514199, 0x21D4745A1D4A7706, 0xA4174FED675766E3}; copy_and_swap_64_aligned(c, d, 1); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x0000000000000000); REQUIRE(c[2] == 0x0000000000000000); REQUIRE(c[3] == 0x0000000000000000); copy_and_swap_64_aligned(c, d, 3); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x994151D8EDEE87E8); REQUIRE(c[2] == 0x06774A1D5A74D421); REQUIRE(c[3] == 0x0000000000000000); copy_and_swap_64_aligned(c, d, 4); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x994151D8EDEE87E8); REQUIRE(c[2] == 0x06774A1D5A74D421); REQUIRE(c[3] == 0xE3665767ED4F17A4); alignas(64) uint64_t e; copy_and_swap_64_aligned(&e, d, 1); REQUIRE(e == 0xEFCDAB8967452301); alignas(64) char f[85] = {0x00}; alignas(64) char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_64_aligned(f, g, 10); REQUIRE(std::strcmp(f, " si sihTtyb 58 as gnol e...gnirtus s'tI t desoppnol eb " "onaht regradnats mngila d") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_aligned(f, g + 16, 8); REQUIRE(std::strcmp(f, "s gnol e...gnirtus s'tI t desoppnol eb " "onaht regradnats mngila d") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_aligned(f, g + 32, 6); REQUIRE(std::strcmp(f, "us s'tI t desoppnol eb " "onaht regradnats mngila d") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_aligned(f, g + 64, 2); REQUIRE(std::strcmp(f, "radnats mngila d") == 0); } TEST_CASE("copy_and_swap_64_unaligned", "[copy_and_swap]") { uint64_t a = 0x1111111111111111, b = 0x0123456789ABCDEF; copy_and_swap_64_unaligned(&a, &b, 1); REQUIRE(a == 0xEFCDAB8967452301); REQUIRE(b == 0x0123456789ABCDEF); uint64_t c[] = {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}; uint64_t d[] = {0x0123456789ABCDEF, 0xE887EEEDD8514199, 0x21D4745A1D4A7706, 0xA4174FED675766E3}; copy_and_swap_64_unaligned(c, d, 1); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x0000000000000000); REQUIRE(c[2] == 0x0000000000000000); REQUIRE(c[3] == 0x0000000000000000); copy_and_swap_64_unaligned(c, d, 3); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x994151D8EDEE87E8); REQUIRE(c[2] == 0x06774A1D5A74D421); REQUIRE(c[3] == 0x0000000000000000); copy_and_swap_64_unaligned(c, d, 4); REQUIRE(c[0] == 0xEFCDAB8967452301); REQUIRE(c[1] == 0x994151D8EDEE87E8); REQUIRE(c[2] == 0x06774A1D5A74D421); REQUIRE(c[3] == 0xE3665767ED4F17A4); uint64_t e; copy_and_swap_64_unaligned(&e, d, 1); REQUIRE(e == 0xEFCDAB8967452301); char f[85] = {0x00}; char g[] = "This is a 85 byte long string... " "It's supposed to be longer than standard alignment."; copy_and_swap_64_unaligned(f, g, 10); REQUIRE(std::strcmp(f, " si sihTtyb 58 as gnol e...gnirtus s'tI t desoppnol eb " "onaht regradnats mngila d") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 1, 10); REQUIRE(std::strcmp(f, "a si sihetyb 58 ts gnol ...gnirpus s'tIot desopgnol " "eb naht redradnatsemngila ") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 2, 10); REQUIRE(std::strcmp(f, " a si si etyb 58rts gnolI ...gnippus s't ot desoegnol " "ebs naht r dradnatnemngila") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 3, 10); REQUIRE(std::strcmp(f, "8 a si sl etyb 5irts gnotI ...gnoppus s'b ot desregnol " "ets naht a dradnatnemngil") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 4, 10); REQUIRE(std::strcmp(f, "58 a si ol etyb nirts gn'tI ...gsoppus seb ot de " "regnol ats nahtla dradn.tnemngi") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 5, 9); REQUIRE(std::strcmp(f, " 58 a sinol etybgnirts gs'tI ...esoppus eb ot dt " "regnolnats nahila drad") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 6, 9); REQUIRE(std::strcmp(f, "b 58 a sgnol ety.gnirts s'tI ..desoppusl eb ot ht " "regnodnats nagila dra") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 7, 9); REQUIRE(std::strcmp(f, "yb 58 a gnol et..gnirtss s'tI . desoppuol eb otaht " "regnadnats nngila dr") == 0); std::memset(f, 0, sizeof(f)); copy_and_swap_64_unaligned(f, g + 8, 9); REQUIRE(std::strcmp(f, "tyb 58 as gnol e...gnirtus s'tI t desoppnol eb onaht " "regradnats mngila d") == 0); } TEST_CASE("copy_and_swap_16_in_32_aligned", "[copy_and_swap]") { constexpr size_t count = 17; alignas(16) std::array src{}; alignas(16) std::array dst{}; // Check alignment (if this fails, adjust allocation) REQUIRE((reinterpret_cast(src.data()) & 0xF) == 0); REQUIRE((reinterpret_cast(dst.data()) & 0xF) == 0); for (size_t i = 0; i < src.size(); ++i) { src[i] = static_cast(i) + 1; // no zero in array } copy_and_swap_16_in_32_aligned(dst.data(), src.data(), count); for (size_t i = 0; i < src.size(); i += 4) { // Check src is untouched REQUIRE(static_cast(src[i + 0]) == i + 1); REQUIRE(static_cast(src[i + 1]) == i + 2); REQUIRE(static_cast(src[i + 2]) == i + 3); REQUIRE(static_cast(src[i + 3]) == i + 4); // Check swapped bytes REQUIRE(static_cast(dst[i + 0]) == static_cast(src[i + 2])); REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i + 3])); REQUIRE(static_cast(dst[i + 2]) == static_cast(src[i + 0])); REQUIRE(static_cast(dst[i + 3]) == static_cast(src[i + 1])); } } TEST_CASE("copy_and_swap_16_in_32_unaligned", "[copy_and_swap]") { constexpr size_t count = 17; std::array src{}; std::array dst{}; for (size_t i = 0; i < src.size(); ++i) { src[i] = static_cast(i) + 1; // no zero in array } copy_and_swap_16_in_32_unaligned(dst.data(), src.data(), count); for (size_t i = 0; i < src.size(); i += 4) { // Check src is untouched REQUIRE(static_cast(src[i + 0]) == i + 1); REQUIRE(static_cast(src[i + 1]) == i + 2); REQUIRE(static_cast(src[i + 2]) == i + 3); REQUIRE(static_cast(src[i + 3]) == i + 4); // Check swapped bytes REQUIRE(static_cast(dst[i + 0]) == static_cast(src[i + 2])); REQUIRE(static_cast(dst[i + 1]) == static_cast(src[i + 3])); REQUIRE(static_cast(dst[i + 2]) == static_cast(src[i + 0])); REQUIRE(static_cast(dst[i + 3]) == static_cast(src[i + 1])); } } TEST_CASE("create_and_close_file_mapping", "Virtual Memory Mapping") { auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount()); auto memory = xe::memory::CreateFileMappingHandle( path, 0x100, xe::memory::PageAccess::kReadWrite, true); REQUIRE(memory != xe::memory::kFileMappingHandleInvalid); xe::memory::CloseFileMappingHandle(memory, path); } TEST_CASE("map_view", "[virtual_memory_mapping]") { auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount()); constexpr size_t length = 0x100; auto memory = xe::memory::CreateFileMappingHandle( path, length, xe::memory::PageAccess::kReadWrite, true); REQUIRE(memory != xe::memory::kFileMappingHandleInvalid); uintptr_t address = 0x100000000; auto view = xe::memory::MapFileView(memory, reinterpret_cast(address), length, xe::memory::PageAccess::kReadWrite, 0); REQUIRE(reinterpret_cast(view) == address); xe::memory::UnmapFileView(memory, reinterpret_cast(address), length); xe::memory::CloseFileMappingHandle(memory, path); } TEST_CASE("read_write_view", "[virtual_memory_mapping]") { constexpr size_t length = 0x100; auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount()); auto memory = xe::memory::CreateFileMappingHandle( path, length, xe::memory::PageAccess::kReadWrite, true); REQUIRE(memory != xe::memory::kFileMappingHandleInvalid); uintptr_t address = 0x100000000; auto view = xe::memory::MapFileView(memory, reinterpret_cast(address), length, xe::memory::PageAccess::kReadWrite, 0); REQUIRE(reinterpret_cast(view) == address); for (uint32_t i = 0; i < length; i += sizeof(uint8_t)) { auto p_value = reinterpret_cast(address + i); *p_value = i; } for (uint32_t i = 0; i < length; i += sizeof(uint8_t)) { auto p_value = reinterpret_cast(address + i); uint8_t value = *p_value; REQUIRE(value == i); } xe::memory::UnmapFileView(memory, reinterpret_cast(address), length); xe::memory::CloseFileMappingHandle(memory, path); } TEST_CASE("make_fourcc", "[fourcc]") { SECTION("'1234'") { const uint32_t fourcc_host = 0x31323334; constexpr fourcc_t fourcc_1 = make_fourcc('1', '2', '3', '4'); constexpr fourcc_t fourcc_2 = make_fourcc("1234"); REQUIRE(fourcc_1 == fourcc_host); REQUIRE(fourcc_2 == fourcc_host); REQUIRE(fourcc_1 == fourcc_2); REQUIRE(fourcc_2 == fourcc_1); } SECTION("'ABcd'") { const uint32_t fourcc_host = 0x41426364; constexpr fourcc_t fourcc_1 = make_fourcc('A', 'B', 'c', 'd'); constexpr fourcc_t fourcc_2 = make_fourcc("ABcd"); REQUIRE(fourcc_1 == fourcc_host); REQUIRE(fourcc_2 == fourcc_host); REQUIRE(fourcc_1 == fourcc_2); REQUIRE(fourcc_2 == fourcc_1); } SECTION("'XEN\\0'") { const uint32_t fourcc_host = 0x58454E00; constexpr fourcc_t fourcc = make_fourcc('X', 'E', 'N', '\0'); REQUIRE(fourcc == fourcc_host); } SECTION("length()!=4") { REQUIRE_THROWS(make_fourcc("AB\0\0")); REQUIRE_THROWS(make_fourcc("AB\0\0AB")); REQUIRE_THROWS(make_fourcc("ABCDEFGH")); } } } // namespace test } // namespace base } // namespace xe