mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-22 17:35:55 +03:00
abc7d5b9a0
According to Jonathan's suggestion, should fix the code from ostree repo. With this patch: - kargs input like "init_on_alloc=1 init_on_free=1", will be parsed as 2 seperated args `init_on_alloc=1` and `init_on_free=1`, instead of whole; - According to https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html, need to keep spaces in double-quotes, like `param="spaces in here"` will be parsed as whole instead of 3. Fixes https://github.com/coreos/rpm-ostree/issues/4821
291 lines
12 KiB
C
291 lines
12 KiB
C
/*
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.0+
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "ostree-kernel-args-private.h"
|
|
#include "otutil.h"
|
|
|
|
static gboolean
|
|
check_string_existance (OstreeKernelArgs *karg, const char *string_to_find)
|
|
{
|
|
g_auto (GStrv) string_list = ostree_kernel_args_to_strv (karg);
|
|
return g_strv_contains ((const char *const *)string_list, string_to_find);
|
|
}
|
|
|
|
static gboolean
|
|
kernel_args_entry_value_equal (gconstpointer data, gconstpointer value)
|
|
{
|
|
const OstreeKernelArgsEntry *e = data;
|
|
return g_strcmp0 (_ostree_kernel_args_entry_get_value (e), value) == 0;
|
|
}
|
|
|
|
static gboolean
|
|
kernel_args_entry_key_equal (gconstpointer data, gconstpointer key)
|
|
{
|
|
const OstreeKernelArgsEntry *e = data;
|
|
return g_strcmp0 (_ostree_kernel_args_entry_get_key (e), key) == 0;
|
|
}
|
|
|
|
static void
|
|
test_kargs_delete (void)
|
|
{
|
|
g_autoptr (GError) error = NULL;
|
|
gboolean ret;
|
|
__attribute__ ((cleanup (ostree_kernel_args_cleanup))) OstreeKernelArgs *karg
|
|
= ostree_kernel_args_new ();
|
|
|
|
ostree_kernel_args_append (karg, "single_key=test");
|
|
ostree_kernel_args_append (karg, "test=firstval");
|
|
ostree_kernel_args_append (karg, "test=secondval");
|
|
ostree_kernel_args_append (karg, "test=");
|
|
ostree_kernel_args_append (karg, "test");
|
|
|
|
/* Delete a non-existant key should fail */
|
|
ret = ostree_kernel_args_delete (karg, "non_existant_key", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Delete a key with multiple values when only specifying key should work if a no-value
|
|
* variant exists */
|
|
ret = ostree_kernel_args_delete (karg, "test", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test"));
|
|
|
|
/* Trying again now should fail since there are only kargs with various values */
|
|
ret = ostree_kernel_args_delete (karg, "test", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Delete a key with a non existant value should fail */
|
|
ret = ostree_kernel_args_delete (karg, "test=non_existant_value", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Delete a key with only one value should fail if the value doesn't match */
|
|
ret = ostree_kernel_args_delete (karg, "single_key=non_existent_value", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Delete a key with only one value should succeed by only specifying key */
|
|
ret = ostree_kernel_args_delete (karg, "single_key", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
/* verify the value array is properly updated */
|
|
GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (karg);
|
|
g_assert (!ot_ptr_array_find_with_equal_func (kargs_array, "single_key",
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (!check_string_existance (karg, "single_key"));
|
|
|
|
/* Delete specific key/value pair */
|
|
ret = ostree_kernel_args_delete (karg, "test=secondval", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test=secondval"));
|
|
|
|
/* Delete key/value pair with empty string value */
|
|
ret = ostree_kernel_args_delete (karg, "test=", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test="));
|
|
|
|
ret = ostree_kernel_args_delete (karg, "test=firstval", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test=firstval"));
|
|
|
|
/* Check that we can delete duplicate keys */
|
|
ostree_kernel_args_append (karg, "test=foo");
|
|
ostree_kernel_args_append (karg, "test=foo");
|
|
check_string_existance (karg, "test=foo");
|
|
ret = ostree_kernel_args_delete (karg, "test=foo", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (check_string_existance (karg, "test=foo"));
|
|
ret = ostree_kernel_args_delete (karg, "test=foo", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test=foo"));
|
|
|
|
/* Make sure we also gracefully do this for key-only args */
|
|
ostree_kernel_args_append (karg, "nosmt");
|
|
ostree_kernel_args_append (karg, "nosmt");
|
|
check_string_existance (karg, "nosmt");
|
|
ret = ostree_kernel_args_delete (karg, "nosmt", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (check_string_existance (karg, "nosmt"));
|
|
ret = ostree_kernel_args_delete (karg, "nosmt", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "nosmt"));
|
|
|
|
/* Make sure we also support quotes and spaces */
|
|
ostree_kernel_args_append (karg, "foo=\"1 2\" bar=0");
|
|
check_string_existance (karg, "foo=\"1 2\"");
|
|
check_string_existance (karg, "bar=0");
|
|
ret = ostree_kernel_args_delete (karg, "foo=\"1 2\" bar=0", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "foo=\"1 2\""));
|
|
g_assert (!check_string_existance (karg, "bar=0"));
|
|
}
|
|
|
|
static void
|
|
test_kargs_replace (void)
|
|
{
|
|
g_autoptr (GError) error = NULL;
|
|
gboolean ret;
|
|
__attribute__ ((cleanup (ostree_kernel_args_cleanup))) OstreeKernelArgs *karg
|
|
= ostree_kernel_args_new ();
|
|
|
|
ostree_kernel_args_append (karg, "single_key");
|
|
ostree_kernel_args_append (karg, "test=firstval");
|
|
ostree_kernel_args_append (karg, "test=secondval");
|
|
|
|
/* Replace when the input key is non-existant should fail */
|
|
ret = ostree_kernel_args_new_replace (karg, "nonexistantkey", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Replace non-existant value with input key=nonexistantvalue=newvalue should fail */
|
|
ret = ostree_kernel_args_new_replace (karg, "single_key=nonexistantval=newval", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Replace with input key=value will fail for a key with multiple values */
|
|
ret = ostree_kernel_args_new_replace (karg, "test=newval", &error);
|
|
g_assert (!ret);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
|
g_clear_error (&error);
|
|
|
|
/* Replace with input key=value for a key with single value should succeed
|
|
* Also note, we also allow ''(empty string) valid to be a value
|
|
*/
|
|
ret = ostree_kernel_args_new_replace (karg, "single_key=newvalue", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "single_key"));
|
|
g_assert (check_string_existance (karg, "single_key=newvalue"));
|
|
|
|
/* Replace with input key=value=newvalue if key and value both
|
|
* exist, the action should succeed
|
|
*/
|
|
ret = ostree_kernel_args_new_replace (karg, "test=firstval=newval", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "test=firstval"));
|
|
g_assert (check_string_existance (karg, "test=newval"));
|
|
|
|
/* Replace with input contains quotes and spaces, it should support */
|
|
ostree_kernel_args_append (karg, "foo=1 bar=\"1 2\"");
|
|
ret = ostree_kernel_args_new_replace (karg, "foo=\"1 2\" bar", &error);
|
|
g_assert_no_error (error);
|
|
g_assert (ret);
|
|
g_assert (!check_string_existance (karg, "foo=1"));
|
|
g_assert (!check_string_existance (karg, "bar=\"1 2\""));
|
|
g_assert (check_string_existance (karg, "foo=\"1 2\""));
|
|
g_assert (check_string_existance (karg, "bar"));
|
|
}
|
|
|
|
/* In this function, we want to verify that ostree_kernel_args_append
|
|
* and ostree_kernel_args_to_string is correct. After that
|
|
* we will use these two functions(append and tostring) in other tests: delete and replace
|
|
*/
|
|
static void
|
|
test_kargs_append (void)
|
|
{
|
|
__attribute__ ((cleanup (ostree_kernel_args_cleanup))) OstreeKernelArgs *append_arg
|
|
= ostree_kernel_args_new ();
|
|
/* Some valid cases (key=value) pair */
|
|
ostree_kernel_args_append (append_arg, "test=valid");
|
|
ostree_kernel_args_append (append_arg, "test=secondvalid");
|
|
ostree_kernel_args_append (append_arg, "test=");
|
|
ostree_kernel_args_append (append_arg, "test");
|
|
ostree_kernel_args_append (append_arg, "second_test");
|
|
ostree_kernel_args_append (append_arg, "second_test=0 second_test=\"1 2\"");
|
|
|
|
/* We loops through the kargs inside table to verify
|
|
* the functionality of append because at this stage
|
|
* we have yet to find the conversion kargs to string fully "functional"
|
|
*/
|
|
GHashTable *kargs_table = _ostree_kernel_arg_get_kargs_table (append_arg);
|
|
GLNX_HASH_TABLE_FOREACH_KV (kargs_table, const char *, key, GPtrArray *, value_array)
|
|
{
|
|
if (g_str_equal (key, "test"))
|
|
{
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, "valid",
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, "secondvalid",
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, "",
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL,
|
|
kernel_args_entry_value_equal, NULL));
|
|
}
|
|
else
|
|
{
|
|
g_assert_cmpstr (key, ==, "second_test");
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL,
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, "0",
|
|
kernel_args_entry_value_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (value_array, "\"1 2\"",
|
|
kernel_args_entry_value_equal, NULL));
|
|
}
|
|
}
|
|
|
|
/* verify the value array is properly updated */
|
|
GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (append_arg);
|
|
g_assert (
|
|
ot_ptr_array_find_with_equal_func (kargs_array, "test", kernel_args_entry_key_equal, NULL));
|
|
g_assert (ot_ptr_array_find_with_equal_func (kargs_array, "second_test",
|
|
kernel_args_entry_key_equal, NULL));
|
|
|
|
/* Up till this point, we verified that the above was all correct, we then
|
|
* check ostree_kernel_args_to_string has the right result
|
|
*/
|
|
g_auto (GStrv) kargs_list = ostree_kernel_args_to_strv (append_arg);
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "test=valid"));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "test=secondvalid"));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "test="));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "test"));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test"));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test=0"));
|
|
g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test=\"1 2\""));
|
|
g_assert_cmpint (7, ==, g_strv_length (kargs_list));
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
g_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/kargs/kargs_append", test_kargs_append);
|
|
g_test_add_func ("/kargs/kargs_delete", test_kargs_delete);
|
|
g_test_add_func ("/kargs/kargs_replace", test_kargs_replace);
|
|
return g_test_run ();
|
|
}
|