ctdb-protocol: Fix marshalling for ctdb_vnn_map
[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
189 COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics);
190 COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map);
191
192 int main(int argc, char *argv[])
193 {
194         if (argc == 2) {
195                 int seed = atoi(argv[1]);
196                 srandom(seed);
197         }
198
199         COMPAT_TEST_FUNC(ctdb_statistics)();
200         COMPAT_TEST_FUNC(ctdb_vnn_map)();
201
202         return 0;
203 }