From patchwork Tue Oct 3 09:10:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407305 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1284BE75436 for ; Tue, 3 Oct 2023 09:13:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 55FCC10E2AD; Tue, 3 Oct 2023 09:13:29 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0AF4810E26F; Tue, 3 Oct 2023 09:13:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324407; x=1727860407; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gSF43gsTUeLo/9BscsXV0SubQpBgl6xhJTCloI7NOBg=; b=WS1PIatPbe0m4cd24x1ahD6LDlv11R3vDlyNBE7QKigZcdOxuVR3U7B6 +z8KMYtQx2kK24VXI8dn/2ifdQ0vR6O7BpwZWBW4lsEWO9W4LxLYmGEbz uZfCgOy9TfvRSUvxXapn7XD2xIO84luzQvDXKpOsxB16/co5NqqKA3F7o 7U3Ni/ft4rNRx5LhjJpiwnZN8GVZJZHfMbIKrGUbg/sV396QmUk4Ewgg8 0dc90seYAY2oNt6h3XaBmVf5MOkipNmqUePsR4N79BRQmqnskt+tNzONs AGbchsHhd9mDFVpFafEuuyDu0yszy70oGxwKl/k6tTYpKAdMELoSSMXFu A==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419695" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419695" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935731" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935731" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:19 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:46 +0200 Message-ID: <20231003091044.407965-12-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 1/9] lib/kunit: Fix handling of potential errors from F_GETFL X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Function fcntl(..., F_GETFL, ...) that returns file status flags may also return a negative error code. Handle that error instead of blindly using the returned value as flags. Signed-off-by: Janusz Krzysztofik Reviewed-by: Kamil Konieczny --- lib/igt_kmod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index d98e6c5f9e..05ff178b27 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -783,8 +783,8 @@ static void __igt_kunit(struct igt_ktest *tst, const char *opts) igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n"); - flags = fcntl(tst->kmsg, F_GETFL, 0) & ~O_NONBLOCK; - igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags) == -1, + igt_skip_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0)); + igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK) == -1, "Could not set /dev/kmsg to blocking mode\n"); igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); From patchwork Tue Oct 3 09:10:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407306 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 98F93E75436 for ; Tue, 3 Oct 2023 09:13:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E1D4710E2C0; Tue, 3 Oct 2023 09:13:31 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 35E8F10E039; Tue, 3 Oct 2023 09:13:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324407; x=1727860407; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lzvV8s+EpQm2AeZ7Nktrs/HZQJ2NeXSeewgj0+Mm3og=; b=CIRadP94+OQ79gsV7xQtZTCi7ynYQLLN4XgnqTmmXXDNu3T9dEscOgpT eHaY3QrMqhuxI9Q32VSfyz+4LN5vco/kPU6UysT2E9niMbwUqDFX17OPn NGGYYlQhgiaRAmvgqux667vvl/DzNiwoa3XL1F57UBY2WIAeN05WwTHVT CDAs5+JJl+QcY8MMwNEuXIoi5ogWXxRQll9jHS+XMhq4ObFg58hueAF8u RlBXtZY1Io6eLm2lyn5cawkGfSiIfH+glKQMz61mVKGLrMSb2k2gldxdi WSswckIBZ1Ut+M+V5P6J7lFccS0EUjZ4Sa86U75TxjDcPnHZiX5oeYfEg Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419698" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419698" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935751" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935751" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:21 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:47 +0200 Message-ID: <20231003091044.407965-13-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 2/9] lib/kunit: Be more verbose on errors X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Use a more verbose variant of igt_fail() when failing a dynamic sub- subtest on kernel taint. Also, print a debug message on string duplication failure. Signed-off-by: Janusz Krzysztofik Reviewed-by: Kamil Konieczny --- lib/igt_kmod.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index 05ff178b27..df0e650d49 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -834,7 +834,7 @@ static void __igt_kunit(struct igt_ktest *tst, const char *opts) if (!pthread_tryjoin_np(modprobe_thread, NULL)) igt_assert_eq(modprobe.err, 0); - igt_fail_on(igt_kernel_tainted(&taints)); + igt_assert_eq(igt_kernel_tainted(&taints), 0); } free(result); @@ -861,7 +861,7 @@ void igt_kunit(const char *module_name, const char *name, const char *opts) */ if (!name) { name = strdup(module_name); - if (name) { + if (!igt_debug_on(!name)) { char *suffix = strstr(name, "_test"); if (!suffix) From patchwork Tue Oct 3 09:10:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407307 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DCE63E75437 for ; Tue, 3 Oct 2023 09:13:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D80E310E2A0; Tue, 3 Oct 2023 09:13:31 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 43A5510E276; Tue, 3 Oct 2023 09:13:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324407; x=1727860407; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=w9EPQd5jzPLg6WCyJIZgR2rX1m23RaW/THesNn3lM7s=; b=VgArYAgh+YYias8oSe6SOQwcpUoQAA80i1lx9vct/sRHNY0KbWTI8zAc tl/ye2NJpr6FUSGk/08qwbU+puEIFTBqzg0Tyz/1FOD53a55/l7i+Vzbb 4z9Py0CO930hq0aTrVsIwFHvNPV7NMd6K17bOikLKvZRe/zoeuI5GRCfQ rGDRG5Rdem39QYPHqmHT2OrWYXndIepdTZFVbPvjv89k24Ymsmk0+IuR7 y6J1dZipB0/cPcmDct5ffHa+6sp3pDEBe85LHrrnkoT/DK3YSsaEXMMnM Wvz5Nde8rdzx6xCBvprbGTMeGSFQLw2v+J5NBhMYlkGyOyJh6SU2Bt2U1 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419703" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419703" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:27 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935766" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935766" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:24 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:48 +0200 Message-ID: <20231003091044.407965-14-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 3/9] lib/kunit: Fix misplaced igt_kunit() doc X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" When igt_kunit() was converted to a helper and wrapped with a new function promoted to take the name and role of the library API, related documentation was left unchanged and still placed in front the demoted function. Update that documentation and move it to where it now belongs. Signed-off-by: Janusz Krzysztofik Reviewed-by: Kamil Konieczny --- lib/igt_kmod.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index df0e650d49..426ae5b26f 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -762,15 +762,6 @@ static void *modprobe_task(void *arg) return NULL; } -/** - * igt_kunit: - * @module_name: the name of the module - * @opts: options to load the module - * - * Loads the test module, parses its (k)tap dmesg output, then unloads it - * - * Returns: IGT default codes - */ static void __igt_kunit(struct igt_ktest *tst, const char *opts) { struct modprobe_data modprobe = { tst->kmod, opts, 0, }; @@ -849,6 +840,14 @@ static void __igt_kunit(struct igt_ktest *tst, const char *opts) igt_skip_on_f(ret, "KTAP parser failed\n"); } +/** + * igt_kunit: + * @module_name: the name of the module + * @name: the name of subtest, if different from that derived from module name + * @opts: options to load the module + * + * Loads the test module, parses its (k)tap dmesg output, then unloads it + */ void igt_kunit(const char *module_name, const char *name, const char *opts) { struct igt_ktest tst = { .kmsg = -1, }; From patchwork Tue Oct 3 09:10:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407308 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 59FF7E75438 for ; Tue, 3 Oct 2023 09:13:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5737710E265; Tue, 3 Oct 2023 09:13:34 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5D87910E2C2; Tue, 3 Oct 2023 09:13:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324413; x=1727860413; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Om66glrfse74I7CDT6gaQzjaa+XQRX61ASMLu5B/vEY=; b=IraXQvMzCps7s24T51nx/Dty4Wn/nlJJX52wir6FfUTOuEHuCL4qn+SK /XACF6YA0DRQgigJqozKkusgHmWXm/TpquSdVdFBtbt1V0Thu8ye0DMiL 05hVwsumsm6EdRfyERrf73uKv+oFo1jjo6eNY0prZiSQ0fyEsu5c6kh9b I4BD04RcW3kVZDsgT5b6gck+vsWdr8DByVGiINxqCoq0jejIId4i+rDRq WO4iLzQlRHC84JINL1cvUY9lZM7yJ5uWkYb9AgCbNcX3FVA7OozpmWztT cpxR7b46vHNRdDAH169pH4/Telqdah+zrZPB8US67LsZZ1mCkNZVNwdIx w==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419723" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419723" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935776" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935776" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:25 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:49 +0200 Message-ID: <20231003091044.407965-15-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 4/9] lib/kunit: Parse KTAP report from the main process thread X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" There was an attempt to parse KTAP reports in the background while a kunit test module is loading. However, since dynamic sub-subtests can be executed only from the main thread, that attempt was not quite successful, as IGT results from all executed kunit test cases were generated only after loading of kunit test module completed. Now that the parser maintains its state and we can call it separately for each input line of a KTAP report, it is perfectly possible to call the parser from the main thread while the module is loading in the background, and convert results from kunit test cases immediately to results of IGT dynamic sub-subtests by running an igt_dynamic() section for each result as soon as returned by the parser. Drop igt_ktap_parser() thread and execute igt_dynamic() for each kunit result obtained from igt_ktap_parse() called from the main thread. Also, drop no longer needed functions from igt_ktap soruces. v3: Fix ktap structure not freed on lseek error, - fix initial SIGCHLD handler not restored, - fix missing handling of potential errors returned by sigaction, - fix potential race of read() vs. ptherad_kill(), use robust mutex for synchronization with modprobe thread, - fix potentially illegal use of igt_assert() called outside of dynamic sub-subtest section, - fix unsupported exit code potentially passed to igt_fail(), - no need to fail a dynamic sub-subtest on potential KTAP parser error after a valid result from the parser has been processed, - fix trailing newlines missing from error messages, - add more debug statements, - integrate common code around kunit_result_free() into it. v2: Interrupt blocking read() on modprobe failure. Signed-off-by: Janusz Krzysztofik Acked-by: Mauro Carvalho Chehab # v2 --- lib/igt_kmod.c | 261 +++++++++++++++++++---- lib/igt_ktap.c | 568 ------------------------------------------------- lib/igt_ktap.h | 22 -- 3 files changed, 222 insertions(+), 629 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index 426ae5b26f..7bca4cdaab 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016 Intel Corporation + * Copyright © 2016-2023 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,7 +26,12 @@ #include #include #include +#include +#include #include +#include + +#include "assembler/brw_compat.h" /* [un]likely() */ #include "igt_aux.h" #include "igt_core.h" @@ -748,9 +753,12 @@ void igt_kselftest_get_tests(struct kmod_module *kmod, } struct modprobe_data { + pthread_t parent; struct kmod_module *kmod; const char *opts; int err; + pthread_mutex_t lock; + pthread_t thread; }; static void *modprobe_task(void *arg) @@ -759,16 +767,132 @@ static void *modprobe_task(void *arg) data->err = modprobe(data->kmod, data->opts); + if (igt_debug_on(data->err)) { + int err; + + while (err = pthread_mutex_trylock(&data->lock), + err && !igt_debug_on(err != EBUSY)) + igt_debug_on(pthread_kill(data->parent, SIGCHLD)); + } else { + /* let main thread use mutex to detect modprobe completion */ + igt_debug_on(pthread_mutex_lock(&data->lock)); + } + return NULL; } +static void kunit_sigchld_handler(int signal) +{ + return; +} + +static int kunit_kmsg_result_get(struct igt_list_head *results, + struct modprobe_data *modprobe, + int fd, struct igt_ktap_results *ktap) +{ + struct sigaction sigchld = { .sa_handler = kunit_sigchld_handler, }, + *saved; + char record[BUF_LEN + 1], *buf; + unsigned long taints; + int ret; + + do { + int err; + + if (igt_debug_on(igt_kernel_tainted(&taints))) + return -ENOTRECOVERABLE; + + err = igt_debug_on(sigaction(SIGCHLD, &sigchld, saved)); + if (err == -1) + return -errno; + else if (unlikely(err)) + return err; + + err = pthread_mutex_lock(&modprobe->lock); + switch (err) { + case EOWNERDEAD: + /* leave the mutex unrecoverable */ + igt_debug_on(pthread_mutex_unlock(&modprobe->lock)); + __attribute__ ((fallthrough)); + case ENOTRECOVERABLE: + igt_debug_on(sigaction(SIGCHLD, saved, NULL)); + if (igt_debug_on(modprobe->err)) + return modprobe->err; + break; + case 0: + break; + default: + igt_debug("pthread_mutex_lock() error: %d\n", err); + igt_debug_on(sigaction(SIGCHLD, saved, NULL)); + return -err; + } + + ret = read(fd, record, BUF_LEN); + + if (!err) { + igt_debug_on(pthread_mutex_unlock(&modprobe->lock)); + igt_debug_on(sigaction(SIGCHLD, saved, NULL)); + } + + if (igt_debug_on(!ret)) + return -ENODATA; + if (igt_debug_on(ret == -1)) + return -errno; + if (unlikely(igt_debug_on(ret < 0))) + break; + + /* skip kmsg continuation lines */ + if (igt_debug_on(*record == ' ')) + continue; + + /* NULL-terminate the record */ + record[ret] = '\0'; + + /* detect start of log message, continue if not found */ + buf = strchrnul(record, ';'); + if (igt_debug_on(*buf == '\0')) + continue; + buf++; + + ret = igt_ktap_parse(buf, ktap); + if (!ret || igt_debug_on(ret != -EINPROGRESS)) + break; + } while (igt_list_empty(results)); + + return ret; +} + +static void kunit_result_free(struct igt_ktap_result **r, + char **suite_name, char **case_name) +{ + if (!*r) + return; + + igt_list_del(&(*r)->link); + + if ((*r)->suite_name != *suite_name) { + free(*suite_name); + *suite_name = (*r)->suite_name; + } + + if ((*r)->case_name != *case_name) { + free(*case_name); + *case_name = (*r)->case_name; + } + + free((*r)->msg); + free(*r); + *r = NULL; +} + static void __igt_kunit(struct igt_ktest *tst, const char *opts) { - struct modprobe_data modprobe = { tst->kmod, opts, 0, }; - struct kmod_module *kunit_kmod; - bool is_builtin; - struct ktap_test_results *results; - pthread_t modprobe_thread; + struct modprobe_data modprobe = { pthread_self(), tst->kmod, opts, 0, }; + char *suite_name = NULL, *case_name = NULL; + struct igt_ktap_result *r, *rn; + struct igt_ktap_results *ktap; + pthread_mutexattr_t attr; + IGT_LIST_HEAD(results); unsigned long taints; int flags, ret; @@ -780,60 +904,119 @@ static void __igt_kunit(struct igt_ktest *tst, const char *opts) igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); - igt_skip_on(kmod_module_new_from_name(kmod_ctx(), "kunit", &kunit_kmod)); - is_builtin = kmod_module_get_initstate(kunit_kmod) == KMOD_MODULE_BUILTIN; - kmod_module_unref(kunit_kmod); + igt_skip_on(pthread_mutexattr_init(&attr)); + igt_skip_on(pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)); + igt_skip_on(pthread_mutex_init(&modprobe.lock, &attr)); - results = ktap_parser_start(tst->kmsg, is_builtin); + ktap = igt_ktap_alloc(&results); + igt_require(ktap); - if (igt_debug_on(pthread_create(&modprobe_thread, NULL, + if (igt_debug_on(pthread_create(&modprobe.thread, NULL, modprobe_task, &modprobe))) { - ktap_parser_cancel(); - igt_ignore_warn(ktap_parser_stop()); + igt_ktap_free(ktap); igt_skip("Failed to create a modprobe thread\n"); } - while (READ_ONCE(results->still_running) || !igt_list_empty(&results->list)) - { - struct ktap_test_results_element *result; - - if (!pthread_tryjoin_np(modprobe_thread, NULL) && modprobe.err) { - ktap_parser_cancel(); + do { + ret = kunit_kmsg_result_get(&results, &modprobe, + tst->kmsg, ktap); + if (igt_debug_on(ret && ret != -EINPROGRESS)) break; - } - if (igt_kernel_tainted(&taints)) { - ktap_parser_cancel(); - pthread_cancel(modprobe_thread); + if (igt_debug_on(igt_list_empty(&results))) break; - } - pthread_mutex_lock(&results->mutex); - if (igt_list_empty(&results->list)) { - pthread_mutex_unlock(&results->mutex); - continue; - } + r = igt_list_first_entry(&results, r, link); - result = igt_list_first_entry(&results->list, result, link); + igt_dynamic_f("%s-%s", r->suite_name, r->case_name) { + if (r->code == IGT_EXIT_INVALID) { + /* parametrized test case, get actual result */ + kunit_result_free(&r, &suite_name, &case_name); - igt_list_del(&result->link); - pthread_mutex_unlock(&results->mutex); + igt_assert(igt_list_empty(&results)); - igt_dynamic(result->test_name) { - igt_assert(READ_ONCE(result->passed)); + ret = kunit_kmsg_result_get(&results, &modprobe, + tst->kmsg, ktap); + if (ret != -EINPROGRESS) + igt_fail_on(ret); + + igt_fail_on(igt_list_empty(&results)); + + r = igt_list_first_entry(&results, r, link); + + igt_fail_on_f(strcmp(r->suite_name, suite_name), + "suite_name expected: %s, got: %s\n", + suite_name, r->suite_name); + igt_fail_on_f(strcmp(r->case_name, case_name), + "case_name expected: %s, got: %s\n", + case_name, r->case_name); + } - if (!pthread_tryjoin_np(modprobe_thread, NULL)) + igt_assert_neq(r->code, IGT_EXIT_INVALID); + + if (r->msg && *r->msg) { + igt_skip_on_f(r->code == IGT_EXIT_SKIP, + "%s\n", r->msg); + igt_fail_on_f(r->code == IGT_EXIT_FAILURE, + "%s\n", r->msg); + igt_abort_on_f(r->code == IGT_EXIT_ABORT, + "%s\n", r->msg); + } else { + igt_skip_on(r->code == IGT_EXIT_SKIP); + igt_fail_on(r->code == IGT_EXIT_FAILURE); + if (r->code == IGT_EXIT_ABORT) + igt_fail(r->code); + } + igt_assert_eq(r->code, IGT_EXIT_SUCCESS); + + switch (pthread_mutex_lock(&modprobe.lock)) { + case 0: + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + break; + case EOWNERDEAD: + /* leave the mutex unrecoverable */ + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + __attribute__ ((fallthrough)); + case ENOTRECOVERABLE: igt_assert_eq(modprobe.err, 0); + break; + default: + igt_debug("pthread_mutex_lock() failed\n"); + break; + } igt_assert_eq(igt_kernel_tainted(&taints), 0); } - free(result); + kunit_result_free(&r, &suite_name, &case_name); + + } while (ret == -EINPROGRESS); + + igt_list_for_each_entry_safe(r, rn, &results, link) + kunit_result_free(&r, &suite_name, &case_name); + + free(case_name); + free(suite_name); + + switch (pthread_mutex_lock(&modprobe.lock)) { + case 0: + igt_debug_on(pthread_cancel(modprobe.thread)); + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + igt_debug_on(pthread_join(modprobe.thread, NULL)); + break; + case EOWNERDEAD: + /* leave the mutex unrecoverable */ + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + break; + case ENOTRECOVERABLE: + break; + default: + igt_debug("pthread_mutex_lock() failed\n"); + igt_debug_on(pthread_join(modprobe.thread, NULL)); + break; } - pthread_join(modprobe_thread, NULL); - - ret = ktap_parser_stop(); + igt_ktap_free(ktap); igt_skip_on(modprobe.err); igt_skip_on(igt_kernel_tainted(&taints)); diff --git a/lib/igt_ktap.c b/lib/igt_ktap.c index 5eac102417..53a6c63288 100644 --- a/lib/igt_ktap.c +++ b/lib/igt_ktap.c @@ -4,17 +4,11 @@ * Copyright © 2023 Intel Corporation */ -#include -#include -#include -#include #include #include #include #include -#include -#include "igt_aux.h" #include "igt_core.h" #include "igt_ktap.h" #include "igt_list.h" @@ -312,565 +306,3 @@ void igt_ktap_free(struct igt_ktap_results *ktap) { free(ktap); } - -#define DELIMITER "-" - -struct ktap_parser_args { - int fd; - bool is_builtin; - int ret; -} ktap_args; - -static struct ktap_test_results results; - -static int log_to_end(enum igt_log_level level, int fd, - char *record, const char *format, ...) __attribute__((format(printf, 4, 5))); - -/** - * log_to_end: - * @level: #igt_log_level - * @record: record to store the read data - * @format: format string - * @...: optional arguments used in the format string - * - * This is an altered version of the generic structured logging helper function - * igt_log capable of reading to the end of a given line. - * - * Returns: 0 for success, or -2 if there's an error reading from the file - */ -static int log_to_end(enum igt_log_level level, int fd, - char *record, const char *format, ...) -{ - va_list args; - const char *lend; - - /* Cutoff after newline character, in order to not display garbage */ - char *cutoff = strchr(record, '\n'); - if (cutoff) { - if (cutoff - record < BUF_LEN) - cutoff[1] = '\0'; - } - - va_start(args, format); - igt_vlog(IGT_LOG_DOMAIN, level, format, args); - va_end(args); - - lend = strchrnul(record, '\n'); - while (*lend == '\0') { - igt_log(IGT_LOG_DOMAIN, level, "%s", record); - - if (read(fd, record, BUF_LEN) < 0) { - if (errno == EPIPE) - igt_warn("kmsg truncated: too many messages. You may want to increase log_buf_len in kmcdline\n"); - else - igt_warn("an error occurred while reading kmsg: %m\n"); - - return -2; - } - - lend = strchrnul(record, '\n'); - } - return 0; -} - -/** - * lookup_value: - * @haystack: the string to search in - * @needle: the string to search for - * - * Returns: the value of the needle in the haystack, or -1 if not found. - */ -static long lookup_value(const char *haystack, const char *needle) -{ - const char *needle_rptr; - char *needle_end; - long num; - - needle_rptr = strcasestr(haystack, needle); - - if (needle_rptr == NULL) - return -1; - - /* Skip search string and whitespaces after it */ - needle_rptr += strlen(needle); - - num = strtol(needle_rptr, &needle_end, 10); - - if (needle_rptr == needle_end) - return -1; - - if (num == LONG_MIN || num == LONG_MAX) - return 0; - - return num > 0 ? num : 0; -} - -/** - * tap_version_present: - * @record: buffer with tap data - * @print_info: whether tap version should be printed or not - * - * Returns: - * 0 if not found - * 1 if found - */ -static int tap_version_present(char* record, bool print_info) -{ - /* - * "(K)TAP version XX" should be the first line on all (sub)tests as per - * https://kernel.org/doc/html/latest/dev-tools/ktap.html#version-lines - * - * but actually isn't, as it currently depends on the KUnit module - * being built-in, so we can't rely on it every time - */ - const char *version_rptr = strcasestr(record, "TAP version "); - char *cutoff; - - if (version_rptr == NULL) - return 0; - - /* Cutoff after newline character, in order to not display garbage */ - cutoff = strchr(version_rptr, '\n'); - if (cutoff) - cutoff[0] = '\0'; - - if (print_info) - igt_info("%s\n", version_rptr); - - return 1; -} - -/** - * find_next_tap_subtest: - * @fd: file descriptor - * @record: buffer used to read fd - * @is_builtin: whether KUnit is built-in or not - * - * Returns: - * 0 if there's missing information - * -1 if not found - * -2 if there are problems while reading the file. - * any other value corresponds to the amount of cases of the next (sub)test - */ -static int find_next_tap_subtest(int fd, char *record, char *test_name, bool is_builtin) -{ - const char *test_lookup_str, *subtest_lookup_str, *name_rptr; - long test_count; - char *cutoff; - - test_name[0] = '\0'; - test_name[BUF_LEN] = '\0'; - - test_lookup_str = " subtest: "; - subtest_lookup_str = " test: "; - - if (!tap_version_present(record, true)) - return -1; - - if (is_builtin) { - if (read(fd, record, BUF_LEN) < 0) { - if (errno == EPIPE) - igt_warn("kmsg truncated: too many messages. You may want to increase log_buf_len in kmcdline\n"); - else - igt_warn("an error occurred while reading kmsg: %m\n"); - - return -2; - } - } - - name_rptr = strcasestr(record, test_lookup_str); - if (name_rptr != NULL) { - name_rptr += strlen(test_lookup_str); - } else { - name_rptr = strcasestr(record, subtest_lookup_str); - if (name_rptr != NULL) - name_rptr += strlen(subtest_lookup_str); - } - - if (name_rptr == NULL) { - if (!is_builtin) - /* We've probably found nothing */ - return -1; - igt_info("Missing test name\n"); - } else { - strncpy(test_name, name_rptr, BUF_LEN); - /* Cutoff after newline character, in order to not display garbage */ - cutoff = strchr(test_name, '\n'); - if (cutoff) - cutoff[0] = '\0'; - - if (read(fd, record, BUF_LEN) < 0) { - if (errno == EPIPE) - igt_warn("kmsg truncated: too many messages. You may want to increase log_buf_len in kmcdline\n"); - else - igt_warn("unknown error reading kmsg (%m)\n"); - - return -2; - } - - /* Now we can be sure we found tests */ - if (!is_builtin) - igt_info("KUnit is not built-in, skipping version check...\n"); - } - - /* - * Total test count will almost always appear as 0..N at the beginning - * of a run, so we use it to reliably identify a new run - */ - test_count = lookup_value(record, ".."); - - if (test_count <= 0) { - igt_info("Missing test count\n"); - if (test_name[0] == '\0') - return 0; - if (log_to_end(IGT_LOG_INFO, fd, record, - "Running some tests in: %s\n", - test_name) < 0) - return -2; - return 0; - } else if (test_name[0] == '\0') { - igt_info("Running %ld tests...\n", test_count); - return 0; - } - - if (log_to_end(IGT_LOG_INFO, fd, record, - "Executing %ld tests in: %s\n", - test_count, test_name) < 0) - return -2; - - return test_count; -} - -/** - * parse_kmsg_for_tap: - * @fd: file descriptor - * @record: buffer used to read fd - * @test_name: buffer to store the test name - * - * Returns: - * 1 if no results were found - * 0 if a test succeded - * -1 if a test failed - * -2 if there are problems reading the file - */ -static int parse_kmsg_for_tap(int fd, char *record, char *test_name) -{ - const char *lstart, *ok_lookup_str, *nok_lookup_str, - *ok_rptr, *nok_rptr, *comment_start, *value_parse_start; - char *test_name_end; - - ok_lookup_str = "ok "; - nok_lookup_str = "not ok "; - - lstart = strchrnul(record, ';'); - - if (*lstart == '\0') { - igt_warn("kmsg truncated: output malformed (%m)\n"); - return -2; - } - - lstart++; - while (isspace(*lstart)) - lstart++; - - nok_rptr = strstr(lstart, nok_lookup_str); - if (nok_rptr != NULL) { - nok_rptr += strlen(nok_lookup_str); - while (isdigit(*nok_rptr) || isspace(*nok_rptr) || *nok_rptr == '-') - nok_rptr++; - test_name_end = strncpy(test_name, nok_rptr, BUF_LEN); - while (!isspace(*test_name_end)) - test_name_end++; - *test_name_end = '\0'; - if (log_to_end(IGT_LOG_WARN, fd, record, - "%s", lstart) < 0) - return -2; - return -1; - } - - comment_start = strchrnul(lstart, '#'); - - /* Check if we're still in a subtest */ - if (*comment_start != '\0') { - comment_start++; - value_parse_start = comment_start; - - if (lookup_value(value_parse_start, "fail: ") > 0) { - if (log_to_end(IGT_LOG_WARN, fd, record, - "%s", lstart) < 0) - return -2; - return -1; - } - } - - ok_rptr = strstr(lstart, ok_lookup_str); - if (ok_rptr != NULL) { - ok_rptr += strlen(ok_lookup_str); - while (isdigit(*ok_rptr) || isspace(*ok_rptr) || *ok_rptr == '-') - ok_rptr++; - test_name_end = strncpy(test_name, ok_rptr, BUF_LEN); - while (!isspace(*test_name_end)) - test_name_end++; - *test_name_end = '\0'; - return 0; - } - - return 1; -} - -/** - * parse_tap_level: - * @fd: file descriptor - * @base_test_name: test_name from upper recursion level - * @test_count: test_count of this level - * @failed_tests: top level failed_tests pointer - * @found_tests: top level found_tests pointer - * @is_builtin: whether the KUnit module is built-in or not - * - * Returns: - * 0 if succeded - * -1 if error occurred - */ -__maybe_unused -static int parse_tap_level(int fd, char *base_test_name, int test_count, bool *failed_tests, - bool *found_tests, bool is_builtin) -{ - char record[BUF_LEN + 1]; - struct ktap_test_results_element *r; - int internal_test_count; - char test_name[BUF_LEN + 1]; - char base_test_name_for_next_level[BUF_LEN + 1]; - - for (int i = 0; i < test_count; i++) { - if (read(fd, record, BUF_LEN) < 0) { - if (errno == EPIPE) - igt_warn("kmsg truncated: too many messages. You may want to increase log_buf_len in kmcdline\n"); - else - igt_warn("error reading kmsg (%m)\n"); - - return -1; - } - - /* Sublevel found */ - if (tap_version_present(record, false)) - { - internal_test_count = find_next_tap_subtest(fd, record, test_name, - is_builtin); - switch (internal_test_count) { - case -2: - /* No more data to read */ - return -1; - case -1: - /* No test found */ - return -1; - case 0: - /* Tests found, but they're missing info */ - *found_tests = true; - return -1; - default: - *found_tests = true; - - memcpy(base_test_name_for_next_level, base_test_name, BUF_LEN); - if (strlen(base_test_name_for_next_level) < BUF_LEN - 1 && - base_test_name_for_next_level[0]) - strncat(base_test_name_for_next_level, DELIMITER, - BUF_LEN - strlen(base_test_name_for_next_level)); - memcpy(base_test_name_for_next_level + strlen(base_test_name_for_next_level), - test_name, BUF_LEN - strlen(base_test_name_for_next_level)); - - if (parse_tap_level(fd, base_test_name_for_next_level, - internal_test_count, failed_tests, found_tests, - is_builtin) == -1) - return -1; - break; - } - } - - switch (parse_kmsg_for_tap(fd, record, test_name)) { - case -2: - return -1; - case -1: - *failed_tests = true; - - r = malloc(sizeof(*r)); - - memcpy(r->test_name, base_test_name, BUF_LEN); - if (strlen(r->test_name) < BUF_LEN - 1) - if (r->test_name[0]) - strncat(r->test_name, DELIMITER, - BUF_LEN - strlen(r->test_name)); - memcpy(r->test_name + strlen(r->test_name), test_name, - BUF_LEN - strlen(r->test_name)); - r->test_name[BUF_LEN] = '\0'; - - r->passed = false; - - pthread_mutex_lock(&results.mutex); - igt_list_add_tail(&r->link, &results.list); - pthread_mutex_unlock(&results.mutex); - - test_name[0] = '\0'; - break; - case 0: - r = malloc(sizeof(*r)); - - memcpy(r->test_name, base_test_name, BUF_LEN); - if (strlen(r->test_name) < BUF_LEN - 1) - if (r->test_name[0]) - strncat(r->test_name, DELIMITER, - BUF_LEN - strlen(r->test_name)); - memcpy(r->test_name + strlen(r->test_name), test_name, - BUF_LEN - strlen(r->test_name)); - r->test_name[BUF_LEN] = '\0'; - - r->passed = true; - - pthread_mutex_lock(&results.mutex); - igt_list_add_tail(&r->link, &results.list); - pthread_mutex_unlock(&results.mutex); - - test_name[0] = '\0'; - break; - default: - break; - } - } - return 0; -} - -/** - * igt_ktap_parser: - * - * This function parses the output of a ktap script and passes it to main thread. - */ -void *igt_ktap_parser(void *unused) -{ - char record[BUF_LEN + 1], *buf, *suite_name = NULL, *case_name = NULL; - struct igt_ktap_results *ktap = NULL; - int fd = ktap_args.fd; - IGT_LIST_HEAD(list); - int err; - - ktap = igt_ktap_alloc(&list); - if (igt_debug_on(!ktap)) - goto igt_ktap_parser_end; - - while (err = read(fd, record, BUF_LEN), err > 0) { - struct igt_ktap_result *r, *rn; - - /* skip kmsg continuation lines */ - if (igt_debug_on(*record == ' ')) - continue; - - /* NULL-terminate the record */ - record[err] = '\0'; - - /* detect start of log message, continue if not found */ - buf = strchrnul(record, ';'); - if (igt_debug_on(*buf == '\0')) - continue; - buf++; - - err = igt_ktap_parse(buf, ktap); - - /* parsing error */ - if (err && err != -EINPROGRESS) - goto igt_ktap_parser_end; - - igt_list_for_each_entry_safe(r, rn, &list, link) { - struct ktap_test_results_element *result = NULL; - int code = r->code; - - if (code != IGT_EXIT_INVALID) - result = calloc(1, sizeof(*result)); - - if (result) { - snprintf(result->test_name, sizeof(result->test_name), - "%s-%s", r->suite_name, r->case_name); - - if (code == IGT_EXIT_SUCCESS) - result->passed = true; - } - - igt_list_del(&r->link); - if (r->suite_name != suite_name) { - free(suite_name); - suite_name = r->suite_name; - } - if (r->case_name != case_name) { - free(case_name); - case_name = r->case_name; - } - free(r->msg); - free(r); - - /* - * no extra result record expected on start - * of parametrized test case -- skip it - */ - if (code == IGT_EXIT_INVALID) - continue; - - if (!result) { - err = -ENOMEM; - goto igt_ktap_parser_end; - } - - pthread_mutex_lock(&results.mutex); - igt_list_add_tail(&result->link, &results.list); - pthread_mutex_unlock(&results.mutex); - } - - /* end of KTAP report */ - if (!err) - goto igt_ktap_parser_end; - } - - if (err < 0) { - if (errno == EPIPE) - igt_warn("kmsg truncated: too many messages. You may want to increase log_buf_len in kmcdline\n"); - else - igt_warn("error reading kmsg (%m)\n"); - } - -igt_ktap_parser_end: - free(suite_name); - free(case_name); - - if (!err) - ktap_args.ret = IGT_EXIT_SUCCESS; - - results.still_running = false; - - if (ktap) - igt_ktap_free(ktap); - - return NULL; -} - -static pthread_t ktap_parser_thread; - -struct ktap_test_results *ktap_parser_start(int fd, bool is_builtin) -{ - IGT_INIT_LIST_HEAD(&results.list); - pthread_mutex_init(&results.mutex, NULL); - results.still_running = true; - - ktap_args.fd = fd; - ktap_args.is_builtin = is_builtin; - ktap_args.ret = IGT_EXIT_FAILURE; - pthread_create(&ktap_parser_thread, NULL, igt_ktap_parser, NULL); - - return &results; -} - -void ktap_parser_cancel(void) -{ - pthread_cancel(ktap_parser_thread); -} - -int ktap_parser_stop(void) -{ - pthread_join(ktap_parser_thread, NULL); - return ktap_args.ret; -} diff --git a/lib/igt_ktap.h b/lib/igt_ktap.h index 6f8da3eab6..c422636bfc 100644 --- a/lib/igt_ktap.h +++ b/lib/igt_ktap.h @@ -27,8 +27,6 @@ #define BUF_LEN 4096 -#include - #include "igt_list.h" struct igt_ktap_result { @@ -45,24 +43,4 @@ struct igt_ktap_results *igt_ktap_alloc(struct igt_list_head *results); int igt_ktap_parse(const char *buf, struct igt_ktap_results *ktap); void igt_ktap_free(struct igt_ktap_results *ktap); -void *igt_ktap_parser(void *unused); - -typedef struct ktap_test_results_element { - char test_name[BUF_LEN + 1]; - bool passed; - struct igt_list_head link; -} ktap_test_results_element; - -struct ktap_test_results { - struct igt_list_head list; - pthread_mutex_t mutex; - bool still_running; -}; - - - -struct ktap_test_results *ktap_parser_start(int fd, bool is_builtin); -void ktap_parser_cancel(void); -int ktap_parser_stop(void); - #endif /* IGT_KTAP_H */ From patchwork Tue Oct 3 09:10:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407309 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 365FBE75436 for ; Tue, 3 Oct 2023 09:13:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 351D310E276; Tue, 3 Oct 2023 09:13:36 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3BFD910E2C2; Tue, 3 Oct 2023 09:13:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324414; x=1727860414; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+Y6jUBlWNLU/D+cQG9AZGIVJHwiZ7fbGEI3+NqblW9A=; b=Qf9cnvfkTV7dpZr4P32y/TRDZrz8N42kMzUa7Pa8r1o85gaW1tU8UlFt /3WOzWR8JuXBc8yCFegsaxzQwb7f2GHJKI5ggvaX0vEjUes+lRkvYWu/S 9XK22WRxalq3SC/GMEaf94hfTFUrhJBdx2zX6z8VygUHfU2DGyGUpizUR FMA1q5l2JIoZvXI8gkgQdaajuToCsZ/pGl9XFscEVoVNp+10z82igLXOe PpM3gEFiUNVRtK41jnhzWMnMWayqx6zvSQ6h0Z4Brh4Cza2CFcslCZPdr TWc02wEEtw6PlEe4YUq6KQrV2Z8yoVeOYQ2fSZ25F2X3oI3CGzrxhKGBK Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419738" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419738" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935793" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935793" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:30 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:50 +0200 Message-ID: <20231003091044.407965-16-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 5/9] lib/kunit: Omit suite name prefix if the same as subtest name X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Kunit test modules usually contain one test suite, named after the module name with the trailing "_test" or "_kunit" suffix omitted. Since we follow the same convention when we derive subtest names from module names, there is a great chance that those two names match. Take this into account when composing names for IGT dynamic sub-subtest names and drop the leading test suite name component when it is the same as subtest name. Signed-off-by: Janusz Krzysztofik Reviewed-by: Mauro Carvalho Chehab --- lib/igt_kmod.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index 7bca4cdaab..387efbb59f 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -885,7 +885,8 @@ static void kunit_result_free(struct igt_ktap_result **r, *r = NULL; } -static void __igt_kunit(struct igt_ktest *tst, const char *opts) +static void +__igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) { struct modprobe_data modprobe = { pthread_self(), tst->kmod, opts, 0, }; char *suite_name = NULL, *case_name = NULL; @@ -928,7 +929,11 @@ static void __igt_kunit(struct igt_ktest *tst, const char *opts) r = igt_list_first_entry(&results, r, link); - igt_dynamic_f("%s-%s", r->suite_name, r->case_name) { + igt_dynamic_f("%s%s%s", + strcmp(r->suite_name, name) ? r->suite_name : "", + strcmp(r->suite_name, name) ? "-" : "", + r->case_name) { + if (r->code == IGT_EXIT_INVALID) { /* parametrized test case, get actual result */ kunit_result_free(&r, &suite_name, &case_name); @@ -1069,7 +1074,7 @@ void igt_kunit(const char *module_name, const char *name, const char *opts) * and for documentation. */ igt_subtest_with_dynamic(name) - __igt_kunit(&tst, opts); + __igt_kunit(&tst, name, opts); igt_fixture igt_ktest_end(&tst); From patchwork Tue Oct 3 09:10:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407310 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 32B57E75438 for ; Tue, 3 Oct 2023 09:13:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8D96F10E2E0; Tue, 3 Oct 2023 09:13:37 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id D242310E2C2; Tue, 3 Oct 2023 09:13:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324416; x=1727860416; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DD8VuKPpOnsT021gZVX18fv0B04T34595iYK1Xzxp2Q=; b=DxUiXntkJa708RvF5irQitvc9Ps2F8PbdAlxGmc1BbA3DO2UNSMqcPr2 DOq0RwqSyLKw+1TsmtZycOuXdZl3OmuuK+IxlbKF27L1EzPLeIzogo+TC 3lbSbWIx81F8RymSD/hBSF63LbxGm6NGysu+mROEF0no/yVhlwBmQT5x6 vVJfZ4rctkUTcGApST7abjoer2vnpO/a9V5E+eTOCPeSedx81ugkn08M9 BmdNIfDExdPl+b31wy2cEYKXMh69BhIseLEqGSiUevM9YkgxTbseouzcx sMQDVyiL+fBqLWnZkxhPeDmaCogEA8zggX4GreRdGFtMQksa0yliwE6y9 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419746" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419746" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935797" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935797" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:32 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:51 +0200 Message-ID: <20231003091044.407965-17-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 6/9] tests/kms_selftest: Let subtest names match suite names X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" There is a rule specified in Kunit Test Style and Nomenclature guidelines [1] that states modules should be named after the test suite, followed by _test. Of course, that rule applies only to modules that provide one test suite per module. As long as that rule is obeyed by authors of Kunit test modules, there is no need to hardcode related IGT subtest names in IGT source code. We are already able to derive subtest names from module names, with their _test or _kunit suffixes stripped. We may expect those names will match Kunit suite names provided by the modules. Drop custom subtest names from IGT Kunit tests that still use them. However, keep the mechanism that allows us to provide a name that differs from that derived from module name. That will be required if we ever need to support a kunit test module that provides multiple test suites (think of i915 selftests code converted to kunit and the i915 module potentially providing three test suites: mock, live and perf). [1] https://docs.kernel.org/dev-tools/kunit/style.html Signed-off-by: Janusz Krzysztofik Reviewed-by: Kamil Konieczny --- tests/kms_selftest.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/tests/kms_selftest.c b/tests/kms_selftest.c index 080ffdf2c0..6618dbe50b 100644 --- a/tests/kms_selftest.c +++ b/tests/kms_selftest.c @@ -37,35 +37,30 @@ * * arg[1]: * - * @drm_cmdline: drm cmdline - * @drm_damage: drm damage - * @drm_dp_mst: drm dp mst + * @drm_cmdline_parser: drm cmdline parser + * @drm_damage_helper: drm damage helper + * @drm_dp_mst_helper: drm dp mst helper * @drm_format_helper: drm format helper * @drm_format: drm format - * @drm_plane: drm plane - * @framebuffer: framebuffer + * @drm_plane_helper: drm plane helper + * @drm_framebuffer: drm framebuffer */ IGT_TEST_DESCRIPTION("Basic sanity check of KMS selftests."); -struct kms_kunittests { - const char *kunit; - const char *name; -}; - igt_main { - static const struct kms_kunittests kunit_subtests[] = { - { "drm_cmdline_parser_test", "drm_cmdline" }, - { "drm_damage_helper_test", "drm_damage" }, - { "drm_dp_mst_helper_test", "drm_dp_mst" }, - { "drm_format_helper_test", "drm_format_helper" }, - { "drm_format_test", "drm_format" }, - { "drm_framebuffer_test", "framebuffer" }, - { "drm_plane_helper_test", "drm_plane" }, - { NULL, NULL} + static const char *kunit_subtests[] = { + "drm_cmdline_parser_test", + "drm_damage_helper_test", + "drm_dp_mst_helper_test", + "drm_format_helper_test", + "drm_format_test", + "drm_framebuffer_test", + "drm_plane_helper_test", + NULL, }; - for (int i = 0; kunit_subtests[i].kunit != NULL; i++) - igt_kunit(kunit_subtests[i].kunit, kunit_subtests[i].name, NULL); + for (int i = 0; kunit_subtests[i] != NULL; i++) + igt_kunit(kunit_subtests[i], NULL, NULL); } From patchwork Tue Oct 3 09:10:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407311 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DD05FE75437 for ; Tue, 3 Oct 2023 09:13:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E832A10E2E6; Tue, 3 Oct 2023 09:13:41 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3295310E2D8; Tue, 3 Oct 2023 09:13:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324420; x=1727860420; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FIF1EHjL7+Al2ztOFOGJaqOUf7ZtpUKJ9/ZVYFlgHv0=; b=FV8/W/ZPGC7RyL5gTO/e4Fm8TzL/ndOYikveAymhU7cNzigK/A1GWUpW GDuuAF4znPSjnFB960L0VyC9kjk+gdIi81CuphAX7GKd7i6EkSxoHQm4g wqbbARfNFp5Upue6BPn1S6Fx0oNibZLVtHui07kyb70USwCmMkScrdMQL WTt4KJk20mtnHO5xvHzX6UTlIdsPYw9dWbJAKyPOYYO+se6Mxra9AVcHc 9mZo5kwuWqrd8z+xmg48hwoKviP7Q1RyWTPJdf86vh9oO+v7GT5X3QHHE HqNnVc7jsaNQUysSfKyNusYWmqj8dbUqFz2YAniKkM8Mod45hwbC743OS Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419748" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419748" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935801" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935801" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:34 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:52 +0200 Message-ID: <20231003091044.407965-18-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 7/9] lib/ktap: Drop workaround for missing top level KTAP headers X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" A workaround was implemented in IGT KTAP parser so it could accepted KTAP reports with missing top level KTAP version and test suite plan headers. Since kernel side commit c95e7c05c139 ("kunit: Report the count of test suites in a module"), included in the mainline kernel since v6.6-rc1, has fixed that issue, that workaround is no longer needed. Drop it. Signed-off-by: Janusz Krzysztofik --- lib/igt_ktap.c | 12 ------------ lib/tests/igt_ktap_parser.c | 3 +-- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/igt_ktap.c b/lib/igt_ktap.c index 53a6c63288..7c52ba11ed 100644 --- a/lib/igt_ktap.c +++ b/lib/igt_ktap.c @@ -84,18 +84,6 @@ int igt_ktap_parse(const char *buf, struct igt_ktap_results *ktap) igt_debug_on(sscanf(buf, "%*1[ ]%*1[ ]%*1[ ]%*1[ ]KTAP%*[ ]version%*[ ]%u %n", &n, &len) == 1 && len == strlen(buf))) { - /* - * TODO: drop the following workaround as soon as - * kernel side issue of missing lines with top level - * KTAP version and test suite plan is fixed. - */ - if (ktap->expect == KTAP_START) { - ktap->suite_count = 1; - ktap->suite_last = 0; - ktap->suite_name = NULL; - ktap->expect = SUITE_START; - } - if (igt_debug_on(ktap->expect != SUITE_START)) return -EPROTO; diff --git a/lib/tests/igt_ktap_parser.c b/lib/tests/igt_ktap_parser.c index 6357bdf6a5..476e14092f 100644 --- a/lib/tests/igt_ktap_parser.c +++ b/lib/tests/igt_ktap_parser.c @@ -190,8 +190,7 @@ static void ktap_top_version(void) ktap = igt_ktap_alloc(&results); igt_require(ktap); - /* TODO: change to -EPROTO as soon as related workaround is dropped */ - igt_assert_eq(igt_ktap_parse(" KTAP version 1\n", ktap), -EINPROGRESS); + igt_assert_eq(igt_ktap_parse(" KTAP version 1\n", ktap), -EPROTO); igt_ktap_free(ktap); ktap = igt_ktap_alloc(&results); From patchwork Tue Oct 3 09:10:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407312 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6400E7543A for ; Tue, 3 Oct 2023 09:13:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C0FD710E2E3; Tue, 3 Oct 2023 09:13:41 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id ABDAE10E2CB; Tue, 3 Oct 2023 09:13:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324420; x=1727860420; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OA9403j95c2N0l87VPui951h12A66/k0Bih+qrZH7rI=; b=U483pLB4D+WBy+3oaM7TqGMrj9q+z8PT6yUoWwfZBKYInLj2LbVduWef AnETf7DOwPQfHzo9DshjTYQD+QQE58cUZFmQ/tV+ylNDG79oINjE/PA3D mb3kurWeSzxAMtSV2VkdjULtttwcldmJ5DuryoO3f8kDnQ/wcXEJwStYK F+tEFyrn1cgg7B11s70r2Py4oP9B0W6u1XfgCyeopdY6jNfhg1V+6JskO wyyfSz+HV/SGSPG1y66GGuSLNM12wM1nU+TOSIy2MrrAIXPvU551x89qF 1c2jZIKpZ+BODGbRo5S2uOqjAzJf95WN6II6ejaX87tiFLYIWT1e25HVJ w==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419754" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419754" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935805" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935805" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:36 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:53 +0200 Message-ID: <20231003091044.407965-19-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 8/9] lib/kunit: Fetch a list of test cases in advance X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Recent improvements to the kernel kunit framework allow us to obtain a list of test cases provided by a kunit test module without actually running them. Use that feature to get a list of expected test cases before we enter a loop around igt_dynamic(). Once done, enter the igt_dynamic() section for each consecutive test case immediately, even before first line of a related KTAP report appears, then look for a result from that test case. That should make our IGT results output still better synchronized with related kernel messages. The list of test cases provided by a kunit test module can be obtained by loading the kunit base module with specific options, then loading the test module. For that to be possible, take care of unloading the kunit base module before each kunit subtest (I was wrong when in one of my previous commit messages I suggested that on final unload of a kunit test module the kunit base module is unloaded automatically as its dependency, however, that didn't matter before, then no separate fix was required). Since that module can then be left loaded with non-default options if an error occurs, unload it explicitly before returning from igt_kunit(). There are two possible ways of getting a list of test cases: by loading the base kunit module with action=list module option, or by filtering out all test cases from being executed while asking for SKIP results from those filtered out. Since the latter provides regular KTAP report that we can alredy parse perfectly, use it instead of trying to identify an unstructured list of test cases of unknown length submitted by the former. If an IGT test that calls igt_kunit() provides a subtest name then use that name to filter out potential test cases that don't belong to the named test suite from the list. To avoid loading any modules if no subtest is going to be executed (e.g., if a nonexistent subtest has been requested), load the kunit modules in list mode from inside the igt_subtest_with_dynamic() section. In order to be free to skip the whole subtest on unmet requirements that need to be verified after that list has been already populated, clean it up from a follow up igt_fixture section. Since we start reading the list of test cases from /dev/kmsg only after the kunit test module is loaded successfully in list only mode, don't synchronize reads with potential modprobe breakage in that case, unlike we still do later when parsing KTAP results in parallel to loading the test module in normal (execute) mode. Since we neither fetch KTAP results before entering igt_dynamic section nor even return an error from KTAP result fetch attempts immediately on modprobe error or kernel taint, break the loop of dynamic sub-subtests explicitly as soon as one of those conditions is detected. Also, don't force IGT SKIP result from the subtest if KTAP parsing hasn't completed. That's perfectly legitimate since we no longer iterate over KTAP results, only over a list of test cases obtained in advance, then we stop parsing KTAP report as soon as we get a result from the last test case from the list. Signed-off-by: Janusz Krzysztofik --- lib/igt_kmod.c | 217 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 157 insertions(+), 60 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index 387efbb59f..4fba77ead4 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -802,34 +802,36 @@ static int kunit_kmsg_result_get(struct igt_list_head *results, if (igt_debug_on(igt_kernel_tainted(&taints))) return -ENOTRECOVERABLE; - err = igt_debug_on(sigaction(SIGCHLD, &sigchld, saved)); - if (err == -1) - return -errno; - else if (unlikely(err)) - return err; - - err = pthread_mutex_lock(&modprobe->lock); - switch (err) { - case EOWNERDEAD: - /* leave the mutex unrecoverable */ - igt_debug_on(pthread_mutex_unlock(&modprobe->lock)); - __attribute__ ((fallthrough)); - case ENOTRECOVERABLE: - igt_debug_on(sigaction(SIGCHLD, saved, NULL)); - if (igt_debug_on(modprobe->err)) - return modprobe->err; - break; - case 0: - break; - default: - igt_debug("pthread_mutex_lock() error: %d\n", err); - igt_debug_on(sigaction(SIGCHLD, saved, NULL)); - return -err; + if (modprobe) { + err = igt_debug_on(sigaction(SIGCHLD, &sigchld, saved)); + if (err == -1) + return -errno; + else if (unlikely(err)) + return err; + + err = pthread_mutex_lock(&modprobe->lock); + switch (err) { + case EOWNERDEAD: + /* leave the mutex unrecoverable */ + igt_debug_on(pthread_mutex_unlock(&modprobe->lock)); + __attribute__ ((fallthrough)); + case ENOTRECOVERABLE: + igt_debug_on(sigaction(SIGCHLD, saved, NULL)); + if (igt_debug_on(modprobe->err)) + return modprobe->err; + break; + case 0: + break; + default: + igt_debug("pthread_mutex_lock() error: %d\n", err); + igt_debug_on(sigaction(SIGCHLD, saved, NULL)); + return -err; + } } ret = read(fd, record, BUF_LEN); - if (!err) { + if (modprobe && !err) { igt_debug_on(pthread_mutex_unlock(&modprobe->lock)); igt_debug_on(sigaction(SIGCHLD, saved, NULL)); } @@ -885,17 +887,15 @@ static void kunit_result_free(struct igt_ktap_result **r, *r = NULL; } -static void -__igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) +static void kunit_get_tests(struct igt_list_head *tests, + struct igt_ktest *tst, + const char *filter, + const char *opts) { - struct modprobe_data modprobe = { pthread_self(), tst->kmod, opts, 0, }; char *suite_name = NULL, *case_name = NULL; struct igt_ktap_result *r, *rn; struct igt_ktap_results *ktap; - pthread_mutexattr_t attr; - IGT_LIST_HEAD(results); - unsigned long taints; - int flags, ret; + int flags, err; igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n"); @@ -905,6 +905,63 @@ __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); + /* + * To get a list of test cases provided by a kunit test module, ask the + * generic kunit module to respond with SKIP result for each test found. + * We could also use action=list kunit parameter to get the listing, + * however, parsing a KTAP report -- something that we alredy can do + * perfectly -- seems to be more safe than extracting a test case list + * of unknown length from /dev/kmsg. + */ + igt_skip_on(igt_kmod_load("kunit", "filter=module=none filter_action=skip")); + igt_skip_on(modprobe(tst->kmod, opts)); + + ktap = igt_ktap_alloc(tests); + igt_require(ktap); + + do { + err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, ktap); + if (err && !igt_debug_on(err != -EINPROGRESS)) { + r = igt_list_last_entry(tests, r, link); + + if (igt_debug_on(r->code != IGT_EXIT_SKIP)) + err = r->code ?: -EPROTO; + } + + } while (err == -EINPROGRESS); + + igt_ktap_free(ktap); + + if (err || filter) { + igt_list_for_each_entry_safe(r, rn, tests, link) { + if (err || strcmp(r->suite_name, filter)) + kunit_result_free(&r, &case_name, &suite_name); + } + } + + igt_skip_on(kmod_module_remove_module(tst->kmod, KMOD_REMOVE_FORCE)); + igt_skip_on(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE)); + + igt_skip_on_f(err, + "KTAP parser failed while getting a list of test cases\n"); +} + +static void __igt_kunit(struct igt_ktest *tst, + const char *name, + const char *opts, + struct igt_list_head *tests) +{ + struct modprobe_data modprobe = { pthread_self(), tst->kmod, opts, 0, }; + char *suite_name = NULL, *case_name = NULL; + struct igt_ktap_result *t, *r = NULL, *rn; + struct igt_ktap_results *ktap; + pthread_mutexattr_t attr; + IGT_LIST_HEAD(results); + int ret = -EINPROGRESS; + unsigned long taints; + + igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); + igt_skip_on(pthread_mutexattr_init(&attr)); igt_skip_on(pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)); igt_skip_on(pthread_mutex_init(&modprobe.lock, &attr)); @@ -918,37 +975,50 @@ __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) igt_skip("Failed to create a modprobe thread\n"); } - do { - ret = kunit_kmsg_result_get(&results, &modprobe, - tst->kmsg, ktap); - if (igt_debug_on(ret && ret != -EINPROGRESS)) - break; - - if (igt_debug_on(igt_list_empty(&results))) - break; - - r = igt_list_first_entry(&results, r, link); - + igt_list_for_each_entry(t, tests, link) { igt_dynamic_f("%s%s%s", - strcmp(r->suite_name, name) ? r->suite_name : "", - strcmp(r->suite_name, name) ? "-" : "", - r->case_name) { + strcmp(t->suite_name, name) ? t->suite_name : "", + strcmp(t->suite_name, name) ? "-" : "", + t->case_name) { + if (!r) { + if (igt_list_empty(&results)) { + igt_assert_eq(ret, -EINPROGRESS); + ret = kunit_kmsg_result_get(&results, + &modprobe, + tst->kmsg, + ktap); + igt_fail_on(igt_list_empty(&results)); + } - if (r->code == IGT_EXIT_INVALID) { - /* parametrized test case, get actual result */ - kunit_result_free(&r, &suite_name, &case_name); + r = igt_list_first_entry(&results, r, link); + } - igt_assert(igt_list_empty(&results)); + while (igt_debug_on_f(strcmp(r->suite_name, t->suite_name), + "suite_name expected: %s, got: %s\n", + t->suite_name, r->suite_name) || + igt_debug_on_f(strcmp(r->case_name, t->case_name), + "case_name expected: %s, got: %s\n", + t->case_name, r->case_name) || + r->code == IGT_EXIT_INVALID) { - ret = kunit_kmsg_result_get(&results, &modprobe, - tst->kmsg, ktap); - if (ret != -EINPROGRESS) - igt_fail_on(ret); + int code = r->code; - igt_fail_on(igt_list_empty(&results)); + kunit_result_free(&r, &suite_name, &case_name); + if (igt_list_empty(&results)) { + igt_assert_eq(ret, -EINPROGRESS); + ret = kunit_kmsg_result_get(&results, + &modprobe, + tst->kmsg, + ktap); + igt_fail_on(igt_list_empty(&results)); + } r = igt_list_first_entry(&results, r, link); + if (code != IGT_EXIT_INVALID) + continue; + + /* result from parametrized test case */ igt_fail_on_f(strcmp(r->suite_name, suite_name), "suite_name expected: %s, got: %s\n", suite_name, r->suite_name); @@ -995,7 +1065,9 @@ __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) kunit_result_free(&r, &suite_name, &case_name); - } while (ret == -EINPROGRESS); + if (modprobe.err || igt_kernel_tainted(&taints)) + break; + } igt_list_for_each_entry_safe(r, rn, &results, link) kunit_result_free(&r, &suite_name, &case_name); @@ -1025,7 +1097,8 @@ __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) igt_skip_on(modprobe.err); igt_skip_on(igt_kernel_tainted(&taints)); - igt_skip_on_f(ret, "KTAP parser failed\n"); + if (ret != -EINPROGRESS) + igt_skip_on_f(ret, "KTAP parser failed\n"); } /** @@ -1039,7 +1112,8 @@ __igt_kunit(struct igt_ktest *tst, const char *name, const char *opts) void igt_kunit(const char *module_name, const char *name, const char *opts) { struct igt_ktest tst = { .kmsg = -1, }; - + const char *filter = name; + IGT_LIST_HEAD(tests); /* * If the caller (an IGT test) provides no subtest name then we @@ -1064,6 +1138,15 @@ void igt_kunit(const char *module_name, const char *name, const char *opts) igt_skip_on(igt_ktest_init(&tst, module_name)); igt_skip_on(igt_ktest_begin(&tst)); + + /* + * Since we need to load kunit base module with specific + * options in order to get a list of test cases, make + * sure that the module is not loaded. However, since + * unload may fail if kunit base module is not loaded, + * ignore any failures, we'll fail later if still loaded. + */ + igt_ignore_warn(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE)); } /* @@ -1073,11 +1156,25 @@ void igt_kunit(const char *module_name, const char *name, const char *opts) * proper namespace for dynamic subtests, with is required for CI * and for documentation. */ - igt_subtest_with_dynamic(name) - __igt_kunit(&tst, name, opts); + igt_subtest_with_dynamic(name) { + kunit_get_tests(&tests, &tst, filter, opts); + igt_skip_on(igt_list_empty(&tests)); + + __igt_kunit(&tst, name, opts, &tests); + } + + igt_fixture { + char *suite_name = NULL, *case_name = NULL; + struct igt_ktap_result *t, *tn; + + igt_list_for_each_entry_safe(t, tn, &tests, link) + kunit_result_free(&t, &suite_name, &case_name); + free(case_name); + free(suite_name); - igt_fixture igt_ktest_end(&tst); + igt_debug_on(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE)); + } igt_ktest_fini(&tst); } From patchwork Tue Oct 3 09:10:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janusz Krzysztofik X-Patchwork-Id: 13407313 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 85200E7543B for ; Tue, 3 Oct 2023 09:13:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B82B310E2EE; Tue, 3 Oct 2023 09:13:45 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by gabe.freedesktop.org (Postfix) with ESMTPS id CD67710E2A9; Tue, 3 Oct 2023 09:13:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696324424; x=1727860424; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/0YpursjmBGJ34pg+hxvDndAJwDi6+zaWM5OhHmA7LU=; b=hdrksE0TB5utBDAyfhGQLGZ31UmekBP+BuWvoBwJrQ8KHIqbrcR8A+8Z yW29ZEGI0dQXBV82PfpGOMsyWH8PS/Vcizd5x9Q0dS1mzBl8tKlfaiL1d 8cy4a1MsmOrk5mLKxIT5fZqhuqE0TWXiMxtH2nVPI3qOoPnbdCwm/hpVF tyIE/Rrx2YqoIWJ90EZyCkMhHCY8fWwryUxh4cxhQMco/544vjpe7P0qX dTiP/eJqUcZzAfMdjU/lBnu5R3pi+cMH2ARx+wYe5gxPZ2yjnZm5BEnEN wA4QfQLMjUMFqK00U/OTIEb9RT6G5HDdRQP15EBV//2JEoa6L4EJciBnJ Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="1419766" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="1419766" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10851"; a="997935811" X-IronPort-AV: E=Sophos;i="6.03,196,1694761200"; d="scan'208";a="997935811" Received: from jkrzyszt-mobl2.ger.corp.intel.com (HELO jkrzyszt-mobl2.intranet) ([10.213.14.111]) by fmsmga006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Oct 2023 02:13:38 -0700 From: Janusz Krzysztofik To: igt-dev@lists.freedesktop.org Date: Tue, 3 Oct 2023 11:10:54 +0200 Message-ID: <20231003091044.407965-20-janusz.krzysztofik@linux.intel.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> References: <20231003091044.407965-11-janusz.krzysztofik@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 9/9] lib/kunit: Execute kunit test cases only when needed X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, Mauro Carvalho Chehab , intel-xe@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" IGT user interface allows to request execution of only those dynamic sub- subtests that match a user provided name pattern. If the user pattern doesn't match any names of test cases provided by a kunit test module used with the subtest to be run then no results from any dynamic sub-subtests will be reported. Since we already know the list of test cases provided by the kunit test module, there is no need to load that module to execute them unless the user pattern matches at least one of those test cases. Don't load the kunit test module in execute mode before entering the loop of dynamic sub-subtests, and do that only from the first actually executed dynamic sub-subtest. Signed-off-by: Janusz Krzysztofik --- lib/igt_kmod.c | 59 ++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index 4fba77ead4..a8a140c9f1 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -962,24 +962,29 @@ static void __igt_kunit(struct igt_ktest *tst, igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); - igt_skip_on(pthread_mutexattr_init(&attr)); - igt_skip_on(pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)); - igt_skip_on(pthread_mutex_init(&modprobe.lock, &attr)); - ktap = igt_ktap_alloc(&results); igt_require(ktap); - if (igt_debug_on(pthread_create(&modprobe.thread, NULL, - modprobe_task, &modprobe))) { - igt_ktap_free(ktap); - igt_skip("Failed to create a modprobe thread\n"); - } - igt_list_for_each_entry(t, tests, link) { igt_dynamic_f("%s%s%s", strcmp(t->suite_name, name) ? t->suite_name : "", strcmp(t->suite_name, name) ? "-" : "", t->case_name) { + if (!modprobe.thread) { + igt_assert_eq(pthread_mutexattr_init(&attr), 0); + igt_assert_eq(pthread_mutexattr_setrobust(&attr, + PTHREAD_MUTEX_ROBUST), + 0); + igt_assert_eq(pthread_mutex_init(&modprobe.lock, + &attr), 0); + + modprobe.err = pthread_create(&modprobe.thread, + NULL, + modprobe_task, + &modprobe); + igt_assert_eq(modprobe.err, 0); + } + if (!r) { if (igt_list_empty(&results)) { igt_assert_eq(ret, -EINPROGRESS); @@ -1075,22 +1080,24 @@ static void __igt_kunit(struct igt_ktest *tst, free(case_name); free(suite_name); - switch (pthread_mutex_lock(&modprobe.lock)) { - case 0: - igt_debug_on(pthread_cancel(modprobe.thread)); - igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); - igt_debug_on(pthread_join(modprobe.thread, NULL)); - break; - case EOWNERDEAD: - /* leave the mutex unrecoverable */ - igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); - break; - case ENOTRECOVERABLE: - break; - default: - igt_debug("pthread_mutex_lock() failed\n"); - igt_debug_on(pthread_join(modprobe.thread, NULL)); - break; + if (modprobe.thread) { + switch (pthread_mutex_lock(&modprobe.lock)) { + case 0: + igt_debug_on(pthread_cancel(modprobe.thread)); + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + igt_debug_on(pthread_join(modprobe.thread, NULL)); + break; + case EOWNERDEAD: + /* leave the mutex unrecoverable */ + igt_debug_on(pthread_mutex_unlock(&modprobe.lock)); + break; + case ENOTRECOVERABLE: + break; + default: + igt_debug("pthread_mutex_lock() failed\n"); + igt_debug_on(pthread_join(modprobe.thread, NULL)); + break; + } } igt_ktap_free(ktap);