Ejemplo n.º 1
0
static void test_mmap_wrong_format_version (const char * tmpFile)
{
	// first write a mmap file
	{
		Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
		KeySet * conf = ksNew (0, KS_END);
		PLUGIN_OPEN ("mmapstorage");

		KeySet * ks = simpleTestKeySet ();
		succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}

	// set wrong version number in mmap header
	FILE * fp;
	if ((fp = fopen (tmpFile, "r+")) == 0)
	{
		yield_error ("fopen() error");
	}
	struct stat sbuf;
	if (stat (tmpFile, &sbuf) == -1)
	{
		yield_error ("stat() error");
	}

	int fd = fileno (fp);
	char * mappedRegion = mmap (0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (mappedRegion == MAP_FAILED)
	{
		ELEKTRA_LOG_WARNING ("error mapping file %s\nmmapSize: " ELEKTRA_STAT_ST_SIZE_F, tmpFile, sbuf.st_size);
		yield_error ("mmap() error");
		return;
	}
	if (fp)
	{
		fclose (fp);
	}

	MmapHeader * mmapHeader = (MmapHeader *) mappedRegion;
	mmapHeader->formatVersion = ELEKTRA_MMAP_FORMAT_VERSION + 1;

	if (msync ((void *) mappedRegion, sbuf.st_size, MS_SYNC) != 0)
	{
		yield_error ("msync() error");
		return;
	}

	if (munmap (mappedRegion, sbuf.st_size) != 0)
	{
		yield_error ("munmap() error");
		return;
	}

	// wrong format version should be detected now
	{
		// we expect an error here
		Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
		KeySet * conf = ksNew (0, KS_END);
		PLUGIN_OPEN ("mmapstorage");

		KeySet * ks = ksNew (0, KS_END);
		succeed_if (plugin->kdbGet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_ERROR,
			    "kdbGet did not detect wrong format version");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}
}
Ejemplo n.º 2
0
static void test_mmap_wrong_magic_keyset (const char * tmpFile)
{
	// first write a mmap file
	{
		Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
		KeySet * conf = ksNew (0, KS_END);
		PLUGIN_OPEN ("mmapstorage");

		KeySet * ks = simpleTestKeySet ();
		succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}

	// now manipulate magic keyset inside the mapped region
	FILE * fp;
	if ((fp = fopen (tmpFile, "r+")) == 0)
	{
		yield_error ("fopen() error");
	}
	struct stat sbuf;
	if (stat (tmpFile, &sbuf) == -1)
	{
		yield_error ("stat() error");
	}

	int fd = fileno (fp);
	char * mappedRegion = mmap (0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (mappedRegion == MAP_FAILED)
	{
		ELEKTRA_LOG_WARNING ("error mapping file %s\nmmapSize: " ELEKTRA_STAT_ST_SIZE_F, tmpFile, sbuf.st_size);
		yield_error ("mmap() error");
		return;
	}
	if (fp)
	{
		fclose (fp);
	}

	KeySet * magicKs = (KeySet *) (mappedRegion + sizeof (MmapHeader));
	magicKs->size = 1234; // magic keyset contains SIZE_MAX here

	if (msync ((void *) mappedRegion, sbuf.st_size, MS_SYNC) != 0)
	{
		yield_error ("msync() error");
		return;
	}

	if (munmap (mappedRegion, sbuf.st_size) != 0)
	{
		yield_error ("munmap() error");
		return;
	}

	// manipulated magic keyset should be detected now
	{
		// we expect an error here
		Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
		KeySet * conf = ksNew (0, KS_END);
		PLUGIN_OPEN ("mmapstorage");

		KeySet * ks = ksNew (0, KS_END);
		succeed_if (plugin->kdbGet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_ERROR,
			    "kdbGet did not detect wrong magic keyset");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}
}
Ejemplo n.º 3
0
void test_key (void)
{
	KeySet * ks;
	Key * cur;
	int counter;

	printf ("Testing Key from xml\n");

	ks = ksNew (0, KS_END);
	exit_if_fail (ksFromXMLfile (ks, srcdir_file ("xmltool/key.xml")) == 0, "ksFromXMLfile(key.xml) failed.");
	counter = 0;
	ksRewind (ks);
	while ((cur = ksNext (ks)))
	{
		counter++;
		/* Prepend key root */
		// snprintf(buf, sizeof(buf), "%s/%s", root, keyName(cur));
		// keySetName(cur, buf);

		/* Make tests ... */
		// printf ("counter: %d - name: %s - value: %s\n", counter, (char*) keyName(cur), (char*)keyValue(cur));
		switch (counter)
		{
		case 1:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 0440, "could not get mode");
			break;
		case 2:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 3:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 0, "could not get uid value");
			succeed_if (keyGetGID (cur) == 20, "could not get gid value");
			break;
		case 4:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetGID (cur) == 40, "could not get gid value");
			break;
		case 5:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 6:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with\nstandard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 20, "could not get uid value");
			break;
		case 7:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Bin@a€ry Key") == 0, "wrong name");
			succeed_if (keyValue (cur) == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 230, "could not get mode");
			// <key type="binary" basename="Ug.ly:Bin@a€ry Key"><comment>Binary key with ugly name</comment></key>
			break;
		case 8:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Dir@ect€ory Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="directory" basename="Ug.ly:Dir@ect€ory Key"><comment>Directory with ugly name</comment></key>
			break;
		case 9:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:St@ri€n.g Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "With a string value") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "string key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="string" basename="Ug.ly:St@ri€n.g Key" value="With a string value"><comment>string key with ugly
			// name</comment></key>
			break;
		}
	}

	ksDel (ks);
}
Ejemplo n.º 4
0
static void test_creatingLookup (void)
{
	printf ("Test creating lookup\n");

	KeySet * ks = ksNew (10, KS_END);

	Key * searchKey = keyNew ("user/something", KEY_VALUE, "a value", KEY_END);
	Key * k0 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k0, "no key was created");
	succeed_if_same_string (keyName (k0), keyName (searchKey));
	succeed_if_same_string (keyString (k0), keyString (searchKey));

	Key * k1 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k1, "no key was returned");
	succeed_if (k0 == k1, "not the same key");

	keyDel (searchKey);
	ksDel (ks);


	ks = ksNew (10, KS_END);

	searchKey = keyNew ("dir/something", KEY_VALUE, "a value", KEY_END);
	k0 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k0, "no key was created");
	succeed_if_same_string (keyName (k0), keyName (searchKey));
	succeed_if_same_string (keyString (k0), keyString (searchKey));

	k1 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k1, "no key was returned");
	succeed_if (k0 == k1, "not the same key");

	keyDel (searchKey);
	ksDel (ks);


	ks = ksNew (10, KS_END);

	searchKey = keyNew ("/something", KEY_CASCADING_NAME, KEY_VALUE, "a value", KEY_END);

	// check if duplication works:
	Key * dupKey = keyDup (searchKey);
	succeed_if_same_string (keyName (dupKey), keyName (searchKey));
	succeed_if_same_string (keyString (dupKey), keyString (searchKey));
	ksAppendKey (ks, dupKey);
	keyDel (dupKey);

	k0 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k0, "no key was created");
	succeed_if_same_string (keyName (k0), keyName (searchKey));
	succeed_if_same_string (keyString (k0), keyString (searchKey));

	k1 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k1, "no key was returned");
	succeed_if (k0 == k1, "not the same key");

	keyDel (searchKey);
	ksDel (ks);


	ks = ksNew (10, KS_END);

	searchKey = keyNew ("proc/something", KEY_VALUE, "a value", KEY_END);
	k0 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k0, "no key was created");
	succeed_if_same_string (keyName (k0), keyName (searchKey));
	succeed_if_same_string (keyString (k0), keyString (searchKey));

	k1 = ksLookup (ks, searchKey, KDB_O_CREATE);
	exit_if_fail (k1, "no key was returned");
	succeed_if (k0 == k1, "not the same key");

	keyDel (searchKey);
	ksDel (ks);
}
Ejemplo n.º 5
0
void test_keyset (void)
{
	KeySet * ks;
	Key * cur;
	int counter;

	printf ("Testing KeySet from xml\n");

	ks = ksNew (0, KS_END);
	exit_if_fail (ksFromXMLfile (ks, srcdir_file ("xmltool/keyset.xml")) == 0, "ksFromXMLfile(key.xml) failed.");
	counter = 0;
	ksRewind (ks);
	while ((cur = ksNext (ks)))
	{
		counter++;

		/* Make tests ... */
		// printf ("counter: %d - %s\n", counter, keyName(cur));
		switch (counter)
		{
		// <key type="43" basename="0-27042916" value="0 216905227"><comment>2551516588474823843</comment></key>
		case 1:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/0-27042916") == 0, "name of first key not correct");
			succeed_if (strcmp (keyValue (cur), "0 216905227") == 0, "value of first key not correct");
			succeed_if (strcmp (keyComment (cur), "2551516588474823843") == 0, "comment of first key not correct");
			break;
		// <key type="253" basename="1-2449524622" value="1 1679328197"><comment>3246436893195629244</comment></key>
		case 2:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/1-2449524622") == 0, "name of 2. key not correct");
			succeed_if (strcmp (keyValue (cur), "1 1679328197") == 0, "value of 2. key not correct");
			succeed_if (strcmp (keyComment (cur), "3246436893195629244") == 0, "comment of 2. key not correct");
			break;
		// <key type="string" basename="dir-1-0">
		case 3:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/dir-1-0") == 0, "name of 3. key not correct");
			break;
		// <key type="114" basename="0-294164813" value="0 216245011"><comment>18454108762891828026</comment></key>
		case 4:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/dir-1-0/0-294164813") == 0, "name of 4. key not correct");
			succeed_if (strcmp (keyValue (cur), "0 216245011") == 0, "value of 4. key not correct");
			succeed_if (strcmp (keyComment (cur), "18454108762891828026") == 0, "comment of 4. key not correct");
			break;
		// <key type="135" basename="1-1479930365" value="1 2732423037"><comment>24597295372375238</comment></key>
		case 5:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/dir-1-0/1-1479930365") == 0, "name of 4. key not correct");
			succeed_if (strcmp (keyValue (cur), "1 2732423037") == 0, "value of 4. key not correct");
			succeed_if (strcmp (keyComment (cur), "24597295372375238") == 0, "comment of 4. key not correct");
			break;
		// <key type="string" basename="dir-2-0">
		case 6:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/dir-1-0/dir-2-0") == 0, "name of 3. key not correct");
			break;
		// <key type="144" basename="0-215571059" value="0 264857705"><comment>2188631490667217086</comment></key>
		case 7:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/dir-1-0/dir-2-0/0-215571059") == 0,
				    "name of 4. key not correct");
			succeed_if (strcmp (keyValue (cur), "0 264857705") == 0, "value of 4. key not correct");
			succeed_if (strcmp (keyComment (cur), "2188631490667217086") == 0, "comment of 4. key not correct");
			break;
		}
	}

	ksDel (ks);
}
Ejemplo n.º 6
0
void test_restoreOnSet () {
	Key *parentKey = keyNew ("user/tests/keytometa", KEY_END);
	KeySet *conf = ksNew (0);
	PLUGIN_OPEN("keytometa");

	KeySet *ks = createSimpleTestKeys ();

	succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1,
			"call to kdbGet was not successful");
	succeed_if(output_error (parentKey), "error in kdbGet");
	succeed_if(output_warnings (parentKey), "warnings in kdbGet");

	Key *key = ksLookupByName(ks, "user/normalkey2", 0);
	succeed_if (key, "normalkey2 was removed");

	/* change the meta information stored in normalkey2
	 * (was generated from convertkey1)
	 */
	keySetMeta(key, "testmeta", "changedtestvalue");

	/* do not touch the meta information of normalkey3
	 * (was generated from convertkey2)
	 */

	succeed_if(plugin->kdbSet (plugin, ks, parentKey) >= 1,
			"call to kdbSet was not successful");
	succeed_if(output_error (parentKey), "error in kdbSet");
	succeed_if(output_warnings (parentKey), "warnings in kdbSet");

	key = ksLookupByName(ks, "user/convertkey1", 0);
	succeed_if (key, "convertkey1 was not restored");
	succeed_if (!strcmp (keyString(key), "changedtestvalue"), "meta information was not written back to convertkey1");

	key = ksLookupByName (ks, "user/convertkey2", 0);
	succeed_if (key, "convertkey2 was not restored");
	succeed_if (!strcmp (keyString(key), "testvalue2"), " value of convertkey2 was modified");

	keyDel (parentKey);
	ksDel(ks);
	PLUGIN_CLOSE ()
	;
}
Ejemplo n.º 7
0
void test_metaMerging ()
{
	Key *parentKey = keyNew ("user/tests/keytometa", KEY_END);
	KeySet *conf = ksNew (0);
	PLUGIN_OPEN("keytometa");

	KeySet* ks = createMergeTestkeys ();
	succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1,
			"call to kdbGet was not successful");
	succeed_if(output_error (parentKey), "error in kdbGet");
	succeed_if(output_warnings (parentKey), "warnings in kdbGet");

	Key *key = ksLookupByName(ks, "user/normalkey1", 0);
	succeed_if (key, "normalkey1 was removed");

	const Key *metaKey1 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey1, "normalkey1 contained no metakey");
	const char *expected1 = "meta line 1\nmeta line 2\nmeta line 3";
	succeed_if (!strcmp (keyString(metaKey1), expected1), "metakey of normalkey1 contained incorrect data");

	key = ksLookupByName(ks, "user/normalkey2", 0);
	succeed_if (key, "normalkey2 was removed");

	const Key *metaKey2 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey2, "normalkey2 contained no metakey");
	const char *expected2 = "meta line 30\nmeta line 31\nmeta line 32";
	succeed_if (!strcmp (keyString(metaKey2), expected2), "metakey of normalkey2 contained incorrect data");

	/* change the value of the middle key */
	keySetMeta(key, "testmeta", "meta line 30\nchanged meta line\nmeta line 32");

	succeed_if(plugin->kdbSet (plugin, ks, parentKey) >= 1,
			"call to kdbSet was not successful");
	succeed_if(output_error (parentKey), "error in kdbSet");
	succeed_if(output_warnings (parentKey), "warnings in kdbSet");

	key = ksLookupByName(ks, "user/convertkey30", 0);
	succeed_if (key, "convertkey30 was not restored");
	succeed_if (!strcmp (keyString(key), "meta line 30"), "value of convertkey30 was modified");

	key = ksLookupByName (ks, "user/convertkey31", 0);
	succeed_if (key, "convertkey31 was not restored");
	succeed_if (!strcmp (keyString(key), "changed meta line"), "meta information was not written back to convertkey31");

	key = ksLookupByName (ks, "user/convertkey32", 0);
	succeed_if (key, "convertkey32 was not restored");
	succeed_if (!strcmp (keyString(key), "meta line 32"), "value of convertkey32 was modified");

	keyDel (parentKey);
	ksDel(ks);
	PLUGIN_CLOSE ();
}
Ejemplo n.º 8
0
void test_simpleAppendModes()
{
	Key *parentKey = keyNew ("user/tests/keytometa", KEY_END);
	KeySet *conf = ksNew (0);
	PLUGIN_OPEN("keytometa");


	KeySet *ks = createSimpleTestKeys ();

	succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1,
			"call to kdbGet was not successful");
	succeed_if(output_error (parentKey), "error in kdbGet");
	succeed_if(output_warnings (parentKey), "warnings in kdbGet");

	/* converted keys must be removed from the result */
	succeed_if (!ksLookupByName(ks, "user/convertkey1", 0), "convertkey1 was not converted");
	succeed_if (!ksLookupByName(ks, "user/convertkey2", 0), "convertkey2 was not converted");

	/* normalkey2 must contain meta information generated from convertkey1 (via next) */
	Key *key = ksLookupByName(ks, "user/normalkey2", 0);
	succeed_if (key, "normalkey2 was removed");

	const Key *metaKey1 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey1, "normalkey1 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey1), "testvalue1"), "metakey of normalkey1 contained incorrect data");

	/* normalkey3 must contain meta information generated from convertkey2 (via previous) */
	key = ksLookupByName (ks, "user/normalkey3", 0);
	succeed_if (key, "normalkey3 was removed");

	const Key *metaKey2 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey2, "normalkey1 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey2), "testvalue2"), "metakey of normalkey2 contained incorrect data");

	keyDel (parentKey);
	ksDel(ks);
	PLUGIN_CLOSE ()
	;
}
Ejemplo n.º 9
0
void test_parentAppendMode()
{
	Key *parentKey = keyNew ("user/tests/keytometa", KEY_END);
	KeySet *conf = ksNew (0);
	PLUGIN_OPEN ("keytometa");

	KeySet *ks = createParentTestKeys ();

	succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1,
			"call to kdbGet was not successful");
	succeed_if(output_error (parentKey), "error in kdbGet");
	succeed_if(output_warnings (parentKey), "warnings in kdbGet");

	/* parentkey1 must contain meta information generated from convertkeydirect (via parent) */
	Key *key = ksLookupByName(ks, "user/parentkey1", 0);
	succeed_if (key, "parentkey1 was removed");

	const Key *metaKey1 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey1, "parentkey1 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey1), "testvalue1"), "metakey of parentkey1 contained incorrect data");

	/* parentkey2 must contain meta information generated from convertkeyhole (via parent) */
	key = ksLookupByName(ks, "user/parentkey2", 0);
	succeed_if (key, "parentkey2 was removed");

	const Key *metaKey2 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey2, "parentkey2 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey2), "testvalue2"), "metakey of parentkey2 contained incorrect data");

	/* parentkey3 must contain meta information generated from convertkeyprev
	 * (via previous append samelevel which falls back to parent) */
	key = ksLookupByName(ks, "user/parentkey3", 0);
	succeed_if (key, "parentkey3 was removed");

	const Key *metaKey3 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey3, "parentkey3 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey3), "testvalue3"), "metakey of parentkey3 contained incorrect data");

	/* normalkey1 must not contain meta data */
	key = ksLookupByName(ks, "user/normalkey1", 0);
	succeed_if (key, "normalkey1 was removed");
	succeed_if (!keyGetMeta (key, "testmeta"), "normalkey1 should not contain any meta data");

	/* parentkey4 must contain meta information generated from convertkeynext
	 * (via next append samelevel which falls back to parent) */
	key = ksLookupByName(ks, "user/parentkey4", 0);
	succeed_if (key, "parentkey4 was removed");

	const Key *metaKey4 = keyGetMeta(key, "testmeta");
	succeed_if (metaKey4, "parentkey4 contained no metakey");
	succeed_if (!strcmp (keyString(metaKey4), "testvalue4"), "metakey of parentkey4 contained incorrect data");

	/* normalkey2 must not contain meta data */
	key = ksLookupByName(ks, "user/normalkey2", 0);
	succeed_if (key, "normalkey2 was removed");
	succeed_if (!keyGetMeta (key, "testmeta"), "normalkey2 should not contain any meta data");

	keyDel (parentKey);
	ksDel (ks);
	PLUGIN_CLOSE();
}