Files
DD3-LoRa-Bridge-MultiSender/test/test_html_escape/test_html_escape.cpp

134 lines
4.0 KiB
C++

#include <Arduino.h>
#include <unity.h>
#include "html_util.h"
static void test_html_escape_basic() {
TEST_ASSERT_EQUAL_STRING("", html_escape("").c_str());
TEST_ASSERT_EQUAL_STRING("plain", html_escape("plain").c_str());
TEST_ASSERT_EQUAL_STRING("a&amp;b", html_escape("a&b").c_str());
TEST_ASSERT_EQUAL_STRING("&lt;tag&gt;", html_escape("<tag>").c_str());
TEST_ASSERT_EQUAL_STRING("&quot;hi&quot;", html_escape("\"hi\"").c_str());
TEST_ASSERT_EQUAL_STRING("it&#39;s", html_escape("it's").c_str());
TEST_ASSERT_EQUAL_STRING("&amp;&lt;&gt;&quot;&#39;", html_escape("&<>\"'").c_str());
}
static void test_html_escape_adversarial() {
TEST_ASSERT_EQUAL_STRING("&amp;amp;", html_escape("&amp;").c_str());
TEST_ASSERT_EQUAL_STRING("\n\r\t", html_escape("\n\r\t").c_str());
const String chunk = "<&>\"'abc\n\r\t";
const String escaped_chunk = "&lt;&amp;&gt;&quot;&#39;abc\n\r\t";
const size_t repeats = 300; // 3.3 KB input
String input;
String expected;
input.reserve(chunk.length() * repeats);
expected.reserve(escaped_chunk.length() * repeats);
for (size_t i = 0; i < repeats; ++i) {
input += chunk;
expected += escaped_chunk;
}
String out = html_escape(input);
TEST_ASSERT_EQUAL_UINT(expected.length(), out.length());
TEST_ASSERT_EQUAL_STRING(expected.c_str(), out.c_str());
TEST_ASSERT_TRUE(out.indexOf("&lt;&amp;&gt;&quot;&#39;abc") >= 0);
}
static void test_url_encode_component_table() {
struct Case {
const char *input;
const char *expected;
};
const Case cases[] = {
{"", ""},
{"abcABC012-_.~", "abcABC012-_.~"},
{"a b", "a%20b"},
{"/\\?&#%\"'", "%2F%5C%3F%26%23%25%22%27"},
{"line\nbreak", "line%0Abreak"},
};
for (size_t i = 0; i < (sizeof(cases) / sizeof(cases[0])); ++i) {
String out = url_encode_component(cases[i].input);
TEST_ASSERT_EQUAL_STRING(cases[i].expected, out.c_str());
}
String control;
control += static_cast<char>(0x01);
control += static_cast<char>(0x1F);
control += static_cast<char>(0x7F);
TEST_ASSERT_EQUAL_STRING("%01%1F%7F", url_encode_component(control).c_str());
const String long_chunk = "AZaz09-_.~ /%?";
const String long_expected_chunk = "AZaz09-_.~%20%2F%25%3F";
String long_input;
String long_expected;
for (size_t i = 0; i < 40; ++i) { // 520 chars
long_input += long_chunk;
long_expected += long_expected_chunk;
}
String long_out_1 = url_encode_component(long_input);
String long_out_2 = url_encode_component(long_input);
TEST_ASSERT_EQUAL_STRING(long_expected.c_str(), long_out_1.c_str());
TEST_ASSERT_EQUAL_STRING(long_out_1.c_str(), long_out_2.c_str());
}
static void test_sanitize_device_id_accepts_and_normalizes() {
String out;
const char *accept_cases[] = {
"F19C",
"f19c",
" f19c ",
"dd3-f19c",
"dd3-F19C",
"dd3-a0b1",
};
for (size_t i = 0; i < (sizeof(accept_cases) / sizeof(accept_cases[0])); ++i) {
TEST_ASSERT_TRUE(sanitize_device_id(accept_cases[i], out));
if (String(accept_cases[i]).indexOf("a0b1") >= 0) {
TEST_ASSERT_EQUAL_STRING("dd3-A0B1", out.c_str());
} else {
TEST_ASSERT_EQUAL_STRING("dd3-F19C", out.c_str());
}
}
}
static void test_sanitize_device_id_rejects_invalid() {
String out = "dd3-KEEP";
const char *reject_cases[] = {
"",
"F",
"FFF",
"FFFFF",
"dd3-12",
"dd3-12345",
"F1 9C",
"dd3-F1\t9C",
"dd3-F19C%00",
"%F19C",
"../F19C",
"dd3-..1A",
"dd3-12/3",
"dd3-12\\3",
"F19G",
"dd3-zzzz",
};
for (size_t i = 0; i < (sizeof(reject_cases) / sizeof(reject_cases[0])); ++i) {
TEST_ASSERT_FALSE(sanitize_device_id(reject_cases[i], out));
}
TEST_ASSERT_EQUAL_STRING("dd3-KEEP", out.c_str());
}
void setup() {
UNITY_BEGIN();
RUN_TEST(test_html_escape_basic);
RUN_TEST(test_html_escape_adversarial);
RUN_TEST(test_url_encode_component_table);
RUN_TEST(test_sanitize_device_id_accepts_and_normalizes);
RUN_TEST(test_sanitize_device_id_rejects_invalid);
UNITY_END();
}
void loop() {}