BadVPN – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /** |
2 | * @file ncdval_test.c |
||
3 | * @author Ambroz Bizjak <ambrop7@gmail.com> |
||
4 | * |
||
5 | * @section LICENSE |
||
6 | * |
||
7 | * Redistribution and use in source and binary forms, with or without |
||
8 | * modification, are permitted provided that the following conditions are met: |
||
9 | * 1. Redistributions of source code must retain the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer. |
||
11 | * 2. Redistributions in binary form must reproduce the above copyright |
||
12 | * notice, this list of conditions and the following disclaimer in the |
||
13 | * documentation and/or other materials provided with the distribution. |
||
14 | * 3. Neither the name of the author nor the |
||
15 | * names of its contributors may be used to endorse or promote products |
||
16 | * derived from this software without specific prior written permission. |
||
17 | * |
||
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
28 | */ |
||
29 | |||
30 | #include <stdio.h> |
||
31 | |||
32 | #include <ncd/NCDVal.h> |
||
33 | #include <ncd/NCDStringIndex.h> |
||
34 | #include <ncd/static_strings.h> |
||
35 | #include <base/BLog.h> |
||
36 | #include <misc/debug.h> |
||
37 | #include <misc/balloc.h> |
||
38 | #include <misc/offset.h> |
||
39 | |||
40 | #define FORCE(cmd) if (!(cmd)) { fprintf(stderr, "failed\n"); exit(1); } |
||
41 | |||
42 | static void test_string (NCDValRef str, const char *data, size_t length) |
||
43 | { |
||
44 | FORCE( !NCDVal_IsInvalid(str) ) |
||
45 | FORCE( NCDVal_IsString(str) ) |
||
46 | FORCE( NCDVal_StringLength(str) == length ) |
||
47 | FORCE( NCDVal_StringHasNulls(str) == !!memchr(data, '\0', length) ) |
||
48 | FORCE( NCDVal_IsStringNoNulls(str) == !memchr(data, '\0', length) ) |
||
49 | FORCE( NCDVal_StringRegionEquals(str, 0, length, data) ) |
||
50 | |||
51 | MemRef mr = NCDVal_StringMemRef(str); |
||
52 | FORCE( mr.ptr == NCDVal_StringData(str) ) |
||
53 | FORCE( mr.len == NCDVal_StringLength(str) ) |
||
54 | FORCE( mr.len == length ) |
||
55 | FORCE( !memcmp(mr.ptr, data, length) ) |
||
56 | } |
||
57 | |||
58 | static void print_indent (int indent) |
||
59 | { |
||
60 | for (int i = 0; i < indent; i++) { |
||
61 | printf(" "); |
||
62 | } |
||
63 | } |
||
64 | |||
65 | static void print_value (NCDValRef val, unsigned int indent) |
||
66 | { |
||
67 | switch (NCDVal_Type(val)) { |
||
68 | case NCDVAL_STRING: { |
||
69 | NCDValNullTermString nts; |
||
70 | FORCE( NCDVal_StringNullTerminate(val, &nts) ) |
||
71 | |||
72 | print_indent(indent); |
||
73 | printf("string(%zu) %s\n", NCDVal_StringLength(val), nts.data); |
||
74 | |||
75 | NCDValNullTermString_Free(&nts); |
||
76 | } break; |
||
77 | |||
78 | case NCDVAL_LIST: { |
||
79 | size_t count = NCDVal_ListCount(val); |
||
80 | |||
81 | print_indent(indent); |
||
82 | printf("list(%zu)\n", NCDVal_ListCount(val)); |
||
83 | |||
84 | for (size_t i = 0; i < count; i++) { |
||
85 | NCDValRef elem_val = NCDVal_ListGet(val, i); |
||
86 | print_value(elem_val, indent + 1); |
||
87 | } |
||
88 | } break; |
||
89 | |||
90 | case NCDVAL_MAP: { |
||
91 | print_indent(indent); |
||
92 | printf("map(%zu)\n", NCDVal_MapCount(val)); |
||
93 | |||
94 | for (NCDValMapElem e = NCDVal_MapOrderedFirst(val); !NCDVal_MapElemInvalid(e); e = NCDVal_MapOrderedNext(val, e)) { |
||
95 | NCDValRef ekey = NCDVal_MapElemKey(val, e); |
||
96 | NCDValRef eval = NCDVal_MapElemVal(val, e); |
||
97 | |||
98 | print_indent(indent + 1); |
||
99 | printf("key=\n"); |
||
100 | print_value(ekey, indent + 2); |
||
101 | |||
102 | print_indent(indent + 1); |
||
103 | printf("val=\n"); |
||
104 | print_value(eval, indent + 2); |
||
105 | } |
||
106 | } break; |
||
107 | } |
||
108 | } |
||
109 | |||
110 | int main () |
||
111 | { |
||
112 | int res; |
||
113 | |||
114 | BLog_InitStdout(); |
||
115 | |||
116 | NCDStringIndex string_index; |
||
117 | FORCE( NCDStringIndex_Init(&string_index) ) |
||
118 | |||
119 | // Some basic usage of values. |
||
120 | |||
121 | NCDValMem mem; |
||
122 | NCDValMem_Init(&mem, &string_index); |
||
123 | |||
124 | NCDValRef s1 = NCDVal_NewString(&mem, "Hello World"); |
||
125 | test_string(s1, "Hello World", 11); |
||
126 | ASSERT( NCDVal_IsString(s1) ) |
||
127 | ASSERT( !NCDVal_IsIdString(s1) ) |
||
128 | ASSERT( NCDVal_Type(s1) == NCDVAL_STRING ) |
||
129 | |||
130 | NCDValRef s2 = NCDVal_NewString(&mem, "This is reeeeeeeeeeeeeallllllllyyyyy fun!"); |
||
131 | FORCE( !NCDVal_IsInvalid(s2) ) |
||
132 | |||
133 | NCDValRef l1 = NCDVal_NewList(&mem, 10); |
||
134 | FORCE( !NCDVal_IsInvalid(l1) ) |
||
135 | |||
136 | FORCE( NCDVal_ListAppend(l1, s1) ) |
||
137 | FORCE( NCDVal_ListAppend(l1, s2) ) |
||
138 | |||
139 | print_value(s1, 0); |
||
140 | print_value(s2, 0); |
||
141 | print_value(l1, 0); |
||
142 | |||
143 | NCDValRef k1 = NCDVal_NewString(&mem, "K1"); |
||
144 | FORCE( !NCDVal_IsInvalid(k1) ) |
||
145 | NCDValRef v1 = NCDVal_NewString(&mem, "V1"); |
||
146 | FORCE( !NCDVal_IsInvalid(v1) ) |
||
147 | |||
148 | NCDValRef k2 = NCDVal_NewString(&mem, "K2"); |
||
149 | FORCE( !NCDVal_IsInvalid(k2) ) |
||
150 | NCDValRef v2 = NCDVal_NewString(&mem, "V2"); |
||
151 | FORCE( !NCDVal_IsInvalid(v2) ) |
||
152 | |||
153 | NCDValRef m1 = NCDVal_NewMap(&mem, 3); |
||
154 | FORCE( !NCDVal_IsInvalid(m1) ) |
||
155 | |||
156 | FORCE( NCDVal_MapInsert(m1, k1, v1, &res) && res ) |
||
157 | FORCE( NCDVal_MapInsert(m1, k2, v2, &res) && res ) |
||
158 | |||
159 | ASSERT( NCDVal_MapGetValue(m1, "K1").idx == v1.idx ) |
||
160 | ASSERT( NCDVal_MapGetValue(m1, "K2").idx == v2.idx ) |
||
161 | ASSERT( NCDVal_IsInvalid(NCDVal_MapGetValue(m1, "K3")) ) |
||
162 | |||
163 | NCDValRef ids1 = NCDVal_NewIdString(&mem, NCD_STRING_ARG1); |
||
164 | test_string(ids1, "_arg1", 5); |
||
165 | ASSERT( !memcmp(NCDVal_StringData(ids1), "_arg1", 5) ) |
||
166 | ASSERT( NCDVal_StringLength(ids1) == 5 ) |
||
167 | ASSERT( !NCDVal_StringHasNulls(ids1) ) |
||
168 | ASSERT( NCDVal_StringEquals(ids1, "_arg1") ) |
||
169 | ASSERT( NCDVal_Type(ids1) == NCDVAL_STRING ) |
||
170 | ASSERT( NCDVal_IsIdString(ids1) ) |
||
171 | |||
172 | NCDValRef ids2 = NCDVal_NewIdString(&mem, NCD_STRING_ARG2); |
||
173 | test_string(ids2, "_arg2", 5); |
||
174 | ASSERT( !memcmp(NCDVal_StringData(ids2), "_arg2", 5) ) |
||
175 | ASSERT( NCDVal_StringLength(ids2) == 5 ) |
||
176 | ASSERT( !NCDVal_StringHasNulls(ids2) ) |
||
177 | ASSERT( NCDVal_StringEquals(ids2, "_arg2") ) |
||
178 | ASSERT( NCDVal_Type(ids2) == NCDVAL_STRING ) |
||
179 | ASSERT( NCDVal_IsIdString(ids2) ) |
||
180 | |||
181 | FORCE( NCDVal_MapInsert(m1, ids1, ids2, &res) && res ) |
||
182 | |||
183 | ASSERT( NCDVal_MapGetValue(m1, "_arg1").idx == ids2.idx ) |
||
184 | |||
185 | print_value(m1, 0); |
||
186 | |||
187 | NCDValRef copy = NCDVal_NewCopy(&mem, m1); |
||
188 | FORCE( !NCDVal_IsInvalid(copy) ) |
||
189 | ASSERT( NCDVal_Compare(copy, m1) == 0 ) |
||
190 | |||
191 | NCDValMem_Free(&mem); |
||
192 | |||
193 | // Try to make copies of a string within the same memory object. |
||
194 | // This is an evil test because we cannot simply copy a string using e.g. |
||
195 | // NCDVal_NewStringBin() - it requires that the buffer passed |
||
196 | // be outside the memory object of the new string. |
||
197 | // We use NCDVal_NewCopy(), which takes care of this by creating |
||
198 | // an uninitialized string using NCDVal_NewStringUninitialized() and |
||
199 | // then copyng the data. |
||
200 | |||
201 | NCDValMem_Init(&mem, &string_index); |
||
202 | |||
203 | NCDValRef s[100]; |
||
204 | |||
205 | s[0] = NCDVal_NewString(&mem, "Eeeeeeeeeeeevil."); |
||
206 | FORCE( !NCDVal_IsInvalid(s[0]) ) |
||
207 | |||
208 | for (int i = 1; i < 100; i++) { |
||
209 | s[i] = NCDVal_NewCopy(&mem, s[i - 1]); |
||
210 | FORCE( !NCDVal_IsInvalid(s[i]) ) |
||
211 | ASSERT( NCDVal_StringEquals(s[i - 1], "Eeeeeeeeeeeevil.") ) |
||
212 | ASSERT( NCDVal_StringEquals(s[i], "Eeeeeeeeeeeevil.") ) |
||
213 | } |
||
214 | |||
215 | for (int i = 0; i < 100; i++) { |
||
216 | ASSERT( NCDVal_StringEquals(s[i], "Eeeeeeeeeeeevil.") ) |
||
217 | } |
||
218 | |||
219 | NCDValMem_Free(&mem); |
||
220 | |||
221 | NCDStringIndex_Free(&string_index); |
||
222 | |||
223 | return 0; |
||
224 | } |