From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on archive.lwn.net X-Spam-Level: X-Spam-Status: No, score=-6.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by archive.lwn.net (Postfix) with ESMTP id 350887D2F0 for ; Thu, 20 Jun 2019 00:15:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730329AbfFTAP2 (ORCPT ); Wed, 19 Jun 2019 20:15:28 -0400 Received: from mail.kernel.org ([198.145.29.99]:56078 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726479AbfFTAP2 (ORCPT ); Wed, 19 Jun 2019 20:15:28 -0400 Received: from kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 93426218BE; Thu, 20 Jun 2019 00:15:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1560989726; bh=Cyw3CS4Us7cHDynulRLePwpLSsuY8ho08g4vXgTjDFM=; h=In-Reply-To:References:To:From:Subject:Cc:Date:From; b=uxkDxyYpF7laGQMQdbheNapqj0FQjS0o/hFsG69mDV7yMnicTh9sX+q1GYO8mfbwg E1z69sHUGBcQdsi2WlYDYbSc4B2+s17Nz6qJQoCAMJgUsjAbryk7FV2ai2kP081uXc 0hRlrWl2NbES9/L1UjKNP/E97FgjeS8RMgUcodoM= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable In-Reply-To: <20190617082613.109131-2-brendanhiggins@google.com> References: <20190617082613.109131-1-brendanhiggins@google.com> <20190617082613.109131-2-brendanhiggins@google.com> To: Brendan Higgins , frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com From: Stephen Boyd Subject: Re: [PATCH v5 01/18] kunit: test: add KUnit test runner core Cc: devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, kunit-dev@googlegroups.com, linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-nvdimm@lists.01.org, linux-um@lists.infradead.org, Alexander.Levin@microsoft.com, Tim.Bird@sony.com, amir73il@gmail.com, dan.carpenter@oracle.com, daniel@ffwll.ch, jdike@addtoit.com, joel@jms.id.au, julia.lawall@lip6.fr, khilman@baylibre.com, knut.omang@oracle.com, logang@deltatee.com, mpe@ellerman.id.au, pmladek@suse.com, rdunlap@infradead.org, richard@nod.at, rientjes@google.com, rostedt@goodmis.org, wfg@linux.intel.com, Brendan Higgins User-Agent: alot/0.8.1 Date: Wed, 19 Jun 2019 17:15:25 -0700 Message-Id: <20190620001526.93426218BE@mail.kernel.org> Sender: linux-doc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org Quoting Brendan Higgins (2019-06-17 01:25:56) > diff --git a/kunit/test.c b/kunit/test.c > new file mode 100644 > index 0000000000000..d05d254f1521f > --- /dev/null > +++ b/kunit/test.c > @@ -0,0 +1,210 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Base unit test (KUnit) API. > + * > + * Copyright (C) 2019, Google LLC. > + * Author: Brendan Higgins > + */ > + > +#include > +#include > + > +static bool kunit_get_success(struct kunit *test) > +{ > + unsigned long flags; > + bool success; > + > + spin_lock_irqsave(&test->lock, flags); > + success =3D test->success; > + spin_unlock_irqrestore(&test->lock, flags); I still don't understand the locking scheme in this code. Is the intention to make getter and setter APIs that are "safe" by adding in a spinlock that is held around getting and setting various members in the kunit structure? In what situation is there more than one thread reading or writing the kunit struct? Isn't it only a single process that is going to be operating on this structure? And why do we need to disable irqs? Are we expecting to be modifying the unit tests from irq contexts? > + > + return success; > +} > + > +static void kunit_set_success(struct kunit *test, bool success) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&test->lock, flags); > + test->success =3D success; > + spin_unlock_irqrestore(&test->lock, flags); > +} > + > +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) > +{ > + return vprintk_emit(0, level, NULL, 0, fmt, args); > +} > + > +static int kunit_printk_emit(int level, const char *fmt, ...) > +{ > + va_list args; > + int ret; > + > + va_start(args, fmt); > + ret =3D kunit_vprintk_emit(level, fmt, args); > + va_end(args); > + > + return ret; > +} > + > +static void kunit_vprintk(const struct kunit *test, > + const char *level, > + struct va_format *vaf) > +{ > + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); > +} > + > +static bool kunit_has_printed_tap_version; Can you please move this into function local scope in the function below? > + > +static void kunit_print_tap_version(void) > +{ > + if (!kunit_has_printed_tap_version) { > + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); > + kunit_has_printed_tap_version =3D true; > + } > +} > + [...] > + > +static bool kunit_module_has_succeeded(struct kunit_module *module) > +{ > + const struct kunit_case *test_case; > + bool success =3D true; > + > + for (test_case =3D module->test_cases; test_case->run_case; test_= case++) > + if (!test_case->success) { > + success =3D false; > + break; Why not 'return false'? > + } > + > + return success; And 'return true'? > +} > + > +static size_t kunit_module_counter =3D 1; > + > +static void kunit_print_subtest_end(struct kunit_module *module) > +{ > + kunit_print_ok_not_ok(false, > + kunit_module_has_succeeded(module), > + kunit_module_counter++, > + module->name); > +} > + > +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, > + size_t test_number) > +{ > + kunit_print_ok_not_ok(true, > + test_case->success, > + test_number, > + test_case->name); > +} > + > +void kunit_init_test(struct kunit *test, const char *name) > +{ > + spin_lock_init(&test->lock); > + test->name =3D name; > + test->success =3D true; > +} > + > +/* > + * Performs all logic to run a test case. > + */ > +static void kunit_run_case(struct kunit_module *module, > + struct kunit_case *test_case) > +{ > + struct kunit test; > + int ret =3D 0; > + > + kunit_init_test(&test, test_case->name); > + > + if (module->init) { > + ret =3D module->init(&test); > + if (ret) { > + kunit_err(&test, "failed to initialize: %d\n", re= t); > + kunit_set_success(&test, false); > + return; > + } > + } > + > + if (!ret) > + test_case->run_case(&test); Do we need this if condition? ret can only be set to non-zero above but then we'll exit the function early so it seems unnecessary. Given that, ret should probably be moved into the module->init path. > + > + if (module->exit) > + module->exit(&test); > + > + test_case->success =3D kunit_get_success(&test); > +} > + From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.kernel.org ([198.145.29.99]:56078 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726479AbfFTAP2 (ORCPT ); Wed, 19 Jun 2019 20:15:28 -0400 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable In-Reply-To: <20190617082613.109131-2-brendanhiggins@google.com> References: <20190617082613.109131-1-brendanhiggins@google.com> <20190617082613.109131-2-brendanhiggins@google.com> From: Stephen Boyd Subject: Re: [PATCH v5 01/18] kunit: test: add KUnit test runner core Date: Wed, 19 Jun 2019 17:15:25 -0700 Message-Id: <20190620001526.93426218BE@mail.kernel.org> Sender: linux-kbuild-owner@vger.kernel.org List-ID: To: Brendan Higgins , frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, kunit-dev@googlegroups.com, linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-nvdimm@lists.01.org, linux-um@lists.infradead.org, Alexander.Levin@microsoft.com, Tim.Bird@sony.com, amir73il@gmail.com, dan.carpenter@oracle.com, daniel@ffwll.ch, jdike@addtoit.com, joel@jms.id.au, julia.lawall@lip6.fr, khilman@baylibre.com, knut.omang@oracle.com, logang@deltatee.com, mpe@ellerman.id.au, pmladek@suse.com, rdunlap@infradead.org, richard@nod.at, rientjes@google.com, rostedt@goodmis.org, wfg@linux.intel.com Quoting Brendan Higgins (2019-06-17 01:25:56) > diff --git a/kunit/test.c b/kunit/test.c > new file mode 100644 > index 0000000000000..d05d254f1521f > --- /dev/null > +++ b/kunit/test.c > @@ -0,0 +1,210 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Base unit test (KUnit) API. > + * > + * Copyright (C) 2019, Google LLC. > + * Author: Brendan Higgins > + */ > + > +#include > +#include > + > +static bool kunit_get_success(struct kunit *test) > +{ > + unsigned long flags; > + bool success; > + > + spin_lock_irqsave(&test->lock, flags); > + success =3D test->success; > + spin_unlock_irqrestore(&test->lock, flags); I still don't understand the locking scheme in this code. Is the intention to make getter and setter APIs that are "safe" by adding in a spinlock that is held around getting and setting various members in the kunit structure? In what situation is there more than one thread reading or writing the kunit struct? Isn't it only a single process that is going to be operating on this structure? And why do we need to disable irqs? Are we expecting to be modifying the unit tests from irq contexts? > + > + return success; > +} > + > +static void kunit_set_success(struct kunit *test, bool success) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&test->lock, flags); > + test->success =3D success; > + spin_unlock_irqrestore(&test->lock, flags); > +} > + > +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) > +{ > + return vprintk_emit(0, level, NULL, 0, fmt, args); > +} > + > +static int kunit_printk_emit(int level, const char *fmt, ...) > +{ > + va_list args; > + int ret; > + > + va_start(args, fmt); > + ret =3D kunit_vprintk_emit(level, fmt, args); > + va_end(args); > + > + return ret; > +} > + > +static void kunit_vprintk(const struct kunit *test, > + const char *level, > + struct va_format *vaf) > +{ > + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); > +} > + > +static bool kunit_has_printed_tap_version; Can you please move this into function local scope in the function below? > + > +static void kunit_print_tap_version(void) > +{ > + if (!kunit_has_printed_tap_version) { > + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); > + kunit_has_printed_tap_version =3D true; > + } > +} > + [...] > + > +static bool kunit_module_has_succeeded(struct kunit_module *module) > +{ > + const struct kunit_case *test_case; > + bool success =3D true; > + > + for (test_case =3D module->test_cases; test_case->run_case; test_= case++) > + if (!test_case->success) { > + success =3D false; > + break; Why not 'return false'? > + } > + > + return success; And 'return true'? > +} > + > +static size_t kunit_module_counter =3D 1; > + > +static void kunit_print_subtest_end(struct kunit_module *module) > +{ > + kunit_print_ok_not_ok(false, > + kunit_module_has_succeeded(module), > + kunit_module_counter++, > + module->name); > +} > + > +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, > + size_t test_number) > +{ > + kunit_print_ok_not_ok(true, > + test_case->success, > + test_number, > + test_case->name); > +} > + > +void kunit_init_test(struct kunit *test, const char *name) > +{ > + spin_lock_init(&test->lock); > + test->name =3D name; > + test->success =3D true; > +} > + > +/* > + * Performs all logic to run a test case. > + */ > +static void kunit_run_case(struct kunit_module *module, > + struct kunit_case *test_case) > +{ > + struct kunit test; > + int ret =3D 0; > + > + kunit_init_test(&test, test_case->name); > + > + if (module->init) { > + ret =3D module->init(&test); > + if (ret) { > + kunit_err(&test, "failed to initialize: %d\n", re= t); > + kunit_set_success(&test, false); > + return; > + } > + } > + > + if (!ret) > + test_case->run_case(&test); Do we need this if condition? ret can only be set to non-zero above but then we'll exit the function early so it seems unnecessary. Given that, ret should probably be moved into the module->init path. > + > + if (module->exit) > + module->exit(&test); > + > + test_case->success =3D kunit_get_success(&test); > +} > + From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1hdkjg-0004Eg-6L for linux-um@lists.infradead.org; Thu, 20 Jun 2019 00:15:29 +0000 MIME-Version: 1.0 In-Reply-To: <20190617082613.109131-2-brendanhiggins@google.com> References: <20190617082613.109131-1-brendanhiggins@google.com> <20190617082613.109131-2-brendanhiggins@google.com> From: Stephen Boyd Subject: Re: [PATCH v5 01/18] kunit: test: add KUnit test runner core Date: Wed, 19 Jun 2019 17:15:25 -0700 Message-Id: <20190620001526.93426218BE@mail.kernel.org> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-um" Errors-To: linux-um-bounces+geert=linux-m68k.org@lists.infradead.org To: Brendan Higgins , frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: pmladek@suse.com, linux-doc@vger.kernel.org, amir73il@gmail.com, Brendan Higgins , dri-devel@lists.freedesktop.org, Alexander.Levin@microsoft.com, linux-kselftest@vger.kernel.org, linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, wfg@linux.intel.com, joel@jms.id.au, rientjes@google.com, jdike@addtoit.com, dan.carpenter@oracle.com, devicetree@vger.kernel.org, linux-kbuild@vger.kernel.org, Tim.Bird@sony.com, linux-um@lists.infradead.org, rostedt@goodmis.org, julia.lawall@lip6.fr, kunit-dev@googlegroups.com, richard@nod.at, rdunlap@infradead.org, linux-kernel@vger.kernel.org, daniel@ffwll.ch, mpe@ellerman.id.au, linux-fsdevel@vger.kernel.org, logang@deltatee.com Quoting Brendan Higgins (2019-06-17 01:25:56) > diff --git a/kunit/test.c b/kunit/test.c > new file mode 100644 > index 0000000000000..d05d254f1521f > --- /dev/null > +++ b/kunit/test.c > @@ -0,0 +1,210 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Base unit test (KUnit) API. > + * > + * Copyright (C) 2019, Google LLC. > + * Author: Brendan Higgins > + */ > + > +#include > +#include > + > +static bool kunit_get_success(struct kunit *test) > +{ > + unsigned long flags; > + bool success; > + > + spin_lock_irqsave(&test->lock, flags); > + success = test->success; > + spin_unlock_irqrestore(&test->lock, flags); I still don't understand the locking scheme in this code. Is the intention to make getter and setter APIs that are "safe" by adding in a spinlock that is held around getting and setting various members in the kunit structure? In what situation is there more than one thread reading or writing the kunit struct? Isn't it only a single process that is going to be operating on this structure? And why do we need to disable irqs? Are we expecting to be modifying the unit tests from irq contexts? > + > + return success; > +} > + > +static void kunit_set_success(struct kunit *test, bool success) > +{ > + unsigned long flags; > + > + spin_lock_irqsave(&test->lock, flags); > + test->success = success; > + spin_unlock_irqrestore(&test->lock, flags); > +} > + > +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) > +{ > + return vprintk_emit(0, level, NULL, 0, fmt, args); > +} > + > +static int kunit_printk_emit(int level, const char *fmt, ...) > +{ > + va_list args; > + int ret; > + > + va_start(args, fmt); > + ret = kunit_vprintk_emit(level, fmt, args); > + va_end(args); > + > + return ret; > +} > + > +static void kunit_vprintk(const struct kunit *test, > + const char *level, > + struct va_format *vaf) > +{ > + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); > +} > + > +static bool kunit_has_printed_tap_version; Can you please move this into function local scope in the function below? > + > +static void kunit_print_tap_version(void) > +{ > + if (!kunit_has_printed_tap_version) { > + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); > + kunit_has_printed_tap_version = true; > + } > +} > + [...] > + > +static bool kunit_module_has_succeeded(struct kunit_module *module) > +{ > + const struct kunit_case *test_case; > + bool success = true; > + > + for (test_case = module->test_cases; test_case->run_case; test_case++) > + if (!test_case->success) { > + success = false; > + break; Why not 'return false'? > + } > + > + return success; And 'return true'? > +} > + > +static size_t kunit_module_counter = 1; > + > +static void kunit_print_subtest_end(struct kunit_module *module) > +{ > + kunit_print_ok_not_ok(false, > + kunit_module_has_succeeded(module), > + kunit_module_counter++, > + module->name); > +} > + > +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, > + size_t test_number) > +{ > + kunit_print_ok_not_ok(true, > + test_case->success, > + test_number, > + test_case->name); > +} > + > +void kunit_init_test(struct kunit *test, const char *name) > +{ > + spin_lock_init(&test->lock); > + test->name = name; > + test->success = true; > +} > + > +/* > + * Performs all logic to run a test case. > + */ > +static void kunit_run_case(struct kunit_module *module, > + struct kunit_case *test_case) > +{ > + struct kunit test; > + int ret = 0; > + > + kunit_init_test(&test, test_case->name); > + > + if (module->init) { > + ret = module->init(&test); > + if (ret) { > + kunit_err(&test, "failed to initialize: %d\n", ret); > + kunit_set_success(&test, false); > + return; > + } > + } > + > + if (!ret) > + test_case->run_case(&test); Do we need this if condition? ret can only be set to non-zero above but then we'll exit the function early so it seems unnecessary. Given that, ret should probably be moved into the module->init path. > + > + if (module->exit) > + module->exit(&test); > + > + test_case->success = kunit_get_success(&test); > +} > + _______________________________________________ linux-um mailing list linux-um@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-um From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stephen Boyd Subject: Re: [PATCH v5 01/18] kunit: test: add KUnit test runner core Date: Wed, 19 Jun 2019 17:15:25 -0700 Message-ID: <20190620001526.93426218BE@mail.kernel.org> References: <20190617082613.109131-1-brendanhiggins@google.com> <20190617082613.109131-2-brendanhiggins@google.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20190617082613.109131-2-brendanhiggins@google.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: pmladek@suse.com, linux-doc@vger.kernel.org, amir73il@gmail.com, Brendan Higgins , dri-devel@lists.freedesktop.org, Alexander.Levin@microsoft.com, linux-kselftest@vger.kernel.org, linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, wfg@linux.intel.com, joel@jms.id.au, rientjes@google.com, jdike@addtoit.com, dan.carpenter@oracle.com, devicetree@vger.kernel.org, linux-kbuild@vger.kernel.org, Tim.Bird@sony.com, linux-um@lists.infradead.org, rostedt@goodmis.org, julia.lawall@lip6.fr, kunit-dev@googlegroups.com, richard@nod.at, rdunlap@infradead.org, linux-kernel@vger.kernel.org, mpe@ellerman.id.au, linux-fsdevel@vger.kernel.org, logang@deltatee.com List-Id: devicetree@vger.kernel.org UXVvdGluZyBCcmVuZGFuIEhpZ2dpbnMgKDIwMTktMDYtMTcgMDE6MjU6NTYpCj4gZGlmZiAtLWdp dCBhL2t1bml0L3Rlc3QuYyBiL2t1bml0L3Rlc3QuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4g aW5kZXggMDAwMDAwMDAwMDAwMC4uZDA1ZDI1NGYxNTIxZgo+IC0tLSAvZGV2L251bGwKPiArKysg Yi9rdW5pdC90ZXN0LmMKPiBAQCAtMCwwICsxLDIxMCBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRl bnRpZmllcjogR1BMLTIuMAo+ICsvKgo+ICsgKiBCYXNlIHVuaXQgdGVzdCAoS1VuaXQpIEFQSS4K PiArICoKPiArICogQ29weXJpZ2h0IChDKSAyMDE5LCBHb29nbGUgTExDLgo+ICsgKiBBdXRob3I6 IEJyZW5kYW4gSGlnZ2lucyA8YnJlbmRhbmhpZ2dpbnNAZ29vZ2xlLmNvbT4KPiArICovCj4gKwo+ ICsjaW5jbHVkZSA8bGludXgvc2NoZWQvZGVidWcuaD4KPiArI2luY2x1ZGUgPGt1bml0L3Rlc3Qu aD4KPiArCj4gK3N0YXRpYyBib29sIGt1bml0X2dldF9zdWNjZXNzKHN0cnVjdCBrdW5pdCAqdGVz dCkKPiArewo+ICsgICAgICAgdW5zaWduZWQgbG9uZyBmbGFnczsKPiArICAgICAgIGJvb2wgc3Vj Y2VzczsKPiArCj4gKyAgICAgICBzcGluX2xvY2tfaXJxc2F2ZSgmdGVzdC0+bG9jaywgZmxhZ3Mp Owo+ICsgICAgICAgc3VjY2VzcyA9IHRlc3QtPnN1Y2Nlc3M7Cj4gKyAgICAgICBzcGluX3VubG9j a19pcnFyZXN0b3JlKCZ0ZXN0LT5sb2NrLCBmbGFncyk7CgpJIHN0aWxsIGRvbid0IHVuZGVyc3Rh bmQgdGhlIGxvY2tpbmcgc2NoZW1lIGluIHRoaXMgY29kZS4gSXMgdGhlCmludGVudGlvbiB0byBt YWtlIGdldHRlciBhbmQgc2V0dGVyIEFQSXMgdGhhdCBhcmUgInNhZmUiIGJ5IGFkZGluZyBpbiBh CnNwaW5sb2NrIHRoYXQgaXMgaGVsZCBhcm91bmQgZ2V0dGluZyBhbmQgc2V0dGluZyB2YXJpb3Vz IG1lbWJlcnMgaW4gdGhlCmt1bml0IHN0cnVjdHVyZT8KCkluIHdoYXQgc2l0dWF0aW9uIGlzIHRo ZXJlIG1vcmUgdGhhbiBvbmUgdGhyZWFkIHJlYWRpbmcgb3Igd3JpdGluZyB0aGUKa3VuaXQgc3Ry dWN0PyBJc24ndCBpdCBvbmx5IGEgc2luZ2xlIHByb2Nlc3MgdGhhdCBpcyBnb2luZyB0byBiZQpv cGVyYXRpbmcgb24gdGhpcyBzdHJ1Y3R1cmU/IEFuZCB3aHkgZG8gd2UgbmVlZCB0byBkaXNhYmxl IGlycXM/IEFyZSB3ZQpleHBlY3RpbmcgdG8gYmUgbW9kaWZ5aW5nIHRoZSB1bml0IHRlc3RzIGZy b20gaXJxIGNvbnRleHRzPwoKPiArCj4gKyAgICAgICByZXR1cm4gc3VjY2VzczsKPiArfQo+ICsK PiArc3RhdGljIHZvaWQga3VuaXRfc2V0X3N1Y2Nlc3Moc3RydWN0IGt1bml0ICp0ZXN0LCBib29s IHN1Y2Nlc3MpCj4gK3sKPiArICAgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gKwo+ICsgICAg ICAgc3Bpbl9sb2NrX2lycXNhdmUoJnRlc3QtPmxvY2ssIGZsYWdzKTsKPiArICAgICAgIHRlc3Qt PnN1Y2Nlc3MgPSBzdWNjZXNzOwo+ICsgICAgICAgc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmdGVz dC0+bG9jaywgZmxhZ3MpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGt1bml0X3ZwcmludGtfZW1p dChpbnQgbGV2ZWwsIGNvbnN0IGNoYXIgKmZtdCwgdmFfbGlzdCBhcmdzKQo+ICt7Cj4gKyAgICAg ICByZXR1cm4gdnByaW50a19lbWl0KDAsIGxldmVsLCBOVUxMLCAwLCBmbXQsIGFyZ3MpOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IGt1bml0X3ByaW50a19lbWl0KGludCBsZXZlbCwgY29uc3QgY2hh ciAqZm10LCAuLi4pCj4gK3sKPiArICAgICAgIHZhX2xpc3QgYXJnczsKPiArICAgICAgIGludCBy ZXQ7Cj4gKwo+ICsgICAgICAgdmFfc3RhcnQoYXJncywgZm10KTsKPiArICAgICAgIHJldCA9IGt1 bml0X3ZwcmludGtfZW1pdChsZXZlbCwgZm10LCBhcmdzKTsKPiArICAgICAgIHZhX2VuZChhcmdz KTsKPiArCj4gKyAgICAgICByZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBrdW5p dF92cHJpbnRrKGNvbnN0IHN0cnVjdCBrdW5pdCAqdGVzdCwKPiArICAgICAgICAgICAgICAgICAg ICAgICAgIGNvbnN0IGNoYXIgKmxldmVsLAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgc3Ry dWN0IHZhX2Zvcm1hdCAqdmFmKQo+ICt7Cj4gKyAgICAgICBrdW5pdF9wcmludGtfZW1pdChsZXZl bFsxXSAtICcwJywgIlx0IyAlczogJXBWIiwgdGVzdC0+bmFtZSwgdmFmKTsKPiArfQo+ICsKPiAr c3RhdGljIGJvb2wga3VuaXRfaGFzX3ByaW50ZWRfdGFwX3ZlcnNpb247CgpDYW4geW91IHBsZWFz ZSBtb3ZlIHRoaXMgaW50byBmdW5jdGlvbiBsb2NhbCBzY29wZSBpbiB0aGUgZnVuY3Rpb24KYmVs b3c/Cgo+ICsKPiArc3RhdGljIHZvaWQga3VuaXRfcHJpbnRfdGFwX3ZlcnNpb24odm9pZCkKPiAr ewo+ICsgICAgICAgaWYgKCFrdW5pdF9oYXNfcHJpbnRlZF90YXBfdmVyc2lvbikgewo+ICsgICAg ICAgICAgICAgICBrdW5pdF9wcmludGtfZW1pdChMT0dMRVZFTF9JTkZPLCAiVEFQIHZlcnNpb24g MTRcbiIpOwo+ICsgICAgICAgICAgICAgICBrdW5pdF9oYXNfcHJpbnRlZF90YXBfdmVyc2lvbiA9 IHRydWU7Cj4gKyAgICAgICB9Cj4gK30KPiArClsuLi5dCj4gKwo+ICtzdGF0aWMgYm9vbCBrdW5p dF9tb2R1bGVfaGFzX3N1Y2NlZWRlZChzdHJ1Y3Qga3VuaXRfbW9kdWxlICptb2R1bGUpCj4gK3sK PiArICAgICAgIGNvbnN0IHN0cnVjdCBrdW5pdF9jYXNlICp0ZXN0X2Nhc2U7Cj4gKyAgICAgICBi b29sIHN1Y2Nlc3MgPSB0cnVlOwo+ICsKPiArICAgICAgIGZvciAodGVzdF9jYXNlID0gbW9kdWxl LT50ZXN0X2Nhc2VzOyB0ZXN0X2Nhc2UtPnJ1bl9jYXNlOyB0ZXN0X2Nhc2UrKykKPiArICAgICAg ICAgICAgICAgaWYgKCF0ZXN0X2Nhc2UtPnN1Y2Nlc3MpIHsKPiArICAgICAgICAgICAgICAgICAg ICAgICBzdWNjZXNzID0gZmFsc2U7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CgpX aHkgbm90ICdyZXR1cm4gZmFsc2UnPwoKPiArICAgICAgICAgICAgICAgfQo+ICsKPiArICAgICAg IHJldHVybiBzdWNjZXNzOwoKQW5kICdyZXR1cm4gdHJ1ZSc/Cgo+ICt9Cj4gKwo+ICtzdGF0aWMg c2l6ZV90IGt1bml0X21vZHVsZV9jb3VudGVyID0gMTsKPiArCj4gK3N0YXRpYyB2b2lkIGt1bml0 X3ByaW50X3N1YnRlc3RfZW5kKHN0cnVjdCBrdW5pdF9tb2R1bGUgKm1vZHVsZSkKPiArewo+ICsg ICAgICAga3VuaXRfcHJpbnRfb2tfbm90X29rKGZhbHNlLAo+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGt1bml0X21vZHVsZV9oYXNfc3VjY2VlZGVkKG1vZHVsZSksCj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAga3VuaXRfbW9kdWxlX2NvdW50ZXIrKywKPiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICBtb2R1bGUtPm5hbWUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCBrdW5pdF9wcmludF90ZXN0X2Nhc2Vfb2tfbm90X29rKHN0cnVjdCBrdW5pdF9jYXNlICp0ZXN0 X2Nhc2UsCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXpl X3QgdGVzdF9udW1iZXIpCj4gK3sKPiArICAgICAgIGt1bml0X3ByaW50X29rX25vdF9vayh0cnVl LAo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RfY2FzZS0+c3VjY2VzcywKPiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0X251bWJlciwKPiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICB0ZXN0X2Nhc2UtPm5hbWUpOwo+ICt9Cj4gKwo+ICt2b2lkIGt1bml0 X2luaXRfdGVzdChzdHJ1Y3Qga3VuaXQgKnRlc3QsIGNvbnN0IGNoYXIgKm5hbWUpCj4gK3sKPiAr ICAgICAgIHNwaW5fbG9ja19pbml0KCZ0ZXN0LT5sb2NrKTsKPiArICAgICAgIHRlc3QtPm5hbWUg PSBuYW1lOwo+ICsgICAgICAgdGVzdC0+c3VjY2VzcyA9IHRydWU7Cj4gK30KPiArCj4gKy8qCj4g KyAqIFBlcmZvcm1zIGFsbCBsb2dpYyB0byBydW4gYSB0ZXN0IGNhc2UuCj4gKyAqLwo+ICtzdGF0 aWMgdm9pZCBrdW5pdF9ydW5fY2FzZShzdHJ1Y3Qga3VuaXRfbW9kdWxlICptb2R1bGUsCj4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGt1bml0X2Nhc2UgKnRlc3RfY2FzZSkKPiAr ewo+ICsgICAgICAgc3RydWN0IGt1bml0IHRlc3Q7Cj4gKyAgICAgICBpbnQgcmV0ID0gMDsKPiAr Cj4gKyAgICAgICBrdW5pdF9pbml0X3Rlc3QoJnRlc3QsIHRlc3RfY2FzZS0+bmFtZSk7Cj4gKwo+ ICsgICAgICAgaWYgKG1vZHVsZS0+aW5pdCkgewo+ICsgICAgICAgICAgICAgICByZXQgPSBtb2R1 bGUtPmluaXQoJnRlc3QpOwo+ICsgICAgICAgICAgICAgICBpZiAocmV0KSB7Cj4gKyAgICAgICAg ICAgICAgICAgICAgICAga3VuaXRfZXJyKCZ0ZXN0LCAiZmFpbGVkIHRvIGluaXRpYWxpemU6ICVk XG4iLCByZXQpOwo+ICsgICAgICAgICAgICAgICAgICAgICAgIGt1bml0X3NldF9zdWNjZXNzKCZ0 ZXN0LCBmYWxzZSk7Cj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwo+ICsgICAgICAg ICAgICAgICB9Cj4gKyAgICAgICB9Cj4gKwo+ICsgICAgICAgaWYgKCFyZXQpCj4gKyAgICAgICAg ICAgICAgIHRlc3RfY2FzZS0+cnVuX2Nhc2UoJnRlc3QpOwoKRG8gd2UgbmVlZCB0aGlzIGlmIGNv bmRpdGlvbj8gcmV0IGNhbiBvbmx5IGJlIHNldCB0byBub24temVybyBhYm92ZSBidXQKdGhlbiB3 ZSdsbCBleGl0IHRoZSBmdW5jdGlvbiBlYXJseSBzbyBpdCBzZWVtcyB1bm5lY2Vzc2FyeS4gR2l2 ZW4gdGhhdCwKcmV0IHNob3VsZCBwcm9iYWJseSBiZSBtb3ZlZCBpbnRvIHRoZSBtb2R1bGUtPmlu aXQgcGF0aC4KCj4gKwo+ICsgICAgICAgaWYgKG1vZHVsZS0+ZXhpdCkKPiArICAgICAgICAgICAg ICAgbW9kdWxlLT5leGl0KCZ0ZXN0KTsKPiArCj4gKyAgICAgICB0ZXN0X2Nhc2UtPnN1Y2Nlc3Mg PSBrdW5pdF9nZXRfc3VjY2VzcygmdGVzdCk7Cj4gK30KPiArCl9fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRl dmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9t YWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbA==