提交 d1a1d841 编写于 作者: E Eric Blake

tests: refactor virstoragetest for less stack space

I'm about to add fields to virStorageFileMetadata, which means
also adding fields to the testFileData struct in virstoragetest.
Alas, adding even one pointer on an x86_64 machine gave me a
dreaded compiler error:

virstoragetest.c:712:1: error: the frame size of 4208 bytes is larger than 4096 bytes [-Werror=frame-larger-than=]

After some experimentation, I realized that each test was creating
yet another testChainData (which contains testFileData) on the stack;
forcing the reuse of one of these structures instead of creating a
fresh one each time drastically reduces the size requirements.  While
at it, I also got rid of a lot of intermediate structs, with some
macro magic that lets me directly build up the destination chains
inline.

For a bit more insight into what this patch does:
The old code uses an intermediate variable as a fixed-size array
of structs:
testFileData chain[] = { a, b };
data.files = chain;

In the new code, the use of VIR_FLATTEN_* allows the TEST_CHAIN()
macro to still take a single argument for each chain, but now of
the form '(a, b)', where it is turned into the var-args 'a, b'
multiple arguments understood by TEST_ONE_CHAIN().  Thus, the
new code avoids an intermediate variable, and directly provides
the list of pointers to be assigned into array elements:
data.files = { &a, &b };

* tests/virstoragetest.c (mymain): Rewrite TEST_ONE_CHAIN to
reuse the same struct for each test, and to take the data
inline rather than via intermediate variables.
(testChainData): Use bounded array of pointers instead of
unlimited array of struct.
(testStorageChain): Reflect struct change.
Signed-off-by: NEric Blake <eblake@redhat.com>
上级 7da61b30
......@@ -218,7 +218,7 @@ struct testChainData
{
const char *start;
enum virStorageFileFormat format;
const testFileData *files;
const testFileData *files[5];
int nfiles;
unsigned int flags;
};
......@@ -267,13 +267,13 @@ testStorageChain(const void *args)
if (virAsprintf(&expect,
"store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d",
NULLSTR(data->files[i].expBackingStore),
NULLSTR(data->files[i].expBackingStoreRaw),
NULLSTR(data->files[i].expDirectory),
data->files[i].expFormat,
data->files[i].expIsFile,
data->files[i].expCapacity,
data->files[i].expEncrypted) < 0 ||
NULLSTR(data->files[i]->expBackingStore),
NULLSTR(data->files[i]->expBackingStoreRaw),
NULLSTR(data->files[i]->expDirectory),
data->files[i]->expFormat,
data->files[i]->expIsFile,
data->files[i]->expCapacity,
data->files[i]->expEncrypted) < 0 ||
virAsprintf(&actual,
"store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d",
NULLSTR(elt->backingStore),
......@@ -312,29 +312,42 @@ mymain(void)
{
int ret;
virCommandPtr cmd = NULL;
struct testChainData data;
/* 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. */
if ((ret = testPrepImages()) != 0)
return ret;
#define TEST_ONE_CHAIN(id, start, format, chain, flags) \
#define TEST_ONE_CHAIN(id, start, format, flags, ...) \
do { \
struct testChainData data = { \
start, format, chain, ARRAY_CARDINALITY(chain), flags, \
size_t i; \
memset(&data, 0, sizeof(data)); \
data = (struct testChainData){ \
start, format, { __VA_ARGS__ }, 0, flags, \
}; \
for (i = 0; i < ARRAY_CARDINALITY(data.files); i++) \
if (data.files[i]) \
data.nfiles++; \
if (virtTestRun("Storage backing chain " id, \
testStorageChain, &data) < 0) \
ret = -1; \
} while (0)
#define VIR_FLATTEN_2(...) __VA_ARGS__
#define VIR_FLATTEN_1(_1) VIR_FLATTEN_2 _1
#define TEST_CHAIN(id, relstart, absstart, format, chain1, flags1, \
chain2, flags2, chain3, flags3, chain4, flags4) \
do { \
TEST_ONE_CHAIN(#id "a", relstart, format, chain1, flags1); \
TEST_ONE_CHAIN(#id "b", relstart, format, chain2, flags2); \
TEST_ONE_CHAIN(#id "c", absstart, format, chain3, flags3); \
TEST_ONE_CHAIN(#id "d", absstart, format, chain4, flags4); \
TEST_ONE_CHAIN(#id "a", relstart, format, flags1, \
VIR_FLATTEN_1(chain1)); \
TEST_ONE_CHAIN(#id "b", relstart, format, flags2, \
VIR_FLATTEN_1(chain2)); \
TEST_ONE_CHAIN(#id "c", absstart, format, flags3, \
VIR_FLATTEN_1(chain3)); \
TEST_ONE_CHAIN(#id "d", absstart, format, flags4, \
VIR_FLATTEN_1(chain4)); \
} while (0)
/* Expected details about files in chains */
......@@ -454,36 +467,31 @@ mymain(void)
/* The actual tests, in several groups. */
/* Missing file */
const testFileData chain0[] = { };
TEST_ONE_CHAIN("0", "bogus", VIR_STORAGE_FILE_RAW, chain0, EXP_FAIL);
TEST_ONE_CHAIN("0", "bogus", VIR_STORAGE_FILE_RAW, EXP_FAIL);
/* Raw image, whether with right format or no specified format */
const testFileData chain1[] = { raw };
TEST_CHAIN(1, "raw", absraw, VIR_STORAGE_FILE_RAW,
chain1, EXP_PASS,
chain1, ALLOW_PROBE | EXP_PASS,
chain1, EXP_PASS,
chain1, ALLOW_PROBE | EXP_PASS);
(&raw), EXP_PASS,
(&raw), ALLOW_PROBE | EXP_PASS,
(&raw), EXP_PASS,
(&raw), ALLOW_PROBE | EXP_PASS);
TEST_CHAIN(2, "raw", absraw, VIR_STORAGE_FILE_AUTO,
chain1, EXP_PASS,
chain1, ALLOW_PROBE | EXP_PASS,
chain1, EXP_PASS,
chain1, ALLOW_PROBE | EXP_PASS);
(&raw), EXP_PASS,
(&raw), ALLOW_PROBE | EXP_PASS,
(&raw), EXP_PASS,
(&raw), ALLOW_PROBE | EXP_PASS);
/* Qcow2 file with relative raw backing, format provided */
const testFileData chain3a[] = { qcow2_relback_relstart, raw };
const testFileData chain3c[] = { qcow2_relback_absstart, raw };
const testFileData chain4a[] = { raw };
TEST_CHAIN(3, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
chain3a, EXP_PASS,
chain3a, ALLOW_PROBE | EXP_PASS,
chain3c, EXP_PASS,
chain3c, ALLOW_PROBE | EXP_PASS);
(&qcow2_relback_relstart, &raw), EXP_PASS,
(&qcow2_relback_relstart, &raw), ALLOW_PROBE | EXP_PASS,
(&qcow2_relback_absstart, &raw), EXP_PASS,
(&qcow2_relback_absstart, &raw), ALLOW_PROBE | EXP_PASS);
TEST_CHAIN(4, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
chain4a, EXP_PASS,
chain3a, ALLOW_PROBE | EXP_PASS,
chain4a, EXP_PASS,
chain3c, ALLOW_PROBE | EXP_PASS);
(&raw), EXP_PASS,
(&qcow2_relback_relstart, &raw), ALLOW_PROBE | EXP_PASS,
(&raw), EXP_PASS,
(&qcow2_relback_absstart, &raw), ALLOW_PROBE | EXP_PASS);
/* Rewrite qcow2 file to use absolute backing name */
virCommandFree(cmd);
......@@ -493,26 +501,23 @@ mymain(void)
ret = -1;
/* Qcow2 file with raw as absolute backing, backing format provided */
const testFileData chain5[] = { qcow2_absback, raw };
const testFileData chain6[] = { raw };
TEST_CHAIN(5, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
chain5, EXP_PASS,
chain5, ALLOW_PROBE | EXP_PASS,
chain5, EXP_PASS,
chain5, ALLOW_PROBE | EXP_PASS);
(&qcow2_absback, &raw), EXP_PASS,
(&qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS,
(&qcow2_absback, &raw), EXP_PASS,
(&qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS);
TEST_CHAIN(6, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
chain6, EXP_PASS,
chain5, ALLOW_PROBE | EXP_PASS,
chain6, EXP_PASS,
chain5, ALLOW_PROBE | EXP_PASS);
(&raw), EXP_PASS,
(&qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS,
(&raw), EXP_PASS,
(&qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS);
/* Wrapped file access */
const testFileData chain7[] = { wrap, qcow2_absback, raw };
TEST_CHAIN(7, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
chain7, EXP_PASS,
chain7, ALLOW_PROBE | EXP_PASS,
chain7, EXP_PASS,
chain7, ALLOW_PROBE | EXP_PASS);
(&wrap, &qcow2_absback, &raw), EXP_PASS,
(&wrap, &qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS,
(&wrap, &qcow2_absback, &raw), EXP_PASS,
(&wrap, &qcow2_absback, &raw), ALLOW_PROBE | EXP_PASS);
/* Rewrite qcow2 and wrap file to omit backing file type */
virCommandFree(cmd);
......@@ -528,13 +533,11 @@ mymain(void)
ret = -1;
/* Qcow2 file with raw as absolute backing, backing format omitted */
const testFileData chain8a[] = { wrap_as_raw, raw };
const testFileData chain8b[] = { wrap_as_probe, qcow2_as_probe, raw };
TEST_CHAIN(8, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
chain8a, EXP_PASS,
chain8b, ALLOW_PROBE | EXP_PASS,
chain8a, EXP_PASS,
chain8b, ALLOW_PROBE | EXP_PASS);
(&wrap_as_raw, &raw), EXP_PASS,
(&wrap_as_probe, &qcow2_as_probe, &raw), ALLOW_PROBE | EXP_PASS,
(&wrap_as_raw, &raw), EXP_PASS,
(&wrap_as_probe, &qcow2_as_probe, &raw), ALLOW_PROBE | EXP_PASS);
/* Rewrite qcow2 to a missing backing file, with backing type */
virCommandFree(cmd);
......@@ -545,12 +548,11 @@ mymain(void)
ret = -1;
/* Qcow2 file with missing backing file but specified type */
const testFileData chain9[] = { qcow2_bogus };
TEST_CHAIN(9, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
chain9, EXP_WARN,
chain9, ALLOW_PROBE | EXP_WARN,
chain9, EXP_WARN,
chain9, ALLOW_PROBE | EXP_WARN);
(&qcow2_bogus), EXP_WARN,
(&qcow2_bogus), ALLOW_PROBE | EXP_WARN,
(&qcow2_bogus), EXP_WARN,
(&qcow2_bogus), ALLOW_PROBE | EXP_WARN);
/* Rewrite qcow2 to a missing backing file, without backing type */
virCommandFree(cmd);
......@@ -560,12 +562,11 @@ mymain(void)
ret = -1;
/* Qcow2 file with missing backing file and no specified type */
const testFileData chain10[] = { qcow2_bogus };
TEST_CHAIN(10, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
chain10, EXP_WARN,
chain10, ALLOW_PROBE | EXP_WARN,
chain10, EXP_WARN,
chain10, ALLOW_PROBE | EXP_WARN);
(&qcow2_bogus), EXP_WARN,
(&qcow2_bogus), ALLOW_PROBE | EXP_WARN,
(&qcow2_bogus), EXP_WARN,
(&qcow2_bogus), ALLOW_PROBE | EXP_WARN);
/* Rewrite qcow2 to use an nbd: protocol as backend */
virCommandFree(cmd);
......@@ -576,21 +577,18 @@ mymain(void)
ret = -1;
/* Qcow2 file with backing protocol instead of file */
const testFileData chain11[] = { qcow2_protocol };
TEST_CHAIN(11, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
chain11, EXP_PASS,
chain11, ALLOW_PROBE | EXP_PASS,
chain11, EXP_PASS,
chain11, ALLOW_PROBE | EXP_PASS);
(&qcow2_protocol), EXP_PASS,
(&qcow2_protocol), ALLOW_PROBE | EXP_PASS,
(&qcow2_protocol), EXP_PASS,
(&qcow2_protocol), ALLOW_PROBE | EXP_PASS);
/* qed file */
const testFileData chain12a[] = { raw };
const testFileData chain12b[] = { qed, raw };
TEST_CHAIN(12, "qed", absqed, VIR_STORAGE_FILE_AUTO,
chain12a, EXP_PASS,
chain12b, ALLOW_PROBE | EXP_PASS,
chain12a, EXP_PASS,
chain12b, ALLOW_PROBE | EXP_PASS);
(&raw), EXP_PASS,
(&qed, &raw), ALLOW_PROBE | EXP_PASS,
(&raw), EXP_PASS,
(&qed, &raw), ALLOW_PROBE | EXP_PASS);
#ifdef HAVE_SYMLINK
/* Rewrite qcow2 and wrap file to use backing names relative to a
......@@ -609,15 +607,12 @@ mymain(void)
ret = -1;
/* Behavior of symlinks to qcow2 with relative backing files */
const testFileData chain13a[] = { link2_rel, link1_rel, raw };
const testFileData chain13c[] = { link2_abs, link1_abs, raw };
TEST_CHAIN(13, "sub/link2", abslink2, VIR_STORAGE_FILE_QCOW2,
chain13a, EXP_PASS,
chain13a, ALLOW_PROBE | EXP_PASS,
chain13c, EXP_PASS,
chain13c, ALLOW_PROBE | EXP_PASS);
(&link2_rel, &link1_rel, &raw), EXP_PASS,
(&link2_rel, &link1_rel, &raw), ALLOW_PROBE | EXP_PASS,
(&link2_abs, &link1_abs, &raw), EXP_PASS,
(&link2_abs, &link1_abs, &raw), ALLOW_PROBE | EXP_PASS);
#endif
/* Final cleanup */
testCleanupImages();
virCommandFree(cmd);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册