On 04/11/2014 12:21 AM, Eric Blake wrote:
I realized that we had no good test coverage of looking up a
name from within a backing chain, even though code like
block-commit is relying on it.
* tests/virstoragetest.c (testStorageLookup): New function.
(mymain): New tests.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
tests/virstoragetest.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
index 029561c..2f181a2 100644
--- a/tests/virstoragetest.c
+++ b/tests/virstoragetest.c
@@ -378,12 +378,81 @@ testStorageChain(const void *args)
return ret;
}
+struct testLookupData
+{
+ virStorageFileMetadataPtr chain;
+ const char *start;
+ const char *name;
+ const char *expResult;
+ virStorageFileMetadataPtr expMeta;
+ const char *expParent;
+};
+
+static int
+testStorageLookup(const void *args)
+{
+ const struct testLookupData *data = args;
+ int ret = 0;
+ const char *actualResult;
+ virStorageFileMetadataPtr actualMeta;
+ const char *actualParent;
+
+ /* This function is documented as giving results within chain, but
+ * as the same string may be duplicated into more than one field,
+ * we rely on STREQ rather than pointer equality. Test twice to
+ * ensure optional parameters don't cause NULL deref. */
+ actualResult = virStorageFileChainLookup(data->chain, data->start,
+ data->name, NULL, NULL);
+
+ if (!data->expResult) {
+ if (!virGetLastError()) {
+ fprintf(stderr, "call should have failed\n");
+ ret = -1;
+ }
+ virResetLastError();
+ } else {
+ if (virGetLastError()) {
+ fprintf(stderr, "call should not have warned\n");
+ ret = -1;
Should ResetLast be called here? So as to not generate future false
positive/failure scenario. Only when running the test directly (e.g.
not via make check or make -C tests ...) with VIR_TEST_DEBUG (or
VERBOSE) did I see the error messages printed (for 0, 8, 16, & 21)
+ }
+ }
+
+ if (STRNEQ_NULLABLE(data->expResult, actualResult)) {
+ fprintf(stderr, "result 1: expected %s, got %s\n",
+ NULLSTR(data->expResult), NULLSTR(actualResult));
+ ret = -1;
+ }
+
+ actualResult = virStorageFileChainLookup(data->chain, data->start,
+ data->name, &actualMeta,
+ &actualParent);
So no LastError checking/clearing here? Just checking... I haven't
followed all the functionality changes before this that closely.
+ if (STRNEQ_NULLABLE(data->expResult, actualResult)) {
+ fprintf(stderr, "result 2: expected %s, got %s\n",
+ NULLSTR(data->expResult), NULLSTR(actualResult));
+ ret = -1;
+ }
+ if (data->expMeta != actualMeta) {
+ fprintf(stderr, "meta: expected %p, got %p\n",
+ data->expMeta, actualMeta);
+ ret = -1;
+ }
+ if (STRNEQ_NULLABLE(data->expParent, actualParent)) {
+ fprintf(stderr, "parent: expected %s, got %s\n",
+ NULLSTR(data->expParent), NULLSTR(actualParent));
+ ret = -1;
+ }
+
+ return ret;
+}
+
static int
mymain(void)
{
int ret;
virCommandPtr cmd = NULL;
struct testChainData data;
+ virStorageFileMetadataPtr chain = NULL;
+ const char *start = NULL;
/* Prep some files with qemu-img; if that is not found on PATH, or
* if it lacks support for qcow2 and qed, skip this test. */
@@ -771,7 +840,105 @@ mymain(void)
(&wrap, &qcow2), EXP_WARN,
(&wrap, &qcow2), ALLOW_PROBE | EXP_WARN);
+ /* Rewrite wrap and qcow2 back to 3-deep chain, absolute backing */
+ virCommandFree(cmd);
+ cmd = virCommandNewArgList(qemuimg, "rebase", "-u",
"-f", "qcow2",
+ "-F", "qcow2", "-b",
absraw, "qcow2", NULL);
+ if (virCommandRun(cmd, NULL) < 0)
+ ret = -1;
+
+ /* Test behavior of chain lookups, absolute backing */
+ start = "wrap";
+ chain = virStorageFileGetMetadata("wrap", VIR_STORAGE_FILE_QCOW2,
+ -1, -1, false);
+ if (!chain)
+ return EXIT_FAILURE;
Whether it matters or not cmd is leaked...
+
+#define TEST_LOOKUP(id, name, result, meta, parent) \
+ do { \
+ struct testLookupData data2 = { chain, start, name, \
+ result, meta, parent, }; \
+ if (virtTestRun("Chain lookup " #id, \
+ testStorageLookup, &data2) < 0) \
+ ret = -1; \
+ } while (0)
+
+ TEST_LOOKUP(0, "bogus", NULL, NULL, NULL);
+ TEST_LOOKUP(1, "wrap", start, chain, NULL);
+ TEST_LOOKUP(2, abswrap, start, chain, NULL);
+ TEST_LOOKUP(3, "qcow2", chain->backingStore, chain->backingMeta,
start);
+ TEST_LOOKUP(4, absqcow2, chain->backingStore, chain->backingMeta, start);
+ TEST_LOOKUP(5, "raw", chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(6, absraw, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(7, NULL, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+
+ /* Rewrite wrap and qcow2 back to 3-deep chain, relative backing */
+ virCommandFree(cmd);
+ cmd = virCommandNewArgList(qemuimg, "rebase", "-u",
"-f", "qcow2",
+ "-F", "raw", "-b",
"raw", "qcow2", NULL);
+ if (virCommandRun(cmd, NULL) < 0)
+ ret = -1;
+
+ virCommandFree(cmd);
+ cmd = virCommandNewArgList(qemuimg, "rebase", "-u",
"-f", "qcow2",
+ "-F", "qcow2", "-b",
"qcow2", "wrap", NULL);
+ if (virCommandRun(cmd, NULL) < 0)
+ ret = -1;
+
+ /* Test behavior of chain lookups, relative backing */
+ start = abswrap;
+ virStorageFileFreeMetadata(chain);
+ chain = virStorageFileGetMetadata(abswrap, VIR_STORAGE_FILE_QCOW2,
+ -1, -1, false);
+ if (!chain)
+ return EXIT_FAILURE;
Whether it matters or not cmd is leaked...
+
+ TEST_LOOKUP(8, "bogus", NULL, NULL, NULL);
+ TEST_LOOKUP(9, "wrap", start, chain, NULL);
+ TEST_LOOKUP(10, abswrap, start, chain, NULL);
+ TEST_LOOKUP(11, "qcow2", chain->backingStore, chain->backingMeta,
start);
+ TEST_LOOKUP(12, absqcow2, chain->backingStore, chain->backingMeta, start);
+ TEST_LOOKUP(13, "raw", chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(14, absraw, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(15, NULL, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+
+ /* Use link to wrap with cross-directory relative backing */
+ virCommandFree(cmd);
+ cmd = virCommandNewArgList(qemuimg, "rebase", "-u",
"-f", "qcow2",
+ "-F", "qcow2", "-b",
"../qcow2", "wrap", NULL);
+ if (virCommandRun(cmd, NULL) < 0)
+ ret = -1;
+
+ /* Test behavior of chain lookups, relative backing */
+ start = "sub/link2";
+ virStorageFileFreeMetadata(chain);
+ chain = virStorageFileGetMetadata(start, VIR_STORAGE_FILE_QCOW2,
+ -1, -1, false);
+ if (!chain)
+ return EXIT_FAILURE;
+
+ TEST_LOOKUP(16, "bogus", NULL, NULL, NULL);
+ TEST_LOOKUP(17, "sub/link2", start, chain, NULL);
+ TEST_LOOKUP(18, "wrap", start, chain, NULL);
+ TEST_LOOKUP(19, abswrap, start, chain, NULL);
+ TEST_LOOKUP(20, "../qcow2", chain->backingStore, chain->backingMeta,
start);
+ TEST_LOOKUP(21, "qcow2", chain->backingStore, chain->backingMeta,
start);
+ TEST_LOOKUP(22, absqcow2, chain->backingStore, chain->backingMeta, start);
+ TEST_LOOKUP(23, "raw", chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(24, absraw, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+ TEST_LOOKUP(25, NULL, chain->backingMeta->backingStore,
+ chain->backingMeta->backingMeta, chain->backingStore);
+
/* Final cleanup */
+ virStorageFileFreeMetadata(chain);
testCleanupImages();
virCommandFree(cmd);
ACK - in general
John