Line data Source code
1 : /* TLD library -- test the TLD version in all files
2 : * Copyright (C) 2011-2015 Made to Order Software Corp.
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the
6 : * "Software"), to deal in the Software without restriction, including
7 : * without limitation the rights to use, copy, modify, merge, publish,
8 : * distribute, sublicense, and/or sell copies of the Software, and to
9 : * permit persons to whom the Software is furnished to do so, subject to
10 : * the following conditions:
11 : *
12 : * The above copyright notice and this permission notice shall be included
13 : * in all copies or substantial portions of the Software.
14 : *
15 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 : */
23 :
24 : /** \file
25 : * \brief Test the tld library versions.
26 : *
27 : * This file implements various test to verify that the
28 : * version is properly defined in all the files as expected.
29 : *
30 : * In the compiled data, the version gets copied using the
31 : * configure_file() from cmake. Other files, such as the changelog,
32 : * require manual labor and thus the version could end up
33 : * being wrong (humans are notorious to forget stuff like that).
34 : */
35 :
36 : #include "libtld/tld.h"
37 : #include <string.h>
38 : #include <stdlib.h>
39 : #include <stdio.h>
40 : #include <limits.h>
41 :
42 : int err_count = 0;
43 : int verbose = 0;
44 :
45 :
46 :
47 1 : void check_version_compiled_with(const char *version)
48 : {
49 1 : if(verbose)
50 : {
51 0 : printf("version library was compiled with: %s\n", LIBTLD_VERSION);
52 : }
53 :
54 1 : if(strcmp(LIBTLD_VERSION, version) != 0)
55 : {
56 0 : ++err_count;
57 0 : fprintf(stderr, "error: compiled with version %s, expected %s instead.\n", LIBTLD_VERSION, version);
58 : }
59 1 : }
60 :
61 :
62 :
63 1 : void check_main_cmakefiles_txt(const char *path, const char *version)
64 : {
65 1 : const int cmakelists_txt_len = 15;
66 1 : const int len = strlen(path);
67 1 : char *filename = malloc(len + cmakelists_txt_len + 1);
68 : FILE *f;
69 : char buf[1024];
70 : char *str;
71 1 : int major = 0;
72 1 : int minor = 0;
73 1 : int patch = 0;
74 :
75 1 : memcpy(filename, path, len);
76 1 : memcpy(filename + len, "/CMakeLists.txt", cmakelists_txt_len + 1); // copy string and '\0'
77 :
78 1 : f = fopen(filename, "r");
79 1 : if(f == NULL)
80 : {
81 0 : ++err_count;
82 0 : perror("error: fopen()");
83 0 : fprintf(stderr, "error: could not open main CMakeLists.txt file (full path: \"%s\")\n:", filename);
84 0 : free(filename);
85 1 : return;
86 : }
87 :
88 68 : while(fgets(buf, sizeof(buf), f) != (char *) 0)
89 : {
90 66 : str = strstr(buf, "LIBTLD_VERSION_MAJOR");
91 66 : if(str != (char *) 0 && str > buf && str[-1] != '{')
92 : {
93 1 : major = atol(str + 20);
94 : }
95 66 : str = strstr(buf, "LIBTLD_VERSION_MINOR");
96 66 : if(str != (char *) 0 && str > buf && str[-1] != '{')
97 : {
98 1 : minor = atol(str + 20);
99 : }
100 66 : str = strstr(buf, "LIBTLD_VERSION_PATCH");
101 66 : if(str != (char *) 0 && str > buf && str[-1] != '{')
102 : {
103 1 : patch = atol(str + 20);
104 : }
105 : }
106 1 : fclose(f);
107 :
108 1 : snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch);
109 :
110 1 : if(verbose)
111 : {
112 0 : printf("main CMakeLists.txt version: %s\n", buf);
113 : }
114 :
115 1 : if(strcmp(buf, version) != 0)
116 : {
117 0 : ++err_count;
118 0 : fprintf(stderr, "error: main CMakeLists.txt version (%s) is %s, expected %s instead.\n", filename, buf, version);
119 : }
120 :
121 1 : free(filename);
122 : }
123 :
124 :
125 1 : void check_libtld_only_cmakefiles_txt(const char *path, const char *version)
126 : {
127 1 : const int cmakelists_txt_len = 31;
128 1 : const int len = strlen(path);
129 1 : char *filename = malloc(len + cmakelists_txt_len + 1);
130 : FILE *f;
131 : char buf[1024];
132 : char *str;
133 1 : int major = 0;
134 1 : int minor = 0;
135 1 : int patch = 0;
136 :
137 1 : memcpy(filename, path, len);
138 1 : memcpy(filename + len, "/dev/libtld-only-CMakeLists.txt", cmakelists_txt_len + 1); // copy string and '\0'
139 :
140 1 : f = fopen(filename, "r");
141 1 : if(f == NULL)
142 : {
143 0 : ++err_count;
144 0 : perror("error: fopen()");
145 0 : fprintf(stderr, "error: could not open libtld only CMakeLists.txt file (full path: \"%s\")\n:", filename);
146 0 : free(filename);
147 1 : return;
148 : }
149 :
150 130 : while(fgets(buf, sizeof(buf), f) != (char *) 0)
151 : {
152 128 : str = strstr(buf, "LIBTLD_VERSION_MAJOR");
153 128 : if(str != (char *) 0 && str > buf && str[-1] != '{')
154 : {
155 1 : major = atol(str + 20);
156 : }
157 128 : str = strstr(buf, "LIBTLD_VERSION_MINOR");
158 128 : if(str != (char *) 0 && str > buf && str[-1] != '{')
159 : {
160 1 : minor = atol(str + 20);
161 : }
162 128 : str = strstr(buf, "LIBTLD_VERSION_PATCH");
163 128 : if(str != (char *) 0 && str > buf && str[-1] != '{')
164 : {
165 1 : patch = atol(str + 20);
166 : }
167 : }
168 1 : fclose(f);
169 :
170 1 : snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch);
171 :
172 1 : if(verbose)
173 : {
174 0 : printf("libtld only CMakeLists.txt version: %s\n", buf);
175 : }
176 :
177 1 : if(strcmp(buf, version) != 0)
178 : {
179 0 : ++err_count;
180 0 : fprintf(stderr, "error: libtld only CMakeLists.txt version (%s) is %s, expected %s instead.\n", filename, buf, version);
181 : }
182 :
183 1 : free(filename);
184 : }
185 :
186 :
187 1 : void check_changelog(const char *path, const char *version)
188 : {
189 1 : const int changelog_len = 17;
190 1 : const int len = strlen(path);
191 1 : char *filename = malloc(len + changelog_len + 1);
192 : FILE *f;
193 : char buf[1024];
194 : char *str;
195 : char *debian_version;
196 : int i;
197 :
198 1 : memcpy(filename, path, len);
199 1 : memcpy(filename + len, "/debian/changelog", changelog_len + 1); // copy string and '\0'
200 :
201 1 : f = fopen(filename, "r");
202 1 : if(f == NULL)
203 : {
204 0 : ++err_count;
205 0 : perror("error: fopen()");
206 0 : fprintf(stderr, "error: could not open debian/changelog file (full path: \"%s\")\n:", filename);
207 0 : free(filename);
208 0 : return;
209 : }
210 :
211 1 : if(fgets(buf, sizeof(buf), f) == (char *) 0)
212 : {
213 0 : ++err_count;
214 0 : perror("error: fgets()");
215 0 : fprintf(stderr, "error: could not read the first line of debian/changelog (full path: \"%s\")\n:", filename);
216 0 : free(filename);
217 0 : fclose(f);
218 0 : return;
219 : }
220 :
221 1 : fclose(f);
222 :
223 1 : if(buf[0] != 'l'
224 1 : || buf[1] != 'i'
225 1 : || buf[2] != 'b'
226 1 : || buf[3] != 't'
227 1 : || buf[4] != 'l'
228 1 : || buf[5] != 'd'
229 1 : || buf[6] != ' '
230 1 : || buf[7] != '(')
231 : {
232 0 : ++err_count;
233 0 : fprintf(stderr, "error: debian/changelog does not start with \"libtld (\" as expected (full path: \"%s\")\n:", filename);
234 0 : free(filename);
235 0 : return;
236 : }
237 :
238 1 : debian_version = buf + 8;
239 :
240 1 : for(i = 0; debian_version[i] != '\0' && debian_version[i] != ')'; ++i);
241 :
242 1 : if(debian_version[i] != ')')
243 : {
244 0 : ++err_count;
245 0 : fprintf(stderr, "error: debian/changelog does not seem to include a valid version (full path: \"%s\")\n:", filename);
246 0 : free(filename);
247 0 : return;
248 : }
249 1 : debian_version[i] = '\0'; // this modifies buf which is fine
250 :
251 : // the debian version is likely to include a build number and platform name
252 1 : i = 0;
253 6 : for(str = debian_version; str != '\0'; ++str)
254 : {
255 6 : if(*str == '~')
256 : {
257 : // stop immediately
258 0 : break;
259 : }
260 6 : else if(*str == '.')
261 : {
262 3 : ++i;
263 3 : if(i >= 3)
264 : {
265 : // stop at the 3rd '.' (i.e. build number)
266 1 : break;
267 : }
268 : }
269 : }
270 1 : *str = '\0'; // remove extra stuff
271 :
272 1 : if(verbose)
273 : {
274 0 : printf("changelog version: %s\n", debian_version);
275 : }
276 :
277 1 : if(strcmp(debian_version, version) != 0)
278 : {
279 0 : ++err_count;
280 0 : fprintf(stderr, "error: changelog version (%s) is %s, expected %s instead.\n", filename, debian_version, version);
281 : }
282 :
283 1 : free(filename);
284 : }
285 :
286 :
287 :
288 1 : int main(int argc, char *argv[])
289 : {
290 1 : const char *version = tld_version();
291 1 : char *path = (char *) 0;
292 : int i;
293 :
294 2 : for(i = 1; i < argc; ++i)
295 : {
296 1 : if(strcmp(argv[i], "-v") == 0)
297 : {
298 0 : verbose = 1;
299 : }
300 : else
301 : {
302 1 : path = argv[i];
303 : }
304 : }
305 :
306 1 : if(path == (char *) 0)
307 : {
308 0 : ++err_count;
309 0 : fprintf(stderr, "error: mandatory source path not specified on command line.\n");
310 : }
311 : else
312 : {
313 1 : if(verbose)
314 : {
315 0 : printf("runtime libtld version: %s\n", version);
316 : }
317 : else
318 : {
319 1 : printf("%s\n", version);
320 : }
321 :
322 1 : check_version_compiled_with(version);
323 1 : check_main_cmakefiles_txt(path, version);
324 1 : check_libtld_only_cmakefiles_txt(path, version);
325 1 : check_changelog(path, version);
326 : }
327 :
328 1 : exit(err_count ? 1 : 0);
329 : }
330 :
331 : /* vim: ts=4 sw=4 et
332 : */
333 :
|