rpm-ostree/tests/check/test-kargs.c
Jonathan Lebon 461a4f792d libpriv/kargs: Tweak delete restrictions
1. Allow deleting keys without values (e.g. `nosmt`) if such a key
   variant exists (i.e. this won't work if there are only e.g.
   `nosmt=foo` and `nosmt=bar` variants).
2. Allow deleting duplicate `keys[=val]` kargs.

Closes: #1834

Closes: #1835
Approved by: cgwalters
2019-05-17 13:44:06 +00:00

233 lines
9.1 KiB
C

#include "config.h"
#include "libglnx.h"
#include "rpmostree-kargs-process.h"
static gboolean
check_string_existance (OstreeKernelArgs *karg,
const char *string_to_find)
{
g_autofree gchar* string_with_spaces = _ostree_kernel_args_to_string (karg);
g_auto(GStrv) string_list = g_strsplit (string_with_spaces, " ", -1);
return g_strv_contains ((const char* const*) string_list, string_to_find);
}
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 (!g_ptr_array_find_with_equal_func (kargs_array, "single_key", g_str_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"));
}
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"));
}
static gboolean
strcmp0_equal (gconstpointer v1,
gconstpointer v2)
{
return g_strcmp0 (v1, v2) == 0;
}
/* 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");
/* 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 (g_ptr_array_find_with_equal_func (value_array, "valid", strcmp0_equal, NULL));
g_assert (g_ptr_array_find_with_equal_func (value_array, "secondvalid", strcmp0_equal, NULL));
g_assert (g_ptr_array_find_with_equal_func (value_array, "", strcmp0_equal, NULL));
g_assert (g_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL));
}
else
{
g_assert_cmpstr (key, ==, "second_test");
g_assert (g_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL));
}
}
/* verify the value array is properly updated */
GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (append_arg);
g_assert (g_ptr_array_find_with_equal_func (kargs_array, "test", g_str_equal, NULL));
g_assert (g_ptr_array_find_with_equal_func (kargs_array, "second_test", g_str_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_autofree gchar* kargs_str = _ostree_kernel_args_to_string (append_arg);
g_auto(GStrv) kargs_list = g_strsplit(kargs_str, " ", -1);
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_cmpint (5, ==, 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 ();
}