validate: Fix multi variable in a single structure field

We were keeping using the GMatchInfo even after modifying the string
which is explicitly stated as invalid in the GRegex documentation

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-devtools/-/merge_requests/179>
This commit is contained in:
Thibault Saunier 2020-04-22 11:27:16 -04:00
parent 58de8e5330
commit bf24fd3d74
4 changed files with 80 additions and 38 deletions

View file

@ -1028,7 +1028,7 @@ gst_validate_replace_variables_in_string (GstStructure * local_vars,
const gchar * in_string) const gchar * in_string)
{ {
gint varname_len; gint varname_len;
GMatchInfo *match_info; GMatchInfo *match_info = NULL;
const gchar *var_value = NULL; const gchar *var_value = NULL;
gchar *tmpstring, *string = g_strdup (in_string); gchar *tmpstring, *string = g_strdup (in_string);
@ -1037,51 +1037,54 @@ gst_validate_replace_variables_in_string (GstStructure * local_vars,
gst_validate_set_globals (NULL); gst_validate_set_globals (NULL);
g_regex_match (_variables_regex, string, 0, &match_info); while (g_regex_match (_variables_regex, string, 0, &match_info)) {
while (g_match_info_matches (match_info)) { if (g_match_info_matches (match_info)) {
GRegex *replace_regex; GRegex *replace_regex;
gchar *tmp, *varname, *pvarname = g_match_info_fetch (match_info, 0); gchar *tmp, *varname, *pvarname = g_match_info_fetch (match_info, 0);
varname_len = strlen (pvarname); varname_len = strlen (pvarname);
varname = g_malloc (sizeof (gchar) * (varname_len - 2)); varname = g_malloc (sizeof (gchar) * (varname_len - 2));
strncpy (varname, &pvarname[2], varname_len - 3); strncpy (varname, &pvarname[2], varname_len - 3);
varname[varname_len - 3] = '\0'; varname[varname_len - 3] = '\0';
if (local_vars && gst_structure_has_field_typed (local_vars, varname, if (local_vars && gst_structure_has_field_typed (local_vars, varname,
G_TYPE_DOUBLE)) { G_TYPE_DOUBLE)) {
var_value = varname; var_value = varname;
} else { } else {
if (local_vars) if (local_vars)
var_value = gst_structure_get_string (local_vars, varname); var_value = gst_structure_get_string (local_vars, varname);
if (!var_value) if (!var_value)
var_value = gst_structure_get_string (global_vars, varname); var_value = gst_structure_get_string (global_vars, varname);
if (!var_value) { if (!var_value) {
g_error g_error
("Trying to use undefined variable : %s (\nlocals: %s\nglobals: %s\n)", ("Trying to use undefined variable : %s (\nlocals: %s\nglobals: %s\n)",
varname, gst_structure_to_string (local_vars), varname, gst_structure_to_string (local_vars),
gst_structure_to_string (global_vars)); gst_structure_to_string (global_vars));
return NULL; return NULL;
}
} }
tmp = g_strdup_printf ("\\$\\(%s\\)", varname);
replace_regex = g_regex_new (tmp, 0, 0, NULL);
g_free (tmp);
tmpstring = string;
string =
g_regex_replace (replace_regex, string, -1, 0, var_value, 0, NULL);
GST_INFO ("Setting variable %s to %s", varname, var_value);
g_free (tmpstring);
g_regex_unref (replace_regex);
g_free (pvarname);
g_free (varname);
} }
g_clear_pointer (&match_info, g_match_info_free);
tmp = g_strdup_printf ("\\$\\(%s\\)", varname);
replace_regex = g_regex_new (tmp, 0, 0, NULL);
g_free (tmp);
tmpstring = string;
string = g_regex_replace (replace_regex, string, -1, 0, var_value, 0, NULL);
GST_INFO ("Setting variable %s to %s", varname, var_value);
g_free (tmpstring);
g_regex_unref (replace_regex);
g_free (pvarname);
g_free (varname);
g_match_info_next (match_info, NULL);
} }
g_match_info_free (match_info);
if (match_info)
g_match_info_free (match_info);
return string; return string;
} }

View file

@ -73,6 +73,7 @@ void gst_validate_spin_on_fault_signals (void);
GST_VALIDATE_API GST_VALIDATE_API
gboolean gst_validate_element_matches_target (GstElement * element, GstStructure * s); gboolean gst_validate_element_matches_target (GstElement * element, GstStructure * s);
gchar * gst_validate_replace_variables_in_string (GstStructure * local_vars, const gchar * in_string); gchar * gst_validate_replace_variables_in_string (GstStructure * local_vars, const gchar * in_string);
GST_VALIDATE_API
void gst_validate_structure_resolve_variables (GstStructure *structure, GstStructure *local_variables); void gst_validate_structure_resolve_variables (GstStructure *structure, GstStructure *local_variables);
void gst_validate_set_globals (GstStructure *structure); void gst_validate_set_globals (GstStructure *structure);

View file

@ -5,6 +5,7 @@ validate_tests = [
['validate/reporting'], ['validate/reporting'],
['validate/overrides'], ['validate/overrides'],
['validate/scenario'], ['validate/scenario'],
['validate/utilities'],
['validate/expression_parser'], ['validate/expression_parser'],
] ]

View file

@ -0,0 +1,37 @@
#include <gst/check/gstcheck.h>
#include <gst/validate/validate.h>
#include <gst/validate/gst-validate-utils.h>
GST_START_TEST (test_resolve_variables)
{
GstStructure *s1 =
gst_structure_from_string ("vars, a=(string)1, b=(string)2", NULL);
GstStructure *s2 = gst_structure_from_string ("test, n=\"$(a)/$(b)\"", NULL);
gst_validate_structure_resolve_variables (s2, s1);
fail_unless_equals_string (gst_structure_get_string (s2, "n"), "1/2");
gst_structure_free (s1);
gst_structure_free (s2);
}
GST_END_TEST;
static Suite *
gst_validate_suite (void)
{
Suite *s = suite_create ("utilities");
TCase *tc_chain = tcase_create ("utilities");
suite_add_tcase (s, tc_chain);
if (atexit (gst_validate_deinit) != 0) {
GST_ERROR ("failed to set gst_validate_deinit as exit function");
}
gst_validate_init ();
tcase_add_test (tc_chain, test_resolve_variables);
gst_validate_deinit ();
return s;
}
GST_CHECK_MAIN (gst_validate);