1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009 Walter Doekes <walter+tthsum@wjd.nu>
4 This file is part of tthsum.
5 
6 tthsum is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 tthsum is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with tthsum.  If not, see <http://www.gnu.org/licenses/>.
18 ======================================================================*/
19 #include "escape.h"
20 
21 #include "test.h"
22 #include "texts.h"
23 #include <string.h>
24 
25 
help_cmp_symmetric(const char * str,const char * escaped,int should_fail)26 static int help_cmp_symmetric(const char* str, const char* escaped,
27 	int should_fail) {
28     char strbuf[2048];
29     char escapedbuf[2048];
30 
31     if (strlen(str) >= 512 || strlen(escaped) >= 2048)
32 	FAIL3("Test values too large: \"%s\" is %u and %u bytes", escaped,
33 		(unsigned)strlen(str), (unsigned)strlen(escaped));
34     strtoctrlesc(escapedbuf, str);
35     if (ctrlesctostr(strbuf, escaped) != 0)
36 	FAIL2("ctrlesctostr failed on \"%s\": %s", escaped, get_error());
37     if ((strcmp(strbuf, str) != 0 || strcmp(escapedbuf, escaped) != 0)
38 	    == !should_fail)
39 	FAIL2("Values %sdiffer for \"%s\"", should_fail ? "do NOT " : "",
40 		escaped);
41 
42     return 0;
43 }
44 
help_cmp_unescape(const char * escaped,const char * result,int should_fail)45 static int help_cmp_unescape(const char* escaped, const char* result,
46 	    int should_fail) {
47     char resultbuf[2048];
48 
49     if (strlen(escaped) >= 2048)
50 	FAIL2("Test value too large: \"%s\" is %u bytes", escaped,
51 		(unsigned)strlen(escaped));
52     if (ctrlesctostr(resultbuf, escaped) != 0)
53 	FAIL2("ctrlesctostr failed on \"%s\": %s", escaped, get_error());
54     if (strcmp(resultbuf, result) == !should_fail)
55 	FAIL2("Values %sdiffer for \"%s\"", should_fail ? "do NOT " : "",
56 		escaped);
57 
58     return 0;
59 }
60 
test_bidirectional_success()61 static int test_bidirectional_success() {
62     return help_cmp_symmetric("", "", 0)
63 	    + help_cmp_symmetric("ABC", "ABC", 0)
64 	    + help_cmp_symmetric("\xff ABC \x80\x81", "\xff ABC \x80\x81", 0)
65 	    + help_cmp_symmetric(
66 		"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
67 		"\\x01\\x02\\x03\\x04\\x05\\x06\\a\\b\\t\\n\\v\\f\\r\\x0e\\x0f",
68 		0)
69 	    + help_cmp_symmetric(
70 		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e"
71 		"\x1f", "\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19"
72 		"\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f", 0);
73 }
74 
test_bidirectional_fail()75 static int test_bidirectional_fail() {
76     return help_cmp_symmetric(" ", "", 1)
77 	 + help_cmp_symmetric("ABC", "ABCD", 1)
78 	 + help_cmp_symmetric("\n", "\\x0a", 1)
79 	 + help_cmp_symmetric("\r\n", "\\n\\n", 1)
80 	 + help_cmp_symmetric("\0", "\\x00", 1); /* \0 is not seen */
81 }
82 
test_unidirectional_success()83 static int test_unidirectional_success() {
84     return help_cmp_unescape("\\x0d\\n", "\r\n", 0)
85 	 + help_cmp_unescape("abcdef", "abcdef", 0)
86 	 + help_cmp_unescape("abc\\x0a\\x0d\\t", "abc\n\r\t", 0)
87 	 + help_cmp_unescape("\\x00foobar", "", 0) /* leading \0 */
88 	 + help_cmp_unescape("\\\\x80\x81\\xff", "\\x80\x81\xff", 0);
89 }
90 
test_unidirectional_fail()91 static int test_unidirectional_fail() {
92     return help_cmp_unescape("\\x0d\\n", "\\x0d\n", 1)
93 	 + help_cmp_unescape("abcdef", "abcdefg", 1)
94 	 + help_cmp_unescape("abc\\x0a\\x0d\\t", "abc\\n\\r\\t", 1)
95 	 + help_cmp_unescape("\\x00foobar", "foobar", 1)
96 	 + help_cmp_unescape("\\\\x80\x81\\xff", "\x80\x81\xff", 1);
97 }
98 
test_decode_success()99 static int test_decode_success() {
100     char buf[256];
101     return ctrlesctostr(buf, "\\x11")
102 	|| ctrlesctostr(buf, "abc\\x00def")
103 	|| ctrlesctostr(buf, "\\x0a\\n\\r\\x0d")
104 	|| ctrlesctostr(buf, "\a\b\t\v\r\n")
105 	|| ctrlesctostr(buf, "\\x1A\\x1a");
106 }
107 
test_decode_fail()108 static int test_decode_fail() {
109     char buf[256];
110     return !ctrlesctostr(buf, "\\x1")
111 	|| !ctrlesctostr(buf, "\\0")
112 	|| !ctrlesctostr(buf, "\\0\\1\\2")
113 	|| !ctrlesctostr(buf, "\\x1g")
114 	|| !ctrlesctostr(buf, "\\g")
115 	|| !ctrlesctostr(buf, "\\N")
116 	|| !ctrlesctostr(buf, "\\x1G");
117 }
118 
119 
120 TESTS(escape_test)
121     TEST(test_bidirectional_success);
122     TEST(test_bidirectional_fail);
123     TEST(test_unidirectional_success);
124     TEST(test_unidirectional_fail);
125     TEST(test_decode_success);
126     TEST(test_decode_fail);
127 ENDTESTS
128