コード例 #1
0
static void test_double_get (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	KeySet * first = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, first, parentKey) == 1, "kdbGet was not successful");
	KeySet * second = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, second, parentKey) == 1, "kdbGet was not successful");
	succeed_if (first->array != second->array, "ks->array points to same thing");

	compare_keyset (first, ks);
	compare_keyset (ks, first);
	compare_keyset (second, ks);
	compare_keyset (ks, second);

	ksDel (ks);
	ks = metaTestKeySet ();
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");

	KeySet * simple = simpleTestKeySet ();
	compare_keyset (first, simple);
	compare_keyset (second, simple);
	ksDel (first);
	ksDel (second);
	ksDel (simple);
	ksDel (ks);
	keyDel (parentKey);
	closeStoragePlugin (storagePlugin);
}
コード例 #2
0
static void test_mmap_ks_copy (const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	KeySet * conf = ksNew (0, KS_END);
	PLUGIN_OPEN ("mmapstorage");
	KeySet * returned = simpleTestKeySet ();

	succeed_if (plugin->kdbSet (plugin, returned, parentKey) == 1, "kdbGet was not successful");
	ksDel (returned);

	returned = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, returned, parentKey) == 1, "kdbGet was not successful");

	KeySet * expected = simpleTestKeySet ();
	compare_keyset (expected, returned);

	KeySet * copiedKs = ksNew (0, KS_END);
	ksCopy (copiedKs, returned);
	compare_keyset (expected, copiedKs);

	ksDel (copiedKs);
	ksDel (expected);
	ksDel (returned);

	keyDel (parentKey);
	PLUGIN_CLOSE ();
}
コード例 #3
0
static void test_ksPop (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	KeySet * poppedKeys = ksNew (0, KS_END);
	succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed");
	succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed");
	succeed_if (ksGetSize (ks) == 1, "ksGetSize after ksPop should be decremented");
	succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed");
	succeed_if (ksGetSize (poppedKeys) == 3, "expecting three keys to be in ks");
	succeed_if (ksPop (ks) == 0, "ks should be empty");
	succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) == -1, "ks should be empty, but is not");

	KeySet * test = simpleTestKeySet ();
	compare_keyset (poppedKeys, test);
	ksDel (test);

	ksDel (poppedKeys);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #4
