• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lws-api-test-lws_struct-sqlite
3  *
4  * Written in 2010-2020 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  *
9  * lws_struct apis are used to serialize and deserialize your C structs and
10  * linked-lists in a standardized way that's very modest on memory but
11  * convenient and easy to maintain.
12  *
13  * The API test shows how to serialize and deserialize a struct with a linked-
14  * list of child structs in JSON using lws_struct APIs.
15  */
16 
17 #include <libwebsockets.h>
18 
19 typedef struct teststruct {
20 	lws_dll2_t		list; /* not directly serialized */
21 
22 	char 			str1[32];
23 	const char		*str2;
24 	uint8_t			u8;
25 	uint16_t		u16;
26 	uint32_t		u32;
27 	uint64_t		u64;
28 	int32_t			s32;
29 } teststruct_t;
30 
31 /*
32  * These are the members that we will serialize and deserialize, not every
33  * member in the struct (eg, the dll2 list member)
34  */
35 
36 static const lws_struct_map_t lsm_teststruct[] = {
37 	LSM_CARRAY	(teststruct_t, str1,		"str1"),
38 	LSM_STRING_PTR  (teststruct_t, str2,		"str2"),
39 	LSM_UNSIGNED	(teststruct_t, u8,		"u8"),
40 	LSM_UNSIGNED	(teststruct_t, u16,		"u16"),
41 	LSM_UNSIGNED	(teststruct_t, u32,		"u32"),
42 	LSM_UNSIGNED	(teststruct_t, u64,		"u64"),
43 	LSM_SIGNED	(teststruct_t, s32,		"s32"),
44 };
45 
46 static const lws_struct_map_t lsm_schema_apitest[] = {
47 	LSM_SCHEMA_DLL2	(teststruct_t, list, NULL, lsm_teststruct, "apitest")
48 };
49 
50 static const char *test_string =
51 	"No one would have believed in the last years of the nineteenth "
52 	"century that this world was being watched keenly and closely by "
53 	"intelligences greater than man's and yet as mortal as his own; that as "
54 	"men busied themselves about their various concerns they were "
55 	"scrutinised and studied, perhaps almost as narrowly as a man with a "
56 	"microscope might scrutinise the transient creatures that swarm and "
57 	"multiply in a drop of water.  With infinite complacency men went to "
58 	"and fro over this globe about their little affairs, serene in their "
59 	"assurance of their empire over matter. It is possible that the "
60 	"infusoria under the microscope do the same.  No one gave a thought to "
61 	"the older worlds of space as sources of human danger, or thought of "
62 	"them only to dismiss the idea of life upon them as impossible or "
63 	"improbable.  It is curious to recall some of the mental habits of "
64 	"those departed days.  At most terrestrial men fancied there might be "
65 	"other men upon Mars, perhaps inferior to themselves and ready to "
66 	"welcome a missionary enterprise. Yet across the gulf of space, minds "
67 	"that are to our minds as ours are to those of the beasts that perish, "
68 	"intellects vast and cool and unsympathetic, regarded this earth with "
69 	"envious eyes, and slowly and surely drew their plans against us.  And "
70 	"early in the twentieth century came the great disillusionment. ";
71 
main(int argc,const char ** argv)72 int main(int argc, const char **argv)
73 {
74 	int e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
75 	struct lws_context_creation_info info;
76 	struct lws_context *context;
77 	struct lwsac *ac = NULL;
78 	lws_dll2_owner_t resown;
79 	teststruct_t ts, *pts;
80 	const char *p;
81 	sqlite3 *db;
82 
83 	if ((p = lws_cmdline_option(argc, argv, "-d")))
84 		logs = atoi(p);
85 
86 	lws_set_log_level(logs, NULL);
87 	lwsl_user("LWS API selftest: lws_struct SQLite\n");
88 
89 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
90 #if defined(LWS_WITH_NETWORK)
91 	info.port = CONTEXT_PORT_NO_LISTEN;
92 #endif
93 	context = lws_create_context(&info);
94 	if (!context) {
95 		lwsl_err("lws init failed\n");
96 		return 1;
97 	}
98 
99 
100 	unlink("_lws_apitest.sq3");
101 
102 	if (lws_struct_sq3_open(context, "_lws_apitest.sq3", 1, &db)) {
103 		lwsl_err("%s: failed to open table\n", __func__);
104 		goto bail;
105 	}
106 
107 	/* 1. populate the struct */
108 
109 	memset(&ts, 0, sizeof(ts));
110 
111 	lws_strncpy(ts.str1, "hello", sizeof(ts.str1));
112 	ts.str2 = test_string;
113 	ts.u8 = 1;
114 	ts.u16 = 512,
115 	ts.u32 = 0x55aa1234; /* 1437209140, */
116 	ts.u64 = 0x34abcdef01ull;
117 	ts.s32 = -1;
118 
119 	/* add our struct to the dll2 owner list */
120 
121 	lws_dll2_owner_clear(&resown);
122 	lws_dll2_add_head(&ts.list, &resown);
123 
124 	/* gratuitously create the table */
125 
126 	if (lws_struct_sq3_create_table(db, lsm_schema_apitest)) {
127 		lwsl_err("%s: Create table failed\n", __func__);
128 		e++;
129 		goto done;
130 	}
131 
132 	/* serialize the items on the dll2 owner */
133 
134 	if (lws_struct_sq3_serialize(db, lsm_schema_apitest, &resown, 0)) {
135 		lwsl_err("%s: Serialize failed\n", __func__);
136 		e++;
137 		goto done;
138 	}
139 
140 	/* resown should be cleared by deserialize, ac is already NULL */
141 
142 	lws_dll2_owner_clear(&resown); /* make sure old resown data is gone */
143 
144 	if (lws_struct_sq3_deserialize(db, NULL, NULL, lsm_schema_apitest,
145 				       &resown, &ac, 0, 1)) {
146 		lwsl_err("%s: Deserialize failed\n", __func__);
147 		e++;
148 		goto done;
149 	}
150 
151 	/* we should have 1 entry in resown now (created into the ac) */
152 
153 	if (resown.count != 1) {
154 		lwsl_err("%s: Expected 1 result got %d\n", __func__,
155 				resown.count);
156 		e++;
157 		goto done;
158 	}
159 
160 	/*
161 	 * Convert the pointer to the embedded lws_dll2 into a pointer
162 	 * to the actual struct with the correct type
163 	 */
164 
165 	pts = lws_container_of(lws_dll2_get_head(&resown),
166 			       teststruct_t, list);
167 
168 	if (strcmp(pts->str1, "hello") ||
169 	    strcmp(pts->str2, test_string) ||
170 	    pts->u8 != 1 ||
171 	    pts->u16 != 512 ||
172 	    pts->u32 != 0x55aa1234 ||
173 	    pts->u64 != 0x34abcdef01ull ||
174 	    pts->s32 != -1) {
175 		lwsl_err("%s: unexpected deser values: %s\n", __func__, pts->str1);
176 		lwsl_err("%s: %s\n", __func__, pts->str2);
177 		lwsl_err("%s: %u %u %u 0x%llx %d\n", __func__, pts->u8, pts->u16,
178 			 pts->u32, (unsigned long long)pts->u64, pts->s32);
179 
180 		e++;
181 		goto done;
182 	}
183 
184 done:
185 	lwsac_free(&ac);
186 	lws_struct_sq3_close(&db);
187 
188 
189 	if (e)
190 		goto bail;
191 
192 	lws_context_destroy(context);
193 
194 	lwsl_user("Completed: PASS\n");
195 
196 	return 0;
197 
198 bail:
199 	lws_context_destroy(context);
200 
201 	lwsl_user("Completed: FAIL\n");
202 
203 	return 1;
204 }
205