128 lines
4.6 KiB
C
128 lines
4.6 KiB
C
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
#include <expat.h>
|
||
|
#include <string.h>
|
||
|
#include "unity.h"
|
||
|
|
||
|
typedef struct {
|
||
|
int depth;
|
||
|
char output[512];
|
||
|
int output_off;
|
||
|
} user_data_t;
|
||
|
|
||
|
static void insert_space(user_data_t *user_data)
|
||
|
{
|
||
|
const char align_str[] = " ";
|
||
|
|
||
|
TEST_ASSERT(sizeof(user_data->output) >= user_data->output_off);
|
||
|
user_data->output[user_data->output_off++] = '\n';
|
||
|
|
||
|
for (int i = 0; i < user_data->depth; i++) {
|
||
|
for (int j = 0; j < strlen(align_str); ++j) {
|
||
|
TEST_ASSERT(sizeof(user_data->output) >= user_data->output_off);
|
||
|
user_data->output[user_data->output_off++] = align_str[j];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void XMLCALL start_element(void *userData, const XML_Char *name, const XML_Char **atts)
|
||
|
{
|
||
|
user_data_t *user_data = (user_data_t *) userData;
|
||
|
|
||
|
insert_space(user_data);
|
||
|
|
||
|
const int ret = snprintf(user_data->output + user_data->output_off,
|
||
|
sizeof(user_data->output) - user_data->output_off,
|
||
|
"<%s>", name);
|
||
|
TEST_ASSERT_EQUAL(strlen(name) + 2, ret); // 2 are the tag characters: "<>"
|
||
|
user_data->output_off += ret;
|
||
|
++user_data->depth;
|
||
|
}
|
||
|
|
||
|
static void XMLCALL end_element(void *userData, const XML_Char *name)
|
||
|
{
|
||
|
user_data_t *user_data = (user_data_t *) userData;
|
||
|
|
||
|
--user_data->depth;
|
||
|
insert_space(user_data);
|
||
|
|
||
|
int ret = snprintf(user_data->output + user_data->output_off, sizeof(user_data->output) - user_data->output_off,
|
||
|
"</%s>", name);
|
||
|
TEST_ASSERT_EQUAL(strlen(name) + 3, ret); // 3 are the tag characters: "</>"
|
||
|
user_data->output_off += ret;
|
||
|
}
|
||
|
|
||
|
static void data_handler(void *userData, const XML_Char *s, int len)
|
||
|
{
|
||
|
user_data_t *user_data = (user_data_t *) userData;
|
||
|
|
||
|
insert_space(user_data);
|
||
|
|
||
|
// s is not zero-terminated
|
||
|
char tmp_str[len+1];
|
||
|
strlcpy(tmp_str, s, len+1);
|
||
|
|
||
|
int ret = snprintf(user_data->output + user_data->output_off, sizeof(user_data->output) - user_data->output_off,
|
||
|
"%s", tmp_str);
|
||
|
TEST_ASSERT_EQUAL(strlen(tmp_str), ret);
|
||
|
user_data->output_off += ret;
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Expat parses XML", "[expat]")
|
||
|
{
|
||
|
const char test_in[] = "<html><title>Page title</title><body><h>header</h><ol><li>A</li>"\
|
||
|
"<li>B</li><li>C</li></ol></body></html>";
|
||
|
const char test_expected[] = "\n"\
|
||
|
"<html>\n"\
|
||
|
" <title>\n"\
|
||
|
" Page title\n"\
|
||
|
" </title>\n"\
|
||
|
" <body>\n"\
|
||
|
" <h>\n"\
|
||
|
" header\n"\
|
||
|
" </h>\n"\
|
||
|
" <ol>\n"\
|
||
|
" <li>\n"\
|
||
|
" A\n"\
|
||
|
" </li>\n"\
|
||
|
" <li>\n"\
|
||
|
" B\n"\
|
||
|
" </li>\n"\
|
||
|
" <li>\n"\
|
||
|
" C\n"\
|
||
|
" </li>\n"\
|
||
|
" </ol>\n"\
|
||
|
" </body>\n"\
|
||
|
"</html>";
|
||
|
user_data_t user_data = {
|
||
|
.depth = 0,
|
||
|
.output = { '\0' },
|
||
|
.output_off = 0
|
||
|
};
|
||
|
|
||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||
|
XML_SetUserData(parser, &user_data);
|
||
|
XML_SetElementHandler(parser, start_element, end_element);
|
||
|
XML_SetCharacterDataHandler(parser, data_handler);
|
||
|
|
||
|
TEST_ASSERT_NOT_EQUAL(XML_STATUS_ERROR, XML_Parse(parser, test_in, strlen(test_in), 1));
|
||
|
XML_ParserFree(parser);
|
||
|
|
||
|
TEST_ASSERT_EQUAL(0, user_data.depth); // all closing tags have been found
|
||
|
|
||
|
TEST_ASSERT_EQUAL(strlen(test_expected), strlen(user_data.output));
|
||
|
TEST_ASSERT_EQUAL_STRING(test_expected, user_data.output);
|
||
|
}
|