0
static void test_ksAppendKey (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	ssize_t appendSize = 0;
	Key * toAppend = keyNew (TEST_ROOT_KEY "/my/new/key", KEY_END);

	if ((appendSize = ksAppendKey (ks, toAppend)) == -1)
	{
		yield_error ("ksAppendKey failed");
	}

	succeed_if (appendSize == (origSize + 1), "ksAppendKey after append should be incremented");
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	ksDel (ks);
	ks = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");
	ssize_t returnedSize = ksGetSize (ks);

	succeed_if (returnedSize == (origSize + 1), "ksGetSize after append should be incremented");

	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #5
0
static void test_mmap_ksCopy (const char * tmpFile)
{
	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");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");
	succeed_if ((ks->flags & KS_FLAG_MMAP_ARRAY) == KS_FLAG_MMAP_ARRAY, "KeySet array not in mmap");

	KeySet * copyKs = ksNew (0, KS_END);
	if (ksCopy (copyKs, ks) == 1)
	{
		compare_keyset (copyKs, ks);
		compare_keyset (ks, copyKs);
	}
	else
	{
		yield_error ("ksCopy failed");
	}

	ksDel (copyKs);
	keyDel (parentKey);
	ksDel (ks);
	PLUGIN_CLOSE ();
}
コード例 #6
0
static void test_ksAppend (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	KeySet * toAppend = ksNew (10, keyNew ("user/tests/storage/zzzz", KEY_VALUE, "root key", KEY_END),
				   keyNew ("user/tests/storage/simpleKey/c", KEY_VALUE, "c value", KEY_END),
				   keyNew ("user/tests/storage/simpleKey/d", KEY_VALUE, "d value", KEY_END), KS_END);
	if (ksAppend (ks, toAppend) == -1)
	{
		yield_error ("ksAppend failed");
	}

	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	ksDel (ks);
	ks = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

	ksDel (toAppend);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #7
0
static void test_ksCopy (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	KeySet * copyKs = ksNew (0, KS_END);
	if (ksCopy (copyKs, ks) == 1)
	{
		compare_keyset (copyKs, ks);
		compare_keyset (ks, copyKs);
	}
	else
	{
		yield_error ("ksCopy failed");
	}

	ksDel (copyKs);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #8
0
static void test_ksLookupByName (const size_t storagePlugin, const char * tmpFile, option_t options)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	const char * name = "user/tests/storage/simpleKey/a";
	Key * found = ksLookupByName (ks, name, options);
	succeed_if (found, "did not find key");
	if (options == KDB_O_POP)
	{
		// make sure key is really popped
		keyDel (found);
		found = ksLookupByName (ks, name, 0);
		succeed_if (!found, "found key that should not exist");
	}

	name = "user/tests/storage/simpleKey/foo";
	found = ksLookupByName (ks, name, options);
	succeed_if (!found, "found key that should not exist");

	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #9
0
static void test_mmap_truncated_file (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 truncate the mmap file by the size of the mmap footer
	FILE * fp;
	if ((fp = fopen (tmpFile, "r+")) == 0)
	{
		yield_error ("error opening file");
	}
	struct stat sbuf;
	if (stat (tmpFile, &sbuf) == -1)
	{
		yield_error ("stat error");
	}

	int fd = fileno (fp);
	if ((ftruncate (fd, sbuf.st_size - sizeof (MmapFooter))) == -1)
	{
		yield_error ("ftruncate error");
	}
	if (fp)
	{
		fclose (fp);
	}

	// truncated file should be detected by mmapstorage
	{
		// after the file was truncated, 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 truncated file");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}
}
コード例 #10
0
static void test_mmap_get_set (const char * tmpFile)
{
	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) == 1, "kdbGet was not successful");
	ksDel (ks);
	ks = simpleTestKeySet ();
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	ksDel (ks);
	ks = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

	KeySet * expected = simpleTestKeySet ();
	compare_keyset (expected, ks);
	compare_keyset (ks, expected);

	ksDel (expected);
	keyDel (parentKey);
	ksDel (ks);
	PLUGIN_CLOSE ();
}
コード例 #11
0
static void test_ksCut (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

	// create keyset with some folder 'other' that we will then cut
	KeySet * ks = simpleTestKeySet ();
	KeySet * other = ksNew (10, keyNew ("user/tests/storage/other", KEY_VALUE, "other key", KEY_END),
				keyNew ("user/tests/storage/other/a", KEY_VALUE, "other a value", KEY_END),
				keyNew ("user/tests/storage/other/b", KEY_VALUE, "other b value", KEY_END), KS_END);
	if (ksAppend (ks, other) == -1)
	{
		yield_error ("ksAppend failed");
	}

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

	// now cut the 'other' folder
	Key * cutKey = keyNew ("user/tests/storage/other", KEY_END);
	KeySet * returned = ksCut (ks, cutKey);
	succeed_if (returned, "keyset is empty (does not contain the cut keyset)");

	KeySet * simple = simpleTestKeySet ();
	compare_keyset (simple, ks);
	compare_keyset (other, returned);

	ksDel (other);
	ksDel (returned);
	ksDel (simple);
	keyDel (cutKey);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #12
0
static void test_ksDupFun (const size_t storagePlugin, const char * tmpFile, KeySet * copyFunction (const KeySet * source))
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

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

	KeySet * dupKs = copyFunction (ks);
	compare_keyset (dupKs, ks);
	compare_keyset (ks, dupKs);

	ksDel (dupKs);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #13
0
static void test_mmap_ksDupFun (const char * tmpFile, KeySet * copyFunction (const KeySet * source))
{
	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");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");
	succeed_if ((ks->flags & KS_FLAG_MMAP_ARRAY) == KS_FLAG_MMAP_ARRAY, "KeySet array not in mmap");

	KeySet * dupKs = copyFunction (ks);
	compare_keyset (dupKs, ks);
	compare_keyset (ks, dupKs);

	ksDel (dupKs);
	keyDel (parentKey);
	ksDel (ks);
	PLUGIN_CLOSE ();
}
コード例 #14
0
static void test_ksGetSize (const size_t storagePlugin, const char * tmpFile)
{
	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
	open_storage_plugin (storagePlugin);
	Plugin * plugin = plugins[storagePlugin];

	KeySet * ks = simpleTestKeySet ();
	ssize_t origSize = ksGetSize (ks);
	succeed_if (origSize > 0, "ks was empty before kdbSet");
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");

	ksDel (ks);
	ks = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");
	ssize_t returnedSize = ksGetSize (ks);
	succeed_if (origSize == returnedSize, "ksGetSize before and after kdbSet, kdbGet differ");

	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
コード例 #15
0
static void test_mmap_open_pipe (void)
{
	// try writing to an invalid file, we simply use a pipe here
	int pipefd[2];
	if (pipe (pipefd) != 0)
	{
		yield_error ("pipe() error");
	}
	char pipeFile[1024];
	sprintf (pipeFile, "/dev/fd/%d", pipefd[1]);
	pipeFile[1023] = '\0';

	Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, pipeFile, KEY_END);
	KeySet * conf = ksNew (0, KS_END);
	PLUGIN_OPEN ("mmapstorage");

	KeySet * ks = simpleTestKeySet ();
	// truncate inside mmap plugin should fail here, since the pipe cannot be truncated
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_ERROR, "kdbSet did not detect error with the file");

	keyDel (parentKey);
	ksDel (ks);
	PLUGIN_CLOSE ();
}
コード例 #16
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 ();
	}
}
コード例 #17
0
static void test_mmap_unlink (const char * tmpFile)
{
	// test file unlinking by overwriting config file while mapped
	int parentPipe[2];
	int childPipe[2];
	if (pipe (parentPipe) != 0 || pipe (childPipe) != 0)
	{
		yield_error ("pipe() error");
	}

	pid_t pid;
	char buf;
	pid = fork ();

	if (pid == -1)
	{
		yield_error ("fork() error");
		return;
	}
	else if (pid == 0)
	{
		// child: open a config file and leave it mapped
		int devnull = open ("/dev/null", O_RDWR);
		if (devnull == -1) _Exit (EXIT_FAILURE);

		// redirect any communication on standard file descriptors to /dev/null
		close (STDIN_FILENO);
		close (STDOUT_FILENO);
		close (STDERR_FILENO);
		if (dup (devnull) == -1) _Exit (EXIT_FAILURE);
		if (dup (devnull) == -1) _Exit (EXIT_FAILURE);
		if (dup (devnull) == -1) _Exit (EXIT_FAILURE);
		close (childPipe[0]);
		close (parentPipe[1]);

		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");
		succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

		if (write (childPipe[1], "a", 1) != 1) _Exit (EXIT_FAILURE); // signal parent that we are ready
		close (childPipe[1]);
		if (read (parentPipe[0], &buf, 1) != 1) _Exit (EXIT_FAILURE); // wait for parent
		close (parentPipe[0]);

		KeySet * expected = simpleTestKeySet ();
		compare_keyset (expected, ks);
		compare_keyset (ks, expected);
		ksDel (expected);
		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();

		_Exit (EXIT_SUCCESS);
	}
	else
	{
		// parent: try and destroy the file that the child has mapped
		close (childPipe[1]);
		close (parentPipe[0]);
		if (read (childPipe[0], &buf, 1) != 1) _Exit (EXIT_FAILURE); // wait for child
		close (childPipe[0]);

		Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END);
		KeySet * conf = ksNew (0, KS_END);
		PLUGIN_OPEN ("mmapstorage");

		KeySet * ks = metaTestKeySet ();
		succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
		if (write (parentPipe[1], "a", 1) != 1) _Exit (EXIT_FAILURE); // signal child that we are done
		close (parentPipe[1]);

		int status;
		waitpid (pid, &status, 0);
		if (status != 0) yield_error ("child process did not exit successfully.");

		keyDel (parentKey);
		ksDel (ks);
		PLUGIN_CLOSE ();
	}
}
コード例 #18
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 ();
	}
}