Message ID | 1347958919-30380-6-git-send-email-xiawenc@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
Il 18/09/2012 11:01, Wenchao Xia ha scritto: > In this example, user first create two qcow2 images, and then get the > backing file relationship information of them. Then does write and read > sync IO on them. Please use gtest so that this can be easily extensible. Paolo > Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> > --- > tests/libqblock/libqblock-test.c | 233 ++++++++++++++++++++++++++++++++++++++ > 1 files changed, 233 insertions(+), 0 deletions(-) > > diff --git a/tests/libqblock/libqblock-test.c b/tests/libqblock/libqblock-test.c > index c05c0c4..c0b7963 100644 > --- a/tests/libqblock/libqblock-test.c > +++ b/tests/libqblock/libqblock-test.c > @@ -1,4 +1,237 @@ > +/* > + * QEMU block layer library test > + * > + * Copyright IBM, Corp. 2012 > + * > + * Authors: > + * Wenchao Xia <xiawenc@linux.vnet.ibm.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2 or later. > + * See the COPYING.LIB file in the top-level directory. > + * > + */ > + > +#include <stdarg.h> > +#include <stdio.h> > +#include <unistd.h> > +#include <inttypes.h> > +#include <string.h> > +#include <stdlib.h> > +#include "libqblock.h" > + > +#define TEST_BUF_SIZE 1024 > +static unsigned char buf_r[TEST_BUF_SIZE]; > +static unsigned char buf_w[TEST_BUF_SIZE] = {0, 0, 0, 0}; > + > +typedef struct VerifyData { > + unsigned char *buf_r; > + unsigned char *buf_w; > + int len; > +} VerifyData; > + > +static void print_loc(QBlockProtInfo *loc) > +{ > + if (loc == NULL) { > + printf("backing file is NULL."); > + return; > + } > + switch (loc->prot_type) { > + case QB_PROT_NONE: > + printf("protocol type [none]."); > + break; > + case QB_PROT_FILE: > + printf("protocol type [file], filename [%s].", > + loc->prot_op.o_file.filename); > + break; > + default: > + printf("protocol type not supported."); > + break; > + } > +} > + > +static void print_info_image_static(QBlockStaticInfo *info) > +{ > + printf("=======image location:\n"); > + print_loc(&info->loc); > + printf("\nvirtual_size %" PRId64 ", format type %d [%s]", > + *(info->member_addr->virt_size), > + info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type)); > + printf("\nbacking image location:\n"); > + print_loc(info->member_addr->backing_loc); > + printf("\n"); > +} > + > +static void test_check(VerifyData *vdata) > +{ > + int cmp; > + cmp = memcmp(vdata->buf_r, vdata->buf_w, vdata->len); > + if (cmp == 0) { > + printf("compare succeed, %d.\n", vdata->buf_r[24]); > + } else { > + printf("!!! compare fail, %d.\n", vdata->buf_r[24]); > + exit(1); > + } > +} > + > int main(int argc, char **argv) > { > + const char *filename1, *filename2; > + QBroker *broker = NULL; > + QBlockState *qbs = NULL; > + QBlockProtInfo *ol = NULL; > + QBlockFmtInfo *of = NULL; > + QBlockStaticInfo *info_st = NULL; > + int ret, flag; > + int test_offset = 510; > + int test_len = 520; > + VerifyData vdata; > + char err_str[1024]; > + > + vdata.buf_r = buf_r; > + vdata.buf_w = buf_w; > + vdata.len = test_len; > + > + filename1 = "./qemu_image1"; > + filename2 = "./qemu_image2"; > + printf("qemu test, filename1 is %s, filename2 is %s.\n", > + filename1, filename2); > + > + ret = qb_broker_new(&broker); > + if (ret < 0) { > + goto free; > + } > + > + ret = qb_state_new(broker, &qbs); > + if (ret < 0) { > + goto free; > + } > + > + ret = qb_prot_info_new(broker, &ol); > + if (ret < 0) { > + goto free; > + } > + > + ret = qb_fmt_info_new(broker, &of); > + if (ret < 0) { > + goto free; > + } > + > + /* create a new image */ > + > + ol->prot_type = QB_PROT_FILE; > + ol->prot_op.o_file.filename = filename2; > + of->fmt_type = QB_FMT_QCOW2; > + of->fmt_op.o_qcow2.virt_size = 100 * 1024; > + flag = 0; > + > + ret = qb_create(broker, qbs, ol, of, flag); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("create fail 1. %s.\n", err_str); > + goto unlink; > + } > + > + ol->prot_type = QB_PROT_FILE; > + ol->prot_op.o_file.filename = filename1; > + of->fmt_type = QB_FMT_QCOW2; > + of->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE; > + of->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename = filename2; > + flag = 0; > + ret = qb_create(broker, qbs, ol, of, flag); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("create fail 2. %s.\n", err_str); > + goto unlink; > + } > + > + /* get informations */ > + ol->prot_type = QB_PROT_FILE; > + ol->prot_op.o_file.filename = filename1; > + of->fmt_type = QB_FMT_NONE; > + flag = LIBQBLOCK_O_NO_BACKING; > + ret = qb_open(broker, qbs, ol, of, flag); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("info getting, open failed. %s.\n", err_str); > + goto free; > + } > + > + while (1) { > + ret = qb_info_image_static_get(broker, qbs, &info_st); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("info get error. %s.\n", err_str); > + goto close; > + } > + print_info_image_static(info_st); > + qb_close(broker, qbs); > + if ((info_st->member_addr->backing_loc == NULL) || > + (info_st->member_addr->backing_loc->prot_type == QB_FMT_NONE)) { > + break; > + } > + *ol = *(info_st->member_addr->backing_loc); > + ret = qb_open(broker, qbs, ol, of, flag); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("info getting, open failed in backing file. %s.\n", > + err_str); > + goto free; > + } > + qb_info_image_static_delete(broker, &info_st); > + } > + /* read and write the image */ > + ol->prot_type = QB_PROT_FILE; > + ol->prot_op.o_file.filename = filename1; > + of->fmt_type = QB_FMT_NONE; > + flag = LIBQBLOCK_O_RDWR; > + ret = qb_open(broker, qbs, ol, of, flag); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("open failed. %s.\n", err_str); > + goto free; > + } > + > + buf_w[1] = 1; > + buf_w[2] = 2; > + buf_w[514] = 4; > + memset(buf_r, 0, sizeof(buf_r)); > + > + ret = qb_write(broker, qbs, buf_w, test_len, test_offset); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("%s.\n", err_str); > + goto close; > + } > + > + ret = qb_read(broker, qbs, buf_r, test_len, test_offset); > + if (ret < 0) { > + qb_error_get_human_str(broker, err_str, sizeof(err_str)); > + printf("%s.\n", err_str); > + goto close; > + } > + > + test_check(&vdata); > + > + close: > + qb_close(broker, qbs); > + unlink: > + unlink(filename1); > + unlink(filename2); > + free: > + if (info_st != NULL) { > + qb_info_image_static_delete(broker, &info_st); > + } > + if (qbs != NULL) { > + qb_state_delete(broker, &qbs); > + } > + if (ol != NULL) { > + qb_prot_info_delete(broker, &ol); > + } > + if (of != NULL) { > + qb_fmt_info_delete(broker, &of); > + } > + if (broker != NULL) { > + qb_broker_delete(&broker); > + } > return 0; > } >
δΊ 2012-9-18 18:10, Paolo Bonzini ει: > Il 18/09/2012 11:01, Wenchao Xia ha scritto: >> In this example, user first create two qcow2 images, and then get the >> backing file relationship information of them. Then does write and read >> sync IO on them. > > Please use gtest so that this can be easily extensible. > > Paolo > OK. >> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> >> --- >> tests/libqblock/libqblock-test.c | 233 ++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 233 insertions(+), 0 deletions(-) >> >> diff --git a/tests/libqblock/libqblock-test.c b/tests/libqblock/libqblock-test.c >> index c05c0c4..c0b7963 100644 >> --- a/tests/libqblock/libqblock-test.c >> +++ b/tests/libqblock/libqblock-test.c >> @@ -1,4 +1,237 @@ >> +/* >> + * QEMU block layer library test >> + * >> + * Copyright IBM, Corp. 2012 >> + * >> + * Authors: >> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com> >> + * >> + * This work is licensed under the terms of the GNU LGPL, version 2 or later. >> + * See the COPYING.LIB file in the top-level directory. >> + * >> + */ >> + >> +#include <stdarg.h> >> +#include <stdio.h> >> +#include <unistd.h> >> +#include <inttypes.h> >> +#include <string.h> >> +#include <stdlib.h> >> +#include "libqblock.h" >> + >> +#define TEST_BUF_SIZE 1024 >> +static unsigned char buf_r[TEST_BUF_SIZE]; >> +static unsigned char buf_w[TEST_BUF_SIZE] = {0, 0, 0, 0}; >> + >> +typedef struct VerifyData { >> + unsigned char *buf_r; >> + unsigned char *buf_w; >> + int len; >> +} VerifyData; >> + >> +static void print_loc(QBlockProtInfo *loc) >> +{ >> + if (loc == NULL) { >> + printf("backing file is NULL."); >> + return; >> + } >> + switch (loc->prot_type) { >> + case QB_PROT_NONE: >> + printf("protocol type [none]."); >> + break; >> + case QB_PROT_FILE: >> + printf("protocol type [file], filename [%s].", >> + loc->prot_op.o_file.filename); >> + break; >> + default: >> + printf("protocol type not supported."); >> + break; >> + } >> +} >> + >> +static void print_info_image_static(QBlockStaticInfo *info) >> +{ >> + printf("=======image location:\n"); >> + print_loc(&info->loc); >> + printf("\nvirtual_size %" PRId64 ", format type %d [%s]", >> + *(info->member_addr->virt_size), >> + info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type)); >> + printf("\nbacking image location:\n"); >> + print_loc(info->member_addr->backing_loc); >> + printf("\n"); >> +} >> + >> +static void test_check(VerifyData *vdata) >> +{ >> + int cmp; >> + cmp = memcmp(vdata->buf_r, vdata->buf_w, vdata->len); >> + if (cmp == 0) { >> + printf("compare succeed, %d.\n", vdata->buf_r[24]); >> + } else { >> + printf("!!! compare fail, %d.\n", vdata->buf_r[24]); >> + exit(1); >> + } >> +} >> + >> int main(int argc, char **argv) >> { >> + const char *filename1, *filename2; >> + QBroker *broker = NULL; >> + QBlockState *qbs = NULL; >> + QBlockProtInfo *ol = NULL; >> + QBlockFmtInfo *of = NULL; >> + QBlockStaticInfo *info_st = NULL; >> + int ret, flag; >> + int test_offset = 510; >> + int test_len = 520; >> + VerifyData vdata; >> + char err_str[1024]; >> + >> + vdata.buf_r = buf_r; >> + vdata.buf_w = buf_w; >> + vdata.len = test_len; >> + >> + filename1 = "./qemu_image1"; >> + filename2 = "./qemu_image2"; >> + printf("qemu test, filename1 is %s, filename2 is %s.\n", >> + filename1, filename2); >> + >> + ret = qb_broker_new(&broker); >> + if (ret < 0) { >> + goto free; >> + } >> + >> + ret = qb_state_new(broker, &qbs); >> + if (ret < 0) { >> + goto free; >> + } >> + >> + ret = qb_prot_info_new(broker, &ol); >> + if (ret < 0) { >> + goto free; >> + } >> + >> + ret = qb_fmt_info_new(broker, &of); >> + if (ret < 0) { >> + goto free; >> + } >> + >> + /* create a new image */ >> + >> + ol->prot_type = QB_PROT_FILE; >> + ol->prot_op.o_file.filename = filename2; >> + of->fmt_type = QB_FMT_QCOW2; >> + of->fmt_op.o_qcow2.virt_size = 100 * 1024; >> + flag = 0; >> + >> + ret = qb_create(broker, qbs, ol, of, flag); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("create fail 1. %s.\n", err_str); >> + goto unlink; >> + } >> + >> + ol->prot_type = QB_PROT_FILE; >> + ol->prot_op.o_file.filename = filename1; >> + of->fmt_type = QB_FMT_QCOW2; >> + of->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE; >> + of->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename = filename2; >> + flag = 0; >> + ret = qb_create(broker, qbs, ol, of, flag); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("create fail 2. %s.\n", err_str); >> + goto unlink; >> + } >> + >> + /* get informations */ >> + ol->prot_type = QB_PROT_FILE; >> + ol->prot_op.o_file.filename = filename1; >> + of->fmt_type = QB_FMT_NONE; >> + flag = LIBQBLOCK_O_NO_BACKING; >> + ret = qb_open(broker, qbs, ol, of, flag); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("info getting, open failed. %s.\n", err_str); >> + goto free; >> + } >> + >> + while (1) { >> + ret = qb_info_image_static_get(broker, qbs, &info_st); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("info get error. %s.\n", err_str); >> + goto close; >> + } >> + print_info_image_static(info_st); >> + qb_close(broker, qbs); >> + if ((info_st->member_addr->backing_loc == NULL) || >> + (info_st->member_addr->backing_loc->prot_type == QB_FMT_NONE)) { >> + break; >> + } >> + *ol = *(info_st->member_addr->backing_loc); >> + ret = qb_open(broker, qbs, ol, of, flag); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("info getting, open failed in backing file. %s.\n", >> + err_str); >> + goto free; >> + } >> + qb_info_image_static_delete(broker, &info_st); >> + } >> + /* read and write the image */ >> + ol->prot_type = QB_PROT_FILE; >> + ol->prot_op.o_file.filename = filename1; >> + of->fmt_type = QB_FMT_NONE; >> + flag = LIBQBLOCK_O_RDWR; >> + ret = qb_open(broker, qbs, ol, of, flag); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("open failed. %s.\n", err_str); >> + goto free; >> + } >> + >> + buf_w[1] = 1; >> + buf_w[2] = 2; >> + buf_w[514] = 4; >> + memset(buf_r, 0, sizeof(buf_r)); >> + >> + ret = qb_write(broker, qbs, buf_w, test_len, test_offset); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("%s.\n", err_str); >> + goto close; >> + } >> + >> + ret = qb_read(broker, qbs, buf_r, test_len, test_offset); >> + if (ret < 0) { >> + qb_error_get_human_str(broker, err_str, sizeof(err_str)); >> + printf("%s.\n", err_str); >> + goto close; >> + } >> + >> + test_check(&vdata); >> + >> + close: >> + qb_close(broker, qbs); >> + unlink: >> + unlink(filename1); >> + unlink(filename2); >> + free: >> + if (info_st != NULL) { >> + qb_info_image_static_delete(broker, &info_st); >> + } >> + if (qbs != NULL) { >> + qb_state_delete(broker, &qbs); >> + } >> + if (ol != NULL) { >> + qb_prot_info_delete(broker, &ol); >> + } >> + if (of != NULL) { >> + qb_fmt_info_delete(broker, &of); >> + } >> + if (broker != NULL) { >> + qb_broker_delete(&broker); >> + } >> return 0; >> } >> > >
diff --git a/tests/libqblock/libqblock-test.c b/tests/libqblock/libqblock-test.c index c05c0c4..c0b7963 100644 --- a/tests/libqblock/libqblock-test.c +++ b/tests/libqblock/libqblock-test.c @@ -1,4 +1,237 @@ +/* + * QEMU block layer library test + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Wenchao Xia <xiawenc@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> +#include <inttypes.h> +#include <string.h> +#include <stdlib.h> +#include "libqblock.h" + +#define TEST_BUF_SIZE 1024 +static unsigned char buf_r[TEST_BUF_SIZE]; +static unsigned char buf_w[TEST_BUF_SIZE] = {0, 0, 0, 0}; + +typedef struct VerifyData { + unsigned char *buf_r; + unsigned char *buf_w; + int len; +} VerifyData; + +static void print_loc(QBlockProtInfo *loc) +{ + if (loc == NULL) { + printf("backing file is NULL."); + return; + } + switch (loc->prot_type) { + case QB_PROT_NONE: + printf("protocol type [none]."); + break; + case QB_PROT_FILE: + printf("protocol type [file], filename [%s].", + loc->prot_op.o_file.filename); + break; + default: + printf("protocol type not supported."); + break; + } +} + +static void print_info_image_static(QBlockStaticInfo *info) +{ + printf("=======image location:\n"); + print_loc(&info->loc); + printf("\nvirtual_size %" PRId64 ", format type %d [%s]", + *(info->member_addr->virt_size), + info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type)); + printf("\nbacking image location:\n"); + print_loc(info->member_addr->backing_loc); + printf("\n"); +} + +static void test_check(VerifyData *vdata) +{ + int cmp; + cmp = memcmp(vdata->buf_r, vdata->buf_w, vdata->len); + if (cmp == 0) { + printf("compare succeed, %d.\n", vdata->buf_r[24]); + } else { + printf("!!! compare fail, %d.\n", vdata->buf_r[24]); + exit(1); + } +} + int main(int argc, char **argv) { + const char *filename1, *filename2; + QBroker *broker = NULL; + QBlockState *qbs = NULL; + QBlockProtInfo *ol = NULL; + QBlockFmtInfo *of = NULL; + QBlockStaticInfo *info_st = NULL; + int ret, flag; + int test_offset = 510; + int test_len = 520; + VerifyData vdata; + char err_str[1024]; + + vdata.buf_r = buf_r; + vdata.buf_w = buf_w; + vdata.len = test_len; + + filename1 = "./qemu_image1"; + filename2 = "./qemu_image2"; + printf("qemu test, filename1 is %s, filename2 is %s.\n", + filename1, filename2); + + ret = qb_broker_new(&broker); + if (ret < 0) { + goto free; + } + + ret = qb_state_new(broker, &qbs); + if (ret < 0) { + goto free; + } + + ret = qb_prot_info_new(broker, &ol); + if (ret < 0) { + goto free; + } + + ret = qb_fmt_info_new(broker, &of); + if (ret < 0) { + goto free; + } + + /* create a new image */ + + ol->prot_type = QB_PROT_FILE; + ol->prot_op.o_file.filename = filename2; + of->fmt_type = QB_FMT_QCOW2; + of->fmt_op.o_qcow2.virt_size = 100 * 1024; + flag = 0; + + ret = qb_create(broker, qbs, ol, of, flag); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("create fail 1. %s.\n", err_str); + goto unlink; + } + + ol->prot_type = QB_PROT_FILE; + ol->prot_op.o_file.filename = filename1; + of->fmt_type = QB_FMT_QCOW2; + of->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE; + of->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename = filename2; + flag = 0; + ret = qb_create(broker, qbs, ol, of, flag); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("create fail 2. %s.\n", err_str); + goto unlink; + } + + /* get informations */ + ol->prot_type = QB_PROT_FILE; + ol->prot_op.o_file.filename = filename1; + of->fmt_type = QB_FMT_NONE; + flag = LIBQBLOCK_O_NO_BACKING; + ret = qb_open(broker, qbs, ol, of, flag); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("info getting, open failed. %s.\n", err_str); + goto free; + } + + while (1) { + ret = qb_info_image_static_get(broker, qbs, &info_st); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("info get error. %s.\n", err_str); + goto close; + } + print_info_image_static(info_st); + qb_close(broker, qbs); + if ((info_st->member_addr->backing_loc == NULL) || + (info_st->member_addr->backing_loc->prot_type == QB_FMT_NONE)) { + break; + } + *ol = *(info_st->member_addr->backing_loc); + ret = qb_open(broker, qbs, ol, of, flag); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("info getting, open failed in backing file. %s.\n", + err_str); + goto free; + } + qb_info_image_static_delete(broker, &info_st); + } + /* read and write the image */ + ol->prot_type = QB_PROT_FILE; + ol->prot_op.o_file.filename = filename1; + of->fmt_type = QB_FMT_NONE; + flag = LIBQBLOCK_O_RDWR; + ret = qb_open(broker, qbs, ol, of, flag); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("open failed. %s.\n", err_str); + goto free; + } + + buf_w[1] = 1; + buf_w[2] = 2; + buf_w[514] = 4; + memset(buf_r, 0, sizeof(buf_r)); + + ret = qb_write(broker, qbs, buf_w, test_len, test_offset); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("%s.\n", err_str); + goto close; + } + + ret = qb_read(broker, qbs, buf_r, test_len, test_offset); + if (ret < 0) { + qb_error_get_human_str(broker, err_str, sizeof(err_str)); + printf("%s.\n", err_str); + goto close; + } + + test_check(&vdata); + + close: + qb_close(broker, qbs); + unlink: + unlink(filename1); + unlink(filename2); + free: + if (info_st != NULL) { + qb_info_image_static_delete(broker, &info_st); + } + if (qbs != NULL) { + qb_state_delete(broker, &qbs); + } + if (ol != NULL) { + qb_prot_info_delete(broker, &ol); + } + if (of != NULL) { + qb_fmt_info_delete(broker, &of); + } + if (broker != NULL) { + qb_broker_delete(&broker); + } return 0; }
In this example, user first create two qcow2 images, and then get the backing file relationship information of them. Then does write and read sync IO on them. Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> --- tests/libqblock/libqblock-test.c | 233 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 233 insertions(+), 0 deletions(-)