tests: xml tests, and a discovered regression

This commit is contained in:
Will Toohey 2025-06-30 19:44:24 +10:00
parent 6b7c43d412
commit 0123317f01
6 changed files with 99 additions and 40 deletions

View File

@ -394,30 +394,7 @@ bool rapidxml_from_avs_filepath(
return false;
}
// if it's not binary, don't even bother parsing with avs
char* xml = NULL;
if (is_binary_prop(f)) {
auto prop = prop_from_file_handle(f);
if (!prop)
return false;
xml = prop_to_xml_string(prop, doc_to_allocate_with);
prop_free(prop);
}
else {
xml = avs_file_to_string(f, doc_to_allocate_with);
}
avs_fs_close(f);
try {
// parse_declaration_node: to get the header <?xml version="1.0" encoding="shift-jis"?>
doc.parse<rapidxml::parse_declaration_node | rapidxml::parse_no_utf8>(xml);
} catch (const rapidxml::parse_error& e) {
log_warning("Couldn't parse xml (%s byte %d)", e.what(), (int)(e.where<char>() - xml));
return false;
}
return true;
return rapidxml_from_avs_file(f, doc, doc_to_allocate_with);
}
// the given property MUST have been created with an 8-byte aligned memory

View File

@ -6,6 +6,8 @@
#include <vector>
using std::string;
#include "log.hpp"
#include "3rd_party/rapidxml.hpp"
/*
@ -238,3 +240,42 @@ static inline uint16_t avs_open_mode_read() {
return 0;
}
}
// just used by rapidxml_from_avs_file
bool is_binary_prop(AVS_FILE f);
char* prop_to_xml_string(property_t prop, rapidxml::xml_document<>& allocator);
// parse_declaration_node: to get the header <?xml version="1.0" encoding="shift-jis"?>
template<int Flags = rapidxml::parse_declaration_node | rapidxml::parse_no_utf8>
bool rapidxml_from_avs_file(
AVS_FILE f,
rapidxml::xml_document<>& doc,
rapidxml::xml_document<>& doc_to_allocate_with
) {
// if it's not binary, don't even bother parsing with avs
char* xml = NULL;
if (is_binary_prop(f)) {
auto prop = prop_from_file_handle(f);
if (!prop)
return false;
xml = prop_to_xml_string(prop, doc_to_allocate_with);
prop_free(prop);
}
else {
xml = avs_file_to_string(f, doc_to_allocate_with);
}
avs_fs_close(f);
try {
doc.parse<Flags>(xml);
} catch (const rapidxml::parse_error& e) {
log_warning("Couldn't parse xml (%s byte %d)", e.what(), (int)(e.where<char>() - xml));
auto f = fopen("debug.xml", "wb");
fwrite(xml, strlen(xml), 1, f);
return false;
}
return true;
}

View File

@ -134,7 +134,10 @@ static const char *boot_cfg = R"(<?xml version="1.0" encoding="SHIFT_JIS"?>
<vfs name="boot" fstype="fs" src="dev/nvram" dst="/dev/nvram" opt="vf=0,posix=1"/>
</mounttable>
</fs>
<log><level>misc</level></log>
<log>
<level>misc</level>
<output_delay __type="u16">0</output_delay>
</log>
<sntp>
<ea_on __type="bool">0</ea_on>
<servers></servers>
@ -154,10 +157,14 @@ LONG WINAPI exc_handler(_EXCEPTION_POINTERS *ExceptionInfo) {
case DBG_PRINTEXCEPTION_C:
break;
default:
fprintf(stderr, "Unhandled exception %lX\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
log_warning("Unhandled exception code 0x%lX at %p\n",
ExceptionInfo->ExceptionRecord->ExceptionCode,
ExceptionInfo->ExceptionRecord->ExceptionAddress
);
break;
}
return EXCEPTION_CONTINUE_SEARCH;
}
}
} // namespace avs_standalone

View File

@ -1,3 +1,4 @@
#include <fstream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
@ -7,6 +8,8 @@
#include "avs_standalone.hpp"
#include "modpath_handler.h"
#include "3rd_party/rapidxml_print.hpp"
using ::testing::Contains;
using ::testing::Optional;
@ -156,43 +159,68 @@ TEST(Xml, MergingWorks) {
ASSERT_GT(f, 0);
rapidxml::xml_document<> xml_doc;
auto xml_text = avs_file_to_string(f, xml_doc);
avs_fs_close(f);
xml_doc.parse<rapidxml::parse_no_utf8>(xml_text);
bool res = rapidxml_from_avs_file<rapidxml::parse_no_utf8>(f, xml_doc, xml_doc);
ASSERT_TRUE(res);
auto node = xml_doc.first_node();
ASSERT_TRUE(node);
ASSERT_NE(node, nullptr);
EXPECT_STREQ(node->name(), "afplist");
node = node->first_node();
ASSERT_TRUE(node);
ASSERT_NE(node, nullptr);
EXPECT_STREQ(node->name(), "afp");
auto attr = node->first_attribute("name");
ASSERT_TRUE(attr);
ASSERT_NE(attr, nullptr);
EXPECT_STREQ(attr->value(), "hare");
auto geo = node->first_node("geo");
ASSERT_TRUE(geo);
ASSERT_NE(geo, nullptr);
EXPECT_STREQ(geo->value(), "5 10 15");
node = node->next_sibling();
ASSERT_TRUE(node);
ASSERT_NE(node, nullptr);
EXPECT_STREQ(node->name(), "afp");
attr = node->first_attribute("name");
ASSERT_TRUE(attr);
ASSERT_NE(attr, nullptr);
EXPECT_STREQ(attr->value(), "hare2");
geo = node->first_node("geo");
ASSERT_TRUE(geo);
ASSERT_NE(geo, nullptr);
EXPECT_STREQ(geo->value(), "20 25 30");
node = node->next_sibling();
ASSERT_FALSE(node);
ASSERT_EQ(node, nullptr);
}
TEST(Regression, BeatStreamAfpXml) {
// M:mounting /data2/graphic/psd_result.ifs to /afp22/data2/graphic/psd_result.ifs with type imagefs and args (null)
int mnt = hook_avs_fs_mount("/afp22/data2/graphic/psd_result.ifs", "/data2/graphic/psd_result.ifs", "imagefs", nullptr);
ASSERT_GT(mnt, 0);
auto f = hook_avs_fs_open("/afp22/data2/graphic/psd_result.ifs/afp/afplist.xml", avs_open_mode_read(), 420);
ASSERT_GT(f, 0);
rapidxml::xml_document<> xml_doc;
bool res = rapidxml_from_avs_file<rapidxml::parse_no_utf8>(f, xml_doc, xml_doc);
ASSERT_TRUE(res);
auto node = xml_doc.first_node();
ASSERT_NE(node, nullptr);
EXPECT_STREQ(node->name(), "afplist");
node = node->last_node();
ASSERT_NE(node, nullptr);
EXPECT_STREQ(node->name(), "afp");
auto attr = node->first_attribute("name");
ASSERT_NE(attr, nullptr);
EXPECT_STREQ(attr->value(), "hare");
auto geo = node->first_node("geo");
ASSERT_NE(geo, nullptr);
EXPECT_STREQ(geo->value(), "5 10 15");
}

View File

@ -0,0 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<afplist>
<afp name="hare">
<geo __type="u16" __count="3">5 10 15</geo>
</afp>
</afplist>