ctdb-protocol: Fix marshalling for ctdb_pulldb
[vlendec/samba-autobuild/.git] / ctdb / tests / src / protocol_types_compat_test.c
1 /*
2    protocol types backward compatibility test
3
4    Copyright (C) Amitay Isaacs  2015
5
6    This program 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    This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/filesys.h"
22
23 #include <assert.h>
24
25 #include "protocol/protocol_basic.c"
26 #include "protocol/protocol_types.c"
27
28 #include "tests/src/protocol_common.h"
29
30 #define COMPAT_TEST_FUNC(NAME)          test_ ##NAME## _compat
31 #define OLD_LEN_FUNC(NAME)              NAME## _len_old
32 #define OLD_PUSH_FUNC(NAME)             NAME## _push_old
33 #define OLD_PULL_FUNC(NAME)             NAME## _pull_old
34
35 #define COMPAT_TYPE1_TEST(TYPE, NAME)   \
36 static void COMPAT_TEST_FUNC(NAME)(void) \
37 { \
38         TALLOC_CTX *mem_ctx; \
39         uint8_t *buf1, *buf2; \
40         TYPE p = { 0 }, p1, p2; \
41         size_t buflen1, buflen2, np = 0; \
42         int ret; \
43 \
44         mem_ctx = talloc_new(NULL); \
45         assert(mem_ctx != NULL); \
46         FILL_FUNC(NAME)(&p); \
47         buflen1 = LEN_FUNC(NAME)(&p); \
48         buflen2 = OLD_LEN_FUNC(NAME)(&p); \
49         assert(buflen1 == buflen2); \
50         buf1 = talloc_zero_size(mem_ctx, buflen1); \
51         assert(buf1 != NULL); \
52         buf2 = talloc_zero_size(mem_ctx, buflen2); \
53         assert(buf2 != NULL); \
54         PUSH_FUNC(NAME)(&p, buf1, &np); \
55         OLD_PUSH_FUNC(NAME)(&p, buf2); \
56         assert(memcmp(buf1, buf2, buflen1) == 0); \
57         ret = PULL_FUNC(NAME)(buf1, buflen1, &p1, &np); \
58         assert(ret == 0); \
59         ret = OLD_PULL_FUNC(NAME)(buf2, buflen2, &p2); \
60         VERIFY_FUNC(NAME)(&p1, &p2); \
61         talloc_free(mem_ctx); \
62 }
63
64 #define COMPAT_TYPE3_TEST(TYPE, NAME)   \
65 static void COMPAT_TEST_FUNC(NAME)(void) \
66 { \
67         TALLOC_CTX *mem_ctx; \
68         uint8_t *buf1, *buf2; \
69         TYPE *p, *p1, *p2; \
70         size_t buflen1, buflen2, np = 0; \
71         int ret; \
72 \
73         mem_ctx = talloc_new(NULL); \
74         assert(mem_ctx != NULL); \
75         p = talloc_zero(mem_ctx, TYPE); \
76         assert(p != NULL); \
77         FILL_FUNC(NAME)(p, p); \
78         buflen1 = LEN_FUNC(NAME)(p); \
79         buflen2 = OLD_LEN_FUNC(NAME)(p); \
80         assert(buflen1 == buflen2); \
81         buf1 = talloc_zero_size(mem_ctx, buflen1); \
82         assert(buf1 != NULL); \
83         buf2 = talloc_zero_size(mem_ctx, buflen2); \
84         assert(buf2 != NULL); \
85         PUSH_FUNC(NAME)(p, buf1, &np); \
86         OLD_PUSH_FUNC(NAME)(p, buf2); \
87         assert(memcmp(buf1, buf2, buflen1) == 0); \
88         ret = PULL_FUNC(NAME)(buf1, buflen1, mem_ctx, &p1, &np); \
89         assert(ret == 0); \
90         ret = OLD_PULL_FUNC(NAME)(buf2, buflen2, mem_ctx, &p2); \
91         VERIFY_FUNC(NAME)(p1, p2); \
92         talloc_free(mem_ctx); \
93 }
94
95
96 static size_t ctdb_statistics_len_old(struct ctdb_statistics *in)
97 {
98         return sizeof(struct ctdb_statistics);
99 }
100
101 static void ctdb_statistics_push_old(struct ctdb_statistics *in, uint8_t *buf)
102 {
103         memcpy(buf, in, sizeof(struct ctdb_statistics));
104 }
105
106 static int ctdb_statistics_pull_old(uint8_t *buf, size_t buflen,
107                                     TALLOC_CTX *mem_ctx,
108                                     struct ctdb_statistics **out)
109 {
110         struct ctdb_statistics *val;
111
112         if (buflen < sizeof(struct ctdb_statistics)) {
113                 return EMSGSIZE;
114         }
115
116         val = talloc(mem_ctx, struct ctdb_statistics);
117         if (val == NULL) {
118                 return ENOMEM;
119         }
120
121         memcpy(val, buf, sizeof(struct ctdb_statistics));
122
123         *out = val;
124         return 0;
125 }
126
127 struct ctdb_vnn_map_wire {
128         uint32_t generation;
129         uint32_t size;
130         uint32_t map[1];
131 };
132
133 static size_t ctdb_vnn_map_len_old(struct ctdb_vnn_map *in)
134 {
135         return offsetof(struct ctdb_vnn_map, map) +
136                in->size * sizeof(uint32_t);
137 }
138
139 static void ctdb_vnn_map_push_old(struct ctdb_vnn_map *in, uint8_t *buf)
140 {
141         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
142
143         memcpy(wire, in, offsetof(struct ctdb_vnn_map, map));
144         memcpy(wire->map, in->map, in->size * sizeof(uint32_t));
145 }
146
147 static int ctdb_vnn_map_pull_old(uint8_t *buf, size_t buflen,
148                                  TALLOC_CTX *mem_ctx,
149                                  struct ctdb_vnn_map **out)
150 {
151         struct ctdb_vnn_map *val;
152         struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
153
154         if (buflen < offsetof(struct ctdb_vnn_map_wire, map)) {
155                 return EMSGSIZE;
156         }
157         if (wire->size > buflen / sizeof(uint32_t)) {
158                 return EMSGSIZE;
159         }
160         if (offsetof(struct ctdb_vnn_map_wire, map) +
161             wire->size * sizeof(uint32_t) <
162             offsetof(struct ctdb_vnn_map_wire, map)) {
163                     return EMSGSIZE;
164         }
165         if (buflen < offsetof(struct ctdb_vnn_map_wire, map) +
166                      wire->size * sizeof(uint32_t)) {
167                 return EMSGSIZE;
168         }
169
170         val = talloc(mem_ctx, struct ctdb_vnn_map);
171         if (val == NULL) {
172                 return ENOMEM;
173         }
174
175         memcpy(val, wire, offsetof(struct ctdb_vnn_map, map));
176
177         val->map = talloc_memdup(val, wire->map,
178                                  wire->size * sizeof(uint32_t));
179         if (val->map == NULL) {
180                 talloc_free(val);
181                 return ENOMEM;
182         }
183
184         *out = val;
185         return 0;
186 }
187
188 struct ctdb_dbid_map_wire {
189         uint32_t num;
190         struct ctdb_dbid dbs[1];
191 };
192
193 static size_t ctdb_dbid_map_len_old(struct ctdb_dbid_map *in)
194 {
195         return sizeof(uint32_t) + in->num * sizeof(struct ctdb_dbid);
196 }
197
198 static void ctdb_dbid_map_push_old(struct ctdb_dbid_map *in, uint8_t *buf)
199 {
200         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
201
202         wire->num = in->num;
203         memcpy(wire->dbs, in->dbs, in->num * sizeof(struct ctdb_dbid));
204 }
205
206 static int ctdb_dbid_map_pull_old(uint8_t *buf, size_t buflen,
207                                   TALLOC_CTX *mem_ctx,
208                                   struct ctdb_dbid_map **out)
209 {
210         struct ctdb_dbid_map *val;
211         struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
212
213         if (buflen < sizeof(uint32_t)) {
214                 return EMSGSIZE;
215         }
216         if (wire->num > buflen / sizeof(struct ctdb_dbid)) {
217                 return EMSGSIZE;
218         }
219         if (sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid) <
220             sizeof(uint32_t)) {
221                 return EMSGSIZE;
222         }
223         if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid)) {
224                 return EMSGSIZE;
225         }
226
227         val = talloc(mem_ctx, struct ctdb_dbid_map);
228         if (val == NULL) {
229                 return ENOMEM;
230         }
231
232         val->num = wire->num;
233
234         val->dbs = talloc_memdup(val, wire->dbs,
235                                  wire->num * sizeof(struct ctdb_dbid));
236         if (val->dbs == NULL) {
237                 talloc_free(val);
238                 return ENOMEM;
239         }
240
241         *out = val;
242         return 0;
243 }
244
245 static size_t ctdb_pulldb_len_old(struct ctdb_pulldb *in)
246 {
247         return sizeof(struct ctdb_pulldb);
248 }
249
250 static void ctdb_pulldb_push_old(struct ctdb_pulldb *in, uint8_t *buf)
251 {
252         memcpy(buf, in, sizeof(struct ctdb_pulldb));
253 }
254
255 static int ctdb_pulldb_pull_old(uint8_t *buf, size_t buflen,
256                                 TALLOC_CTX *mem_ctx, struct ctdb_pulldb **out)
257 {
258         struct ctdb_pulldb *val;
259
260         if (buflen < sizeof(struct ctdb_pulldb)) {
261                 return EMSGSIZE;
262         }
263
264         val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
265         if (val == NULL) {
266                 return ENOMEM;
267         }
268
269         *out = val;
270         return 0;
271 }
272
273
274 COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics);
275 COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map);
276 COMPAT_TYPE3_TEST(struct ctdb_dbid_map, ctdb_dbid_map);
277 COMPAT_TYPE3_TEST(struct ctdb_pulldb, ctdb_pulldb);
278
279 int main(int argc, char *argv[])
280 {
281         if (argc == 2) {
282                 int seed = atoi(argv[1]);
283                 srandom(seed);
284         }
285
286         COMPAT_TEST_FUNC(ctdb_statistics)();
287         COMPAT_TEST_FUNC(ctdb_vnn_map)();
288         COMPAT_TEST_FUNC(ctdb_dbid_map)();
289         COMPAT_TEST_FUNC(ctdb_pulldb)();
290
291         return 0;
292 }