From 7ae106d4340bd755a5ca843a4a356f1a7a61df3c Mon Sep 17 00:00:00 2001 From: Asim R P Date: Tue, 27 Aug 2019 17:21:30 +0530 Subject: [PATCH v1 2/5] Add syntax to declare a step that is expected to block The syntax is (note the "&" suffix): permutation "step_1" "step_2"& "step_3" This is useful for defining steps that are expected to block for reasons other than waiting on a lock. For example, an injected fault may cause a backend to suspend until another event occurs. Isolation tester will move on to execute step_3 without waiting for step_2 to finish, because it is expected to block. I've incorporated review feedback from Alvaro Herrera and Michael Paquier. --- src/test/isolation/isolationtester.c | 31 ++++++++++++++++++------------- src/test/isolation/isolationtester.h | 11 +++++++++-- src/test/isolation/specparse.y | 32 +++++++++++++++++++++++++------- src/test/isolation/specscanner.l | 8 ++++++++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index 556b46d93f..38b6fbdf4e 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -333,7 +333,7 @@ run_named_permutations(TestSpec *testspec) /* Find all the named steps using the lookup table */ for (j = 0; j < p->nsteps; j++) { - Step **this = (Step **) bsearch(p->stepnames[j], + Step **this = (Step **) bsearch(p->steps[j].name, testspec->allsteps, testspec->nallsteps, sizeof(Step *), @@ -342,10 +342,11 @@ run_named_permutations(TestSpec *testspec) if (this == NULL) { fprintf(stderr, "undefined step \"%s\" specified in permutation\n", - p->stepnames[j]); + p->steps[j].name); exit(1); } steps[j] = *this; + steps[j]->blocks = p->steps[j].blocks; } /* And run them */ @@ -714,19 +715,23 @@ try_complete_step(TestSpec *testspec, Step *step, int flags) if (flags & STEP_NONBLOCK) { bool waiting; - - res = PQexecPrepared(conns[0], PREP_WAITING, 1, - &backend_pid_strs[step->session + 1], - NULL, NULL, 0); - if (PQresultStatus(res) != PGRES_TUPLES_OK || - PQntuples(res) != 1) + if (step->blocks) + waiting = true; + else { - fprintf(stderr, "lock wait query failed: %s", - PQerrorMessage(conns[0])); - exit(1); + res = PQexecPrepared(conns[0], PREP_WAITING, 1, + &backend_pid_strs[step->session + 1], + NULL, NULL, 0); + if (PQresultStatus(res) != PGRES_TUPLES_OK || + PQntuples(res) != 1) + { + fprintf(stderr, "lock wait query failed: %s", + PQerrorMessage(conns[0])); + exit(1); + } + waiting = ((PQgetvalue(res, 0, 0))[0] == 't'); + PQclear(res); } - waiting = ((PQgetvalue(res, 0, 0))[0] == 't'); - PQclear(res); if (waiting) /* waiting to acquire a lock */ { diff --git a/src/test/isolation/isolationtester.h b/src/test/isolation/isolationtester.h index d9d2a14ecf..3c49ba81bb 100644 --- a/src/test/isolation/isolationtester.h +++ b/src/test/isolation/isolationtester.h @@ -30,6 +30,7 @@ struct Step { int session; bool used; + bool blocks; char *name; char *sql; char *errormsg; @@ -37,8 +38,14 @@ struct Step typedef struct { - int nsteps; - char **stepnames; + char *name; + bool blocks; +} PermutationStep; + +typedef struct +{ + int nsteps; + PermutationStep *steps; } Permutation; typedef struct diff --git a/src/test/isolation/specparse.y b/src/test/isolation/specparse.y index 2dfe3533ff..35a59a315f 100644 --- a/src/test/isolation/specparse.y +++ b/src/test/isolation/specparse.y @@ -44,8 +44,8 @@ TestSpec parseresult; /* result of parsing is left here */ %type step %type permutation -%token sqlblock string_literal -%token PERMUTATION SESSION SETUP STEP TEARDOWN TEST +%token sqlblock string_literal string_with_blocks +%token BLOCKING PERMUTATION SESSION SETUP STEP TEARDOWN TEST %% @@ -143,6 +143,7 @@ step: STEP string_literal sqlblock { $$ = pg_malloc(sizeof(Step)); + $$->blocks = false; $$->name = $2; $$->sql = $3; $$->used = false; @@ -183,7 +184,7 @@ permutation: PERMUTATION string_literal_list { $$ = pg_malloc(sizeof(Permutation)); - $$->stepnames = (char **) $2.elements; + $$->steps = (PermutationStep *) $2.elements; $$->nsteps = $2.nelements; } ; @@ -192,15 +193,32 @@ string_literal_list: string_literal_list string_literal { $$.elements = pg_realloc($1.elements, - ($1.nelements + 1) * sizeof(void *)); - $$.elements[$1.nelements] = $2; + ($1.nelements + 1) * sizeof(PermutationStep)); + ((PermutationStep *) ($$.elements))[$1.nelements].name = $2; + ((PermutationStep *) ($$.elements))[$1.nelements].blocks = false; $$.nelements = $1.nelements + 1; } | string_literal { $$.nelements = 1; - $$.elements = pg_malloc(sizeof(void *)); - $$.elements[0] = $1; + $$.elements = pg_malloc(sizeof(PermutationStep)); + ((PermutationStep *) ($$.elements))[0].name = $1; + ((PermutationStep *) ($$.elements))[0].blocks = false; + } + | string_literal_list string_with_blocks + { + $$.elements = pg_realloc($1.elements, + ($1.nelements + 1) * sizeof(PermutationStep)); + ((PermutationStep *) ($$.elements))[$1.nelements].name = $2; + ((PermutationStep *) ($$.elements))[$1.nelements].blocks = true; + $$.nelements = $1.nelements + 1; + } + | string_with_blocks + { + $$.nelements = 1; + $$.elements = pg_malloc(sizeof(PermutationStep)); + ((PermutationStep *) ($$.elements))[0].name = $1; + ((PermutationStep *) ($$.elements))[0].blocks = true; } ; diff --git a/src/test/isolation/specscanner.l b/src/test/isolation/specscanner.l index 3924c99294..9a2620c050 100644 --- a/src/test/isolation/specscanner.l +++ b/src/test/isolation/specscanner.l @@ -39,6 +39,8 @@ static void addlitchar(char c); non_newline [^\n\r] space [ \t\r\f] +blocks [&] + comment ("#"{non_newline}*) %% @@ -69,6 +71,12 @@ teardown { return TEARDOWN; } BEGIN(INITIAL); return(string_literal); } +\"{blocks} { + litbuf[litbufpos] = '\0'; + yylval.str = pg_strdup(litbuf); + BEGIN(INITIAL); + return(string_with_blocks); + } . { addlitchar(yytext[0]); } \n { yyerror("unexpected newline in quoted string"); } <> { yyerror("unterminated quoted string"); } -- 2.14.3 (Apple Git-98)