1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* util/profile/test_vtable.c - Test program for vtable-backed profiles */
3 /*
4  * Copyright (C) 2011 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 /*
28  * This test program exercises vtable profile functionality using two vtables,
29  * one which implements just the basic methods and one which implements all of
30  * the methods.  The program doesn't attempt to create a working profile
31  * implementation; it just verifies the expected control flow into the vtable
32  * and back out to the caller.
33  */
34 
35 #include <k5-platform.h>
36 #include "profile.h"
37 
38 static int basic_cbdata;
39 static int full_cbdata;
40 static const char *empty_names[] = { NULL };
41 static const char *name_string = "get_string";
42 static const char *name_int = "get_int";
43 static const char *name_bool = "get_bool";
44 
45 static long
basic_get_values(void * cbdata,const char * const * names,char *** ret_values)46 basic_get_values(void *cbdata, const char *const *names, char ***ret_values)
47 {
48     assert(cbdata == &basic_cbdata);
49     assert(names == empty_names);
50     *ret_values = calloc(3, sizeof(*ret_values));
51     (*ret_values)[0] = strdup("one");
52     (*ret_values)[1] = strdup("two");
53     (*ret_values)[2] = NULL;
54     return 0;
55 }
56 
57 static void
free_values(void * cbdata,char ** values)58 free_values(void *cbdata, char **values)
59 {
60     char **v;
61 
62     for (v = values; *v; v++)
63         free(*v);
64     free(values);
65 }
66 
67 static long
full_get_values(void * cbdata,const char * const * names,char *** ret_values)68 full_get_values(void *cbdata, const char *const *names, char ***ret_values)
69 {
70     assert(cbdata == &full_cbdata);
71     *ret_values = calloc(2, sizeof(*ret_values));
72     if (names[0] == name_string)
73         (*ret_values)[0] = strdup("string result");
74     else if (names[0] == name_int)
75         (*ret_values)[0] = strdup("23");
76     else if (names[0] == name_bool)
77         (*ret_values)[0] = strdup("on");
78     else {
79         free(*ret_values);
80         return PROF_NO_RELATION;
81     }
82     (*ret_values)[1] = NULL;
83     return 0;
84 }
85 
86 static void
full_cleanup(void * cbdata)87 full_cleanup(void *cbdata)
88 {
89     assert(cbdata == &full_cbdata);
90 }
91 
92 static long
full_copy(void * cbdata,void ** ret_cbdata)93 full_copy(void *cbdata, void **ret_cbdata)
94 {
95     assert(cbdata == &full_cbdata);
96     *ret_cbdata = &full_cbdata;
97     return 0;
98 }
99 
100 struct iterator {
101     int count;
102 };
103 
104 static long
full_iterator_create(void * cbdata,const char * const * names,int flags,void ** ret_iter)105 full_iterator_create(void *cbdata, const char *const *names, int flags,
106                      void **ret_iter)
107 {
108     struct iterator *iter;
109 
110     assert(cbdata == &full_cbdata);
111     assert(names == empty_names);
112     assert(flags == 126);
113     iter = malloc(sizeof(*iter));
114     iter->count = 0;
115     *ret_iter = iter;
116     return 0;
117 }
118 
119 static long
full_iterator(void * cbdata,void * iter_arg,char ** ret_name,char ** ret_value)120 full_iterator(void *cbdata, void *iter_arg, char **ret_name, char **ret_value)
121 {
122     struct iterator *iter = iter_arg;
123 
124     assert(cbdata == &full_cbdata);
125     assert(iter->count >= 0 && iter->count <= 2);
126     if (iter->count == 0) {
127         *ret_name = strdup("name1");
128         *ret_value = strdup("value1");
129     } else if (iter->count == 1) {
130         *ret_name = strdup("name2");
131         *ret_value = NULL;
132     } else {
133         *ret_name = NULL;
134         *ret_value = NULL;
135     }
136     iter->count++;
137     return 0;
138 }
139 
140 static void
full_iterator_free(void * cbdata,void * iter_arg)141 full_iterator_free(void *cbdata, void *iter_arg)
142 {
143     struct iterator *iter = iter_arg;
144 
145     assert(cbdata == &full_cbdata);
146     assert(iter->count == 3);
147     free(iter);
148 }
149 
150 static void
full_free_string(void * cbdata,char * string)151 full_free_string(void *cbdata, char *string)
152 {
153     assert(cbdata == &full_cbdata);
154     free(string);
155 }
156 
157 static long
full_writable(void * cbdata,int * writable)158 full_writable(void *cbdata, int *writable)
159 {
160     assert(cbdata == &full_cbdata);
161     *writable = 12;
162     return 0;
163 }
164 
165 static long
full_modified(void * cbdata,int * modified)166 full_modified(void *cbdata, int *modified)
167 {
168     assert(cbdata == &full_cbdata);
169     *modified = 6;
170     return 0;
171 }
172 
173 static long
full_update_relation(void * cbdata,const char ** names,const char * old_value,const char * new_value)174 full_update_relation(void *cbdata, const char **names,
175                      const char *old_value, const char *new_value)
176 {
177     assert(cbdata == &full_cbdata);
178     assert(names == empty_names);
179     assert(old_value == name_string || old_value == NULL);
180     assert(new_value == NULL);
181     return 0;
182 }
183 
184 static long
full_rename_section(void * cbdata,const char ** names,const char * new_name)185 full_rename_section(void *cbdata, const char **names, const char *new_name)
186 {
187     assert(cbdata == &full_cbdata);
188     assert(names == empty_names);
189     assert(new_name == name_int);
190     return 0;
191 }
192 
193 static long
full_add_relation(void * cbdata,const char ** names,const char * new_value)194 full_add_relation(void *cbdata, const char **names, const char *new_value)
195 {
196     assert(cbdata == &full_cbdata);
197     assert(names == empty_names);
198     assert(new_value == name_bool);
199     return 0;
200 }
201 
202 static long
full_flush(void * cbdata)203 full_flush(void *cbdata)
204 {
205     assert(cbdata == &full_cbdata);
206     return 0;
207 }
208 
209 struct profile_vtable basic_vtable = {
210     1,
211     basic_get_values,
212     free_values,
213 };
214 
215 struct profile_vtable full_vtable = {
216     1,
217     full_get_values,
218     free_values,
219     full_cleanup,
220     full_copy,
221 
222     full_iterator_create,
223     full_iterator,
224     full_iterator_free,
225     full_free_string,
226 
227     full_writable,
228     full_modified,
229     full_update_relation,
230     full_rename_section,
231     full_add_relation,
232     full_flush
233 };
234 
main()235 int main()
236 {
237     profile_t profile;
238     char **values, *str, *name, *value;
239     void *iter;
240     int intval;
241 
242     assert(profile_init_vtable(&basic_vtable, &basic_cbdata, &profile) == 0);
243     assert(profile_get_values(profile, empty_names, &values) == 0);
244     assert(strcmp(values[0], "one") == 0);
245     assert(strcmp(values[1], "two") == 0);
246     assert(values[2] == NULL);
247     profile_free_list(values);
248     assert(profile_iterator_create(profile, NULL, 0, &iter) ==
249            PROF_UNSUPPORTED);
250     assert(profile_is_writable(profile, &intval) == 0);
251     assert(intval == 0);
252     assert(profile_is_modified(profile, &intval) == 0);
253     assert(intval == 0);
254     assert(profile_update_relation(profile, NULL, NULL, NULL) ==
255            PROF_UNSUPPORTED);
256     assert(profile_clear_relation(profile, NULL) == PROF_UNSUPPORTED);
257     assert(profile_rename_section(profile, NULL, NULL) == PROF_UNSUPPORTED);
258     assert(profile_add_relation(profile, NULL, NULL) == PROF_UNSUPPORTED);
259     profile_flush(profile);
260     profile_abandon(profile);
261 
262     assert(profile_init_vtable(&full_vtable, &full_cbdata, &profile) == 0);
263     assert(profile_get_string(profile, name_string, NULL, NULL, "wrong",
264                               &str) == 0);
265     assert(strcmp(str, "string result") == 0);
266     profile_release_string(str);
267     assert(profile_get_integer(profile, name_int, NULL, NULL, 24,
268                                &intval) == 0);
269     assert(intval == 23);
270     assert(profile_get_boolean(profile, name_bool, NULL, NULL, 0,
271                                &intval) == 0);
272     assert(intval == 1);
273     assert(profile_get_integer(profile, "xxx", NULL, NULL, 62, &intval) == 0);
274     assert(intval == 62);
275 
276     assert(profile_iterator_create(profile, empty_names, 126, &iter) == 0);
277     assert(profile_iterator(&iter, &name, &value) == 0);
278     assert(strcmp(name, "name1") == 0);
279     assert(strcmp(value, "value1") == 0);
280     profile_release_string(name);
281     profile_release_string(value);
282     assert(profile_iterator(&iter, &name, &value) == 0);
283     assert(strcmp(name, "name2") == 0);
284     assert(value == NULL);
285     profile_release_string(name);
286     assert(profile_iterator(&iter, &name, &value) == 0);
287     assert(iter == NULL);
288     assert(name == NULL);
289     assert(value == NULL);
290 
291     assert(profile_is_writable(profile, &intval) == 0);
292     assert(intval == 12);
293     assert(profile_is_modified(profile, &intval) == 0);
294     assert(intval == 6);
295     assert(profile_update_relation(profile, empty_names, name_string,
296                                    NULL) == 0);
297     assert(profile_clear_relation(profile, empty_names) == 0);
298     assert(profile_rename_section(profile, empty_names, name_int) == 0);
299     assert(profile_add_relation(profile, empty_names, name_bool) == 0);
300     profile_release(profile);
301 
302     return 0;
303 }
304