charset: Rewrote utf8_validate, and added four new functions:
[ccan] / ccan / charset / test / run-surrogate-pair.c
1 #include <ccan/charset/charset.c>
2 #include <ccan/tap/tap.h>
3
4 #include <string.h>
5
6 #include "common.h"
7
8 /*
9  * Testing procedure for from_surrogate_pair and to_surrogate_pair:
10  *
11  *  * For each Unicode code point from 0x10000 to 0x10FFFF:
12  *    - Call to_surrogate_pair, and make sure that:
13  *      - It returns true.
14  *      - uc is 0xD800..0xDBFF
15  *      - lc is 0xDC00..0xDFFF
16  *    - Call from_surrogate_pair on the pair, and make sure that
17  *      it returns the original character.
18  *  * For various invalid arguments to to_surrogate_pair
19  *    (U+0000..U+FFFF and U+110000...):
20  *    - Call to_surrogate_pair, and make sure it:
21  *      - Returns false.
22  *      - Sets *uc and *lc to REPLACEMENT_CHARACTER.
23  *  * For various invalid arguments to from_surrogate_pair
24  *    (uc: not 0xD800..0xDBFF, lc: not 0xDC00..0xDFFF):
25  *    - Call from_surrogate_pair, and make sure
26  *      it returns REPLACEMENT_CHARACTER.
27  */
28
29 #define INVALID_TRIAL_COUNT     10000
30
31 #define range(r, lo, hi)  ((r) % ((hi)-(lo)+1) + (lo))
32
33 static void test_valid(void)
34 {
35         uchar_t unicode;
36         unsigned int uc, lc;
37         
38         for (unicode = 0x10000; unicode <= 0x10FFFF; unicode++) {
39                 if (to_surrogate_pair(unicode, &uc, &lc) != true) {
40                         fail("to_surrogate_pair did not return true on valid input.");
41                         return;
42                 }
43                 if (!(uc >= 0xD800 && uc <= 0xDBFF)) {
44                         fail("to_surrogate_pair: uc is out of range");
45                         return;
46                 }
47                 if (!(lc >= 0xDC00 && lc <= 0xDFFF)) {
48                         fail("to_surrogate_pair: lc is out of range");
49                         return;
50                 }
51                 if (from_surrogate_pair(uc, lc) != unicode) {
52                         fail("Surrogate pair conversion did not preserve original value (U+%04lX).", (unsigned long)unicode);
53                         return;
54                 }
55         }
56         
57         pass("to_surrogate_pair and from_surrogate_pair work for all valid arguments.");
58 }
59
60 static void test_invalid_to_surrogate_pair(void)
61 {
62         long i;
63         uchar_t unicode;
64         unsigned int uc, lc;
65         
66         for (i = 1; i <= INVALID_TRIAL_COUNT; i++) {
67                 if (rand32() % 2) {
68                         unicode = range(rand32(), 0x0, 0xFFFF);
69                 } else {
70                         do {
71                                 unicode = rand32();
72                         } while (unicode < 0x110000);
73                 }
74                 
75                 if (to_surrogate_pair(unicode, &uc, &lc) != false) {
76                         fail("to_surrogate_pair did not return false on invalid input.");
77                         return;
78                 }
79                 if (uc != REPLACEMENT_CHARACTER || lc != REPLACEMENT_CHARACTER) {
80                         fail("to_surrogate_pair did not set uc and lc to the replacement character on invalid input.");
81                         return;
82                 }
83         }
84         
85         pass("to_surrogate_pair seems to handle invalid argument values properly.");
86 }
87
88 static void test_invalid_from_surrogate_pair(void)
89 {
90         long i;
91         unsigned int uc, lc;
92         
93         for (i = 1; i <= INVALID_TRIAL_COUNT; i++) {
94                 switch (rand32() % 3) {
95                         case 0:
96                                 uc = range(rand32(), 0x0, 0xD7FF);
97                                 break;
98                         case 1:
99                                 uc = range(rand32(), 0xDC00, 0xDFFF);
100                                 break;
101                         default:
102                                 uc = range(rand32(), 0xE000, 0xFFFF);
103                                 break;
104                 }
105                 switch (rand32() % 3) {
106                         case 0:
107                                 lc = range(rand32(), 0x0, 0xD7FF);
108                                 break;
109                         case 1:
110                                 lc = range(rand32(), 0xD800, 0xDBFF);
111                                 break;
112                         default:
113                                 lc = range(rand32(), 0xE000, 0xFFFF);
114                                 break;
115                 }
116                 
117                 if (from_surrogate_pair(uc, lc) != REPLACEMENT_CHARACTER) {
118                         fail("from_surrogate_pair(0x%04X, 0x%04X) did not return the replacement character", uc, lc);
119                         return;
120                 }
121         }
122         
123         pass("from_surrogate_pair seems to handle invalid arguments properly.");
124 }
125
126 int main(void)
127 {
128         plan_tests(3);
129         
130         test_valid();
131         test_invalid_to_surrogate_pair();
132         test_invalid_from_surrogate_pair();
133         
134         return exit_status();
135 }