From patchwork Thu Aug 29 18:13:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783534 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F53A1B81AF for ; Thu, 29 Aug 2024 18:14:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955243; cv=none; b=ophbg+jaSvo7byFwUMoKjeAyBkQ8S45c1RTeT6jQpOCgVVf1F5HzmAW3VtRpRZJ7WAflHNMOXrJ2F790v34ay44KxqOquB20gBdNCc3hapD83mGSOPVwQ0sufao0a+214Q4hy1f3Flpsqr7IoJEZJ1A0zqFvSEfxRnzhXhEvIQ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955243; c=relaxed/simple; bh=DHjTZDh5IupglN5LpuQT50PBCXxQfXP83MHvVKsDzEg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ABwN5wITWS9nvq/ozENCayowy/r4VVCoBIJuaJG4y9kDYm+N7rF5KQT2rctFuw9LylUwHQgnKOmFgO10rMSViIc6HBmxLLsB+NXG5Z1hDipnbgk/9C8wwBKymzw1ibp80c4pTTxNhu3kPJcXX4ks29ogYoszIW8mG03Hui9RFyE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=cLNdc7lN; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="cLNdc7lN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955241; x=1756491241; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DHjTZDh5IupglN5LpuQT50PBCXxQfXP83MHvVKsDzEg=; b=cLNdc7lNtjPM9HNuvs0N4f16eGfI0lYiFdRLNkCCNvnm6W91X2ssbe7/ 0mjxBr4nKNVk4GwGjFax+JG0KkCesAazJvaQgZ2keF7IdUv56yQEdlW8j Vdmd6Npy/zWcrc+7CI+MDt1XZLIXr04CZfyb1vUIbbw4tgstSUUin1xvU eqOV38yntAdeLttHCErtRIWHUABP/9AJkU6gbOJ3D0I54K+4spYZnV+OR KXue/4QthLPhEru/G2/uSk/4KJD1+W2JtwOq/M31amVuGD2x6c8oR7yS/ nHBcc1hfRxF/tjaJNraQXrIU75kREAVT0TkyGhyY3rDgnopzg38o/NqQA w==; X-CSE-ConnectionGUID: j+8boKxfRDK7pCercUSEcw== X-CSE-MsgGUID: BtSWFUcuRHKc3vGWEFdZKg== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238432" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238432" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:01 -0700 X-CSE-ConnectionGUID: 93wrvDhdRZGSuPpeEiZYPQ== X-CSE-MsgGUID: O1gzga54TQGVk0ewNkc7qw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353215" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:13:59 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , Lucas De Marchi , David Gow Subject: [PATCH v3 1/6] kunit: Introduce kunit_is_running() Date: Thu, 29 Aug 2024 20:13:43 +0200 Message-Id: <20240829181348.1572-2-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Wrap uses of the static key 'kunit_running' into a helper macro to allow future checks to be placed in the code residing outside of the CONFIG_KUNIT. We will start using this in upcoming patch. Signed-off-by: Michal Wajdeczko Reviewed-by: Rae Moar Reviewed-by: Lucas De Marchi Reviewed-by: David Gow --- include/kunit/test-bug.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/kunit/test-bug.h b/include/kunit/test-bug.h index 47aa8f21ccce..e8ea3bab7250 100644 --- a/include/kunit/test-bug.h +++ b/include/kunit/test-bug.h @@ -25,6 +25,13 @@ extern struct kunit_hooks_table { void *(*get_static_stub_address)(struct kunit *test, void *real_fn_addr); } kunit_hooks; +/** + * kunit_is_running() - True, if KUnit test is currently running. + * + * If CONFIG_KUNIT is not enabled, it will compile down to a false. + */ +#define kunit_is_running() static_branch_unlikely(&kunit_running) + /** * kunit_get_current_test() - Return a pointer to the currently running * KUnit test. @@ -40,7 +47,7 @@ extern struct kunit_hooks_table { */ static inline struct kunit *kunit_get_current_test(void) { - if (!static_branch_unlikely(&kunit_running)) + if (!kunit_is_running()) return NULL; return current->kunit_test; @@ -53,7 +60,7 @@ static inline struct kunit *kunit_get_current_test(void) * If a KUnit test is running in the current task, mark that test as failed. */ #define kunit_fail_current_test(fmt, ...) do { \ - if (static_branch_unlikely(&kunit_running)) { \ + if (kunit_is_running()) { \ /* Guaranteed to be non-NULL when kunit_running true*/ \ kunit_hooks.fail_current_test(__FILE__, __LINE__, \ fmt, ##__VA_ARGS__); \ @@ -64,6 +71,7 @@ static inline struct kunit *kunit_get_current_test(void) static inline struct kunit *kunit_get_current_test(void) { return NULL; } +#define kunit_is_running() false #define kunit_fail_current_test(fmt, ...) do {} while (0) #endif From patchwork Thu Aug 29 18:13:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783535 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AD9A1B5EC8 for ; Thu, 29 Aug 2024 18:14:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955244; cv=none; b=anvM9dzpuLjgUOONiBJHfUT2DG+II4ahUGl3WFgEsur9YsvjTkL90Ga5SoyfjSDT1pQyYgR2sPzXNr1vXmaZweMZOzCnK3fJ4Bmo0UpaKQo1CjojKHuADyGEiYgQe1oBnDCgBOKLPmXIdLMp2LEcbemE5ZWDHNwBxkoy/rSfDWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955244; c=relaxed/simple; bh=YKnkV684Szy48IHSUnldBzj/JFtnEHMA6jrXEj4Ev9U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kc9gqC+SM3/Wc/cgMsWR5Zdy/JoGfcGrCXPBvaGWeh72NLjN1i73fzg+OVnN2+it3DCzX7ToAH0ADOtp20zYOVa2xLTomkdqZQbeTnXErVuQSaNkizUOb8TXu6cgDtRUBV88/DxGwpOV3eRzC8DPY7H4cLaYSEtXmO5GRfV++L8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=H0ix+Unn; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="H0ix+Unn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955243; x=1756491243; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YKnkV684Szy48IHSUnldBzj/JFtnEHMA6jrXEj4Ev9U=; b=H0ix+Unn3kkNOXe38Ppq2k1Z5IXV3i6EDUz11xRWW7KOvChIMMy1mQMB sTA8w1z6RgrrG1Tqjw4evtW2WkPygbcvpizpfNS+Rp1C9swlb54RQxtHa 81kFr8wtHD5jdO+EcbYjY4TNGPOm0N5wt24SLnNPjUYJKrFxIDqNXFj/k 9kpuygXvdv8So2VhkIs7niVBIc0zA7i/N5fGpeLi2n2SOzKVP2Qs/6gVN 8jCv0AHC644OyAoy2bWuXcN0ebtVT7GuIIbWTi/CAp2GQW5mkBrWsqKAo pHbI1i03JeumZhhp96v8Fjauojqaz4Buz/PgA4lhwDX85/qc1KaYo994q A==; X-CSE-ConnectionGUID: tFnXAgw6SSSk13UAi6qxgg== X-CSE-MsgGUID: kdaxaA9rQfCtkC7q+mirwA== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238435" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238435" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:03 -0700 X-CSE-ConnectionGUID: /EgrKxqvRKCYhcc/XmWGZQ== X-CSE-MsgGUID: LG5Db8MzSFCwOVOaSlJu4g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353227" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:01 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , David Gow , Lucas De Marchi Subject: [PATCH v3 2/6] kunit: Add macro to conditionally expose declarations to tests Date: Thu, 29 Aug 2024 20:13:44 +0200 Message-Id: <20240829181348.1572-3-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The DECLARE_IF_KUNIT macro will introduces identifiers only if CONFIG_KUNIT is enabled. Otherwise if CONFIG_KUNIT is not enabled no identifiers from the param list will be defined. Signed-off-by: Michal Wajdeczko Reviewed-by: Rae Moar Reviewed-by: David Gow --- Cc: Lucas De Marchi --- v2: include struct example in macro comment (Lucas) reformat kernel-doc for better output (Michal) --- include/kunit/visibility.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/kunit/visibility.h b/include/kunit/visibility.h index 0dfe35feeec6..c1825381adfc 100644 --- a/include/kunit/visibility.h +++ b/include/kunit/visibility.h @@ -11,6 +11,25 @@ #define _KUNIT_VISIBILITY_H #if IS_ENABLED(CONFIG_KUNIT) + /** + * DECLARE_IF_KUNIT - Conditionally introduce identifiers + * @body: identifiers to be introduced conditionally + * + * This macro introduces identifiers only if CONFIG_KUNIT is enabled. + * Otherwise if CONFIG_KUNIT is not enabled no identifiers will be defined. + * + * .. code-block:: C + * + * struct example { + * // @foo: regular data + * int foo; + * + * // private: data available only for CONFIG_KUNIT + * DECLARE_IF_KUNIT(int bar); + * }; + */ + #define DECLARE_IF_KUNIT(body...) body + /** * VISIBLE_IF_KUNIT - A macro that sets symbols to be static if * CONFIG_KUNIT is not enabled. Otherwise if CONFIG_KUNIT is enabled @@ -26,6 +45,7 @@ #define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, \ EXPORTED_FOR_KUNIT_TESTING) #else + #define DECLARE_IF_KUNIT(body...) #define VISIBLE_IF_KUNIT static #define EXPORT_SYMBOL_IF_KUNIT(symbol) #endif From patchwork Thu Aug 29 18:13:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783536 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D86951B5EC8 for ; Thu, 29 Aug 2024 18:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955247; cv=none; b=ns+/raut/IQDPK3gTb4sLSxL1wfFXkUNd0OIqmkc1al753up2FEaS+8fs/GtD7ELq0BH8jemqe5UDN8olLM2vqCS89JGCLB+oYU+KjI59UE+4481ag5prSZiO/QwaITrUIL7Th9FaK+VxUQ9E1bRPGCJ3MZDBL33H/U1meHjJwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955247; c=relaxed/simple; bh=oILEKqZ+d3w35AdoRuN4hOm7lzeZfLL5pZaFOKCVrsk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rjfhK7lW0l2Y1f0Ondqljlgdg556L2mUmZLJ04jvEzNuA/SqgzMnqJAZz9vlp+GQLog4XywASlouz3yZQWyBleO9o4H8vdQCJQz9K7mklOz9CeoNMgm0h7ASYZdchEA25NujPwl4oUHuKlkEl5eqy6d/H1D9Qvpi749dXgiVRfg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=dwtQu9NA; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="dwtQu9NA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955246; x=1756491246; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oILEKqZ+d3w35AdoRuN4hOm7lzeZfLL5pZaFOKCVrsk=; b=dwtQu9NAr5l4aKFjrHhHws0+nMDQmlRfGvyYCOO79wWHTw6BfBneSmAI +MMsn1ezrLK0KHixng0Yne7h0KIWAExsEvhY84GANEonAxcVCDO0wv74C ezhKXvtveN9lZ8xHhI51aJrWRTfCb7/HiAyA9brR6T+Sld/9dLSdXqYg6 eN7SSzhCKL3Xs8LC//jDsOUnrY6gUnyBEaGefoYoSrU9WCHF4CV5Onrq7 qUQxAsr610r9HS7QUaWnVX4oYxyP15Qjz+iAyU5CWDQqtFJp3tilAnoSM htU8AWIQAYpaEmobp9+bIZwGl9Cymxj9nEOhh1dXVZMSikew02lm0Jqyg A==; X-CSE-ConnectionGUID: RQGlskJYRliK0mzHIvJuEA== X-CSE-MsgGUID: 5foA/jMySB2AYtgXJUIaqA== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238440" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238440" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:05 -0700 X-CSE-ConnectionGUID: 0OO065MHQ066VSzBkJgqkg== X-CSE-MsgGUID: Kv8poLzgSjy9P9kfMjaUlw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353241" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:03 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , David Gow , Lucas De Marchi Subject: [PATCH v3 3/6] kunit: Add macro to conditionally expose expressions to tests Date: Thu, 29 Aug 2024 20:13:45 +0200 Message-Id: <20240829181348.1572-4-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The VALUE_IF_KUNIT macro will add expression statement only if the CONFIG_KUNIT is enabled. Otherwise if CONFIG_KUNIT is not enabled it will evaluate always to 0. Signed-off-by: Michal Wajdeczko --- Cc: Rae Moar Cc: David Gow Cc: Lucas De Marchi --- v2: add simple usage example (Rae) reformat kernel-doc for better output (Michal) s/ONLY_IF_KUNIT/VALUE_IF_KUNIT --- include/kunit/visibility.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/kunit/visibility.h b/include/kunit/visibility.h index c1825381adfc..b156cafa4705 100644 --- a/include/kunit/visibility.h +++ b/include/kunit/visibility.h @@ -30,6 +30,25 @@ */ #define DECLARE_IF_KUNIT(body...) body + /** + * VALUE_IF_KUNIT - Conditionally evaluate an expression + * @expr: the expression to be evaluated conditionally + * + * This macro evaluates expression statement only if CONFIG_KUNIT is enabled. + * Otherwise if CONFIG_KUNIT is not enabled it will evaluate always to 0. + * + * .. code-block:: C + * + * int real_func(int i) + * { + * if (VALUE_IF_KUNIT(i == 0xC0FFE)) + * return 0; + * + * return i + 1; + * } + */ + #define VALUE_IF_KUNIT(expr...) expr + /** * VISIBLE_IF_KUNIT - A macro that sets symbols to be static if * CONFIG_KUNIT is not enabled. Otherwise if CONFIG_KUNIT is enabled @@ -46,6 +65,7 @@ EXPORTED_FOR_KUNIT_TESTING) #else #define DECLARE_IF_KUNIT(body...) + #define VALUE_IF_KUNIT(expr...) 0 #define VISIBLE_IF_KUNIT static #define EXPORT_SYMBOL_IF_KUNIT(symbol) #endif From patchwork Thu Aug 29 18:13:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783537 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EAE2A1B5EC8 for ; Thu, 29 Aug 2024 18:14:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955249; cv=none; b=jkhSonPpluKLL233ql4G51GwWSm1IdFBYx8bRlaqgZ7LxLbu4IWXMivl4LKypBTITGVEnrP58bO69Gf68vNynOI3HNtw9/l3U7Fe6kxBq5VBpjPrAocjVKezl7okNhJjpMIthxPqWwWn6gN5uPwXPhfmNV0D0LKi+3Ch2IoFfVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955249; c=relaxed/simple; bh=ka6wmWAbYpWxsJl4n3Hk0EkO97Gkfq3RX8CScp/osIU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Z5mA52iDJWZKO2JfVqRGHSKAtHVR0/XYYr0l2gYD6YT1ZvXi8+qD5ITxerosQFwJAs7WJQwxuuPlN27b9/srMr4K++OkEfdx/TCQTJC9cNRVpZvV8cb5tK0H9QUwUssK0bi6X4tubDwzcn/oBPp6B5tzGdarRh7xgaHAgkQQqf0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PaP6MCYF; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PaP6MCYF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955248; x=1756491248; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ka6wmWAbYpWxsJl4n3Hk0EkO97Gkfq3RX8CScp/osIU=; b=PaP6MCYFDGe3c5vjtlT6mt3hJY2IRUNj2FqYfrKAV38G+EHr9Gq32kYg ILTU6+lpLNDoO6fI7CAexlT0ZghoramrPbH5rMG7ljuK+PzCwZHp450l4 2YXKm4jx/W+/SpbofFmnX0lPW1Qbb3qBsi3mgsRj+325rp7GGDF03KIOq 7LcAKyD2WEFekhhtLt67U8HY7hvzMnc1ZdBMdkI+2QcPtossKPnEacT4k OV53BdFNpuKrfdQxN+YeFKfD3a8TU/HBjRAfip9j8ecLxyiDK2apTO3OS 98LeEwhjFIUPOQoc0ojlZWgkGMe+EtJClc4kJ7LG1aJIT6YuEGvyo3nKo g==; X-CSE-ConnectionGUID: aipLrFpeTPSrGHCA/PWpOw== X-CSE-MsgGUID: rSvxr5O4T0iG5e78oMM7ww== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238445" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238445" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:07 -0700 X-CSE-ConnectionGUID: ZtNuXy2iTnuUVUZ2W0EoKQ== X-CSE-MsgGUID: HOVUP1MFTQeWH8qhNabowQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353247" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:05 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , David Gow , Daniel Latypov , Lucas De Marchi Subject: [PATCH v3 4/6] kunit: Allow function redirection outside of the KUnit thread Date: Thu, 29 Aug 2024 20:13:46 +0200 Message-Id: <20240829181348.1572-5-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently, the 'static stub' API only allows function redirection for calls made from the kthread of the current test, which prevents the use of this functionality when the tested code is also used by other threads, outside of the KUnit test, like from the workqueue. Add another set of macros to allow redirection to the replacement functions, which, unlike the KUNIT_STATIC_STUB_REDIRECT, will affect all calls done during the test execution. These new stubs, named 'global', must be declared using dedicated KUNIT_DECLARE_GLOBAL_STUB() macro and then can be placed either as global static variables or as part of the other structures. To properly maintain stubs lifecycle, they can be activated only from the main KUnit context. Some precaution is taken to avoid changing or deactivating replacement functions if one is still used by other thread. Signed-off-by: Michal Wajdeczko --- Cc: Rae Moar Cc: David Gow Cc: Daniel Latypov Cc: Lucas De Marchi --- v2: s/FIXED_STUB/GLOBAL_STUB (David, Lucas) make it little more thread safe (Rae, David) wait until stub call finishes before test end (David) wait until stub call finishes before changing stub (David) allow stub deactivation (Rae) prefer kunit log (David) v3: fix s/fixed/global in comments (Lucas) improve sanitize (Lucas, Michal) --- include/kunit/static_stub.h | 158 ++++++++++++++++++++++++++++++++++++ lib/kunit/static_stub.c | 50 ++++++++++++ 2 files changed, 208 insertions(+) diff --git a/include/kunit/static_stub.h b/include/kunit/static_stub.h index bf940322dfc0..350731eda523 100644 --- a/include/kunit/static_stub.h +++ b/include/kunit/static_stub.h @@ -12,12 +12,15 @@ /* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */ #define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0) +#define KUNIT_GLOBAL_STUB_REDIRECT(stub_name, args...) do {} while (0) +#define KUNIT_DECLARE_GLOBAL_STUB(stub_name, stub_type) #else #include #include +#include /* for CLASS */ #include /* for {un,}likely() */ #include /* for task_struct */ @@ -109,5 +112,160 @@ void __kunit_activate_static_stub(struct kunit *test, */ void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr); +/** + * struct kunit_global_stub - Represents a context of global function stub. + * @replacement: The address of replacement function. + * @owner: The KUnit test that owns the stub, valid only when @busy > 0. + * @busy: The stub busyness counter incremented on entry to the replacement + * function, decremented on exit, used to signal if the stub is idle. + * @idle: The completion state to indicate when the stub is idle again. + * + * This structure is for KUnit internal use only. + * See KUNIT_DECLARE_GLOBAL_STUB(). + */ +struct kunit_global_stub { + void *replacement; + struct kunit *owner; + atomic_t busy; + struct completion idle; +}; + +/** + * KUNIT_DECLARE_GLOBAL_STUB() - Declare a global function stub. + * @stub_name: The name of the stub, must be a valid identifier + * @stub_type: The type of the function that this stub will replace + * + * This macro will declare new identifier of an anonymous type that will + * represent global stub function that could be used by KUnit. It can be stored + * outside of the KUnit code. If the CONFIG_KUNIT is not enabled this will + * be evaluated to an empty statement. + * + * The anonymous type introduced by this macro is mostly a wrapper to generic + * struct kunit_global_stub but with additional dummy member, that is never + * used directly, but is needed to maintain the type of the stub function. + */ +#define KUNIT_DECLARE_GLOBAL_STUB(stub_name, stub_type) \ +union { \ + struct kunit_global_stub base; \ + typeof(stub_type) dummy; \ +} stub_name + +/* Internal struct to define guard class */ +struct kunit_global_stub_guard { + struct kunit_global_stub *stub; + void *active_replacement; +}; + +/* Internal class used to guard stub calls */ +DEFINE_CLASS(kunit_global_stub_guard, + struct kunit_global_stub_guard, + ({ + struct kunit_global_stub *stub = _T.stub; + bool active = !!_T.active_replacement; + + if (active && !atomic_dec_return(&stub->busy)) + complete_all(&stub->idle); + }), + ({ + class_kunit_global_stub_guard_t guard; + bool active = !!atomic_inc_not_zero(&stub->busy); + + guard.stub = stub; + guard.active_replacement = active ? READ_ONCE(stub->replacement) : NULL; + + guard; + }), + struct kunit_global_stub *stub) + +/** + * KUNIT_GLOBAL_STUB_REDIRECT() - Call a global function stub if activated. + * @stub: The function stub declared using KUNIT_DECLARE_GLOBAL_STUB() + * @args: All of the arguments passed to this stub + * + * This is a function prologue which is used to allow calls to the current + * function to be redirected if a KUnit is running. If the KUnit is not + * running or stub is not yet activated the function will continue execution + * as normal. + * + * The function stub must be declared with KUNIT_DECLARE_GLOBAL_STUB() that is + * stored in a place that is accessible from both the test code, which will + * activate this stub using kunit_activate_global_stub(), and from the function, + * where we will do this redirection using KUNIT_GLOBAL_STUB_REDIRECT(). + * + * Unlike the KUNIT_STATIC_STUB_REDIRECT(), this redirection will work + * even if the caller is not in a KUnit context (like a worker thread). + * + * Example: + * + * .. code-block:: c + * + * KUNIT_DECLARE_GLOBAL_STUB(func_stub, int (*)(int n)); + * + * int real_func(int n) + * { + * KUNIT_GLOBAL_STUB_REDIRECT(func_stub, n); + * return n + 1; + * } + * + * int replacement_func(int n) + * { + * return n + 100; + * } + * + * void example_test(struct kunit *test) + * { + * KUNIT_EXPECT_EQ(test, real_func(1), 2); + * kunit_activate_global_stub(test, func_stub, replacement_func); + * KUNIT_EXPECT_EQ(test, real_func(1), 101); + * } + */ +#define KUNIT_GLOBAL_STUB_REDIRECT(stub, args...) do { \ + if (kunit_is_running()) { \ + typeof(stub) *__stub = &(stub); \ + CLASS(kunit_global_stub_guard, guard)(&__stub->base); \ + typeof(__stub->dummy) replacement = guard.active_replacement; \ + if (unlikely(replacement)) { \ + kunit_info(__stub->base.owner, "%s: redirecting to %ps\n", \ + __func__, replacement); \ + return replacement(args); \ + } \ + } \ +} while (0) + +void __kunit_activate_global_stub(struct kunit *test, struct kunit_global_stub *stub, + void *replacement_addr); + +/** + * kunit_activate_global_stub() - Setup a global function stub. + * @test: Test case that wants to activate a global function stub + * @stub: The location of the function stub pointer + * @replacement: The replacement function + * + * This helper setups a function stub with the replacement function. + * It will also automatically deactivate the stub at the test end. + * + * The redirection can be disabled with kunit_deactivate_global_stub(). + * The stub must be declared using KUNIT_DECLARE_GLOBAL_STUB(). + */ +#define kunit_activate_global_stub(test, stub, replacement) do { \ + typeof(stub) *__stub = &(stub); \ + typecheck_fn(typeof(__stub->dummy), (replacement)); \ + __kunit_activate_global_stub((test), &__stub->base, (replacement)); \ +} while (0) + +void __kunit_deactivate_global_stub(struct kunit *test, struct kunit_global_stub *stub); + +/** + * kunit_deactivate_global_stub() - Disable a global function stub. + * @test: Test case that wants to deactivate a global function stub + * @stub: The location of the function stub pointer + * + * The stub must be declared using KUNIT_DECLARE_GLOBAL_STUB(). + */ +#define kunit_deactivate_global_stub(test, stub) do { \ + typeof(stub) *__stub = &(stub); \ + __kunit_deactivate_global_stub((test), &__stub->base); \ +} while (0) + #endif #endif diff --git a/lib/kunit/static_stub.c b/lib/kunit/static_stub.c index 92b2cccd5e76..c7000c8dbabe 100644 --- a/lib/kunit/static_stub.c +++ b/lib/kunit/static_stub.c @@ -121,3 +121,53 @@ void __kunit_activate_static_stub(struct kunit *test, } } EXPORT_SYMBOL_GPL(__kunit_activate_static_stub); + +static void sanitize_global_stub(void *data) +{ + struct kunit *test = kunit_get_current_test(); + struct kunit_global_stub *stub = data; + + KUNIT_EXPECT_NE(test, 0, atomic_read(&stub->busy)); + KUNIT_EXPECT_PTR_EQ(test, test, READ_ONCE(stub->owner)); + + reinit_completion(&stub->idle); + if (!atomic_dec_and_test(&stub->busy)) { + kunit_info(test, "waiting for %ps\n", stub->replacement); + KUNIT_EXPECT_EQ(test, 0, wait_for_completion_interruptible(&stub->idle)); + } + + WRITE_ONCE(stub->owner, NULL); + WRITE_ONCE(stub->replacement, NULL); +} + +/* + * Helper function for kunit_activate_global_stub(). The macro does + * typechecking, so use it instead. + */ +void __kunit_activate_global_stub(struct kunit *test, + struct kunit_global_stub *stub, + void *replacement_addr) +{ + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stub); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, replacement_addr); + + kunit_release_action(test, sanitize_global_stub, stub); + KUNIT_EXPECT_EQ(test, 0, atomic_read(&stub->busy)); + + init_completion(&stub->idle); + WRITE_ONCE(stub->owner, test); + WRITE_ONCE(stub->replacement, replacement_addr); + + KUNIT_ASSERT_EQ(test, 1, atomic_inc_return(&stub->busy)); + KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test, sanitize_global_stub, stub)); +} +EXPORT_SYMBOL_GPL(__kunit_activate_global_stub); + +/* + * Helper function for kunit_deactivate_global_stub(). Use it instead. + */ +void __kunit_deactivate_global_stub(struct kunit *test, struct kunit_global_stub *stub) +{ + kunit_release_action(test, sanitize_global_stub, stub); +} +EXPORT_SYMBOL_GPL(__kunit_deactivate_global_stub); From patchwork Thu Aug 29 18:13:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783538 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9AB271B5EC8 for ; Thu, 29 Aug 2024 18:14:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955253; cv=none; b=un2swNFldWrqsSrvEzDYEnANtuLQxKeiFCj7GcZu4bcGGIDS39l28li6j4woxknyQjaZmNrJYjdWb1J0nAqjcAiadwgrjkl9tP773y0sKdW0uiFlZPP8V2bA/Pjf7X9XRVPDKZz8H8W0cczQSpD4rCjeLozEGwoGCtJvDW8a/8U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955253; c=relaxed/simple; bh=gu6yIHIg1ZLpGbyyL4EVKcRKYlbwSg0WzmfwB5AX4Jo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TTDIts2z9j8IfbPumZI39/kSFyKJ6Erem0Y4EqQnEKSFktD3mxP7X/RsrsIQTeSdmqqecOPA+lHiYtQSdEXJifKKJVh0TvjvmfuzFIIpDDnpMm/JR0DtfQyyvDn9U5e6ShjmHAI2qk4+VC4J0Uyl5KHrjrw8GA7AZ9ShSUM2zUs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=lF7wmtgR; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lF7wmtgR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955251; x=1756491251; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gu6yIHIg1ZLpGbyyL4EVKcRKYlbwSg0WzmfwB5AX4Jo=; b=lF7wmtgRgJ0+SJNUCfTvbw6HUxiU+cf5w/yaMAef/DKjCG1qb/4qzXQP iPoxk8uMzoOLnZz/tG8mx5NPVAPxvvMR7E1BmkQDhqzzXCbIZPfDn9zDh n2jukFWss0EVWB32I1JTqpdmRY2zqRsArVafFEZ5AfIYfgORgYwGqLXJa 8Zfh/Qg7Uk/tS+m1dsvIU78akWbDmtdqpmcvHUk4UJfhMWvAY03JY7aZy yJgBNN4bncD/zil8FlBLBuxu/uiix3CtFm+ouvjBCyCQs52NKZDzi9zzL gdblbbkiCdXCrSdifjQ4ZldZlUfiuUgeCYqIEfJ0FTP7X8A77Ga3MMev+ A==; X-CSE-ConnectionGUID: 1Rf6RXBEQWSYNQAcJXQr7A== X-CSE-MsgGUID: pZsXEd8QTWiNe3zl7QwuqQ== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238450" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238450" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:10 -0700 X-CSE-ConnectionGUID: pYn9Jd2ESUyFCeigI4fHpg== X-CSE-MsgGUID: Oic0d2DsSKu5vXgCnLqZZQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353254" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:07 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , David Gow , Lucas De Marchi , Daniel Latypov Subject: [PATCH v3 5/6] kunit: Add example with alternate function redirection method Date: Thu, 29 Aug 2024 20:13:47 +0200 Message-Id: <20240829181348.1572-6-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add example how to use KUNIT_GLBAL_STUB_REDIRECT and compare its usage with the KUNIT_STATIC_STUB_REDIRECT. Signed-off-by: Michal Wajdeczko Reviewed-by: Rae Moar #v1 Reviewed-by: David Gow #v1 Reviewed-by: Lucas De Marchi --- Cc: Daniel Latypov --- v2: add missing testcase description (Rae) and rebase v3: fix s/fixed/global (Lucas) drop stale comment in commit message (Michal) --- lib/kunit/kunit-example-test.c | 67 ++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c index 3056d6bc705d..0a64f9c17b24 100644 --- a/lib/kunit/kunit-example-test.c +++ b/lib/kunit/kunit-example-test.c @@ -6,8 +6,10 @@ * Author: Brendan Higgins */ +#include #include #include +#include /* * This is the most fundamental element of KUnit, the test case. A test case @@ -221,6 +223,70 @@ static void example_static_stub_using_fn_ptr_test(struct kunit *test) KUNIT_EXPECT_EQ(test, add_one(1), 2); } +/* This could be a location of various global stub functions. */ +static struct { + KUNIT_DECLARE_GLOBAL_STUB(add_two, int (*)(int i)); +} stubs; + +/* This is a function we'll replace with stubs. */ +static int add_two(int i) +{ + /* This will trigger the stub if active. */ + KUNIT_STATIC_STUB_REDIRECT(add_two, i); + KUNIT_GLOBAL_STUB_REDIRECT(stubs.add_two, i); + + return i + 2; +} + +struct add_two_async_work { + struct work_struct work; + int param; + int result; +}; + +static void add_two_async_func(struct work_struct *work) +{ + struct add_two_async_work *w = container_of(work, typeof(*w), work); + + w->result = add_two(w->param); +} + +static int add_two_async(int i) +{ + struct add_two_async_work w = { .param = i }; + + INIT_WORK_ONSTACK(&w.work, add_two_async_func); + schedule_work(&w.work); + flush_work(&w.work); + destroy_work_on_stack(&w.work); + + return w.result; +} + +/* + * This test shows how to use KUNIT_GLOBAL_STUB_REDIRECT and compares its + * usage with the KUNIT_STATIC_STUB_REDIRECT. + */ +static void example_global_stub_test(struct kunit *test) +{ + /* static stub redirection works only for KUnit thread */ + kunit_activate_static_stub(test, add_two, subtract_one); + KUNIT_EXPECT_EQ(test, add_two(1), subtract_one(1)); + KUNIT_EXPECT_NE_MSG(test, add_two_async(1), subtract_one(1), + "stub shouldn't be active outside KUnit thread!"); + + kunit_deactivate_static_stub(test, add_two); + KUNIT_EXPECT_EQ(test, add_two(1), add_two(1)); + + /* global stub redirection works for KUnit and other threads */ + kunit_activate_global_stub(test, stubs.add_two, subtract_one); + KUNIT_EXPECT_EQ(test, add_two(1), subtract_one(1)); + KUNIT_EXPECT_EQ(test, add_two_async(1), subtract_one(1)); + + kunit_deactivate_global_stub(test, stubs.add_two); + KUNIT_EXPECT_EQ(test, add_two(1), add_two(1)); +} + static const struct example_param { int value; } example_params_array[] = { @@ -294,6 +360,7 @@ static struct kunit_case example_test_cases[] = { KUNIT_CASE(example_all_expect_macros_test), KUNIT_CASE(example_static_stub_test), KUNIT_CASE(example_static_stub_using_fn_ptr_test), + KUNIT_CASE(example_global_stub_test), KUNIT_CASE(example_priv_test), KUNIT_CASE_PARAM(example_params_test, example_gen_params), KUNIT_CASE_SLOW(example_slow_test), From patchwork Thu Aug 29 18:13:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Wajdeczko X-Patchwork-Id: 13783539 X-Patchwork-Delegate: brendanhiggins@google.com Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A0D661B81BC for ; Thu, 29 Aug 2024 18:14:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955254; cv=none; b=U3Y+/jHcpA6xu6EgBFimNFG4yvQqSg1WWw2XNqfV0cSpIQ7ZCwJGgOV5CIx0hTm3SE6lPWFEqYiVOJ192SkJWPVd+RWJp7e8hEYRxvYLlUr9748+z1DNAlnbV+1IiEFMzBp9d9X3OqfQwGxkDBV5M0/KbaPeZD7cv5NuLxADTs0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724955254; c=relaxed/simple; bh=j17FxC2q9JsZ5Sd6M61sTCz1rZvBj8On6+3nC7HiN0M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=o9leoC0eC8dtnFfgxapUOP2tl1QtK3+UyhZ1mPoBQiVUP/tdVzSarqHK5OWI3bwDK0pl8cfm1ICt554WL+JdC3U9v0SZph81J9SdTjgJrfdZYTnBxsZvIrXWKk3wx6+EZ4/xqd7E/iV3cbKQBEayk+S/n33aqM6h6eYuF8qf64s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Zo11xdlO; arc=none smtp.client-ip=192.198.163.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Zo11xdlO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1724955252; x=1756491252; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=j17FxC2q9JsZ5Sd6M61sTCz1rZvBj8On6+3nC7HiN0M=; b=Zo11xdlOgldXp7b9MoPabSxF4rOhijUlVGaRyisx50Z1n1eNln/CObCG 8qHHTowyQ6k/Z1UVZwCLaikY1XFj0z/prjiBVBLVyvrg10NmINqwBgPDg FYEmQzRl/eX/upzk4+qkOpk7yXZh1eeoH1DBW/t3Q79HppQSTePuTPYV5 ORiKyBXdnqB7ze/vpYd5LApdyguyc2PJykiJX5hh3sKcMZtwezsSMTlgK yFQlsVxMZ4ovcXms+IIpf5F2d5wms8m07iRnQtSh/gaPt3bcffNDPHswH mR7EvFr37CKNuvlonfiYtzwHTA94Rjt6w5fAhZMkKhcR4VNPCS1E0v6x9 w==; X-CSE-ConnectionGUID: Xnuvv48MTbue8hV5AzE6QA== X-CSE-MsgGUID: mRw5zDprR3uaBF/HKseJhQ== X-IronPort-AV: E=McAfee;i="6700,10204,11179"; a="34238455" X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="34238455" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:12 -0700 X-CSE-ConnectionGUID: yeYEHNvxR5+bAjyxzRfhQw== X-CSE-MsgGUID: YWVfprqtREywNgYTAF/cZw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,186,1719903600"; d="scan'208";a="63353259" Received: from mwajdecz-mobl.ger.corp.intel.com ([10.245.120.199]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Aug 2024 11:14:10 -0700 From: Michal Wajdeczko To: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com Cc: Michal Wajdeczko , Rae Moar , David Gow , Lucas De Marchi Subject: [PATCH v3 6/6] kunit: Add some selftests for global stub redirection macros Date: Thu, 29 Aug 2024 20:13:48 +0200 Message-Id: <20240829181348.1572-7-michal.wajdeczko@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20240829181348.1572-1-michal.wajdeczko@intel.com> References: <20240829181348.1572-1-michal.wajdeczko@intel.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 While we already have few ASSERT() within the implementation, it's always better to have dedicated test cases. Add tests for: - automatic deactivation of the stubs at the test end - blocked deactivation until all active stub calls finish - blocked stub change until all active stub calls finish - safe abuse (deactivation without activation) Signed-off-by: Michal Wajdeczko --- Cc: Rae Moar Cc: David Gow Cc: Lucas De Marchi --- lib/kunit/kunit-test.c | 254 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 253 insertions(+), 1 deletion(-) diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index 37e02be1e710..eb1bb312ad71 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -6,8 +6,10 @@ * Author: Brendan Higgins */ #include "linux/gfp_types.h" +#include #include #include +#include #include #include @@ -866,10 +868,260 @@ static struct kunit_suite kunit_current_test_suite = { .test_cases = kunit_current_test_cases, }; +static struct { + /* this stub matches the real function */ + KUNIT_DECLARE_GLOBAL_STUB(first_stub, int (*)(int i)); + /* this stub matches only return type of the real function */ + KUNIT_DECLARE_GLOBAL_STUB(second_stub, int (*)(int bit, int data)); + /* this is an example stub that returns void */ + KUNIT_DECLARE_GLOBAL_STUB(void_stub, void (*)(void)); + /* this is an example how to store additional data for use by stubs */ + DECLARE_IF_KUNIT(int data); + DECLARE_IF_KUNIT(int counter); +} stubs = { + DECLARE_IF_KUNIT(.data = 3), +}; + +static int real_func(int i) +{ + KUNIT_GLOBAL_STUB_REDIRECT(stubs.first_stub, i); + KUNIT_GLOBAL_STUB_REDIRECT(stubs.second_stub, BIT(i), stubs.data); + + return i; +} + +struct real_work { + struct work_struct work; + int param; + int result; +}; + +static void real_work_func(struct work_struct *work) +{ + struct real_work *w = container_of(work, typeof(*w), work); + + w->result = real_func(w->param); +} + +static int real_func_async(int i) +{ + struct real_work w = { .param = i, .result = -EINPROGRESS }; + + INIT_WORK_ONSTACK(&w.work, real_work_func); + schedule_work(&w.work); + flush_work(&w.work); + destroy_work_on_stack(&w.work); + + return w.result; +} + +static int replacement_func(int i) +{ + return i + 1; +} + +static int other_replacement_func(int i) +{ + return i + 10; +} + +static int super_replacement_func(int bit, int data) +{ + return bit * data; +} + +static int slow_replacement_func(int i) +{ + schedule_timeout_interruptible(HZ / 20); + return replacement_func(i); +} + +static void real_void_func(void) +{ + KUNIT_GLOBAL_STUB_REDIRECT(stubs.void_stub); + DECLARE_IF_KUNIT(stubs.counter++); +} + +static void replacement_void_func(void) +{ + stubs.counter--; +} + +static void expect_deactivated(void *data) +{ + struct kunit *test = kunit_get_current_test(); + + KUNIT_EXPECT_NULL(test, stubs.first_stub.base.owner); + KUNIT_EXPECT_NULL(test, stubs.first_stub.base.replacement); + KUNIT_EXPECT_NULL(test, stubs.second_stub.base.owner); + KUNIT_EXPECT_NULL(test, stubs.second_stub.base.replacement); + KUNIT_EXPECT_NULL(test, stubs.void_stub.base.owner); + KUNIT_EXPECT_NULL(test, stubs.void_stub.base.replacement); +} + +static void kunit_global_stub_test_deactivate(struct kunit *test) +{ + /* make sure everything will be deactivated */ + KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test, expect_deactivated, test)); + + /* deactivate without activate */ + kunit_deactivate_global_stub(test, stubs.first_stub); + + /* deactivate twice */ + kunit_deactivate_global_stub(test, stubs.first_stub); + + /* allow to skip deactivation (will be tested by expect_deactivated action) */ + kunit_activate_global_stub(test, stubs.first_stub, replacement_func); +} + +static void kunit_global_stub_test_activate(struct kunit *test) +{ + int real, replacement, other, super, i = 2; + + /* prerequisites */ + real_void_func(); + KUNIT_ASSERT_EQ(test, stubs.counter, 1); + replacement_void_func(); + KUNIT_ASSERT_EQ(test, stubs.counter, 0); + + /* prerequisites cont'd */ + KUNIT_ASSERT_EQ(test, real_func(i), real = real_func_async(i)); + KUNIT_ASSERT_NE(test, real_func(i), replacement = replacement_func(i)); + KUNIT_ASSERT_NE(test, real_func(i), other = other_replacement_func(i)); + KUNIT_ASSERT_NE(test, real_func(i), super = super_replacement_func(BIT(i), stubs.data)); + + /* make sure everything will be deactivated */ + KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test, expect_deactivated, test)); + + /* allow to activate replacement */ + kunit_activate_global_stub(test, stubs.void_stub, replacement_void_func); + real_void_func(); + KUNIT_ASSERT_EQ(test, stubs.counter, -1); + + /* allow to activate replacement */ + kunit_activate_global_stub(test, stubs.first_stub, replacement_func); + KUNIT_EXPECT_EQ(test, real_func(i), replacement); + KUNIT_EXPECT_EQ(test, real_func_async(i), replacement); + + /* allow to change replacement */ + kunit_activate_global_stub(test, stubs.first_stub, other_replacement_func); + KUNIT_EXPECT_EQ(test, real_func(i), other); + KUNIT_EXPECT_EQ(test, real_func_async(i), other); + + /* allow to deactivate replacement */ + kunit_deactivate_global_stub(test, stubs.first_stub); + KUNIT_EXPECT_EQ(test, real_func(i), real); + KUNIT_EXPECT_EQ(test, real_func_async(i), real); + + /* allow to activate replacement with different arguments */ + kunit_activate_global_stub(test, stubs.second_stub, super_replacement_func); + KUNIT_EXPECT_EQ(test, real_func(i), super); + KUNIT_EXPECT_EQ(test, real_func_async(i), super); + + /* allow to deactivate twice */ + kunit_deactivate_global_stub(test, stubs.second_stub); + kunit_deactivate_global_stub(test, stubs.second_stub); + KUNIT_EXPECT_EQ(test, real_func_async(i), real); + KUNIT_EXPECT_EQ(test, real_func(i), real); +} + +static void flush_real_work(void *data) +{ + struct real_work *w = data; + + flush_work(&w->work); +} + +static void __kunit_global_stub_test_slow(struct kunit *test, bool replace) +{ + int real, replacement, other, i = replace ? 3 : 5; + struct real_work *w; + + /* prerequisites */ + KUNIT_ASSERT_EQ(test, real_func(i), real = real_func_async(i)); + KUNIT_ASSERT_NE(test, real_func(i), replacement = slow_replacement_func(i)); + KUNIT_ASSERT_NE(test, real_func(i), other = other_replacement_func(i)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, w = kunit_kzalloc(test, sizeof(*w), GFP_KERNEL)); + INIT_WORK(&w->work, real_work_func); + KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test, flush_real_work, w)); + KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test, expect_deactivated, test)); + + /* allow to activate replacement */ + kunit_activate_global_stub(test, stubs.first_stub, slow_replacement_func); + KUNIT_EXPECT_EQ(test, real_func_async(i), replacement); + + w->param = i; + w->result = 0; + queue_work(system_long_wq, &w->work); + + /* wait until work starts */ + while (work_pending(&w->work)) + schedule_timeout_interruptible(HZ / 100); + KUNIT_EXPECT_NE(test, work_busy(&w->work), 0); + + /* wait until work enters the stub */ + while (atomic_read(&stubs.first_stub.base.busy) < 2) + schedule_timeout_interruptible(HZ / 100); + + /* stub should be still busy(2) at this point */ + KUNIT_EXPECT_EQ(test, 2, atomic_read(&stubs.first_stub.base.busy)); + KUNIT_EXPECT_EQ(test, w->result, 0); + + if (replace) { + /* try replace the stub, it should be just activated(1) */ + kunit_activate_global_stub(test, stubs.first_stub, other_replacement_func); + KUNIT_EXPECT_EQ(test, 1, atomic_read(&stubs.first_stub.base.busy)); + } else { + /* try to deactivate the stub, it should be disabled(0) */ + kunit_deactivate_global_stub(test, stubs.first_stub); + KUNIT_EXPECT_EQ(test, 0, atomic_read(&stubs.first_stub.base.busy)); + } + + /* and results from the worker should be available */ + KUNIT_EXPECT_EQ(test, w->result, replacement); + KUNIT_EXPECT_NE(test, w->result, real); + KUNIT_EXPECT_NE(test, w->result, other); + + if (replace) + KUNIT_EXPECT_EQ(test, real_func_async(i), other); + else + KUNIT_EXPECT_EQ(test, real_func_async(i), real); +} + +static void kunit_global_stub_test_slow_deactivate(struct kunit *test) +{ + __kunit_global_stub_test_slow(test, false); +} + +static void kunit_global_stub_test_slow_replace(struct kunit *test) +{ + __kunit_global_stub_test_slow(test, true); +} + +static int kunit_global_stub_test_init(struct kunit *test) +{ + stubs.counter = 0; + return 0; +} + +static struct kunit_case kunit_global_stub_test_cases[] = { + KUNIT_CASE(kunit_global_stub_test_activate), + KUNIT_CASE(kunit_global_stub_test_deactivate), + KUNIT_CASE_SLOW(kunit_global_stub_test_slow_deactivate), + KUNIT_CASE_SLOW(kunit_global_stub_test_slow_replace), + {} +}; + +static struct kunit_suite kunit_global_stub_suite = { + .name = "kunit_global_stub", + .init = kunit_global_stub_test_init, + .test_cases = kunit_global_stub_test_cases, +}; + kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, &kunit_log_test_suite, &kunit_status_test_suite, &kunit_current_test_suite, &kunit_device_test_suite, - &kunit_fault_test_suite); + &kunit_fault_test_suite, &kunit_global_stub_suite); MODULE_DESCRIPTION("KUnit test for core test infrastructure"); MODULE_LICENSE("GPL v2");