1 /*
2  * This file is part of libmodulemd
3  * Copyright (C) 2018 Red Hat, Inc.
4  *
5  * Fedora-License-Identifier: MIT
6  * SPDX-2.0-License-Identifier: MIT
7  * SPDX-3.0-License-Identifier: MIT
8  *
9  * This program is free software.
10  * For more information on the license, see COPYING.
11  * For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>.
12  */
13 
14 #include <glib.h>
15 #include <glib/gstdio.h>
16 #include <locale.h>
17 #include <signal.h>
18 
19 #include "modulemd-subdocument-info.h"
20 #include "modulemd-obsoletes.h"
21 #include "private/glib-extensions.h"
22 #include "private/modulemd-subdocument-info-private.h"
23 #include "private/modulemd-obsoletes-private.h"
24 #include "private/modulemd-util.h"
25 #include "private/modulemd-yaml.h"
26 #include "private/test-utils.h"
27 
28 static void
obsoletes_test_construct(void)29 obsoletes_test_construct (void)
30 {
31   g_autoptr (ModulemdObsoletes) e = NULL;
32 
33   /* Test new() with a valid mdversion and module name */
34   e = modulemd_obsoletes_new (1, 2, "testmodule", "teststream", "testmessage");
35   g_assert_nonnull (e);
36   g_assert_true (MODULEMD_IS_OBSOLETES (e));
37   g_assert_cmpint (modulemd_obsoletes_get_mdversion (e), ==, 1);
38   g_assert_cmpstr (modulemd_obsoletes_get_module_name (e), ==, "testmodule");
39   g_assert_cmpstr (modulemd_obsoletes_get_module_stream (e), ==, "teststream");
40   g_assert_cmpstr (modulemd_obsoletes_get_message (e), ==, "testmessage");
41   g_clear_object (&e);
42 
43   /* Test new() with a NULL module_name */
44   modulemd_test_signal = 0;
45   signal (SIGTRAP, modulemd_test_signal_handler);
46   e = modulemd_obsoletes_new (
47     MD_OBSOLETES_VERSION_ONE, 2, NULL, "teststream", "testmessage");
48   g_assert_cmpint (modulemd_test_signal, ==, SIGTRAP);
49   /* If we trap the error, obsoletes actually returns a value here, so free it */
50   g_clear_object (&e);
51 
52   /* Test new() with a NULL module_context */
53   modulemd_test_signal = 0;
54   signal (SIGTRAP, modulemd_test_signal_handler);
55   e = modulemd_obsoletes_new (
56     MD_OBSOLETES_VERSION_ONE, 2, "testmodule", NULL, "testmessage");
57   g_assert_cmpint (modulemd_test_signal, ==, SIGTRAP);
58   /* If we trap the error, obsoletes actually returns a value here, so free it */
59   g_clear_object (&e);
60 
61   /* Test new() with a NULL message */
62   modulemd_test_signal = 0;
63   signal (SIGTRAP, modulemd_test_signal_handler);
64   e = modulemd_obsoletes_new (
65     MD_OBSOLETES_VERSION_ONE, 2, "testmodule", "teststream", NULL);
66   g_assert_cmpint (modulemd_test_signal, ==, SIGTRAP);
67   /* If we trap the error, obsoletes actually returns a value here, so free it */
68   g_clear_object (&e);
69 }
70 
71 static void
obsoletes_test_copy(void)72 obsoletes_test_copy (void)
73 {
74   g_autoptr (ModulemdObsoletes) e = NULL;
75   g_autoptr (ModulemdObsoletes) e_copy = NULL;
76 
77   e = modulemd_obsoletes_new (
78     MD_OBSOLETES_VERSION_ONE, 2, "testmodule", "teststream", "testmessage");
79 
80   e_copy = modulemd_obsoletes_copy (e);
81 
82   g_assert_nonnull (e_copy);
83   g_assert_true (MODULEMD_IS_OBSOLETES (e_copy));
84   g_assert_cmpint (modulemd_obsoletes_get_mdversion (e_copy), ==, 1);
85   g_assert_cmpint (modulemd_obsoletes_get_modified (e_copy), ==, 2);
86   g_assert_cmpstr (
87     modulemd_obsoletes_get_module_name (e_copy), ==, "testmodule");
88   g_assert_cmpstr (
89     modulemd_obsoletes_get_module_stream (e_copy), ==, "teststream");
90   g_assert_cmpstr (modulemd_obsoletes_get_message (e_copy), ==, "testmessage");
91 
92   g_clear_object (&e_copy);
93 
94   /* Test if we also copy optional field */
95   modulemd_obsoletes_set_module_context (e, "testcontext");
96   modulemd_obsoletes_set_eol_date (e, 9);
97   modulemd_obsoletes_set_obsoleted_by (e, "nodejs", "12");
98 
99   e_copy = modulemd_obsoletes_copy (e);
100   g_assert_nonnull (e_copy);
101   g_assert_true (MODULEMD_IS_OBSOLETES (e_copy));
102   g_assert_cmpint (modulemd_obsoletes_get_mdversion (e_copy), ==, 1);
103   g_assert_cmpint (modulemd_obsoletes_get_modified (e_copy), ==, 2);
104   g_assert_cmpuint (modulemd_obsoletes_get_reset (e), ==, FALSE);
105   g_assert_cmpstr (
106     modulemd_obsoletes_get_module_name (e_copy), ==, "testmodule");
107   g_assert_cmpstr (
108     modulemd_obsoletes_get_module_stream (e_copy), ==, "teststream");
109   g_assert_cmpstr (
110     modulemd_obsoletes_get_module_context (e_copy), ==, "testcontext");
111   g_assert_cmpuint (modulemd_obsoletes_get_eol_date (e_copy), ==, 9);
112   g_assert_cmpstr (modulemd_obsoletes_get_message (e_copy), ==, "testmessage");
113   g_assert_cmpstr (
114     modulemd_obsoletes_get_obsoleted_by_module_name (e_copy), ==, "nodejs");
115   g_assert_cmpstr (
116     modulemd_obsoletes_get_obsoleted_by_module_stream (e_copy), ==, "12");
117   g_clear_object (&e_copy);
118   g_clear_object (&e);
119 }
120 
121 static void
obsoletes_test_validate(void)122 obsoletes_test_validate (void)
123 {
124   g_autoptr (ModulemdObsoletes) e = NULL;
125   g_autoptr (GError) error = NULL;
126 
127   e = modulemd_obsoletes_new (
128     MD_OBSOLETES_VERSION_ONE, 2, "module", "stream", "message");
129   g_assert_nonnull (e);
130 
131   g_assert_true (modulemd_obsoletes_validate (e, &error));
132   g_assert_null (error);
133   g_clear_object (&e);
134 
135   /* Invalid mdversion */
136   e = modulemd_obsoletes_new (999, 2, "module", "stream", "message");
137   g_assert_nonnull (e);
138 
139   g_assert_false (modulemd_obsoletes_validate (e, &error));
140   g_assert_nonnull (error);
141   g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
142   g_clear_object (&e);
143   g_clear_error (&error);
144 
145   /* Invalid modified */
146   e = modulemd_obsoletes_new (
147     MD_OBSOLETES_VERSION_ONE, 0, "module", "stream", "message");
148   g_assert_nonnull (e);
149 
150   g_assert_false (modulemd_obsoletes_validate (e, &error));
151   g_assert_nonnull (error);
152   g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
153   g_clear_object (&e);
154   g_clear_error (&error);
155 
156   /* obsoleted_by have to be both set or unset */
157   e = modulemd_obsoletes_new (
158     MD_OBSOLETES_VERSION_ONE, 2, "module", "stream", "message");
159   modulemd_obsoletes_set_obsoleted_by_module_name (e,
160                                                    "only name without stream");
161   g_assert_nonnull (e);
162 
163   g_assert_false (modulemd_obsoletes_validate (e, &error));
164   g_assert_nonnull (error);
165   g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
166   g_clear_object (&e);
167   g_clear_error (&error);
168 
169   e = modulemd_obsoletes_new (
170     MD_OBSOLETES_VERSION_ONE, 2, "module", "stream", "message");
171   modulemd_obsoletes_set_obsoleted_by_module_stream (
172     e, "only stream without module name");
173   g_assert_nonnull (e);
174 
175   g_assert_false (modulemd_obsoletes_validate (e, &error));
176   g_assert_nonnull (error);
177   g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
178   g_clear_object (&e);
179   g_clear_error (&error);
180 }
181 
182 static void
obsoletes_test_get_mdversion(void)183 obsoletes_test_get_mdversion (void)
184 {
185   g_autoptr (ModulemdObsoletes) e = NULL;
186   guint64 mdversion;
187 
188   e = modulemd_obsoletes_new (
189     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
190   g_assert_true (MODULEMD_IS_OBSOLETES (e));
191 
192   mdversion = modulemd_obsoletes_get_mdversion (e);
193   g_assert_cmpuint (mdversion, ==, MD_OBSOLETES_VERSION_LATEST);
194 }
195 
196 static void
obsoletes_test_modified(void)197 obsoletes_test_modified (void)
198 {
199   g_autoptr (ModulemdObsoletes) e = NULL;
200   guint64 modified;
201 
202   e = modulemd_obsoletes_new (
203     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
204   g_assert_true (MODULEMD_IS_OBSOLETES (e));
205 
206   modified = modulemd_obsoletes_get_modified (e);
207   g_assert_cmpuint (modified, ==, 2);
208 
209 
210   modulemd_obsoletes_set_modified (e, 9);
211   modified = modulemd_obsoletes_get_modified (e);
212   g_assert_cmpuint (modified, ==, 9);
213 }
214 
215 static void
obsoletes_test_reset(void)216 obsoletes_test_reset (void)
217 {
218   g_autoptr (ModulemdObsoletes) e = NULL;
219 
220   e = modulemd_obsoletes_new (
221     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
222   g_assert_true (MODULEMD_IS_OBSOLETES (e));
223 
224   g_assert_cmpuint (modulemd_obsoletes_get_reset (e), ==, FALSE);
225 
226   modulemd_obsoletes_set_reset (e, TRUE);
227   g_assert_cmpuint (modulemd_obsoletes_get_reset (e), ==, TRUE);
228 
229   g_clear_object (&e);
230 }
231 
232 static void
obsoletes_test_eol_date(void)233 obsoletes_test_eol_date (void)
234 {
235   g_autoptr (ModulemdObsoletes) e = NULL;
236 
237   e = modulemd_obsoletes_new (
238     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
239   g_assert_true (MODULEMD_IS_OBSOLETES (e));
240 
241   g_assert_cmpuint (modulemd_obsoletes_get_eol_date (e), ==, 0);
242 
243   modulemd_obsoletes_set_eol_date (e, 9);
244   g_assert_cmpuint (modulemd_obsoletes_get_eol_date (e), ==, 9);
245 }
246 
247 static void
obsoletes_test_message(void)248 obsoletes_test_message (void)
249 {
250   g_autoptr (ModulemdObsoletes) e = NULL;
251   const gchar *message;
252 
253   e = modulemd_obsoletes_new (
254     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
255   g_assert_true (MODULEMD_IS_OBSOLETES (e));
256 
257   message = modulemd_obsoletes_get_message (e);
258   g_assert_cmpstr (message, ==, "testmessage");
259 
260   modulemd_obsoletes_set_message (e, "test");
261   message = modulemd_obsoletes_get_message (e);
262   g_assert_cmpstr (message, ==, "test");
263 }
264 
265 static void
obsoletes_test_context(void)266 obsoletes_test_context (void)
267 {
268   g_autoptr (ModulemdObsoletes) e = NULL;
269   const gchar *context;
270 
271   e = modulemd_obsoletes_new (
272     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
273   g_assert_true (MODULEMD_IS_OBSOLETES (e));
274 
275   context = modulemd_obsoletes_get_module_context (e);
276   g_assert_null (context);
277 
278   modulemd_obsoletes_set_module_context (e, "testcontext");
279   context = modulemd_obsoletes_get_module_context (e);
280   g_assert_cmpstr (context, ==, "testcontext");
281 }
282 
283 
284 static void
obsoletes_test_obsoleted_by(void)285 obsoletes_test_obsoleted_by (void)
286 {
287   g_autoptr (ModulemdObsoletes) e = NULL;
288   const gchar *obsoleted_by_module_name;
289   const gchar *obsoleted_by_module_stream;
290 
291   e = modulemd_obsoletes_new (
292     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testcontext");
293   g_assert_true (MODULEMD_IS_OBSOLETES (e));
294 
295   obsoleted_by_module_name =
296     modulemd_obsoletes_get_obsoleted_by_module_name (e);
297   obsoleted_by_module_stream =
298     modulemd_obsoletes_get_obsoleted_by_module_stream (e);
299   g_assert_null (obsoleted_by_module_name);
300   g_assert_null (obsoleted_by_module_stream);
301 
302   modulemd_obsoletes_set_obsoleted_by (e, "nodejs", "12");
303   obsoleted_by_module_name =
304     modulemd_obsoletes_get_obsoleted_by_module_name (e);
305   obsoleted_by_module_stream =
306     modulemd_obsoletes_get_obsoleted_by_module_stream (e);
307   g_assert_cmpstr (obsoleted_by_module_name, ==, "nodejs");
308   g_assert_cmpstr (obsoleted_by_module_stream, ==, "12");
309 }
310 
311 static void
obsoletes_test_is_active(void)312 obsoletes_test_is_active (void)
313 {
314   g_autoptr (ModulemdObsoletes) e = NULL;
315 
316   e = modulemd_obsoletes_new (
317     MD_OBSOLETES_VERSION_LATEST, 2, "testmodule", "teststream", "testmessage");
318   g_assert_true (MODULEMD_IS_OBSOLETES (e));
319 
320   g_assert_cmpuint (modulemd_obsoletes_get_eol_date (e), ==, 0);
321   g_assert_true (modulemd_obsoletes_is_active (e));
322 
323   modulemd_obsoletes_set_eol_date (e, 290001011200);
324   g_assert_false (modulemd_obsoletes_is_active (e));
325 
326   modulemd_obsoletes_set_eol_date (e, 199901011200);
327   g_assert_true (modulemd_obsoletes_is_active (e));
328 }
329 
330 static void
obsoletes_test_parse_yaml(void)331 obsoletes_test_parse_yaml (void)
332 {
333   MMD_INIT_YAML_PARSER (parser);
334   MMD_INIT_YAML_EVENT (event);
335   g_autofree gchar *yaml_path = NULL;
336   g_autoptr (ModulemdObsoletes) e = NULL;
337   int yaml_ret;
338   g_autoptr (FILE) yaml_stream = NULL;
339   g_autoptr (GError) error = NULL;
340   g_autoptr (ModulemdSubdocumentInfo) subdoc = NULL;
341 
342   /* Validate that we can read the specification without issues */
343   yaml_path = g_strdup_printf ("%s/yaml_specs/modulemd_obsoletes_v1.yaml",
344                                g_getenv ("MESON_SOURCE_ROOT"));
345   g_assert_nonnull (yaml_path);
346 
347   yaml_stream = g_fopen (yaml_path, "rbe");
348   g_assert_nonnull (yaml_stream);
349 
350   yaml_parser_set_input_file (&parser, yaml_stream);
351 
352   /* The first event must be the stream start */
353   yaml_ret = yaml_parser_parse (&parser, &event);
354   g_assert_true (yaml_ret);
355   g_assert_cmpint (event.type, ==, YAML_STREAM_START_EVENT);
356   yaml_event_delete (&event);
357 
358   /* The second event must be the document start */
359   yaml_ret = yaml_parser_parse (&parser, &event);
360   g_assert_true (yaml_ret);
361   g_assert_cmpint (event.type, ==, YAML_DOCUMENT_START_EVENT);
362   yaml_event_delete (&event);
363 
364   subdoc = modulemd_yaml_parse_document_type (&parser);
365   g_assert_nonnull (subdoc);
366   g_assert_null (modulemd_subdocument_info_get_gerror (subdoc));
367 
368   g_assert_cmpint (modulemd_subdocument_info_get_doctype (subdoc),
369                    ==,
370                    MODULEMD_YAML_DOC_OBSOLETES);
371   g_assert_cmpint (modulemd_subdocument_info_get_mdversion (subdoc), ==, 1);
372   g_assert_nonnull (modulemd_subdocument_info_get_yaml (subdoc));
373 
374   e = modulemd_obsoletes_parse_yaml (subdoc, TRUE, &error);
375   g_assert_no_error (error);
376   g_assert_null (error);
377   g_assert_nonnull (e);
378 
379   g_assert_cmpint (modulemd_obsoletes_get_mdversion (e), ==, 1);
380   g_assert_cmpstr (modulemd_obsoletes_get_module_name (e), ==, "nodejs");
381   g_assert_cmpstr (modulemd_obsoletes_get_module_stream (e), ==, "11");
382   g_assert_cmpint (modulemd_obsoletes_get_modified (e), ==, 201805231425);
383   g_assert_cmpstr (modulemd_obsoletes_get_message (e),
384                    ==,
385                    "Module stream nodejs:11 is no longer supported. It is "
386                    "recommended to switch to nodejs:12");
387 
388   g_assert_cmpstr (
389     modulemd_obsoletes_get_obsoleted_by_module_name (e), ==, "nodejs");
390   g_assert_cmpstr (
391     modulemd_obsoletes_get_obsoleted_by_module_stream (e), ==, "12");
392 }
393 
394 static void
obsoletes_test_emit_yaml(void)395 obsoletes_test_emit_yaml (void)
396 {
397   MMD_INIT_YAML_EMITTER (emitter);
398   MMD_INIT_YAML_EVENT (event);
399   MMD_INIT_YAML_STRING (&emitter, yaml_string);
400 
401   g_autoptr (GError) error = NULL;
402   g_autoptr (ModulemdObsoletes) e = NULL;
403   e = modulemd_obsoletes_new (MD_OBSOLETES_VERSION_LATEST,
404                               202001012020,
405                               "testmodule",
406                               "teststream",
407                               "testmessage");
408 
409   g_assert_true (mmd_emitter_start_stream (&emitter, &error));
410   g_assert_true (modulemd_obsoletes_emit_yaml (e, &emitter, &error));
411   g_assert_true (mmd_emitter_end_stream (&emitter, &error));
412   g_assert_nonnull (yaml_string->str);
413   g_assert_cmpstr (yaml_string->str,
414                    ==,
415                    "---\n"
416                    "document: modulemd-obsoletes\n"
417                    "version: 1\n"
418                    "data:\n"
419                    "  modified: 2020-01-01T20:20Z\n"
420                    "  module: testmodule\n"
421                    "  stream: \"teststream\"\n"
422                    "  message: testmessage\n"
423                    "...\n");
424 
425   modulemd_obsoletes_set_module_context (e, "testcontext");
426   modulemd_obsoletes_set_eol_date (e, 202001010000);
427   modulemd_obsoletes_set_obsoleted_by (e, "nodejs", "12");
428 
429   MMD_REINIT_YAML_STRING (&emitter, yaml_string);
430   g_assert_true (mmd_emitter_start_stream (&emitter, &error));
431   g_assert_true (modulemd_obsoletes_emit_yaml (e, &emitter, &error));
432   g_assert_true (mmd_emitter_end_stream (&emitter, &error));
433   g_assert_nonnull (yaml_string->str);
434   g_assert_cmpstr (yaml_string->str,
435                    ==,
436                    "---\n"
437                    "document: modulemd-obsoletes\n"
438                    "version: 1\n"
439                    "data:\n"
440                    "  modified: 2020-01-01T20:20Z\n"
441                    "  module: testmodule\n"
442                    "  stream: \"teststream\"\n"
443                    "  context: testcontext\n"
444                    "  eol_date: 2020-01-01T00:00Z\n"
445                    "  message: testmessage\n"
446                    "  obsoleted_by:\n"
447                    "    module: nodejs\n"
448                    "    stream: \"12\"\n"
449                    "...\n");
450 }
451 
452 int
main(int argc,char * argv[])453 main (int argc, char *argv[])
454 {
455   setlocale (LC_ALL, "");
456 
457   g_test_init (&argc, &argv, NULL);
458   g_test_bug_base ("https://bugzilla.redhat.com/show_bug.cgi?id=");
459 
460   // Define the tests.
461 
462   g_test_add_func ("/modulemd/v2/obsoletes/construct",
463                    obsoletes_test_construct);
464 
465   g_test_add_func ("/modulemd/v2/obsoletes/copy", obsoletes_test_copy);
466 
467   g_test_add_func ("/modulemd/v2/obsoletes/validate", obsoletes_test_validate);
468 
469   g_test_add_func ("/modulemd/v2/obsoletes/version",
470                    obsoletes_test_get_mdversion);
471   g_test_add_func ("/modulemd/v2/obsoletes/modified", obsoletes_test_modified);
472   g_test_add_func ("/modulemd/v2/obsoletes/reset", obsoletes_test_reset);
473   g_test_add_func ("/modulemd/v2/obsoletes/eol_date", obsoletes_test_eol_date);
474   g_test_add_func ("/modulemd/v2/obsoletes/message", obsoletes_test_message);
475   g_test_add_func ("/modulemd/v2/obsoletes/context", obsoletes_test_context);
476   g_test_add_func ("/modulemd/v2/obsoletes/obsoletes_by",
477                    obsoletes_test_obsoleted_by);
478   g_test_add_func ("/modulemd/v2/obsoletes/active", obsoletes_test_is_active);
479 
480   g_test_add_func ("/modulemd/v2/obsoletes/yaml/parse",
481                    obsoletes_test_parse_yaml);
482   g_test_add_func ("/modulemd/v2/obsoletes/yaml/emit",
483                    obsoletes_test_emit_yaml);
484 
485   return g_test_run ();
486 }
487