Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iE4KG-0001r5-Rf for pgsql-committers@arkaria.postgresql.org; Sat, 28 Sep 2019 04:27:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1iE4KE-0008N9-IY for pgsql-committers@arkaria.postgresql.org; Sat, 28 Sep 2019 04:27:18 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iE4KD-0008I9-Nq for pgsql-committers@lists.postgresql.org; Sat, 28 Sep 2019 04:27:18 +0000 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1iE4K6-0005ZH-67 for pgsql-committers@lists.postgresql.org; Sat, 28 Sep 2019 04:27:15 +0000 Received: by mail-pg1-x544.google.com with SMTP id z12so4455358pgp.9 for ; Fri, 27 Sep 2019 21:27:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=jPkGy+IV19HVTx0dHHCz4am26shvDh1bAtbrsEgMb10=; b=UKXx1+2pSlO1bPcqdWMZ4zIFrh7p48nySWwC+9fbOqC2qk7CBWxabxa6Q+ca+pwVvK Ezf391pRQ5TjRZQ7L2lZil8/GgVK2iYJpUvMIxt24q8KsHH7Rwv2ENF1n8Jx71UoBBet UBegue+b3mJlrel+NgwJumKonMPdHRExsreA4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=jPkGy+IV19HVTx0dHHCz4am26shvDh1bAtbrsEgMb10=; b=uI5RXN3NVeXOUYVeYznV5bnAZbEbtgNzwfxV7hhPkbMcimabIlmEIeCAq3OnpuPrNm m0g/oRjDSBxQXfixdx53sENYq5/drtwbsHzB9lT7JIit1/Z8IAacTmiJzfHIvjKJbI/0 jUyMVN3VpS6X9MJO3EbLYO3yJx8XV6D8JaVn9LrDjJ9XOUz4Npgb+706VJHONTk8UcBi dbMESyTaQmfSvdFQyXZIfwru4ApBr+hAOwTSbimEthp3N0nia4SDTmAVu7fl6t7jV51V P+YvsUIdDrcksTQB/vWveS90y2HyYpJSr6CxACtziZ36wYH5t2geyQkgp2ryKFPLHqOV 4Llw== X-Gm-Message-State: APjAAAUjMqHtZog1VNcdn6g1lGwR0iVdOYY3WfhRukhkFv6SyAC2Ylns 4slOwB55MRuh5g3XAYecd1kC+Q== X-Google-Smtp-Source: APXvYqwYnMhaPGyQ4FR4bp4ycEVe0xmmq0MW+XM6anFco9IIPRkUSCBtWPebpXoHWL9/xijG0w9aeg== X-Received: by 2002:a63:5356:: with SMTP id t22mr12213577pgl.400.1569644828791; Fri, 27 Sep 2019 21:27:08 -0700 (PDT) Received: from rfd.leadboat.com (108-233-125-46.lightspeed.sntcca.sbcglobal.net. [108.233.125.46]) by smtp.gmail.com with ESMTPSA id u17sm6244118pgf.8.2019.09.27.21.27.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Sep 2019 21:27:07 -0700 (PDT) Date: Fri, 27 Sep 2019 21:27:05 -0700 From: Noah Misch To: Andres Freund Cc: Alvaro Herrera , pgsql-committers@lists.postgresql.org Subject: Re: pgsql: Test pg_atomic_fetch_add_ with variable addend and 16-bit edge c Message-ID: <20190928042705.GA3857200@rfd.leadboat.com> References: <20190915160021.GA24376@alvherre.pgsql> <20190915221450.GA3500204@rfd.leadboat.com> <20190916044752.s5ajrua52tx5u2rt@alap3.anarazel.de> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="6c2NcOVqGQ03X4Wi" Content-Disposition: inline In-Reply-To: <20190916044752.s5ajrua52tx5u2rt@alap3.anarazel.de> User-Agent: Mutt/1.5.24 (2015-08-30) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --6c2NcOVqGQ03X4Wi Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sun, Sep 15, 2019 at 09:47:52PM -0700, Andres Freund wrote: > On 2019-09-15 15:14:50 -0700, Noah Misch wrote: > > --- a/src/test/regress/regress.c > > +++ b/src/test/regress/regress.c > > @@ -670,6 +670,16 @@ test_atomic_flag(void) > > pg_atomic_clear_flag(&flag); > > } > > > > +#define EXPECT(result_expr, expected_expr) \ > > + do { \ > > + uint32 result = (result_expr); \ > > + uint32 expected = (expected_expr); \ > > + if (result != expected) \ > > + elog(ERROR, \ > > + "%s yielded %u, expected %s in file \"%s\" line %u", \ > > + #result_expr, result, #expected_expr, __FILE__, __LINE__); \ > > + } while (0) > > + > Unfortunately we can't easily make this type independent. The local > variables are needed to avoid multiple evaluation. While we could infer > their type using compiler specific magic (__typeof__() or C++), we'd > still need to print them. We could however remove the local variables, > and purely rely on stringification of the arguments for printing the > error. > I'd name it EXPECT_EQ_U32 or such, but otherwise I think this is a clear > improvement. EXPECT_EQ_U32 works for me; I mildly prefer that to a type-independent macro that doesn't print the unexpected value. Attached. --6c2NcOVqGQ03X4Wi Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="regress-atomics-macros-v1.patch" diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index 8cc1568..9294751 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -41,6 +41,33 @@ #include "utils/memutils.h" +#define EXPECT_TRUE(expr) \ + do { \ + if (!(expr)) \ + elog(ERROR, \ + "%s was unexpectedly false in file \"%s\" line %u", \ + #expr, __FILE__, __LINE__); \ + } while (0) +#define EXPECT_EQ_U32(result_expr, expected_expr) \ + do { \ + uint32 result = (result_expr); \ + uint32 expected = (expected_expr); \ + if (result != expected) \ + elog(ERROR, \ + "%s yielded %u, expected %s in file \"%s\" line %u", \ + #result_expr, result, #expected_expr, __FILE__, __LINE__); \ + } while (0) + +#define EXPECT_EQ_U64(result_expr, expected_expr) \ + do { \ + uint64 result = (result_expr); \ + uint64 expected = (expected_expr); \ + if (result != expected) \ + elog(ERROR, \ + "%s yielded " UINT64_FORMAT ", expected %s in file \"%s\" line %u", \ + #result_expr, result, #expected_expr, __FILE__, __LINE__); \ + } while (0) + #define LDELIM '(' #define RDELIM ')' #define DELIM ',' @@ -646,27 +673,13 @@ test_atomic_flag(void) pg_atomic_flag flag; pg_atomic_init_flag(&flag); - - if (!pg_atomic_unlocked_test_flag(&flag)) - elog(ERROR, "flag: unexpectedly set"); - - if (!pg_atomic_test_set_flag(&flag)) - elog(ERROR, "flag: couldn't set"); - - if (pg_atomic_unlocked_test_flag(&flag)) - elog(ERROR, "flag: unexpectedly unset"); - - if (pg_atomic_test_set_flag(&flag)) - elog(ERROR, "flag: set spuriously #2"); - + EXPECT_TRUE(pg_atomic_unlocked_test_flag(&flag)); + EXPECT_TRUE(pg_atomic_test_set_flag(&flag)); + EXPECT_TRUE(!pg_atomic_unlocked_test_flag(&flag)); + EXPECT_TRUE(!pg_atomic_test_set_flag(&flag)); pg_atomic_clear_flag(&flag); - - if (!pg_atomic_unlocked_test_flag(&flag)) - elog(ERROR, "flag: unexpectedly set #2"); - - if (!pg_atomic_test_set_flag(&flag)) - elog(ERROR, "flag: couldn't set"); - + EXPECT_TRUE(pg_atomic_unlocked_test_flag(&flag)); + EXPECT_TRUE(pg_atomic_test_set_flag(&flag)); pg_atomic_clear_flag(&flag); } @@ -678,75 +691,38 @@ test_atomic_uint32(void) int i; pg_atomic_init_u32(&var, 0); - - if (pg_atomic_read_u32(&var) != 0) - elog(ERROR, "atomic_read_u32() #1 wrong"); - + EXPECT_EQ_U32(pg_atomic_read_u32(&var), 0); pg_atomic_write_u32(&var, 3); - - if (pg_atomic_read_u32(&var) != 3) - elog(ERROR, "atomic_read_u32() #2 wrong"); - - if (pg_atomic_fetch_add_u32(&var, pg_atomic_read_u32(&var) - 2) != 3) - elog(ERROR, "atomic_fetch_add_u32() #1 wrong"); - - if (pg_atomic_fetch_sub_u32(&var, 1) != 4) - elog(ERROR, "atomic_fetch_sub_u32() #1 wrong"); - - if (pg_atomic_sub_fetch_u32(&var, 3) != 0) - elog(ERROR, "atomic_sub_fetch_u32() #1 wrong"); - - if (pg_atomic_add_fetch_u32(&var, 10) != 10) - elog(ERROR, "atomic_add_fetch_u32() #1 wrong"); - - if (pg_atomic_exchange_u32(&var, 5) != 10) - elog(ERROR, "pg_atomic_exchange_u32() #1 wrong"); - - if (pg_atomic_exchange_u32(&var, 0) != 5) - elog(ERROR, "pg_atomic_exchange_u32() #0 wrong"); + EXPECT_EQ_U32(pg_atomic_read_u32(&var), 3); + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, pg_atomic_read_u32(&var) - 2), + 3); + EXPECT_EQ_U32(pg_atomic_fetch_sub_u32(&var, 1), 4); + EXPECT_EQ_U32(pg_atomic_sub_fetch_u32(&var, 3), 0); + EXPECT_EQ_U32(pg_atomic_add_fetch_u32(&var, 10), 10); + EXPECT_EQ_U32(pg_atomic_exchange_u32(&var, 5), 10); + EXPECT_EQ_U32(pg_atomic_exchange_u32(&var, 0), 5); /* test around numerical limits */ - if (pg_atomic_fetch_add_u32(&var, INT_MAX) != 0) - elog(ERROR, "pg_atomic_fetch_add_u32() #2 wrong"); - - if (pg_atomic_fetch_add_u32(&var, INT_MAX) != INT_MAX) - elog(ERROR, "pg_atomic_add_fetch_u32() #3 wrong"); - + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, INT_MAX), 0); + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, INT_MAX), INT_MAX); pg_atomic_fetch_add_u32(&var, 2); /* wrap to 0 */ - - if (pg_atomic_fetch_add_u32(&var, PG_INT16_MAX) != 0) - elog(ERROR, "pg_atomic_fetch_add_u32() #3 wrong"); - - if (pg_atomic_fetch_add_u32(&var, PG_INT16_MAX + 1) != PG_INT16_MAX) - elog(ERROR, "pg_atomic_fetch_add_u32() #4 wrong"); - - if (pg_atomic_fetch_add_u32(&var, PG_INT16_MIN) != 2 * PG_INT16_MAX + 1) - elog(ERROR, "pg_atomic_fetch_add_u32() #5 wrong"); - - if (pg_atomic_fetch_add_u32(&var, PG_INT16_MIN - 1) != PG_INT16_MAX) - elog(ERROR, "pg_atomic_fetch_add_u32() #6 wrong"); - + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, PG_INT16_MAX), 0); + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, PG_INT16_MAX + 1), + PG_INT16_MAX); + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, PG_INT16_MIN), + 2 * PG_INT16_MAX + 1); + EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&var, PG_INT16_MIN - 1), + PG_INT16_MAX); pg_atomic_fetch_add_u32(&var, 1); /* top up to UINT_MAX */ - - if (pg_atomic_read_u32(&var) != UINT_MAX) - elog(ERROR, "atomic_read_u32() #2 wrong"); - - if (pg_atomic_fetch_sub_u32(&var, INT_MAX) != UINT_MAX) - elog(ERROR, "pg_atomic_fetch_sub_u32() #2 wrong"); - - if (pg_atomic_read_u32(&var) != (uint32) INT_MAX + 1) - elog(ERROR, "atomic_read_u32() #3 wrong: %u", pg_atomic_read_u32(&var)); - - expected = pg_atomic_sub_fetch_u32(&var, INT_MAX); - if (expected != 1) - elog(ERROR, "pg_atomic_sub_fetch_u32() #3 wrong: %u", expected); - + EXPECT_EQ_U32(pg_atomic_read_u32(&var), UINT_MAX); + EXPECT_EQ_U32(pg_atomic_fetch_sub_u32(&var, INT_MAX), UINT_MAX); + EXPECT_EQ_U32(pg_atomic_read_u32(&var), (uint32) INT_MAX + 1); + EXPECT_EQ_U32(pg_atomic_sub_fetch_u32(&var, INT_MAX), 1); pg_atomic_sub_fetch_u32(&var, 1); /* fail exchange because of old expected */ expected = 10; - if (pg_atomic_compare_exchange_u32(&var, &expected, 1)) - elog(ERROR, "atomic_compare_exchange_u32() changed value spuriously"); + EXPECT_TRUE(!pg_atomic_compare_exchange_u32(&var, &expected, 1)); /* CAS is allowed to fail due to interrupts, try a couple of times */ for (i = 0; i < 1000; i++) @@ -757,31 +733,18 @@ test_atomic_uint32(void) } if (i == 1000) elog(ERROR, "atomic_compare_exchange_u32() never succeeded"); - if (pg_atomic_read_u32(&var) != 1) - elog(ERROR, "atomic_compare_exchange_u32() didn't set value properly"); - + EXPECT_EQ_U32(pg_atomic_read_u32(&var), 1); pg_atomic_write_u32(&var, 0); /* try setting flagbits */ - if (pg_atomic_fetch_or_u32(&var, 1) & 1) - elog(ERROR, "pg_atomic_fetch_or_u32() #1 wrong"); - - if (!(pg_atomic_fetch_or_u32(&var, 2) & 1)) - elog(ERROR, "pg_atomic_fetch_or_u32() #2 wrong"); - - if (pg_atomic_read_u32(&var) != 3) - elog(ERROR, "invalid result after pg_atomic_fetch_or_u32()"); - + EXPECT_TRUE(!(pg_atomic_fetch_or_u32(&var, 1) & 1)); + EXPECT_TRUE(pg_atomic_fetch_or_u32(&var, 2) & 1); + EXPECT_EQ_U32(pg_atomic_read_u32(&var), 3); /* try clearing flagbits */ - if ((pg_atomic_fetch_and_u32(&var, ~2) & 3) != 3) - elog(ERROR, "pg_atomic_fetch_and_u32() #1 wrong"); - - if (pg_atomic_fetch_and_u32(&var, ~1) != 1) - elog(ERROR, "pg_atomic_fetch_and_u32() #2 wrong: is %u", - pg_atomic_read_u32(&var)); + EXPECT_EQ_U32(pg_atomic_fetch_and_u32(&var, ~2) & 3, 3); + EXPECT_EQ_U32(pg_atomic_fetch_and_u32(&var, ~1), 1); /* no bits set anymore */ - if (pg_atomic_fetch_and_u32(&var, ~0) != 0) - elog(ERROR, "pg_atomic_fetch_and_u32() #3 wrong"); + EXPECT_EQ_U32(pg_atomic_fetch_and_u32(&var, ~0), 0); } static void @@ -792,37 +755,20 @@ test_atomic_uint64(void) int i; pg_atomic_init_u64(&var, 0); - - if (pg_atomic_read_u64(&var) != 0) - elog(ERROR, "atomic_read_u64() #1 wrong"); - + EXPECT_EQ_U64(pg_atomic_read_u64(&var), 0); pg_atomic_write_u64(&var, 3); - - if (pg_atomic_read_u64(&var) != 3) - elog(ERROR, "atomic_read_u64() #2 wrong"); - - if (pg_atomic_fetch_add_u64(&var, pg_atomic_read_u64(&var) - 2) != 3) - elog(ERROR, "atomic_fetch_add_u64() #1 wrong"); - - if (pg_atomic_fetch_sub_u64(&var, 1) != 4) - elog(ERROR, "atomic_fetch_sub_u64() #1 wrong"); - - if (pg_atomic_sub_fetch_u64(&var, 3) != 0) - elog(ERROR, "atomic_sub_fetch_u64() #1 wrong"); - - if (pg_atomic_add_fetch_u64(&var, 10) != 10) - elog(ERROR, "atomic_add_fetch_u64() #1 wrong"); - - if (pg_atomic_exchange_u64(&var, 5) != 10) - elog(ERROR, "pg_atomic_exchange_u64() #1 wrong"); - - if (pg_atomic_exchange_u64(&var, 0) != 5) - elog(ERROR, "pg_atomic_exchange_u64() #0 wrong"); + EXPECT_EQ_U64(pg_atomic_read_u64(&var), 3); + EXPECT_EQ_U64(pg_atomic_fetch_add_u64(&var, pg_atomic_read_u64(&var) - 2), + 3); + EXPECT_EQ_U64(pg_atomic_fetch_sub_u64(&var, 1), 4); + EXPECT_EQ_U64(pg_atomic_sub_fetch_u64(&var, 3), 0); + EXPECT_EQ_U64(pg_atomic_add_fetch_u64(&var, 10), 10); + EXPECT_EQ_U64(pg_atomic_exchange_u64(&var, 5), 10); + EXPECT_EQ_U64(pg_atomic_exchange_u64(&var, 0), 5); /* fail exchange because of old expected */ expected = 10; - if (pg_atomic_compare_exchange_u64(&var, &expected, 1)) - elog(ERROR, "atomic_compare_exchange_u64() changed value spuriously"); + EXPECT_TRUE(!pg_atomic_compare_exchange_u64(&var, &expected, 1)); /* CAS is allowed to fail due to interrupts, try a couple of times */ for (i = 0; i < 100; i++) @@ -833,31 +779,19 @@ test_atomic_uint64(void) } if (i == 100) elog(ERROR, "atomic_compare_exchange_u64() never succeeded"); - if (pg_atomic_read_u64(&var) != 1) - elog(ERROR, "atomic_compare_exchange_u64() didn't set value properly"); + EXPECT_EQ_U64(pg_atomic_read_u64(&var), 1); pg_atomic_write_u64(&var, 0); /* try setting flagbits */ - if (pg_atomic_fetch_or_u64(&var, 1) & 1) - elog(ERROR, "pg_atomic_fetch_or_u64() #1 wrong"); - - if (!(pg_atomic_fetch_or_u64(&var, 2) & 1)) - elog(ERROR, "pg_atomic_fetch_or_u64() #2 wrong"); - - if (pg_atomic_read_u64(&var) != 3) - elog(ERROR, "invalid result after pg_atomic_fetch_or_u64()"); - + EXPECT_TRUE(!(pg_atomic_fetch_or_u64(&var, 1) & 1)); + EXPECT_TRUE(pg_atomic_fetch_or_u64(&var, 2) & 1); + EXPECT_EQ_U64(pg_atomic_read_u64(&var), 3); /* try clearing flagbits */ - if ((pg_atomic_fetch_and_u64(&var, ~2) & 3) != 3) - elog(ERROR, "pg_atomic_fetch_and_u64() #1 wrong"); - - if (pg_atomic_fetch_and_u64(&var, ~1) != 1) - elog(ERROR, "pg_atomic_fetch_and_u64() #2 wrong: is " UINT64_FORMAT, - pg_atomic_read_u64(&var)); + EXPECT_EQ_U64((pg_atomic_fetch_and_u64(&var, ~2) & 3), 3); + EXPECT_EQ_U64(pg_atomic_fetch_and_u64(&var, ~1), 1); /* no bits set anymore */ - if (pg_atomic_fetch_and_u64(&var, ~0) != 0) - elog(ERROR, "pg_atomic_fetch_and_u64() #3 wrong"); + EXPECT_EQ_U64(pg_atomic_fetch_and_u64(&var, ~0), 0); } --6c2NcOVqGQ03X4Wi--