Skip to content

Commit 0132015

Browse files
ppisarsgallagher
authored andcommitted
modulemd v2: Relax context up to 13 characters including underscore
cb50741 (Add BuildConfig object) commit broke scratch builds: $ rhpkg module-scratch-build --file perl-YAML.yaml --buildrequires platform:el8.5.0 Submitting the module build... Could not execute module_scratch_build: The build failed with: modulemd-error-quark: Could not validate stream to emit: Non-alphanumeric character in stream context 'a6d43775_1' (1) The reason is that a scratch build automatically adds an underscore suffix (e.g. "_1)" to the context value. This patch fixes it by allowing the underscore character and prolonging a limit of 10 characters with 3 additional characters (i.e. up to 99 scratch builds). We keep v3 context strict as it was (no underscore, 10 characters) to prevent packagers from specifying a context in v3 which could not be scratch-built later. A specification was amended accordingly. This dichotomy is dictated by the fact that v3 is an input-only format, while v2 is both input and output format for MBS. The implemented tests discovered that reading v2 document with a static context does not perform a validation in contrast to reading a v3 document. This patch does not change it. It instead marks the affected tests as TODO and test an explicit validation in addition. <#549>
1 parent 1bc2faa commit 0132015

File tree

5 files changed

+244
-6
lines changed

5 files changed

+244
-6
lines changed

modulemd/include/private/modulemd-module-stream-v2-private.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#pragma once
1515

16+
#include "modulemd-module-stream.h"
1617
#include "modulemd-module-stream-v2.h"
1718
#include "modulemd-subdocument-info.h"
1819
#include <glib-object.h>
@@ -22,6 +23,17 @@
2223
G_BEGIN_DECLS
2324

2425

26+
/**
27+
* MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN:
28+
*
29+
* The ModuleStream v3 specification defines the maximum lenth of the context
30+
* field. Just before building, the v3 format is converted to v2 format. But
31+
* if a scratch build was requested, an underscore with a decimal number (e.g.
32+
* "_1") is appended to the v2 context. Allow up to 99 scratch builds here.
33+
*/
34+
#define MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN (MMD_MAXCONTEXTLEN + 3)
35+
36+
2537
/**
2638
* SECTION: modulemd-module-stream-v2-private
2739
* @title: Modulemd.ModuleStreamV2 (Private)

modulemd/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ c_tests = {
271271
'component_module' : [ 'tests/test-modulemd-component-module.c' ],
272272
'component_rpm' : [ 'tests/test-modulemd-component-rpm.c' ],
273273
'compression' : [ 'tests/test-modulemd-compression.c' ],
274+
'context' : [ 'tests/test-modulemd-context.c' ],
274275
'defaults' : [ 'tests/test-modulemd-defaults.c' ],
275276
'defaultsv1' : [ 'tests/test-modulemd-defaults-v1.c' ],
276277
'dependencies' : [ 'tests/test-modulemd-dependencies.c' ],

modulemd/modulemd-module-stream-v2.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ static gboolean
12371237
modulemd_module_stream_v2_validate_context (const gchar *context,
12381238
GError **error)
12391239
{
1240-
/* must be string of up to MMD_MAXCONTEXTLEN [a-zA-Z0-9] */
1240+
/* must be string of up to MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN [a-zA-Z0-9_] */
12411241

12421242
if (context == NULL || *context == '\0')
12431243
{
@@ -1246,25 +1246,25 @@ modulemd_module_stream_v2_validate_context (const gchar *context,
12461246
return FALSE;
12471247
}
12481248

1249-
if (strlen (context) > MMD_MAXCONTEXTLEN)
1249+
if (strlen (context) > MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN)
12501250
{
12511251
g_set_error (error,
12521252
MODULEMD_ERROR,
12531253
MMD_ERROR_VALIDATE,
12541254
"Stream context '%s' exceeds maximum length (%d)",
12551255
context,
1256-
MMD_MAXCONTEXTLEN);
1256+
MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN);
12571257
return FALSE;
12581258
}
12591259

12601260
for (const gchar *i = context; *i != '\0'; i++)
12611261
{
1262-
if (!g_ascii_isalnum (*i))
1262+
if (!g_ascii_isalnum (*i) && *i != '_')
12631263
{
12641264
g_set_error (error,
12651265
MODULEMD_ERROR,
12661266
MMD_ERROR_VALIDATE,
1267-
"Non-alphanumeric character in stream context '%s'",
1267+
"Stream context '%s' can only contain [a-zA-Z0-9_] characters",
12681268
context);
12691269
return FALSE;
12701270
}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* This file is part of libmodulemd
3+
* Copyright (C) 2021 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 <locale.h>
15+
#include <glib.h>
16+
#include "modulemd.h"
17+
#include "config.h"
18+
19+
static void
20+
test_modulemd_v3_context_valid (void)
21+
{
22+
const gchar *yaml_string = NULL;
23+
g_autoptr (GError) error = NULL;
24+
g_autoptr (GObject) object = NULL;
25+
GType type = G_TYPE_INVALID;
26+
27+
yaml_string =
28+
"---\n"
29+
"document: modulemd-packager\n"
30+
"version: 3\n"
31+
"data:\n"
32+
" name: trivialname\n"
33+
" stream: trivialstream\n"
34+
" summary: Trivial Summary\n"
35+
" description: >-\n"
36+
" Trivial Description\n"
37+
" license: [MIT]\n"
38+
" configurations:\n"
39+
" - context: a234567890\n"
40+
" platform: foo\n"
41+
"...\n";
42+
type = modulemd_read_packager_string (yaml_string, &object, &error);
43+
g_assert_true (type == MODULEMD_TYPE_PACKAGER_V3);
44+
g_assert_no_error (error);
45+
}
46+
47+
48+
static void
49+
test_modulemd_v3_context_overlong (void)
50+
{
51+
const gchar *yaml_string = NULL;
52+
g_autoptr (GError) error = NULL;
53+
g_autoptr (GObject) object = NULL;
54+
GType type = G_TYPE_INVALID;
55+
56+
yaml_string =
57+
"---\n"
58+
"document: modulemd-packager\n"
59+
"version: 3\n"
60+
"data:\n"
61+
" name: trivialname\n"
62+
" stream: trivialstream\n"
63+
" summary: Trivial Summary\n"
64+
" description: >-\n"
65+
" Trivial Description\n"
66+
" license: [MIT]\n"
67+
" configurations:\n"
68+
" - context: a2345678901\n"
69+
" platform: foo\n"
70+
"...\n";
71+
type = modulemd_read_packager_string (yaml_string, &object, &error);
72+
g_assert_true (type == G_TYPE_INVALID);
73+
g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
74+
}
75+
76+
77+
static void
78+
test_modulemd_v3_context_bad_underscore (void)
79+
{
80+
const gchar *yaml_string = NULL;
81+
g_autoptr (GError) error = NULL;
82+
g_autoptr (GObject) object = NULL;
83+
GType type = G_TYPE_INVALID;
84+
85+
yaml_string =
86+
"---\n"
87+
"document: modulemd-packager\n"
88+
"version: 3\n"
89+
"data:\n"
90+
" name: trivialname\n"
91+
" stream: trivialstream\n"
92+
" summary: Trivial Summary\n"
93+
" description: >-\n"
94+
" Trivial Description\n"
95+
" license: [MIT]\n"
96+
" configurations:\n"
97+
" - context: _\n"
98+
" platform: foo\n"
99+
"...\n";
100+
type = modulemd_read_packager_string (yaml_string, &object, &error);
101+
g_assert_true (type == G_TYPE_INVALID);
102+
g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
103+
}
104+
105+
106+
static void
107+
test_modulemd_v2_context_valid (void)
108+
{
109+
const gchar *yaml_string = NULL;
110+
g_autoptr (GError) error = NULL;
111+
g_autoptr (GObject) object = NULL;
112+
GType type = G_TYPE_INVALID;
113+
114+
yaml_string =
115+
"---\n"
116+
"document: modulemd\n"
117+
"version: 2\n"
118+
"data:\n"
119+
" name: trivialname\n"
120+
" stream: trivialstream\n"
121+
" summary: Trivial Summary\n"
122+
" description: >-\n"
123+
" Trivial Description\n"
124+
" license:\n"
125+
" module: [MIT]\n"
126+
" static_context: true\n"
127+
" context: a234567890_23\n"
128+
"...\n";
129+
type = modulemd_read_packager_string (yaml_string, &object, &error);
130+
g_assert_true (type == MODULEMD_TYPE_MODULE_STREAM_V2);
131+
g_assert_no_error (error);
132+
/* Reading v2 document does not validate it; validating explictly */
133+
g_assert_true (modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (object), &error));
134+
}
135+
136+
137+
static void
138+
test_modulemd_v2_context_overlong (void)
139+
{
140+
const gchar *yaml_string = NULL;
141+
g_autoptr (GError) error = NULL;
142+
g_autoptr (GObject) object = NULL;
143+
GType type = G_TYPE_INVALID;
144+
145+
yaml_string =
146+
"---\n"
147+
"document: modulemd\n"
148+
"version: 2\n"
149+
"data:\n"
150+
" name: trivialname\n"
151+
" stream: trivialstream\n"
152+
" summary: Trivial Summary\n"
153+
" description: >-\n"
154+
" Trivial Description\n"
155+
" license:\n"
156+
" module: [MIT]\n"
157+
" static_context: true\n"
158+
" context: a234567890_234\n"
159+
"...\n";
160+
type = modulemd_read_packager_string (yaml_string, &object, &error);
161+
g_assert_true (type == G_TYPE_INVALID);
162+
g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
163+
if (type != G_TYPE_INVALID)
164+
{
165+
g_test_incomplete ("Reading v2 document does not validate it");
166+
/* Validating explicitly */
167+
g_assert_false (modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (object), &error));
168+
}
169+
}
170+
171+
172+
static void
173+
test_modulemd_v2_context_bad_character (void)
174+
{
175+
const gchar *yaml_string = NULL;
176+
g_autoptr (GError) error = NULL;
177+
g_autoptr (GObject) object = NULL;
178+
GType type = G_TYPE_INVALID;
179+
180+
yaml_string =
181+
"---\n"
182+
"document: modulemd\n"
183+
"version: 2\n"
184+
"data:\n"
185+
" name: trivialname\n"
186+
" stream: trivialstream\n"
187+
" summary: Trivial Summary\n"
188+
" description: >-\n"
189+
" Trivial Description\n"
190+
" license:\n"
191+
" module: [MIT]\n"
192+
" static_context: true\n"
193+
" context: '-'\n"
194+
"...\n";
195+
type = modulemd_read_packager_string (yaml_string, &object, &error);
196+
g_assert_true (type == G_TYPE_INVALID);
197+
g_assert_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE);
198+
if (type != G_TYPE_INVALID)
199+
{
200+
g_test_incomplete ("Reading v2 document does not validate it");
201+
/* Validating explicitly */
202+
g_assert_false (modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (object), &error));
203+
}
204+
}
205+
206+
207+
int
208+
main (int argc, char *argv[])
209+
{
210+
setlocale (LC_ALL, "");
211+
g_test_init (&argc, &argv, NULL);
212+
g_test_set_nonfatal_assertions ();
213+
g_test_bug_base ("https://github.com/fedora-modularity/libmodulemd/issues/");
214+
g_test_bug ("549");
215+
216+
g_test_add_func ("/modulemd/v3/context/valid", test_modulemd_v3_context_valid);
217+
g_test_add_func ("/modulemd/v3/context/overlong", test_modulemd_v3_context_overlong);
218+
g_test_add_func ("/modulemd/v3/context/bad_underscore", test_modulemd_v3_context_bad_underscore);
219+
220+
g_test_add_func ("/modulemd/v2/context/valid", test_modulemd_v2_context_valid);
221+
g_test_add_func ("/modulemd/v2/context/overlong", test_modulemd_v2_context_overlong);
222+
g_test_add_func ("/modulemd/v2/context/bad_character", test_modulemd_v2_context_bad_character);
223+
224+
return g_test_run ();
225+
}

yaml_specs/modulemd_stream_v2.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ data:
8888
# Mandatory for module metadata in a yum/dnf repository.
8989
#
9090
# If 'static_context' is set to True:
91-
# The context flag is a string of up to ten [a-zA-Z0-9] characters
91+
# The context flag is a string of up to thirteen [a-zA-Z0-9_] characters
9292
# representing a build and runtime configuration for this stream. This
9393
# string is arbitrary but must be unique in this module stream.
9494
#

0 commit comments

Comments
 (0)