Received: by 2002:a05:6358:9144:b0:117:f937:c515 with SMTP id r4csp1093502rwr; Wed, 3 May 2023 10:04:22 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6eHMOkarDMIGrosrHF1C/6pdB/pmYlhpWVtuNVwngU+lGTaRzcTXU91DM0/ItXHBfABifS X-Received: by 2002:a05:6a20:1610:b0:f5:ff1c:f6a8 with SMTP id l16-20020a056a20161000b000f5ff1cf6a8mr27233954pzj.20.1683133462177; Wed, 03 May 2023 10:04:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683133462; cv=none; d=google.com; s=arc-20160816; b=CHXlV2qQi7Kck4ws0Bi7V9gZXw4fl5ZEDUmVD1E6Wsnc+j6MUYaebCj/Jzrm4bjf3B X5qPIws+LF178UwpZM5BQXhvtpNCAsacvgjP7QsMI3cMqtcsGhTvcObmc9iebHZNqRpj Ys5hoxZgrQvEx8iCe2fHdFAun34If+ei7xD28bZWJeBNl6uj2di8S/HT0uYgaYlwxf8e 7O6ENUkFSvM1hVVayRHYOavWQzPxc0pE6ZpufXnLAb0G4y4HaUWPDU5Mj7Z2syJCDvqX Scu18NsPiF27ALhvXMc4IzZJzica107DFNqc0c4S2FK0KxeZuWI87v4HM8BKK0wDwUp2 77sQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:references :cc:to:from:content-language:subject:user-agent:mime-version:date :message-id:dkim-signature; bh=iRHETFIZFIl9iMCD50OnzRUeVg7Q2LLZPzZ0l0Nj65c=; b=xhPAiEZg9YH0wmt6pB8Z+cDj9FYA9y7sO3GtYsRr4xcRoHYdC5U2xKqFXPErZQ5J7q Cdp4dO7bw5Fzn3MIBhVsXsbaMUo/aD4IViwZqZlRsvfwOrBXo7OHpTuRdG0GApfPRjcx ux1RZpApELpIyAsjbU5nZLX4LyvDnXLiKgCy8iP+Se9obetE78Nnjh/CXz6bLWwSgesP aunsnIZHTV9utktfGOqAF1705ZiFZFQagUO2KGdlt+cJVjHsemPFgfUSCid1b18FPL5x 83ilPCXen8+FSe2nGgyCPzeSzVJCxD9po5RBHaGTxSGZY1wH168K4EJhdFw3GQLp2f6p mWKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SQsAqn3a; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t6-20020a625f06000000b006251fb701a6si33007347pfb.285.2023.05.03.10.04.09; Wed, 03 May 2023 10:04:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SQsAqn3a; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229738AbjECQyC (ORCPT + 99 others); Wed, 3 May 2023 12:54:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229515AbjECQyA (ORCPT ); Wed, 3 May 2023 12:54:00 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3830472B8 for ; Wed, 3 May 2023 09:53:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683132788; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iRHETFIZFIl9iMCD50OnzRUeVg7Q2LLZPzZ0l0Nj65c=; b=SQsAqn3a2DTL9vy4GU2eoJjrcXyQk6x0n4Rk4b05Z8t78hGL9jvHP8IkDnrdaurVTy4Xr4 gQd1t/wY7eTo2FdXMoaHUJ4QshnnLj4n7FNTj6/F0gE0Lmn0bT4VochqacrLBDfcG0ajPx wzvAH5bOOAudmZhdFC5JT6I3oiCkFZI= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-611-QvqjN9_-PMqiY9K_M3wJkA-1; Wed, 03 May 2023 12:53:07 -0400 X-MC-Unique: QvqjN9_-PMqiY9K_M3wJkA-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-5ef8c84cae4so81308686d6.1 for ; Wed, 03 May 2023 09:53:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683132786; x=1685724786; h=content-transfer-encoding:in-reply-to:references:cc:to:from :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=iRHETFIZFIl9iMCD50OnzRUeVg7Q2LLZPzZ0l0Nj65c=; b=Wnt2q92UtR69blNoQqtvgJPbcEGAUuIduYDl6zs12KEk/eRWaVrV5MMH/aFPtTzEPc Ribj/SHPiNM/5vvxx1gRCHbVDB1k/TsIsZx8GOT7dW/IGn67GB8ooRl3gpArO+o/i4Sa HRvIInxFTQwG3haZbD7502sns5ZVOgC36aGtpjFE1lzAOAPCzSy17KpsltdiUu7EtSEb TfX1mBTFRo6IYU7NBpyoJmDo4hBmVXFJnb2ltcaE7Zx+nYNl7wN+NhYt//Q8f8kHujXk iXHgwf+Y8WfyzLMsgBPalOyYKbLLyDnEtkIqidwnVm97kLZ12VAGHyIs0Y9+FvJ2Pqe1 cejQ== X-Gm-Message-State: AC+VfDyHEYafBWtS1nLdjnjiQbl4RAHYvlWhIIZ+Igl4BW31XQLLXF/L WoJKmVeUC1cm5ADzkbwXJi2GqMFgLJUeSaL3nzuxItMI4/pnAv7p1i/0wDSdpldEhB6qz3oS2hC tZWdG8ro2jYLKTOMPLL2/2I87+HDVF08= X-Received: by 2002:a05:6214:20a5:b0:616:55f5:ca94 with SMTP id 5-20020a05621420a500b0061655f5ca94mr9562421qvd.29.1683132786482; Wed, 03 May 2023 09:53:06 -0700 (PDT) X-Received: by 2002:a05:6214:20a5:b0:616:55f5:ca94 with SMTP id 5-20020a05621420a500b0061655f5ca94mr9562400qvd.29.1683132786164; Wed, 03 May 2023 09:53:06 -0700 (PDT) Received: from [192.168.9.16] (net-2-34-28-169.cust.vodafonedsl.it. [2.34.28.169]) by smtp.gmail.com with ESMTPSA id v14-20020a0ccd8e000000b006039f5a247esm10053547qvm.78.2023.05.03.09.53.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 May 2023 09:53:05 -0700 (PDT) Message-ID: <594789b2-eb5d-11fc-9c47-310bdb258f7c@redhat.com> Date: Wed, 3 May 2023 18:53:02 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 Subject: Re: [RFC PATCH v4 1/4] fpga: add fake FPGA manager Content-Language: en-US From: Marco Pagani To: Xu Yilun Cc: Moritz Fischer , Wu Hao , Tom Rix , linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org References: <20230417122308.131453-1-marpagan@redhat.com> <20230417122308.131453-2-marpagan@redhat.com> In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,NICE_REPLY_A, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2023-04-26 17:44, Marco Pagani wrote: > > > On 2023-04-20 20:31, Xu Yilun wrote: >> On 2023-04-17 at 14:23:05 +0200, Marco Pagani wrote: >>> Add fake FPGA manager platform driver with support functions. >>> The driver checks the programming sequence using KUnit expectations. >>> This module is part of the KUnit tests for the FPGA subsystem. >>> >>> Signed-off-by: Marco Pagani >>> --- >>> drivers/fpga/tests/fake-fpga-mgr.c | 386 +++++++++++++++++++++++++++++ >>> drivers/fpga/tests/fake-fpga-mgr.h | 43 ++++ >>> 2 files changed, 429 insertions(+) >>> create mode 100644 drivers/fpga/tests/fake-fpga-mgr.c >>> create mode 100644 drivers/fpga/tests/fake-fpga-mgr.h >>> >>> diff --git a/drivers/fpga/tests/fake-fpga-mgr.c b/drivers/fpga/tests/fake-fpga-mgr.c >>> new file mode 100644 >>> index 000000000000..636df637b291 >>> --- /dev/null >>> +++ b/drivers/fpga/tests/fake-fpga-mgr.c >>> @@ -0,0 +1,386 @@ >>> +// SPDX-License-Identifier: GPL-2.0 >>> +/* >>> + * Driver for the fake FPGA manager >>> + * >>> + * Copyright (C) 2023 Red Hat, Inc. >>> + * >>> + * Author: Marco Pagani >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "fake-fpga-mgr.h" >>> + >>> +#define FAKE_FPGA_MGR_DEV_NAME "fake_fpga_mgr" >>> + >>> +#define FAKE_HEADER_BYTE 0x3f >>> +#define FAKE_HEADER_SIZE FPGA_IMG_BLOCK >>> + >>> +struct fake_mgr_priv { >>> + int rcfg_count; >>> + bool op_parse_header; >>> + bool op_write_init; >>> + bool op_write; >>> + bool op_write_sg; >>> + bool op_write_complete; >>> + struct kunit *test; >>> +}; >>> + >>> +struct fake_mgr_data { >>> + struct kunit *test; >>> +}; >>> + >>> +static void check_header(struct kunit *test, const u8 *buf); >>> + >>> +static enum fpga_mgr_states op_state(struct fpga_manager *mgr) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) >>> + kunit_info(priv->test, "Fake FPGA manager: state\n"); >>> + >>> + return FPGA_MGR_STATE_UNKNOWN; >>> +} >>> + >>> +static u64 op_status(struct fpga_manager *mgr) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) >>> + kunit_info(priv->test, "Fake FPGA manager: status\n"); >>> + >>> + return 0; >>> +} >>> + >>> +static int op_parse_header(struct fpga_manager *mgr, struct fpga_image_info *info, >>> + const char *buf, size_t count) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) { >>> + kunit_info(priv->test, "Fake FPGA manager: parse_header\n"); >>> + >>> + KUNIT_EXPECT_EQ(priv->test, mgr->state, >>> + FPGA_MGR_STATE_PARSE_HEADER); >>> + >>> + check_header(priv->test, buf); >>> + } >>> + >>> + priv->op_parse_header = true; >>> + >>> + return 0; >>> +} >>> + >>> +static int op_write_init(struct fpga_manager *mgr, struct fpga_image_info *info, >>> + const char *buf, size_t count) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) { >>> + kunit_info(priv->test, "Fake FPGA manager: write_init\n"); >>> + >>> + KUNIT_EXPECT_EQ(priv->test, mgr->state, >>> + FPGA_MGR_STATE_WRITE_INIT); >>> + } >>> + >>> + priv->op_write_init = true; >>> + >>> + return 0; >>> +} >>> + >>> +static int op_write(struct fpga_manager *mgr, const char *buf, size_t count) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) { >>> + kunit_info(priv->test, "Fake FPGA manager: write\n"); >>> + >>> + KUNIT_EXPECT_EQ(priv->test, mgr->state, >>> + FPGA_MGR_STATE_WRITE); >>> + } >>> + >>> + priv->op_write = true; >>> + >>> + return 0; >>> +} >>> + >>> +static int op_write_sg(struct fpga_manager *mgr, struct sg_table *sgt) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) { >>> + kunit_info(priv->test, "Fake FPGA manager: write_sg\n"); >>> + >>> + KUNIT_EXPECT_EQ(priv->test, mgr->state, >>> + FPGA_MGR_STATE_WRITE); >>> + } >>> + >>> + priv->op_write_sg = true; >>> + >>> + return 0; >>> +} >>> + >>> +static int op_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) { >>> + kunit_info(priv->test, "Fake FPGA manager: write_complete\n"); >>> + >>> + KUNIT_EXPECT_EQ(priv->test, mgr->state, >>> + FPGA_MGR_STATE_WRITE_COMPLETE); >>> + } >>> + >>> + priv->op_write_complete = true; >>> + priv->rcfg_count++; >>> + >>> + return 0; >>> +} >>> + >>> +static void op_fpga_remove(struct fpga_manager *mgr) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr->priv; >>> + >>> + if (priv->test) >>> + kunit_info(priv->test, "Fake FPGA manager: remove\n"); >>> +} >>> + >>> +static const struct fpga_manager_ops fake_fpga_mgr_ops = { >>> + .initial_header_size = FAKE_HEADER_SIZE, >>> + .skip_header = false, >>> + .state = op_state, >>> + .status = op_status, >>> + .parse_header = op_parse_header, >>> + .write_init = op_write_init, >>> + .write = op_write, >>> + .write_sg = op_write_sg, >>> + .write_complete = op_write_complete, >>> + .fpga_remove = op_fpga_remove, >>> +}; >>> + >>> +/** >>> + * fake_fpga_mgr_register() - register a fake FPGA manager. >>> + * @mgr_ctx: fake FPGA manager context data structure. >>> + * @test: KUnit test context object. >>> + * >>> + * Return: pointer to a new fake FPGA manager on success, an ERR_PTR() >>> + * encoded error code on failure. >>> + */ >>> +struct fake_fpga_mgr * >>> +fake_fpga_mgr_register(struct kunit *test, struct device *parent) >>> +{ >>> + struct fake_fpga_mgr *mgr_ctx; >>> + struct fake_mgr_data pdata; >>> + int ret; >>> + >>> + mgr_ctx = kzalloc(sizeof(*mgr_ctx), GFP_KERNEL); >>> + if (!mgr_ctx) { >>> + ret = -ENOMEM; >>> + goto err_mem; >>> + } >>> + >>> + mgr_ctx->pdev = platform_device_alloc(FAKE_FPGA_MGR_DEV_NAME, >>> + PLATFORM_DEVID_AUTO); >>> + if (!mgr_ctx->pdev) { >>> + pr_err("Fake FPGA manager device allocation failed\n"); >>> + ret = -ENOMEM; >>> + goto err_mem; >>> + } >>> + >>> + pdata.test = test; >>> + platform_device_add_data(mgr_ctx->pdev, &pdata, sizeof(pdata)); >>> + >>> + mgr_ctx->pdev->dev.parent = parent; >>> + ret = platform_device_add(mgr_ctx->pdev); >>> + if (ret) { >>> + pr_err("Fake FPGA manager device add failed\n"); >>> + goto err_pdev; >>> + } >>> + >>> + mgr_ctx->mgr = platform_get_drvdata(mgr_ctx->pdev); >>> + >>> + if (test) >>> + kunit_info(test, "Fake FPGA manager registered\n"); >>> + >>> + return mgr_ctx; >>> + >>> +err_pdev: >>> + platform_device_put(mgr_ctx->pdev); >>> + kfree(mgr_ctx); >>> +err_mem: >>> + return ERR_PTR(ret); >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_register); >>> + >>> +/** >>> + * fake_fpga_mgr_unregister() - unregister a fake FPGA manager. >>> + * @mgr_ctx: fake FPGA manager context data structure. >>> + */ >>> +void fake_fpga_mgr_unregister(struct fake_fpga_mgr *mgr_ctx) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + struct kunit *test; >>> + >>> + if (!mgr_ctx) >>> + return; >>> + >>> + priv = mgr_ctx->mgr->priv; >>> + test = priv->test; >>> + >>> + if (mgr_ctx->pdev) { >>> + platform_device_unregister(mgr_ctx->pdev); >>> + if (test) >>> + kunit_info(test, "Fake FPGA manager unregistered\n"); >>> + } >>> + >>> + kfree(mgr_ctx); >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_unregister); >>> + >>> +/** >>> + * fake_fpga_mgr_get_rcfg_count() - get the number of reconfigurations. >>> + * @mgr_ctx: fake FPGA manager context data structure. >>> + * >>> + * Return: number of reconfigurations. >>> + */ >>> +int fake_fpga_mgr_get_rcfg_count(const struct fake_fpga_mgr *mgr_ctx) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr_ctx->mgr->priv; >>> + >>> + return priv->rcfg_count; >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_get_rcfg_count); >>> + >>> +/** >>> + * fake_fpga_mgr_fill_header() - fill an image buffer with the test header. >>> + * @buf: image buffer. >>> + */ >>> +void fake_fpga_mgr_fill_header(u8 *buf) >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < FAKE_HEADER_SIZE; i++) >>> + buf[i] = FAKE_HEADER_BYTE; >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_fill_header); >>> + >>> +static void check_header(struct kunit *test, const u8 *buf) >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < FAKE_HEADER_SIZE; i++) >>> + KUNIT_EXPECT_EQ(test, buf[i], FAKE_HEADER_BYTE); >>> +} >>> + >>> +static void clear_op_flags(struct fake_mgr_priv *priv) >>> +{ >>> + priv->op_parse_header = false; >>> + priv->op_write_init = false; >>> + priv->op_write = false; >>> + priv->op_write_sg = false; >>> + priv->op_write_complete = false; >>> +} >>> + >>> +/** >>> + * fake_fpga_mgr_check_write_buf() - check if programming using a buffer succeeded. >>> + * @mgr_ctx: fake FPGA manager context data structure. >>> + */ >>> +void fake_fpga_mgr_check_write_buf(struct fake_fpga_mgr *mgr_ctx) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr_ctx->mgr->priv; >>> + >>> + if (priv->test) { >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_parse_header, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write_init, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write_complete, true); >>> + } >>> + >>> + clear_op_flags(priv); >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_check_write_buf); >>> + >>> +/** >>> + * fake_fpga_mgr_check_write_sgt() - check if programming using a s.g. table succeeded. >>> + * @mgr_ctx: fake FPGA manager context data structure. >>> + */ >>> +void fake_fpga_mgr_check_write_sgt(struct fake_fpga_mgr *mgr_ctx) >>> +{ >>> + struct fake_mgr_priv *priv; >>> + >>> + priv = mgr_ctx->mgr->priv; >>> + >>> + if (priv->test) { >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_parse_header, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write_init, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write_sg, true); >>> + KUNIT_EXPECT_EQ(priv->test, priv->op_write_complete, true); >>> + } >>> + >>> + clear_op_flags(priv); >>> +} >>> +EXPORT_SYMBOL_GPL(fake_fpga_mgr_check_write_sgt); >> >> I'm wondering, if we could move all these exported functions out of >> fake_fpga driver module. And make this driver module serves FPGA >> mgr framework only, just like other fpga drivers do. >> >> I assume the main requirement is to check the statistics produced >> by the fake fpga driver. Directly accessing mgr->priv outside the >> driver could be unwanted. To solve this, could we create a shared >> buffer for the statistics and pass to fake drivers by platform data. >> >> I hope move all the tester's actions in fpga-test.c, so that people >> could easily see from code what a user need to do to enable fpga >> reprogramming and what are expected in one file. The fake drivers could >> be kept as simple, they only move the process forward and produce >> statistics. >> >> Thanks, >> Yilun >> > > I agree with you. Initially, I wanted to keep all KUnit test assertions > and expectations contained in fpga-test. However, I could not find a simple > way to test that the FPGA manager performs the correct state transitions > during programming. So I ended up putting KUnit assertions in the methods > of the low-level fake driver as a first solution. > > I like your suggestion of using a shared buffer to have a cleaner > implementation. My only concern is that it would make the code more complex. > I will work on this for V5. > I experimented with a couple of alternatives to move all tests inside fpga-test and remove the external functions. Unfortunately, each alternative comes with its drawbacks. Using a shared buffer (e.g., kfifo) to implement an events buffer between fake mgr/bridge and the fpga-test overcomplicates the code (i.e., defining message structs, enums for the operations, locks, etc.). Moving fake modules' (mgr, bridge, region) implementations inside fpga-test makes fpga-test monolithic and harder to understand and maintain. Accessing modules' private data directly from fpga-test breaks encapsulation. Overall, it seems to me that using external functions to get the state of fake modules is the least-worst alternative. What are your thoughts and preferences? Thanks, Marco >>> [...]