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_operator_handle (void) { EventOperator *oper1, *oper2, *oper3, *oper4, *oper5; char *env1[2], *env2[3], *env[2]; Event *event; int ret; TEST_FUNCTION ("event_operator_handle"); oper1 = event_operator_new (NULL, EVENT_OR, NULL, NULL); oper2 = event_operator_new (NULL, EVENT_AND, NULL, NULL); oper3 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL); oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL); oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL); oper5->env = env1; oper5->env[0] = "BAR=$WIBBLE"; oper5->env[1] = NULL; nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT); nih_tree_add (&oper2->node, &oper3->node, NIH_TREE_LEFT); nih_tree_add (&oper2->node, &oper4->node, NIH_TREE_RIGHT); nih_tree_add (&oper1->node, &oper5->node, NIH_TREE_RIGHT); /* Check that a non-matching event doesn't touch the tree. */ TEST_FEATURE ("with non-matching event"); event = event_new (NULL, "frodo", NULL); ret = event_operator_handle (oper1, event, NULL); TEST_EQ (ret, FALSE); TEST_EQ (oper1->value, FALSE); TEST_EQ (oper2->value, FALSE); TEST_EQ (oper3->value, FALSE); TEST_EQ_P (oper3->event, NULL); TEST_EQ (oper4->value, FALSE); TEST_EQ_P (oper4->event, NULL); TEST_EQ (oper5->value, FALSE); TEST_EQ_P (oper5->event, NULL); TEST_EQ (event->blockers, 0); /* Check that matching an event in the tree results in the event * being referenced and blocked, and stored in the operator. * The tree value should not be updated since the expression is not * TRUE. */ TEST_FEATURE ("with matching event"); event = event_new (NULL, "foo", NULL); ret = event_operator_handle (oper1, event, NULL); TEST_EQ (ret, TRUE); TEST_EQ (oper1->value, FALSE); TEST_EQ (oper2->value, FALSE); TEST_EQ (oper3->value, TRUE); TEST_EQ_P (oper3->event, event); TEST_EQ (oper4->value, FALSE); TEST_EQ_P (oper4->event, NULL); TEST_EQ (oper5->value, FALSE); TEST_EQ_P (oper5->event, NULL); TEST_EQ (event->blockers, 1); /* Check that a duplicate matching event in the tree is not * referenced or blocked since the tree already matched the first. */ TEST_FEATURE ("with duplicate matching event"); event = event_new (NULL, "foo", NULL); TEST_FREE_TAG (oper3->event); ret = event_operator_handle (oper1, event, NULL); TEST_EQ (ret, FALSE); TEST_EQ (oper1->value, FALSE); TEST_EQ (oper2->value, FALSE); TEST_EQ (oper3->value, TRUE); TEST_NE_P (oper3->event, event); TEST_NOT_FREE (oper3->event); TEST_EQ (oper4->value, FALSE); TEST_EQ_P (oper4->event, NULL); TEST_EQ (oper5->value, FALSE); TEST_EQ_P (oper5->event, NULL); TEST_EQ (event->blockers, 0); nih_free (event); /* Check that matching an event in the tree results in the event * being referenced and blocked, and stored in the operator. * Since the event tips the balance, it should update the expression. */ TEST_FEATURE ("with matching event and complete expression"); event = event_new (NULL, "bar", NULL); ret = event_operator_handle (oper1, event, NULL); TEST_EQ (ret, TRUE); TEST_EQ (oper1->value, TRUE); TEST_EQ (oper2->value, TRUE); TEST_EQ (oper3->value, TRUE); TEST_NE_P (oper3->event, NULL); TEST_EQ (oper4->value, TRUE); TEST_EQ_P (oper4->event, event); TEST_EQ (oper5->value, FALSE); TEST_EQ_P (oper5->event, NULL); TEST_EQ (event->blockers, 1); event_operator_reset (oper1); /* Check that an environment array is passed through and used to * match the expression. */ TEST_FEATURE ("with environment"); event = event_new (NULL, "baz", NULL); event->env = env2; event->env[0] = "FOO=bar"; event->env[1] = "BAR=baz"; event->env[2] = NULL; env[0] = "WIBBLE=baz"; env[1] = NULL; ret = event_operator_handle (oper1, event, env); TEST_EQ (ret, TRUE); TEST_EQ (oper1->value, TRUE); TEST_EQ (oper2->value, FALSE); TEST_EQ (oper3->value, FALSE); TEST_EQ_P (oper4->event, NULL); TEST_EQ (oper4->value, FALSE); TEST_EQ_P (oper4->event, NULL); TEST_EQ (oper5->value, TRUE); TEST_EQ_P (oper5->event, event); TEST_EQ (event->blockers, 1); event_operator_reset (oper1); nih_free (oper1); nih_free (oper2); nih_free (oper3); nih_free (oper4); nih_free (oper5); event_poll (); }