void test_set_pidfile (void) { const char *filename, *ptr; TEST_FUNCTION ("nih_main_set_pidfile"); program_name = "test"; /* Check that we can set a pidfile for use, and have the string * copied and returned. */ TEST_FEATURE ("with new location"); filename = "/path/to/pid"; nih_main_set_pidfile (filename); ptr = nih_main_get_pidfile (); TEST_EQ_STR (ptr, filename); TEST_NE_P (ptr, filename); /* Check that we can pass NULL to have the default location set * instead. */ TEST_FEATURE ("with default location"); nih_main_set_pidfile (NULL); ptr = nih_main_get_pidfile (); TEST_EQ_STR (ptr, "/var/run/test.pid"); nih_main_set_pidfile (NULL); }
void test_preamble (void) { char *str; TEST_FUNCTION ("output_preamble"); /* Check that a preamble for a source file is correctly generated, * with the package name, source file path and copyright all * present. */ TEST_FEATURE ("with path"); TEST_ALLOC_FAIL { str = output_preamble (NULL, "path.c"); if (test_alloc_failed) { TEST_EQ_P (str, NULL); continue; } TEST_EQ_STR (str, ("/* test\n" " *\n" " * path.c - auto-generated D-Bus bindings\n" " *\n" " * Copyright (C) 2009 Joe Bloggs.\n" " *\n" " * This file was automatically generated; see the source for copying\n" " * conditions.\n" " */\n" "\n")); nih_free (str); } /* Check that a preamble for a header file (NULL path) is correctly * generated with the package name and copyright present. */ TEST_FEATURE ("with no path"); TEST_ALLOC_FAIL { str = output_preamble (NULL, NULL); if (test_alloc_failed) { TEST_EQ_P (str, NULL); continue; } TEST_EQ_STR (str, ("/* test\n" " *\n" " * Copyright (C) 2009 Joe Bloggs.\n" " *\n" " * This file was automatically generated; see the source for copying\n" " * conditions.\n" " */\n" "\n")); nih_free (str); } }
void test_parent (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_alloc_parent"); /* Check that nih_alloc_parent returns TRUE when the passed object * is a child of the passed parent. */ TEST_FEATURE ("with child and parent"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); TEST_TRUE (nih_alloc_parent (ptr2, ptr1)); nih_free (ptr1); /* Check that nih_alloc_parent returns TRUE when the passed object * is a child of the NULL parent. */ TEST_FEATURE ("with child and NULL parent"); ptr1 = nih_alloc (NULL, 10); TEST_TRUE (nih_alloc_parent (ptr1, NULL)); nih_free (ptr1); /* Check that nih_alloc_parent returns FALSE when the passed object * is a child but not of the passed parent. */ TEST_FEATURE ("with child and wrong parent"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); ptr3 = nih_alloc (NULL, 10); TEST_FALSE (nih_alloc_parent (ptr2, ptr3)); nih_free (ptr1); nih_free (ptr3); /* Check that nih_alloc_parent returns FALSE when the passed object * is an orphan. */ TEST_FEATURE ("with orphan"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (NULL, 10); TEST_FALSE (nih_alloc_parent (ptr2, ptr1)); nih_free (ptr1); nih_free (ptr2); }
void test_cgroup_name_new (void) { CGroupName *cgname; nih_local char *parent = NULL; TEST_FUNCTION ("cgroup_name_new"); parent = nih_strdup (NULL, "a parent object"); TEST_NE_P (parent, NULL); TEST_FEATURE ("no parent, name"); TEST_ALLOC_FAIL { cgname = cgroup_name_new (NULL, "foo."); if (test_alloc_failed) { TEST_EQ_P (cgname, NULL); continue; } TEST_NE_P (cgname, NULL); TEST_ALLOC_SIZE (cgname, sizeof (CGroupName)); TEST_ALLOC_PARENT (cgname, NULL); TEST_EQ_STR (cgname->name, "foo."); TEST_ALLOC_SIZE (cgname->name, 1+strlen ("foo.")); TEST_ALLOC_PARENT (cgname->name, cgname); TEST_LIST_EMPTY (&cgname->settings); } TEST_FEATURE ("parent, name"); TEST_ALLOC_FAIL { cgname = cgroup_name_new (parent, "bar"); if (test_alloc_failed) { TEST_EQ_P (cgname, NULL); continue; } TEST_NE_P (cgname, NULL); TEST_ALLOC_SIZE (cgname, sizeof (CGroupName)); TEST_ALLOC_PARENT (cgname, parent); TEST_EQ_STR (cgname->name, "bar"); TEST_ALLOC_SIZE (cgname->name, 1+strlen ("bar")); TEST_ALLOC_PARENT (cgname->name, cgname); TEST_LIST_EMPTY (&cgname->settings); } }
void test_getn (void) { char **env = NULL; size_t len = 0; const char *ret; TEST_FUNCTION ("environ_getn"); len = 0; env = nih_str_array_new (NULL); /* Check that an empty table always returns NULL. */ TEST_FEATURE ("with empty table"); ret = environ_getn (env, "FOO", 3); TEST_EQ_P (ret, NULL); assert (nih_str_array_add (&env, NULL, &len, "FOOLISH=no")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); /* Check that a key that is present is returned. */ TEST_FEATURE ("with key to be found"); ret = environ_getn (env, "BAR", 3); TEST_EQ_STR (ret, "BAZ"); /* Check that a key that doesn't exist returns NULL. */ TEST_FEATURE ("with key not found"); ret = environ_getn (env, "MEEP", 4); TEST_EQ_P (ret, NULL); /* Check that the key is not prefix-matched. */ TEST_FEATURE ("with key that is prefix of another"); ret = environ_getn (env, "FOO", 3); TEST_EQ_P (ret, NULL); /* Check that the length is honoured. */ TEST_FEATURE ("with longer key"); ret = environ_getn (env, "FOOLISH", 3); TEST_EQ_P (ret, NULL); nih_free (env); }
/** * test_checks: * * Perform any checks necessary before real tests are run. **/ void test_checks (void) { int ret; TEST_GROUP ("test environment"); /* * Warn (*) if overlayfs detected. * * (*) - Don't fail in the hope that one day someone might fix * overlayfs. */ TEST_FEATURE ("checking for overlayfs"); if (check_for_overlayfs ()) { nih_warn ("Found overlayfs mounts"); nih_warn ("This environment will probably cause tests to fail mysteriously!!"); nih_warn ("See bug LP:#882147 for further details."); } #ifdef ENABLE_CGROUPS if (file_exists ("/sys/fs/cgroup/cgmanager/sock")) { TEST_FEATURE ("checking for cgmanager"); ret = connect_to_cgmanager (); switch (ret) { case -2: nih_warn ("Found no cgroup manager"); goto out_skip; case -1: nih_warn ("Error connecting to cgmanager"); goto out_skip; case 0: print_my_cgroup (); break; default: nih_warn ("Unknown error from connect_to_cgmanager: %d", ret); goto out_skip; } TEST_FEATURE ("cgroup sandbox"); if (check_cgroup_sandbox() != 0) nih_warn ("Could not create cgroup sandbox"); } else { nih_warn ("Skipping CGManager tests, CGManager socket not found"); } out_skip: disconnect_cgmanager(); if (ret) nih_warn ("Skipping CGManager tests, CGManager not properly configured"); #endif /* ENABLE_CGROUPS */ }
void test_local (void) { void *parent; void *_ptr; TEST_GROUP ("nih_local"); /* Make sure that when a variable goes out of scope, it's freed. */ TEST_FEATURE ("with variable going out of scope"); do { nih_local void *ptr; ptr = nih_alloc (NULL, 100); nih_alloc_set_destructor (ptr, destructor_called); destructor_was_called = 0; } while (0); TEST_TRUE (destructor_was_called); /* Make sure that if a variable is referenced while in scope, it * is not freed. */ TEST_FEATURE ("with referenced variable"); parent = nih_alloc (NULL, 100); do { nih_local void *ptr; ptr = nih_alloc (NULL, 100); nih_ref (ptr, parent); _ptr = ptr; nih_alloc_set_destructor (ptr, destructor_called); destructor_was_called = 0; } while (0); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (_ptr, parent); nih_free (parent); /* Make sure we don't need to allocate the variable. */ TEST_FEATURE ("with NULL variable"); do { nih_local void *ptr = NULL; } while (0); }
void test_read_pidfile (void) { FILE *f; char filename[PATH_MAX]; TEST_FUNCTION ("nih_main_read_pidfile"); TEST_FILENAME (filename); nih_main_set_pidfile (filename); /* Check that reading from a valid pid file will return the pid * stored there. */ TEST_FEATURE ("with valid pid file"); f = fopen (filename, "w"); fprintf (f, "1234\n"); fclose (f); TEST_EQ (nih_main_read_pidfile (), 1234); /* Check that reading from a pid file without a newline will still * return the pid stored there. */ TEST_FEATURE ("with no newline in pid file"); f = fopen (filename, "w"); fprintf (f, "1234"); fclose (f); TEST_EQ (nih_main_read_pidfile (), 1234); /* Check that reading from an invalid pid file returns -1. */ TEST_FEATURE ("with invalid pid file"); f = fopen (filename, "w"); fprintf (f, "foo\n1234\n"); fclose (f); TEST_EQ (nih_main_read_pidfile (), -1); /* Check that reading from a non-existant pid file returns -1. */ TEST_FEATURE ("with non-existant pid file"); nih_main_unlink_pidfile (); TEST_EQ (nih_main_read_pidfile (), -1); nih_main_set_pidfile (NULL); }
void test_sprintf (void) { char *str1, *str2; TEST_FUNCTION ("nih_sprintf"); /* Check that we can create a formatted string with no parent, * it should be allocated with nih_alloc and be the right length. */ TEST_FEATURE ("with no parent"); TEST_ALLOC_FAIL { str1 = nih_sprintf (NULL, "this %s a test %d", "is", 54321); if (test_alloc_failed) { TEST_EQ_P (str1, NULL); continue; } TEST_ALLOC_PARENT (str1, NULL); TEST_ALLOC_SIZE (str1, strlen (str1) + 1); TEST_EQ_STR (str1, "this is a test 54321"); nih_free (str1); } /* Check that we can create a string with a parent. */ TEST_FEATURE ("with a parent"); str1 = nih_sprintf (NULL, "this %s a test %d", "is", 54321); TEST_ALLOC_FAIL { str2 = nih_sprintf (str1, "another %d test %s", 12345, "string"); if (test_alloc_failed) { TEST_EQ_P (str2, NULL); continue; } TEST_ALLOC_PARENT (str2, str1); TEST_ALLOC_SIZE (str2, strlen (str2) + 1); TEST_EQ_STR (str2, "another 12345 test string"); nih_free (str2); } nih_free (str1); }
void test_vsprintf (void) { char *str1, *str2; TEST_FUNCTION ("nih_vsprintf"); /* Check that we can create a formatted string for a va_list, * first with no parent. */ TEST_FEATURE ("with no parent"); TEST_ALLOC_FAIL { str1 = my_vsprintf (NULL, "this %s a test %d", "is", 54321); if (test_alloc_failed) { TEST_EQ_P (str1, NULL); continue; } TEST_ALLOC_PARENT (str1, NULL); TEST_ALLOC_SIZE (str1, strlen (str1) + 1); TEST_EQ_STR (str1, "this is a test 54321"); nih_free (str1); } /* And then with a parent. */ TEST_FEATURE ("with a parent"); str1 = my_vsprintf (NULL, "this %s a test %d", "is", 54321); TEST_ALLOC_FAIL { str2 = my_vsprintf (str1, "another %d test %s", 12345, "string"); if (test_alloc_failed) { TEST_EQ_P (str2, NULL); continue; } TEST_ALLOC_PARENT (str2, str1); TEST_ALLOC_SIZE (str2, strlen (str2) + 1); TEST_EQ_STR (str2, "another 12345 test string"); nih_free (str2); } nih_free (str1); }
void test_strdup (void) { char *str1, *str2; TEST_FUNCTION ("nih_strdup"); /* Check that we can create a duplicate of another string, * allocated with nih_alloc and no parent. */ TEST_FEATURE ("with no parent"); TEST_ALLOC_FAIL { str1 = nih_strdup (NULL, "this is a test"); if (test_alloc_failed) { TEST_EQ_P (str1, NULL); continue; } TEST_ALLOC_PARENT (str1, NULL); TEST_ALLOC_SIZE (str1, strlen (str1) + 1); TEST_EQ_STR (str1, "this is a test"); nih_free (str1); } /* And check we can allocate with a parent. */ TEST_FEATURE ("with a parent"); str1 = nih_strdup (NULL, "this is a test"); TEST_ALLOC_FAIL { str2 = nih_strdup (str1, "another test string"); if (test_alloc_failed) { TEST_EQ_P (str2, NULL); continue; } TEST_ALLOC_PARENT (str2, str1); TEST_ALLOC_SIZE (str2, strlen (str2) + 1); TEST_EQ_STR (str2, "another test string"); nih_free (str2); } nih_free (str1); }
void test_all_valid (void) { char **env; int valid; TEST_FUNCTION ("environ_all_valid"); /* Check that a valid environment table returns TRUE. */ TEST_FEATURE ("with valid table"); env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, NULL, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, NULL, "BAR=BAZ")); valid = environ_all_valid (env); TEST_TRUE (valid); nih_free (env); /* Check that an empty environment table is valid. */ TEST_FEATURE ("with empty table"); env = nih_str_array_new (NULL); valid = environ_all_valid (env); TEST_TRUE (valid); nih_free (env); /* Check that an entry without an equals means the table is not * valid. */ TEST_FEATURE ("with missing equals"); env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, NULL, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, NULL, "BAR")); assert (nih_str_array_add (&env, NULL, NULL, "WIBBLE=woo")); valid = environ_all_valid (env); TEST_FALSE (valid); nih_free (env); }
void test_from_name (void) { ProcessType process; TEST_FUNCTION ("process_from_name"); /* Check that PROCESS_MAIN is returned for the string. */ TEST_FEATURE ("with main process"); process = process_from_name ("main"); TEST_EQ (process, PROCESS_MAIN); /* Check that PROCESS_SECURITY is returned for the string. */ TEST_FEATURE ("with security process"); process = process_from_name ("security"); TEST_EQ (process, PROCESS_SECURITY); /* Check that PROCESS_PRE_START is returned for the string. */ TEST_FEATURE ("with pre-start process"); process = process_from_name ("pre-start"); TEST_EQ (process, PROCESS_PRE_START); /* Check that PROCESS_POST_START is returned for the string. */ TEST_FEATURE ("with post-start process"); process = process_from_name ("post-start"); TEST_EQ (process, PROCESS_POST_START); /* Check that PROCESS_PRE_STOP is returned for the string. */ TEST_FEATURE ("with pre-stop process"); process = process_from_name ("pre-stop"); TEST_EQ (process, PROCESS_PRE_STOP); /* Check that PROCESS_POST_STOP is returned for the string. */ TEST_FEATURE ("with post-stop process"); process = process_from_name ("post-stop"); TEST_EQ (process, PROCESS_POST_STOP); /* Check that -1 is returned for an invalid string. */ TEST_FEATURE ("with invalid process"); process = process_from_name ("wibble"); TEST_EQ (process, (ProcessType)-1); }
void test_name (void) { const char *name; TEST_FUNCTION ("process_name"); /* Check that PROCESS_MAIN returns the right string. */ TEST_FEATURE ("with main process"); name = process_name (PROCESS_MAIN); TEST_EQ_STR (name, "main"); /* Check that PROCESS_SECURITY returns the right string. */ TEST_FEATURE ("with security process"); name = process_name (PROCESS_SECURITY); TEST_EQ_STR (name, "security"); /* Check that PROCESS_PRE_START returns the right string. */ TEST_FEATURE ("with pre-start process"); name = process_name (PROCESS_PRE_START); TEST_EQ_STR (name, "pre-start"); /* Check that PROCESS_POST_START returns the right string. */ TEST_FEATURE ("with post-start process"); name = process_name (PROCESS_POST_START); TEST_EQ_STR (name, "post-start"); /* Check that PROCESS_PRE_STOP returns the right string. */ TEST_FEATURE ("with pre-stop process"); name = process_name (PROCESS_PRE_STOP); TEST_EQ_STR (name, "pre-stop"); /* Check that PROCESS_POST_STOP returns the right string. */ TEST_FEATURE ("with post-stop process"); name = process_name (PROCESS_POST_STOP); TEST_EQ_STR (name, "post-stop"); /* Check that an invalid process returns NULL. */ TEST_FEATURE ("with invalid process"); name = process_name (1234); TEST_EQ_P (name, NULL); }
void test_alloc (void) { void *ptr1; void *ptr2; TEST_FUNCTION ("nih_alloc"); /* Check allocation remembers the size, and is possible without * a parent. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 8096); memset (ptr1, 'x', 8096); TEST_ALLOC_SIZE (ptr1, 8096); TEST_ALLOC_PARENT (ptr1, NULL); /* Check that allocation with a parent remembers the parent */ TEST_FEATURE ("with a parent"); ptr2 = nih_alloc (ptr1, 10); memset (ptr2, 'x', 10); TEST_ALLOC_SIZE (ptr2, 10); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr1); /* Check that nih_alloc returns NULL if allocation fails. */ TEST_FEATURE ("with failed allocation"); __nih_malloc = malloc_null; ptr1 = nih_new (NULL, int); __nih_malloc = malloc; TEST_EQ_P (ptr1, NULL); }
void test_operator_destroy (void) { EventOperator *oper; Event *event; TEST_FUNCTION ("event_operator_destroy"); /* Check that when an event operator is destroyed, the referenced * event is unblocked and unreferenced. */ TEST_FEATURE ("with referenced event"); oper = event_operator_new (NULL, EVENT_MATCH, "foo", NULL); oper->value = TRUE; event = event_new (NULL, "foo", NULL); oper->event = event; event_block (event); nih_free (oper); TEST_EQ (event->blockers, 0); nih_free (event); /* Check that when an event operator without an event is destroyed, * everything works. */ TEST_FEATURE ("without referenced event"); oper = event_operator_new (NULL, EVENT_MATCH, "foo", NULL); nih_free (oper); event_poll (); }
void test_new (void) { void *ptr1; void *ptr2; TEST_FUNCTION ("nih_new"); /* Check that nih_new works if we don't give it a parent, the block * should be allocated with the size of the type given. */ TEST_FEATURE ("with no parent"); ptr1 = nih_new (NULL, int); TEST_ALLOC_SIZE (ptr1, sizeof (int)); TEST_ALLOC_PARENT (ptr1, NULL); /* Check that nih_new works if we do give a parent. */ TEST_FEATURE ("with parent"); ptr2 = nih_new (ptr1, char); TEST_ALLOC_SIZE (ptr2, sizeof (char)); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr1); /* Check that nih_new returns NULL if allocation fails. */ TEST_FEATURE ("with failed allocation"); __nih_malloc = malloc_null; ptr1 = nih_new (NULL, int); __nih_malloc = malloc; TEST_EQ_P (ptr1, NULL); }
void test_expand (void) { NihError *error; char *env[7], *str; TEST_FUNCTION ("environ_expand"); env[0] = "FOO=frodo"; env[1] = "BAR=bilbo"; env[2] = "BAZ=xx"; env[3] = "HOBBIT=FOO"; env[4] = "NULL="; env[5] = "DOH=oops"; env[6] = NULL; nih_error_push_context(); nih_error_pop_context (); /* Check that we can expand a string containing no expansion. */ TEST_FEATURE ("with no expansion"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "this is a test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "this is a test"); nih_free (str); } /* Check that we can expand a simple string containing a reference * from the environment, with the reference replaced by the environment * variable value. */ TEST_FEATURE ("with simple expansion"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "this is a $FOO test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "this is a frodo test"); nih_free (str); } /* Check that we can expand a simple string containing a reference * from the environment that is smaller than the reference, with the * reference replaced by the environment variable value. */ TEST_FEATURE ("with simple expansion of smaller value"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "this is a $BAZ test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "this is a xx test"); nih_free (str); } /* Check that we can expand a simple string containing a reference * from the environment that is exactly the same size as the * reference, with the reference replaced by the environment variable * value. */ TEST_FEATURE ("with simple expansion of same size value"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "this is a $DOH test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "this is a oops test"); nih_free (str); } /* Check that we can expand a string containing multiple simple * references, with each replaced by the variable value. */ TEST_FEATURE ("with multiple simple expansions"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "test $FOO $BAR$BAZ", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "test frodo bilboxx"); nih_free (str); } /* Check that we can expand a string containing a bracketed * reference, allowing it to nestle against other alphanumerics. */ TEST_FEATURE ("with simple bracketed expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAR}test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "bilbotest"); nih_free (str); } /* Check that we can expand a string containing multiple bracketed * references, allowing it to nestle against other alphanumerics. */ TEST_FEATURE ("with multiple simple bracketed expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAR}${FOO}test${BAZ}", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "bilbofrodotestxx"); nih_free (str); } /* Check that simple expressions may appear within bracketed * expressions, causing them to be evaluted and the evalution * serving as the reference. */ TEST_FEATURE ("with simple expression inside bracketed expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${$HOBBIT} baggins", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "frodo baggins"); nih_free (str); } /* Check that bracketed expressions may appear within bracketed * expressions. */ TEST_FEATURE ("with bracketed expression inside bracketed expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${${HOBBIT}} baggins", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "frodo baggins"); nih_free (str); } /* Check that we can substitute a default value if the variable * we were after was unset. */ TEST_FEATURE ("with bracketed default expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${MEEP-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "a test"); nih_free (str); } /* Check that a default expression uses the environment value if * it is actually set. */ TEST_FEATURE ("with bracketed default expression for set variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAZ-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "xxtest"); nih_free (str); } /* Check that a default expression uses the environment value if * it is actually set, even if it is NULL. */ TEST_FEATURE ("with bracketed default expression for null variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${NULL-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "test"); nih_free (str); } /* Check that we can substitute a default value if the variable * we were after was unset (or null). */ TEST_FEATURE ("with bracketed default or null expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${MEEP:-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "a test"); nih_free (str); } /* Check that a default or null expression uses the environment value * if it is actually set and not null. */ TEST_FEATURE ("with bracketed default or null expression for set variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAZ:-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "xxtest"); nih_free (str); } /* Check that we can substitute a default value if the variable * we were after was null. */ TEST_FEATURE ("with bracketed default or null expression for null variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${NULL:-a }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "a test"); nih_free (str); } /* Check that we don't substitute an alternate value if the * variable we were after was unset. */ TEST_FEATURE ("with bracketed alternate expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${MEEP+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "test"); nih_free (str); } /* Check that we use the alternate value if the environment variable * is actually set. */ TEST_FEATURE ("with bracketed alternate expression for set variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAZ+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "good test"); nih_free (str); } /* Check that we use the alternate value if the environment variable * is set, even if it is NULL. */ TEST_FEATURE ("with bracketed alternate expression for null variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${NULL+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "good test"); nih_free (str); } /* Check that we don't substitute an alternate value if the * variable we were after was unset (or null). */ TEST_FEATURE ("with bracketed alternate or null expression"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${MEEP:+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "test"); nih_free (str); } /* Check that we use the alternate value if the environment variable * is actually set and not null. */ TEST_FEATURE ("with bracketed alternate or null expression for set variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${BAZ:+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "good test"); nih_free (str); } /* Check that we don't substitute an alternate value if the * variable we were after was set, but was null. */ TEST_FEATURE ("with bracketed alternate or null expression for null variable"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${NULL:+good }test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "test"); nih_free (str); } /* Check that references on either side of an expression are * expanded before evaluation. */ TEST_FEATURE ("with references in bracketed expression argument"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${$BAZ:-${$HOBBIT}}test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "frodotest"); nih_free (str); } /* Check that a literal dollar sign with no following text is * treated just as a dollar sign. */ TEST_FEATURE ("with dollar sign in whitespace"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "this is a $ test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "this is a $ test"); nih_free (str); } /* Check that a literal dollar sign in text can be followed by empty * brackets to be just as a dollar sign. */ TEST_FEATURE ("with bracketed dollar sign"); TEST_ALLOC_FAIL { str = environ_expand (NULL, "${}test", env); if (test_alloc_failed) { TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENOMEM); nih_free (error); continue; } TEST_EQ_STR (str, "$test"); nih_free (str); } /* Check that attempting to expand an unknown variable results in * an error being raised. */ TEST_FEATURE ("with simple expansion of unknown variable"); str = environ_expand (NULL, "this is a $WIBBLE test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM); nih_free (error); /* Check that attempting to expand an unknown variable results in * an error being raised. */ TEST_FEATURE ("with bracketed expansion of unknown variable"); str = environ_expand (NULL, "this is a ${WIBBLE} test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM); nih_free (error); /* Check that attempting to expand an unknown variable results in * an error being raised. */ TEST_FEATURE ("with expansion of unknown variable within expression name"); str = environ_expand (NULL, "this is a ${$WIBBLE:-$FOO} test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM); nih_free (error); /* Check that attempting to expand an unknown variable results in * an error being raised. */ TEST_FEATURE ("with expansion of unknown variable within expression argument"); str = environ_expand (NULL, "this is a ${$FOO:-$WIBBLE} test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM); nih_free (error); /* Check that inventing a new operator results in an error * being raised. */ TEST_FEATURE ("with unknown operator in expression"); str = environ_expand (NULL, "this is a ${$FOO:!$BAR test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_EXPECTED_OPERATOR); nih_free (error); /* Check that forgetting to close a brace results in an error * being raised. */ TEST_FEATURE ("with missing close brace after expression"); str = environ_expand (NULL, "this is a ${$FOO:-$BAR test", env); TEST_EQ_P (str, NULL); error = nih_error_get (); TEST_EQ (error->number, ENVIRON_MISMATCHED_BRACES); nih_free (error); }
const int idx = 0; p->deviceIndex = idx; WHEN("I assign it with a different input device") bool res = PlayerTrySetUnusedInputDevice(p, INPUT_DEVICE_MOUSE, 0); THEN("the assignment should fail") SHOULD_BE_FALSE(res); AND("the player's input device should be unchanged") SHOULD_INT_EQUAL((int)p->inputDevice, (int)d); SHOULD_INT_EQUAL(p->deviceIndex, idx); SCENARIO_END SCENARIO("Assign already used device") GIVEN("a player with an unset input device") PlayerData *p = CArrayGet(&gPlayerDatas, 0); p->inputDevice = INPUT_DEVICE_UNSET; AND("a player with a keyboard device") PlayerData *p2 = CArrayGet(&gPlayerDatas, 1); p2->inputDevice = INPUT_DEVICE_KEYBOARD; p2->deviceIndex = 0; WHEN("I assign the first player with the second's input device") bool res = PlayerTrySetUnusedInputDevice( p, p2->inputDevice, p2->deviceIndex); THEN("the assignment should fail") SHOULD_BE_FALSE(res); AND("the player's input device should be unset") SHOULD_INT_EQUAL((int)p->inputDevice, (int)INPUT_DEVICE_UNSET); SCENARIO_END PlayerDataTerminate(&gPlayerDatas); FEATURE_END CBEHAVE_RUN("Player features are:", TEST_FEATURE(assign_unused))
void test_cgroup_job_start (void) { char confdir[PATH_MAX]; char logdir[PATH_MAX]; char flagfile[PATH_MAX]; nih_local char *cmd = NULL; pid_t dbus_pid = 0; pid_t upstart_pid = 0; char **output; size_t lines; size_t len; nih_local char *logfile = NULL; nih_local char *logfile_name = NULL; nih_local char *contents = NULL; if (geteuid ()) { printf ("INFO: skipping %s tests as not running as root\n", __func__); fflush (NULL); return; } TEST_GROUP ("cgroup manager handling"); TEST_FILENAME (confdir); TEST_EQ (mkdir (confdir, 0755), 0); TEST_FILENAME (logdir); TEST_EQ (mkdir (logdir, 0755), 0); TEST_FILENAME (flagfile); /* Use the "secret" interface */ TEST_EQ (setenv ("UPSTART_CONFDIR", confdir, 1), 0); TEST_EQ (setenv ("UPSTART_LOGDIR", logdir, 1), 0); TEST_DBUS (dbus_pid); /*******************************************************************/ TEST_FEATURE ("Ensure startup job does not start until cgmanager available"); contents = nih_sprintf (NULL, "start on startup\n" "\n" "cgroup memory mem-%s\n" "\n" "exec echo hello\n", __func__); TEST_NE_P (contents, NULL); CREATE_FILE (confdir, "cgroup.conf", contents); logfile_name = NIH_MUST (nih_sprintf (NULL, "%s/%s", logdir, "cgroup.log")); start_upstart_common (&upstart_pid, FALSE, FALSE, confdir, logdir, NULL); cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "cgroup"); TEST_NE_P (cmd, NULL); RUN_COMMAND (NULL, cmd, &output, &lines); TEST_EQ (lines, 1); /* job should *NOT* start on startup */ TEST_EQ_STR (output[0], "cgroup stop/waiting"); nih_free (output); TEST_FALSE (file_exists (logfile_name)); cmd = nih_sprintf (NULL, "%s notify-cgroup-manager-address %s 2>&1", get_initctl (), CGMANAGER_DBUS_SOCK); TEST_NE_P (cmd, NULL); RUN_COMMAND (NULL, cmd, &output, &lines); TEST_EQ (lines, 0); WAIT_FOR_FILE (logfile_name); logfile = nih_file_read (NULL, logfile_name, &len); TEST_NE_P (logfile, NULL); TEST_EQ_STR (logfile, "hello\r\n"); DELETE_FILE (confdir, "cgroup.conf"); assert0 (unlink (logfile_name)); /*******************************************************************/ TEST_FEATURE ("Ensure bogus cgroups don't crash init"); contents = nih_sprintf (NULL, "cgroup name\n" "\n" "exec echo hello\n"); TEST_NE_P (contents, NULL); CREATE_FILE (confdir, "cgroup-name.conf", contents); logfile_name = NIH_MUST (nih_sprintf (NULL, "%s/%s", logdir, "cgroup-name.log")); cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "cgroup-name"); TEST_NE_P (cmd, NULL); RUN_COMMAND (NULL, cmd, &output, &lines); TEST_EQ (lines, 1); /* job is not running yet */ TEST_EQ_STR (output[0], "cgroup-name stop/waiting"); nih_free (output); TEST_FALSE (file_exists (logfile_name)); cmd = nih_sprintf (NULL, "%s start %s 2>&1", get_initctl (), "cgroup-name"); TEST_NE_P (cmd, NULL); RUN_COMMAND (NULL, cmd, &output, &lines); TEST_EQ (lines, 1); TEST_EQ_STR (output[0], "initctl: Job failed to start"); DELETE_FILE (confdir, "cgroup-name.conf"); /*******************************************************************/ STOP_UPSTART (upstart_pid); TEST_DBUS_END (dbus_pid); TEST_EQ (rmdir (confdir), 0); TEST_EQ (rmdir (logdir), 0); /*******************************************************************/ }
void test_cgroup_setting_new (void) { CGroupSetting *setting; nih_local char *parent= NULL; parent = nih_strdup (NULL, "a parent object"); TEST_NE_P (parent, NULL); TEST_FUNCTION ("cgroup_setting_new"); TEST_FEATURE ("no parent, key, no value"); TEST_ALLOC_FAIL { setting = cgroup_setting_new (NULL, "foo", NULL); if (test_alloc_failed) { TEST_EQ_P (setting, NULL); continue; } TEST_ALLOC_SIZE (setting, sizeof (CGroupSetting)); TEST_ALLOC_PARENT (setting, NULL); TEST_EQ_STR (setting->key, "foo"); TEST_ALLOC_SIZE (setting->key, 1+strlen ("foo")); TEST_ALLOC_PARENT (setting->key, setting); nih_free (setting); } TEST_FEATURE ("parent, key, no value"); TEST_ALLOC_FAIL { setting = cgroup_setting_new (parent, "hello world", NULL); if (test_alloc_failed) { TEST_EQ_P (setting, NULL); continue; } TEST_ALLOC_SIZE (setting, sizeof (CGroupSetting)); TEST_ALLOC_PARENT (setting, parent); TEST_EQ_STR (setting->key, "hello world"); TEST_ALLOC_SIZE (setting->key, 1+strlen ("hello world")); TEST_ALLOC_PARENT (setting->key, setting); nih_free (setting); } TEST_FEATURE ("no parent, key, value"); TEST_ALLOC_FAIL { setting = cgroup_setting_new (NULL, "hello world", "a value"); if (test_alloc_failed) { TEST_EQ_P (setting, NULL); continue; } TEST_ALLOC_SIZE (setting, sizeof (CGroupSetting)); TEST_ALLOC_PARENT (setting, NULL); TEST_EQ_STR (setting->key, "hello world"); TEST_ALLOC_SIZE (setting->key, 1+strlen ("hello world")); TEST_ALLOC_PARENT (setting->key, setting); TEST_EQ_STR (setting->value, "a value"); TEST_ALLOC_SIZE (setting->value, 1+strlen ("a value")); TEST_ALLOC_PARENT (setting->value, setting); nih_free (setting); } TEST_FEATURE ("parent, key, value"); TEST_ALLOC_FAIL { setting = cgroup_setting_new (parent, "hello world", "a value"); if (test_alloc_failed) { TEST_EQ_P (setting, NULL); continue; } TEST_ALLOC_SIZE (setting, sizeof (CGroupSetting)); TEST_ALLOC_PARENT (setting, parent); TEST_EQ_STR (setting->key, "hello world"); TEST_ALLOC_SIZE (setting->key, 1+strlen ("hello world")); TEST_ALLOC_PARENT (setting->key, setting); TEST_EQ_STR (setting->value, "a value"); TEST_ALLOC_SIZE (setting->value, 1+strlen ("a value")); TEST_ALLOC_PARENT (setting->value, setting); nih_free (setting); } }
void test_add (void) { char **env = NULL, **ret; size_t len = 0; TEST_FUNCTION ("environ_add"); /* Check that we can add a variable to a new environment table * and that it is appended to the array. */ TEST_FEATURE ("with empty table"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); } ret = environ_add (&env, NULL, &len, TRUE, "FOO=BAR"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 0); TEST_EQ_P (env[0], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 1); TEST_ALLOC_PARENT (env[0], env); TEST_ALLOC_SIZE (env[0], 8); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_P (env[1], NULL); nih_free (env); } /* Check that we can add a variable to an environment table with * existing different entries and that it is appended to the array. */ TEST_FEATURE ("with new variable"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); } ret = environ_add (&env, NULL, &len, TRUE, "FRODO=BAGGINS"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 2); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_P (env[2], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_ALLOC_PARENT (env[2], env); TEST_ALLOC_SIZE (env[2], 14); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); } /* Check that we can add a variable from the environment to the table * and that it is appended to the array. */ TEST_FEATURE ("with new variable from environment"); putenv ("FRODO=BAGGINS"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); } ret = environ_add (&env, NULL, &len, TRUE, "FRODO"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 2); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_P (env[2], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_ALLOC_PARENT (env[2], env); TEST_ALLOC_SIZE (env[2], 14); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); } unsetenv ("FRODO"); /* Check that when we attempt to add a variable that's not in the * environment, the table is not extended. */ TEST_FEATURE ("with new variable unset in environment"); unsetenv ("FRODO"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); } ret = environ_add (&env, NULL, &len, TRUE, "FRODO"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 2); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_P (env[2], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 2); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_P (env[2], NULL); nih_free (env); } /* Check that we can replace a variable in the environment table * when one already exists with the same or different value. */ TEST_FEATURE ("with replacement variable"); TEST_ALLOC_FAIL { char *old_env; TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); } old_env = env[1]; TEST_FREE_TAG (old_env); ret = environ_add (&env, NULL, &len, TRUE, "BAR=WIBBLE"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_NOT_FREE (old_env); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); continue; } TEST_FREE (old_env); TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_ALLOC_PARENT (env[1], env); TEST_ALLOC_SIZE (env[1], 11); TEST_EQ_STR (env[1], "BAR=WIBBLE"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); } /* Check that we can replace a variable from the environment in the * environment table when one already exists with the same or * different value. */ TEST_FEATURE ("with replacement variable from environment"); putenv ("BAR=WIBBLE"); TEST_ALLOC_FAIL { char *old_env; TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); assert (nih_str_array_add (&env, NULL, &len, "BILBO=TOOK")); } old_env = env[1]; TEST_FREE_TAG (old_env); ret = environ_add (&env, NULL, &len, TRUE, "BAR"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_NOT_FREE (old_env); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); continue; } TEST_FREE (old_env); TEST_NE_P (ret, NULL); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_ALLOC_PARENT (env[1], env); TEST_ALLOC_SIZE (env[1], 11); TEST_EQ_STR (env[1], "BAR=WIBBLE"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); } unsetenv ("BAR"); /* Check that when we attempt to replace a variable that's unset * in the environment, the existing variable is removed from the * table. */ TEST_FEATURE ("with replacement variable unset in environment"); unsetenv ("BAR"); TEST_ALLOC_FAIL { char *old_env; TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); assert (nih_str_array_add (&env, NULL, &len, "BILBO=TOOK")); } old_env = env[1]; TEST_FREE_TAG (old_env); ret = environ_add (&env, NULL, &len, TRUE, "BAR"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_NOT_FREE (old_env); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); continue; } TEST_FREE (old_env); TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "FRODO=BAGGINS"); TEST_EQ_STR (env[2], "BILBO=TOOK"); TEST_EQ_P (env[3], NULL); nih_free (env); } unsetenv ("BAR"); /* Check that we can add a variable to an environment table with * existing different entries and that it is appended to the array, * even if replace is FALSE. */ TEST_FEATURE ("with new variable but no replace"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); } ret = environ_add (&env, NULL, &len, FALSE, "FRODO=BAGGINS"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 2); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_P (env[2], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_ALLOC_PARENT (env[2], env); TEST_ALLOC_SIZE (env[2], 14); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); } /* Check that when a variable already exists in the environment * table, and we're not replacing, the original value is left * untouched. */ TEST_FEATURE ("with existing variable"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); } ret = environ_add (&env, NULL, &len, FALSE, "BAR=WIBBLE"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 3); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_P (env[3], NULL); nih_free (env); } /* Check that when a variable from the environment already exists in * the environment table, and we're not replacing, the original value * is left untouched. */ TEST_FEATURE ("with existing variable from environment"); putenv ("BAR=WIBBLE"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); assert (nih_str_array_add (&env, NULL, &len, "BILBO=TOOK")); } ret = environ_add (&env, NULL, &len, FALSE, "BAR"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); } unsetenv ("BAR"); /* Check that when a variable from the environment is unset it * does not remove an existing variable in the environment table * if we're not replacing. */ TEST_FEATURE ("with existing variable unset in environment"); unsetenv ("BAR"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (nih_str_array_add (&env, NULL, &len, "FOO=BAR")); assert (nih_str_array_add (&env, NULL, &len, "BAR=BAZ")); assert (nih_str_array_add (&env, NULL, &len, "FRODO=BAGGINS")); assert (nih_str_array_add (&env, NULL, &len, "BILBO=TOOK")); } ret = environ_add (&env, NULL, &len, FALSE, "BAR"); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "FRODO=BAGGINS"); TEST_EQ_STR (env[3], "BILBO=TOOK"); TEST_EQ_P (env[4], NULL); nih_free (env); } unsetenv ("BAR"); }
void test_append (void) { char **env = NULL, **new_env, **ret; size_t len = 0; TEST_FUNCTION ("environ_append"); /* Check that we can append all new entries onto the end of an * existing environment table, without modifying the entries passed. */ TEST_FEATURE ("with new entries"); new_env = nih_str_array_new (NULL); assert (environ_add (&new_env, NULL, NULL, TRUE, "MILK=white")); assert (environ_add (&new_env, NULL, NULL, TRUE, "TEA=green")); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (environ_add (&env, NULL, &len, TRUE, "FOO=BAR")); assert (environ_add (&env, NULL, &len, TRUE, "BAR=BAZ")); } ret = environ_append (&env, NULL, &len, TRUE, new_env); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); nih_free (env); continue; } TEST_EQ_P (ret, env); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "MILK=white"); TEST_EQ_STR (env[3], "TEA=green"); TEST_EQ_P (env[4], NULL); nih_free (env); } nih_free (new_env); /* Check that if entries are being replaced, those values from the * new table replace the values in the old table. */ TEST_FEATURE ("with replacement entries"); new_env = nih_str_array_new (NULL); assert (environ_add (&new_env, NULL, NULL, TRUE, "MILK=white")); assert (environ_add (&new_env, NULL, NULL, TRUE, "TEA=green")); assert (environ_add (&new_env, NULL, NULL, TRUE, "FOO=apricot")); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (environ_add (&env, NULL, &len, TRUE, "FOO=BAR")); assert (environ_add (&env, NULL, &len, TRUE, "BAR=BAZ")); } ret = environ_append (&env, NULL, &len, TRUE, new_env); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); nih_free (env); continue; } TEST_EQ_P (ret, env); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=apricot"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "MILK=white"); TEST_EQ_STR (env[3], "TEA=green"); TEST_EQ_P (env[4], NULL); nih_free (env); } nih_free (new_env); /* Check that if entries are being preserved, those values from the * new table are ignored. */ TEST_FEATURE ("with preserve existing entries"); new_env = nih_str_array_new (NULL); assert (environ_add (&new_env, NULL, NULL, TRUE, "MILK=white")); assert (environ_add (&new_env, NULL, NULL, TRUE, "TEA=green")); assert (environ_add (&new_env, NULL, NULL, TRUE, "FOO=apricot")); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { len = 0; env = nih_str_array_new (NULL); assert (environ_add (&env, NULL, &len, TRUE, "FOO=BAR")); assert (environ_add (&env, NULL, &len, TRUE, "BAR=BAZ")); } ret = environ_append (&env, NULL, &len, FALSE, new_env); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); nih_free (env); continue; } TEST_EQ_P (ret, env); TEST_EQ (len, 4); TEST_EQ_STR (env[0], "FOO=BAR"); TEST_EQ_STR (env[1], "BAR=BAZ"); TEST_EQ_STR (env[2], "MILK=white"); TEST_EQ_STR (env[3], "TEA=green"); TEST_EQ_P (env[4], NULL); nih_free (env); } nih_free (new_env); }
void test_libupstart (void) { nih_local NihDBusProxy *upstart = NULL; nih_local char *version = NULL; int ret; pid_t upstart_pid; pid_t dbus_pid; char xdg_runtime_dir[PATH_MAX]; nih_local char *orig_xdg_runtime_dir = NULL; nih_local char *session_file = NULL; nih_local char *path = NULL; TEST_GROUP ("libupstart"); TEST_FEATURE ("version"); TEST_FILENAME (xdg_runtime_dir); TEST_EQ (mkdir (xdg_runtime_dir, 0755), 0); /* Take care to avoid disrupting users environment by saving and * restoring this variable (assuming the tests all pass...). */ orig_xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR"); if (orig_xdg_runtime_dir) orig_xdg_runtime_dir = NIH_MUST (nih_strdup (NULL, orig_xdg_runtime_dir)); assert0 (setenv ("XDG_RUNTIME_DIR", xdg_runtime_dir, 1)); /*******************************************************************/ /* Create a private Session Init instance to connect to */ TEST_DBUS (dbus_pid); START_UPSTART (upstart_pid, TRUE); upstart = upstart_open (NULL); TEST_NE_P (upstart, NULL); /* Basic test (that does not change the state of the system * running this test) to see if we can query version of running * Upstart instance. */ ret = upstart_get_version_sync (NULL, upstart, &version); TEST_EQ (ret, 0); nih_message ("Running instance version: '%s'", version); assert0 (fnmatch ("init (upstart*)", version, 0x0)); STOP_UPSTART (upstart_pid); TEST_DBUS_END (dbus_pid); /*******************************************************************/ if (orig_xdg_runtime_dir) { /* restore */ setenv ("XDG_RUNTIME_DIR", orig_xdg_runtime_dir, 1); } else { assert0 (unsetenv ("XDG_RUNTIME_DIR")); } session_file = get_session_file (xdg_runtime_dir, upstart_pid); unlink (session_file); /* Remove the directory tree the Session Init created */ path = NIH_MUST (nih_sprintf (NULL, "%s/upstart/sessions", xdg_runtime_dir)); assert0 (rmdir (path)); path = NIH_MUST (nih_sprintf (NULL, "%s/upstart", xdg_runtime_dir)); assert0 (rmdir (path)); assert0 (rmdir (xdg_runtime_dir)); }
void test_cgroup_new (void) { nih_local char *parent = NULL; CGroup *cgroup; TEST_FUNCTION ("cgroup_new"); parent = nih_strdup (NULL, "a parent object"); TEST_NE_P (parent, NULL); TEST_FEATURE ("no parent, controller"); TEST_ALLOC_FAIL { cgroup = cgroup_new (NULL, "cpuset"); if (test_alloc_failed) { TEST_EQ_P (cgroup, NULL); continue; } TEST_NE_P (cgroup, NULL); TEST_ALLOC_SIZE (cgroup, sizeof (CGroup)); TEST_ALLOC_PARENT (cgroup, NULL); TEST_EQ_STR (cgroup->controller, "cpuset"); TEST_ALLOC_SIZE (cgroup->controller, 1+strlen ("cpuset")); TEST_ALLOC_PARENT (cgroup->controller, cgroup); TEST_LIST_EMPTY (&cgroup->names); nih_free (cgroup); } TEST_FEATURE ("parent, controller"); TEST_ALLOC_FAIL { cgroup = cgroup_new (parent, "perf_event"); if (test_alloc_failed) { TEST_EQ_P (cgroup, NULL); continue; } TEST_NE_P (cgroup, NULL); TEST_ALLOC_SIZE (cgroup, sizeof (CGroup)); TEST_ALLOC_PARENT (cgroup, parent); TEST_EQ_STR (cgroup->controller, "perf_event"); TEST_ALLOC_SIZE (cgroup->controller, 1+strlen ("perf_event")); TEST_ALLOC_PARENT (cgroup->controller, cgroup); TEST_LIST_EMPTY (&cgroup->names); nih_free (cgroup); } }
void test_realloc (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_realloc"); /* Check that nih_realloc behaves like nih_alloc if the pointer is * NULL (it should, in fact, just call it) */ TEST_FEATURE ("as nih_alloc"); ptr1 = nih_realloc (NULL, NULL, 4096); memset (ptr1, 'x', 4096); TEST_ALLOC_SIZE (ptr1, 4096); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); /* Check that nih_realloc works if the block doesn't have a parent. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 4096); memset (ptr1, 'x', 4096); ptr1 = nih_realloc (ptr1, NULL, 8096); memset (ptr1, 'x', 8096); TEST_ALLOC_SIZE (ptr1, 8096); TEST_ALLOC_PARENT (ptr1, NULL); /* Check that nih_realloc works if the block has a parent, the size * should change but the parent should remain the same. */ TEST_FEATURE ("with a parent"); ptr2 = nih_alloc (ptr1, 5); memset (ptr2, 'x', 5); ptr2 = nih_realloc (ptr2, ptr1, 10); memset (ptr2, 'x', 10); TEST_ALLOC_SIZE (ptr2, 10); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr1); /* Check that nih_realloc works if the block being reallocated has * a child. This is fiddly as they need their parent pointers * adjusted. */ TEST_FEATURE ("with a child"); ptr1 = nih_alloc (NULL, 128); memset (ptr1, 'x', 128); ptr2 = nih_alloc (ptr1, 512); memset (ptr2, 'x', 512); ptr3 = nih_realloc (ptr1, NULL, 1024); memset (ptr3, 'x', 1024); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr3); /* Check that nih_realloc returns NULL and doesn't alter the block * if the allocator fails. */ TEST_FEATURE ("with failing realloc"); ptr1 = nih_alloc (NULL, 10); assert (ptr1); memset (ptr1, 'x', 10); __nih_realloc = realloc_null; ptr2 = nih_realloc (ptr1, NULL, 200); __nih_realloc = realloc; TEST_EQ_P (ptr2, NULL); TEST_ALLOC_SIZE (ptr1, 10); nih_free (ptr1); }
void test_free (void) { void * ptr1; void * ptr2; Parent *parent; int ret; TEST_FUNCTION ("nih_free"); /* Check that nih_free works if the block has no parent. The * destructor should get called and nih_free should return that * return value. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); /* Check that nih_free works if the block has a parent. The * destructor should get called and nih_free should return that * return value. */ TEST_FEATURE ("with parent"); ptr2 = nih_alloc (NULL, 20); ptr1 = nih_alloc (ptr2, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); nih_free (ptr2); /* Check that the destructor on any children also gets called, which * is as good a indication as any that the children are being freed. */ TEST_FEATURE ("with destructor on child"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr2, child_destructor_called); child_destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 0); /* Check that both destructors on parent and children are called, * and that the return value from nih_free is that of the parent's. */ TEST_FEATURE ("with child and destructors"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr1, destructor_called); nih_alloc_set_destructor (ptr2, child_destructor_called); destructor_was_called = 0; child_destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 2); /* Check that a child of an object may be included in a sibling * linked list allocated earlier. At the point the child destructor * is called, the sibling must not have been freed otherwise it * cannot cut itself out. */ TEST_FEATURE ("with child in older sibling list"); parent = nih_new (NULL, Parent); __nih_malloc = my_list_head_malloc; parent->list = nih_new (parent, NihList); nih_list_init (parent->list); __nih_malloc = malloc; parent->child = nih_new (parent, Child); nih_list_init (&parent->child->entry); nih_list_add (parent->list, &parent->child->entry); nih_alloc_set_destructor (parent->child, child_destructor_test); __nih_free = my_list_head_free; nih_free (parent); __nih_free = free; /* Check that a child of an object may be included in a sibling * linked list allocated later. At the point the child destructor * is called, the sibling must not have been freed otherwise it * cannot cut itself out. */ TEST_FEATURE ("with child in younger sibling list"); parent = nih_new (NULL, Parent); parent->child = nih_new (parent, Child); nih_list_init (&parent->child->entry); __nih_malloc = my_list_head_malloc; parent->list = nih_new (parent, NihList); nih_list_init (parent->list); __nih_malloc = malloc; nih_list_add (parent->list, &parent->child->entry); nih_alloc_set_destructor (parent->child, child_destructor_test); __nih_free = my_list_head_free; nih_free (parent); __nih_free = free; }
void test_discard (void) { void *ptr1; void *ptr2; int ret; TEST_FUNCTION ("nih_discard"); /* Check that nih_discard works if the block has no parent, freeing * the object. The destructor should get called and nih_discard * should return that return value. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); /* Check that nih_discard does nothing it the block has a parent. */ TEST_FEATURE ("with parent"); ptr2 = nih_alloc (NULL, 20); ptr1 = nih_alloc (ptr2, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_discard (ptr1); TEST_FALSE (destructor_was_called); TEST_EQ (ret, 0); nih_free (ptr2); /* Check that the destructor on any children also gets called, which * is as good a indication as any that the children are being freed. */ TEST_FEATURE ("with destructor on child"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr2, child_destructor_called); child_destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 0); /* Check that both destructors on parent and children are called, * and that the return value from nih_discard is that of the parent's. */ TEST_FEATURE ("with child and destructors"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr1, destructor_called); nih_alloc_set_destructor (ptr2, child_destructor_called); destructor_was_called = 0; child_destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (destructor_was_called); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 2); }
void test_unref (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_unref"); /* Check that we can remove a reference from an object with multiple * parents, which means the object will not be freed. */ TEST_FEATURE ("with multiple parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); ptr3 = nih_alloc (NULL, 100); memset (ptr2, 'z', 100); nih_ref (ptr2, ptr3); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr1); nih_free (ptr3); /* Check that when we remove the last reference from an object, * the object is freed. */ TEST_FEATURE ("with last parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_TRUE (destructor_was_called); nih_free (ptr1); /* Check that we have to remove the NULL reference from an object * for it to be freed. */ TEST_FEATURE ("with only NULL parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; nih_unref (ptr1, NULL); TEST_TRUE (destructor_was_called); /* Check that we can remove the NULL reference leaving a reference * to a different object. */ TEST_FEATURE ("with no parent and other parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (NULL, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, NULL); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_FALSE (nih_alloc_parent (ptr2, NULL)); nih_free (ptr1); /* Check that an object with multiple NULL references must have * them both removed before it will be freed. */ TEST_FEATURE ("with multiple NULL parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_ref (ptr1, NULL); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; nih_unref (ptr1, NULL); TEST_FALSE (destructor_was_called); nih_unref (ptr1, NULL); TEST_TRUE (destructor_was_called); /* Check that an object with multiple identical references must have * them both removed before it will be freed. */ TEST_FEATURE ("with multiple identical parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_FALSE (destructor_was_called); nih_unref (ptr2, ptr1); TEST_TRUE (destructor_was_called); nih_free (ptr1); }
void test_ref (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_ref"); /* Check that we can add a reference to an object that has no * parent, and this does not remove the NULL reference. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (NULL, 100); memset (ptr2, 'y', 100); nih_ref (ptr1, ptr2); TEST_ALLOC_PARENT (ptr1, ptr2); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); nih_free (ptr2); /* Check that we can add a reference to an object that already has * a parent, and that both shall be parents afterwards. */ TEST_FEATURE ("with existing parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); ptr3 = nih_alloc (NULL, 100); memset (ptr2, 'z', 100); nih_ref (ptr2, ptr3); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr1); nih_free (ptr3); /* Check that we can add a new NULL reference to an object that * already has a parent, and that both shall be parents afterwards. */ TEST_FEATURE ("with existing parent and new NULL"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, NULL); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, NULL); nih_free (ptr1); nih_free (ptr2); /* Check that we can add a second NULL reference to an object that * already has one. */ TEST_FEATURE ("with additional NULL parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_ref (ptr1, NULL); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); /* Check that we can add a second reference to an object that already * has a reference from the same parent. */ TEST_FEATURE ("with additional existing parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr2); nih_free (ptr1); }