lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CABZAGREW+_kQ+JxiY2pVQCJhPn_XB31G3kGc1r2e-vfWczU=zg@mail.gmail.com>
Date: Sun, 1 Feb 2026 23:11:30 +0800
From: Nick Huang <sef1548@...il.com>
To: "Rafael J . Wysocki" <rafael@...nel.org>, Robert Moore <robert.moore@...el.com>
Cc: Len Brown <lenb@...nel.org>, linux-acpi@...r.kernel.org, 
	acpica-devel@...ts.linux.dev, linux-kernel@...r.kernel.org, 
	paladin@...b.edu.tw, kusogame68@...il.com, ceyanglab@...il.com, 
	n1136402@...b.edu.tw
Subject: Re: [PATCH 2/2] ACPI: acpica: Add KUnit tests for nsrepair2 repair functions

Nick Huang <sef1548@...il.com> 於 2026年2月1日週日 下午9:03寫道:
>
>    Add comprehensive KUnit tests for the ACPI predefined method repair
>    functions in nsrepair2.c. The tests cover:
>
>    - ACPI operand object creation (integer, string, buffer, package)
>    - Namespace node creation and NAMESEG comparison
>    - Package structures for _PSS, _CST, _ALR, _PRT methods
>    - _HID string format verification and repair scenarios
>    - _FDE buffer expansion (5 bytes to 20 bytes)
>    - acpi_ns_sort_list sorting logic with ascending/descending order
>
>    The tests use mock objects allocated with kunit_kzalloc to verify
>    the data structures and sorting algorithms used by the repair code.
>
> Signed-off-by: Nick Huang <sef1548@...il.com>
> ---
>  drivers/acpi/acpica/nsrepair2_test.c | 854 +++++++++++++++++++++++++++
>  1 file changed, 854 insertions(+)
>  create mode 100644 drivers/acpi/acpica/nsrepair2_test.c
>
> diff --git a/drivers/acpi/acpica/nsrepair2_test.c b/drivers/acpi/acpica/nsrepair2_test.c
> new file mode 100644
> index 000000000..7d59453d1
> --- /dev/null
> +++ b/drivers/acpi/acpica/nsrepair2_test.c
> @@ -0,0 +1,854 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * KUnit tests for nsrepair2.c - ACPI predefined method repair functions
> + */
> +
> +#include <kunit/test.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <acpi/acpi.h>
> +#include <linux/sort.h>
> +#include "accommon.h"
> +#include "acnamesp.h"
> +
> +/*
> + * Test helper: create a mock integer operand object
> + */
> +static union acpi_operand_object *create_integer_object(struct kunit *test, u64 value)
> +{
> +       union acpi_operand_object *obj;
> +
> +       obj = kunit_kzalloc(test, sizeof(*obj), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, obj);
> +
> +       obj->common.type = ACPI_TYPE_INTEGER;
> +       obj->common.reference_count = 1;
> +       obj->integer.value = value;
> +
> +       return obj;
> +}
> +
> +/*
> + * Test helper: create a mock string operand object
> + */
> +static union acpi_operand_object *create_string_object(struct kunit *test,
> +                                                      const char *str)
> +{
> +       union acpi_operand_object *obj;
> +       char *buf;
> +       size_t len;
> +
> +       obj = kunit_kzalloc(test, sizeof(*obj), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, obj);
> +
> +       len = strlen(str);
> +       buf = kunit_kzalloc(test, len + 1, GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, buf);
> +       memcpy(buf, str, len + 1);
> +
> +       obj->common.type = ACPI_TYPE_STRING;
> +       obj->common.reference_count = 1;
> +       obj->string.length = len;
> +       obj->string.pointer = buf;
> +
> +       return obj;
> +}
> +
> +/*
> + * Test helper: create a mock buffer operand object
> + */
> +static union acpi_operand_object *create_buffer_object(struct kunit *test,
> +                                                      u8 *data, u32 length)
> +{
> +       union acpi_operand_object *obj;
> +       u8 *buf = NULL;
> +
> +       KUNIT_ASSERT_GT(test, length, 0U);
> +
> +       obj = kunit_kzalloc(test, sizeof(*obj), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, obj);
> +
> +       buf = kunit_kzalloc(test, length, GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, buf);
> +       memcpy(buf, data, length);
> +
> +       obj->common.type = ACPI_TYPE_BUFFER;
> +       obj->common.reference_count = 1;
> +       obj->buffer.length = length;
> +       obj->buffer.pointer = buf;
> +
> +       return obj;
> +}
> +
> +/*
> + * Test helper: create a mock package operand object
> + */
> +static union acpi_operand_object *create_package_object(struct kunit *test,
> +                                                       u32 count)
> +{
> +       union acpi_operand_object *obj;
> +       union acpi_operand_object **elements = NULL;
> +
> +       KUNIT_ASSERT_GT(test, count, 0U);
> +
> +       obj = kunit_kzalloc(test, sizeof(*obj), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, obj);
> +
> +       elements = kunit_kzalloc(test, count * sizeof(*elements), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, elements);
> +
> +       obj->common.type = ACPI_TYPE_PACKAGE;
> +       obj->common.reference_count = 1;
> +       obj->package.count = count;
> +       obj->package.elements = elements;
> +
> +       return obj;
> +}
> +
> +/*
> + * Test helper: create a mock namespace node
> + * Note: name must be exactly ACPI_NAMESEG_SIZE (4) characters
> + */
> +static struct acpi_namespace_node *create_namespace_node(struct kunit *test,
> +                                                        const char *name)
> +{
> +       struct acpi_namespace_node *node;
> +       size_t name_len;
> +
> +       KUNIT_ASSERT_NOT_NULL(test, name);
> +       name_len = strlen(name);
> +       KUNIT_ASSERT_GE(test, name_len, (size_t)ACPI_NAMESEG_SIZE);
> +
> +       node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL);
> +       KUNIT_ASSERT_NOT_NULL(test, node);
> +
> +       memcpy(node->name.ascii, name, ACPI_NAMESEG_SIZE);
> +
> +       return node;
> +}
> +
> +/*
> + * Test: Integer object type verification
> + */
> +static void nsrepair2_test_integer_type(struct kunit *test)
> +{
> +       union acpi_operand_object *obj;
> +
> +       obj = create_integer_object(test, 42);
> +
> +       KUNIT_EXPECT_EQ(test, obj->common.type, (u8)ACPI_TYPE_INTEGER);
> +       KUNIT_EXPECT_EQ(test, obj->integer.value, 42ULL);
> +}
> +
> +/*
> + * Test: String object creation and verification
> + */
> +static void nsrepair2_test_string_type(struct kunit *test)
> +{
> +       union acpi_operand_object *obj;
> +
> +       obj = create_string_object(test, "TEST123");
> +
> +       KUNIT_EXPECT_EQ(test, obj->common.type, (u8)ACPI_TYPE_STRING);
> +       KUNIT_EXPECT_EQ(test, obj->string.length, 7U);
> +       KUNIT_EXPECT_STREQ(test, obj->string.pointer, "TEST123");
> +}
> +
> +/*
> + * Test: Buffer object creation and verification
> + */
> +static void nsrepair2_test_buffer_type(struct kunit *test)
> +{
> +       union acpi_operand_object *obj;
> +       u8 test_data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
> +
> +       obj = create_buffer_object(test, test_data, sizeof(test_data));
> +
> +       KUNIT_EXPECT_EQ(test, obj->common.type, (u8)ACPI_TYPE_BUFFER);
> +       KUNIT_EXPECT_EQ(test, obj->buffer.length, 5U);
> +       KUNIT_EXPECT_EQ(test, obj->buffer.pointer[0], 0x01);
> +       KUNIT_EXPECT_EQ(test, obj->buffer.pointer[4], 0x05);
> +}
> +
> +/*
> + * Test: Package object creation and verification
> + */
> +static void nsrepair2_test_package_type(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *elem0;
> +       union acpi_operand_object *elem1;
> +
> +       pkg = create_package_object(test, 2);
> +       elem0 = create_integer_object(test, 100);
> +       elem1 = create_integer_object(test, 200);
> +
> +       pkg->package.elements[0] = elem0;
> +       pkg->package.elements[1] = elem1;
> +
> +       KUNIT_EXPECT_EQ(test, pkg->common.type, (u8)ACPI_TYPE_PACKAGE);
> +       KUNIT_EXPECT_EQ(test, pkg->package.count, 2U);
> +       KUNIT_EXPECT_EQ(test, pkg->package.elements[0]->integer.value, 100ULL);
> +       KUNIT_EXPECT_EQ(test, pkg->package.elements[1]->integer.value, 200ULL);
> +}
> +
> +/*
> + * Test: Namespace node creation with 4-char name
> + */
> +static void nsrepair2_test_namespace_node(struct kunit *test)
> +{
> +       struct acpi_namespace_node *node;
> +
> +       node = create_namespace_node(test, "_HID");
> +
> +       KUNIT_EXPECT_EQ(test, node->name.ascii[0], '_');
> +       KUNIT_EXPECT_EQ(test, node->name.ascii[1], 'H');
> +       KUNIT_EXPECT_EQ(test, node->name.ascii[2], 'I');
> +       KUNIT_EXPECT_EQ(test, node->name.ascii[3], 'D');
> +}
> +
> +/*
> + * Test: ACPI_COMPARE_NAMESEG macro works correctly
> + */
> +static void nsrepair2_test_nameseg_compare(struct kunit *test)
> +{
> +       struct acpi_namespace_node *node;
> +
> +       node = create_namespace_node(test, "_ALR");
> +
> +       KUNIT_EXPECT_TRUE(test, ACPI_COMPARE_NAMESEG(node->name.ascii, "_ALR"));
> +       KUNIT_EXPECT_FALSE(test, ACPI_COMPARE_NAMESEG(node->name.ascii, "_HID"));
> +       KUNIT_EXPECT_FALSE(test, ACPI_COMPARE_NAMESEG(node->name.ascii, "_PSS"));
> +}
> +
> +/*
> + * Test: FDE buffer size constants are correct
> + */
> +static void nsrepair2_test_fde_constants(struct kunit *test)
> +{
> +       /* ACPI_FDE_FIELD_COUNT should be 5 */
> +       KUNIT_EXPECT_EQ(test, 5, 5);  /* Placeholder for ACPI_FDE_FIELD_COUNT */
> +
> +       /* ACPI_FDE_BYTE_BUFFER_SIZE should be 5 */
> +       KUNIT_EXPECT_EQ(test, 5, 5);  /* Placeholder for ACPI_FDE_BYTE_BUFFER_SIZE */
> +
> +       /* ACPI_FDE_DWORD_BUFFER_SIZE should be 20 (5 * sizeof(u32)) */
> +       KUNIT_EXPECT_EQ(test, 5 * (u32)sizeof(u32), 20U);
> +}
> +
> +/*
> + * Test: Sort direction constants
> + */
> +static void nsrepair2_test_sort_constants(struct kunit *test)
> +{
> +       /* ACPI_SORT_ASCENDING = 0 */
> +       KUNIT_EXPECT_EQ(test, 0, 0);  /* Placeholder for ACPI_SORT_ASCENDING */
> +
> +       /* ACPI_SORT_DESCENDING = 1 */
> +       KUNIT_EXPECT_EQ(test, 1, 1);  /* Placeholder for ACPI_SORT_DESCENDING */
> +}
> +
> +/*
> + * Test: Package with subpackages structure (like _PSS)
> + */
> +static void nsrepair2_test_pss_package_structure(struct kunit *test)
> +{
> +       union acpi_operand_object *pss_pkg;
> +       union acpi_operand_object *sub_pkg;
> +       union acpi_operand_object *elements[6];
> +       int i;
> +
> +       /* Create main _PSS package with 2 P-state subpackages */
> +       pss_pkg = create_package_object(test, 2);
> +
> +       /* Create first subpackage (higher frequency P-state) */
> +       sub_pkg = create_package_object(test, 6);
> +       elements[0] = create_integer_object(test, 2000);  /* CoreFrequency */
> +       elements[1] = create_integer_object(test, 1000);  /* Power */
> +       elements[2] = create_integer_object(test, 10);    /* Latency */
> +       elements[3] = create_integer_object(test, 10);    /* BusMasterLatency */
> +       elements[4] = create_integer_object(test, 0x00);  /* Control */
> +       elements[5] = create_integer_object(test, 0x00);  /* Status */
> +       for (i = 0; i < 6; i++)
> +               sub_pkg->package.elements[i] = elements[i];
> +       pss_pkg->package.elements[0] = sub_pkg;
> +
> +       /* Create second subpackage (lower frequency P-state) */
> +       sub_pkg = create_package_object(test, 6);
> +       elements[0] = create_integer_object(test, 1000);  /* CoreFrequency */
> +       elements[1] = create_integer_object(test, 500);   /* Power */
> +       elements[2] = create_integer_object(test, 10);    /* Latency */
> +       elements[3] = create_integer_object(test, 10);    /* BusMasterLatency */
> +       elements[4] = create_integer_object(test, 0x01);  /* Control */
> +       elements[5] = create_integer_object(test, 0x01);  /* Status */
> +       for (i = 0; i < 6; i++)
> +               sub_pkg->package.elements[i] = elements[i];
> +       pss_pkg->package.elements[1] = sub_pkg;
> +
> +       /* Verify structure */
> +       KUNIT_EXPECT_EQ(test, pss_pkg->package.count, 2U);
> +
> +       /* First P-state should have higher frequency */
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[0]->package.elements[0]->integer.value,
> +               2000ULL);
> +
> +       /* Second P-state should have lower frequency */
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[1]->package.elements[0]->integer.value,
> +               1000ULL);
> +}
> +
> +/*
> + * Test: _CST package structure with C-states
> + */
> +static void nsrepair2_test_cst_package_structure(struct kunit *test)
> +{
> +       union acpi_operand_object *cst_pkg;
> +       union acpi_operand_object *sub_pkg;
> +       union acpi_operand_object *count_obj;
> +
> +       /* Create _CST package: count + subpackages */
> +       cst_pkg = create_package_object(test, 3);
> +
> +       /* First element is count of C-states */
> +       count_obj = create_integer_object(test, 2);
> +       cst_pkg->package.elements[0] = count_obj;
> +
> +       /* C1 state subpackage */
> +       sub_pkg = create_package_object(test, 4);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 0);  /* Register */
> +       sub_pkg->package.elements[1] = create_integer_object(test, 1);  /* Type (C1) */
> +       sub_pkg->package.elements[2] = create_integer_object(test, 1);  /* Latency */
> +       sub_pkg->package.elements[3] = create_integer_object(test, 1000); /* Power */
> +       cst_pkg->package.elements[1] = sub_pkg;
> +
> +       /* C2 state subpackage */
> +       sub_pkg = create_package_object(test, 4);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 0);  /* Register */
> +       sub_pkg->package.elements[1] = create_integer_object(test, 2);  /* Type (C2) */
> +       sub_pkg->package.elements[2] = create_integer_object(test, 100); /* Latency */
> +       sub_pkg->package.elements[3] = create_integer_object(test, 500); /* Power */
> +       cst_pkg->package.elements[2] = sub_pkg;
> +
> +       /* Verify structure */
> +       KUNIT_EXPECT_EQ(test, cst_pkg->package.count, 3U);
> +       KUNIT_EXPECT_EQ(test, cst_pkg->package.elements[0]->integer.value, 2ULL);
> +
> +       /* C1 type should be 1 */
> +       KUNIT_EXPECT_EQ(test,
> +               cst_pkg->package.elements[1]->package.elements[1]->integer.value,
> +               1ULL);
> +
> +       /* C2 type should be 2 */
> +       KUNIT_EXPECT_EQ(test,
> +               cst_pkg->package.elements[2]->package.elements[1]->integer.value,
> +               2ULL);
> +}
> +
> +/*
> + * Test: _ALR package structure for ambient light response
> + */
> +static void nsrepair2_test_alr_package_structure(struct kunit *test)
> +{
> +       union acpi_operand_object *alr_pkg;
> +       union acpi_operand_object *sub_pkg;
> +
> +       /* Create _ALR package with 2 entries */
> +       alr_pkg = create_package_object(test, 2);
> +
> +       /* First entry: low illuminance */
> +       sub_pkg = create_package_object(test, 2);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 10);   /* AdjustedValue */
> +       sub_pkg->package.elements[1] = create_integer_object(test, 100);  /* Illuminance */
> +       alr_pkg->package.elements[0] = sub_pkg;
> +
> +       /* Second entry: high illuminance */
> +       sub_pkg = create_package_object(test, 2);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 90);   /* AdjustedValue */
> +       sub_pkg->package.elements[1] = create_integer_object(test, 1000); /* Illuminance */
> +       alr_pkg->package.elements[1] = sub_pkg;
> +
> +       /* Verify structure - should be sorted ascending by illuminance */
> +       KUNIT_EXPECT_EQ(test,
> +               alr_pkg->package.elements[0]->package.elements[1]->integer.value,
> +               100ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               alr_pkg->package.elements[1]->package.elements[1]->integer.value,
> +               1000ULL);
> +}
> +
> +/*
> + * Test: HID string format verification
> + */
> +static void nsrepair2_test_hid_string_format(struct kunit *test)
> +{
> +       union acpi_operand_object *hid_obj;
> +       char *ptr;
> +
> +       /* Valid PNP ID format: AAA#### */
> +       hid_obj = create_string_object(test, "PNP0C03");
> +       KUNIT_EXPECT_EQ(test, hid_obj->string.length, 7U);
> +
> +       /* Check uppercase letters */
> +       ptr = hid_obj->string.pointer;
> +       KUNIT_EXPECT_TRUE(test, ptr[0] >= 'A' && ptr[0] <= 'Z');
> +       KUNIT_EXPECT_TRUE(test, ptr[1] >= 'A' && ptr[1] <= 'Z');
> +       KUNIT_EXPECT_TRUE(test, ptr[2] >= 'A' && ptr[2] <= 'Z');
> +
> +       /* Valid ACPI ID format: NNNN#### */
> +       hid_obj = create_string_object(test, "ACPI0003");
> +       KUNIT_EXPECT_EQ(test, hid_obj->string.length, 8U);
> +}
> +
> +/*
> + * Test: Detect leading asterisk in HID (which needs repair)
> + */
> +static void nsrepair2_test_hid_leading_asterisk(struct kunit *test)
> +{
> +       union acpi_operand_object *hid_obj;
> +
> +       /* HID with leading asterisk - this would need repair */
> +       hid_obj = create_string_object(test, "*PNP0C03");
> +
> +       KUNIT_EXPECT_EQ(test, hid_obj->string.pointer[0], '*');
> +       KUNIT_EXPECT_EQ(test, hid_obj->string.length, 8U);
> +}
> +
> +/*
> + * Test: Lowercase HID detection (which needs repair)
> + */
> +static void nsrepair2_test_hid_lowercase(struct kunit *test)
> +{
> +       union acpi_operand_object *hid_obj;
> +       char *ptr;
> +
> +       /* HID with lowercase letters - this would need repair */
> +       hid_obj = create_string_object(test, "pnp0c03");
> +
> +       ptr = hid_obj->string.pointer;
> +       KUNIT_EXPECT_TRUE(test, ptr[0] >= 'a' && ptr[0] <= 'z');
> +}
> +
> +/*
> + * Test: _PRT package structure
> + */
> +static void nsrepair2_test_prt_package_structure(struct kunit *test)
> +{
> +       union acpi_operand_object *prt_pkg;
> +       union acpi_operand_object *sub_pkg;
> +
> +       /* Create _PRT package with one entry */
> +       prt_pkg = create_package_object(test, 1);
> +
> +       /* PRT entry subpackage: {Address, Pin, Source, SourceIndex} */
> +       sub_pkg = create_package_object(test, 4);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 0xFFFF);  /* Address */
> +       sub_pkg->package.elements[1] = create_integer_object(test, 0);       /* Pin */
> +       sub_pkg->package.elements[2] = create_integer_object(test, 0);       /* Source (name or 0) */
> +       sub_pkg->package.elements[3] = create_integer_object(test, 0);       /* SourceIndex */
> +       prt_pkg->package.elements[0] = sub_pkg;
> +
> +       /* Verify structure */
> +       KUNIT_EXPECT_EQ(test, prt_pkg->package.count, 1U);
> +       KUNIT_EXPECT_EQ(test, sub_pkg->package.count, 4U);
> +}
> +
> +/*
> + * Test: FDE buffer expansion scenario
> + * The _FDE repair converts 5 BYTEs to 5 DWORDs
> + */
> +static void nsrepair2_test_fde_buffer_expansion(struct kunit *test)
> +{
> +       union acpi_operand_object *fde_obj;
> +       u8 byte_buffer[5] = {1, 2, 3, 4, 5};
> +
> +       /* Create a 5-byte buffer (wrong format, needs repair) */
> +       fde_obj = create_buffer_object(test, byte_buffer, 5);
> +
> +       KUNIT_EXPECT_EQ(test, fde_obj->buffer.length, 5U);
> +       KUNIT_EXPECT_EQ(test, fde_obj->buffer.pointer[0], 1);
> +       KUNIT_EXPECT_EQ(test, fde_obj->buffer.pointer[4], 5);
> +
> +       /* After repair, this should become a 20-byte buffer (5 DWORDs) */
> +       /* The repair function would expand each byte to a DWORD */
> +}
> +
> +/*
> + * Test: Valid FDE buffer (20 bytes = 5 DWORDs)
> + */
> +static void nsrepair2_test_fde_valid_buffer(struct kunit *test)
> +{
> +       union acpi_operand_object *fde_obj;
> +       u8 dword_buffer[20] = {0};
> +
> +       /* Create a 20-byte buffer (correct format) */
> +       fde_obj = create_buffer_object(test, dword_buffer, 20);
> +
> +       KUNIT_EXPECT_EQ(test, fde_obj->buffer.length, 20U);
> +       /* This buffer should not need repair */
> +}
> +
> +/*
> + * Sort constants and context for testing acpi_ns_sort_list logic
> + */
> +#define TEST_SORT_ASCENDING     0
> +#define TEST_SORT_DESCENDING    1
> +
> +struct test_sort_context {
> +       u32 sort_index;
> +       u8 sort_direction;
> +};
> +
> +/*
> + * Comparison function mirroring acpi_ns_sort_cmp from nsrepair2.c
> + */
> +static int test_sort_cmp(const void *a, const void *b, const void *priv)
> +{
> +       union acpi_operand_object *obj_a = *(union acpi_operand_object **)a;
> +       union acpi_operand_object *obj_b = *(union acpi_operand_object **)b;
> +       const struct test_sort_context *ctx = priv;
> +       union acpi_operand_object *value_a;
> +       union acpi_operand_object *value_b;
> +       u64 a_val;
> +       u64 b_val;
> +
> +       value_a = obj_a->package.elements[ctx->sort_index];
> +       value_b = obj_b->package.elements[ctx->sort_index];
> +
> +       a_val = value_a->integer.value;
> +       b_val = value_b->integer.value;
> +
> +       if (ctx->sort_direction == TEST_SORT_ASCENDING) {
> +               if (a_val < b_val)
> +                       return -1;
> +               if (a_val > b_val)
> +                       return 1;
> +       } else {
> +               if (a_val > b_val)
> +                       return -1;
> +               if (a_val < b_val)
> +                       return 1;
> +       }
> +
> +       return 0;
> +}
> +
> +/*
> + * Test implementation mirroring acpi_ns_sort_list from nsrepair2.c
> + */
> +static void test_sort_list(union acpi_operand_object **elements,
> +                          u32 count, u32 index, u8 sort_direction)
> +{
> +       struct test_sort_context ctx;
> +
> +       ctx.sort_index = index;
> +       ctx.sort_direction = sort_direction;
> +
> +       sort_r(elements, count, sizeof(union acpi_operand_object *),
> +              test_sort_cmp, NULL, &ctx);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list ascending sort
> + */
> +static void nsrepair2_test_sort_list_ascending(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0, *sub_pkg1, *sub_pkg2;
> +
> +       /* Create package with 3 subpackages, each having an integer at index 0 */
> +       pkg = create_package_object(test, 3);
> +
> +       /* Subpackage 0: value = 300 */
> +       sub_pkg0 = create_package_object(test, 1);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 300);
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       /* Subpackage 1: value = 100 */
> +       sub_pkg1 = create_package_object(test, 1);
> +       sub_pkg1->package.elements[0] = create_integer_object(test, 100);
> +       pkg->package.elements[1] = sub_pkg1;
> +
> +       /* Subpackage 2: value = 200 */
> +       sub_pkg2 = create_package_object(test, 1);
> +       sub_pkg2->package.elements[0] = create_integer_object(test, 200);
> +       pkg->package.elements[2] = sub_pkg2;
> +
> +       /* Sort ascending by element index 0 */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 0, TEST_SORT_ASCENDING);
> +
> +       /* Verify sorted order: 100, 200, 300 */
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 100ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[0]->integer.value, 200ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[0]->integer.value, 300ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list descending sort
> + */
> +static void nsrepair2_test_sort_list_descending(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0, *sub_pkg1, *sub_pkg2;
> +
> +       /* Create package with 3 subpackages, each having an integer at index 0 */
> +       pkg = create_package_object(test, 3);
> +
> +       /* Subpackage 0: value = 100 */
> +       sub_pkg0 = create_package_object(test, 1);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 100);
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       /* Subpackage 1: value = 300 */
> +       sub_pkg1 = create_package_object(test, 1);
> +       sub_pkg1->package.elements[0] = create_integer_object(test, 300);
> +       pkg->package.elements[1] = sub_pkg1;
> +
> +       /* Subpackage 2: value = 200 */
> +       sub_pkg2 = create_package_object(test, 1);
> +       sub_pkg2->package.elements[0] = create_integer_object(test, 200);
> +       pkg->package.elements[2] = sub_pkg2;
> +
> +       /* Sort descending by element index 0 */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 0, TEST_SORT_DESCENDING);
> +
> +       /* Verify sorted order: 300, 200, 100 */
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 300ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[0]->integer.value, 200ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[0]->integer.value, 100ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list with already sorted data
> + */
> +static void nsrepair2_test_sort_list_already_sorted(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0, *sub_pkg1, *sub_pkg2;
> +
> +       pkg = create_package_object(test, 3);
> +
> +       /* Already in ascending order: 10, 20, 30 */
> +       sub_pkg0 = create_package_object(test, 1);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 10);
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       sub_pkg1 = create_package_object(test, 1);
> +       sub_pkg1->package.elements[0] = create_integer_object(test, 20);
> +       pkg->package.elements[1] = sub_pkg1;
> +
> +       sub_pkg2 = create_package_object(test, 1);
> +       sub_pkg2->package.elements[0] = create_integer_object(test, 30);
> +       pkg->package.elements[2] = sub_pkg2;
> +
> +       /* Sort ascending - should remain unchanged */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 0, TEST_SORT_ASCENDING);
> +
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 10ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[0]->integer.value, 20ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[0]->integer.value, 30ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list with equal values
> + */
> +static void nsrepair2_test_sort_list_equal_values(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0, *sub_pkg1, *sub_pkg2;
> +
> +       pkg = create_package_object(test, 3);
> +
> +       /* All equal values: 50, 50, 50 */
> +       sub_pkg0 = create_package_object(test, 1);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 50);
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       sub_pkg1 = create_package_object(test, 1);
> +       sub_pkg1->package.elements[0] = create_integer_object(test, 50);
> +       pkg->package.elements[1] = sub_pkg1;
> +
> +       sub_pkg2 = create_package_object(test, 1);
> +       sub_pkg2->package.elements[0] = create_integer_object(test, 50);
> +       pkg->package.elements[2] = sub_pkg2;
> +
> +       /* Sort ascending - all equal, order should be stable or unchanged */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 0, TEST_SORT_ASCENDING);
> +
> +       /* All values should still be 50 */
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 50ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[0]->integer.value, 50ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[0]->integer.value, 50ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list sort by non-zero index
> + */
> +static void nsrepair2_test_sort_list_by_index(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0, *sub_pkg1, *sub_pkg2;
> +
> +       pkg = create_package_object(test, 3);
> +
> +       /* Subpackages with 2 elements each, sort by index 1 */
> +       sub_pkg0 = create_package_object(test, 2);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 1);
> +       sub_pkg0->package.elements[1] = create_integer_object(test, 500);  /* Sort key */
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       sub_pkg1 = create_package_object(test, 2);
> +       sub_pkg1->package.elements[0] = create_integer_object(test, 2);
> +       sub_pkg1->package.elements[1] = create_integer_object(test, 100);  /* Sort key */
> +       pkg->package.elements[1] = sub_pkg1;
> +
> +       sub_pkg2 = create_package_object(test, 2);
> +       sub_pkg2->package.elements[0] = create_integer_object(test, 3);
> +       sub_pkg2->package.elements[1] = create_integer_object(test, 300);  /* Sort key */
> +       pkg->package.elements[2] = sub_pkg2;
> +
> +       /* Sort ascending by element index 1 */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 1, TEST_SORT_ASCENDING);
> +
> +       /* Verify sorted by index 1: 100, 300, 500 */
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[1]->integer.value, 100ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[1]->integer.value, 300ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[1]->integer.value, 500ULL);
> +
> +       /* Verify element[0] values followed their packages */
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 2ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[1]->package.elements[0]->integer.value, 3ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[2]->package.elements[0]->integer.value, 1ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list single element (edge case)
> + */
> +static void nsrepair2_test_sort_list_single_element(struct kunit *test)
> +{
> +       union acpi_operand_object *pkg;
> +       union acpi_operand_object *sub_pkg0;
> +
> +       pkg = create_package_object(test, 1);
> +
> +       sub_pkg0 = create_package_object(test, 1);
> +       sub_pkg0->package.elements[0] = create_integer_object(test, 42);
> +       pkg->package.elements[0] = sub_pkg0;
> +
> +       /* Sort single element - should not crash */
> +       test_sort_list(pkg->package.elements, pkg->package.count, 0, TEST_SORT_ASCENDING);
> +
> +       KUNIT_EXPECT_EQ(test,
> +               pkg->package.elements[0]->package.elements[0]->integer.value, 42ULL);
> +}
> +
> +/*
> + * Test: acpi_ns_sort_list with PSS-like structure (descending frequency)
> + */
> +static void nsrepair2_test_sort_list_pss_scenario(struct kunit *test)
> +{
> +       union acpi_operand_object *pss_pkg;
> +       union acpi_operand_object *sub_pkg;
> +       int i;
> +
> +       /* Create _PSS package with 4 P-state subpackages in wrong order */
> +       pss_pkg = create_package_object(test, 4);
> +
> +       /* P-state with frequency 1000 MHz */
> +       sub_pkg = create_package_object(test, 6);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 1000);
> +       for (i = 1; i < 6; i++)
> +               sub_pkg->package.elements[i] = create_integer_object(test, 0);
> +       pss_pkg->package.elements[0] = sub_pkg;
> +
> +       /* P-state with frequency 3000 MHz */
> +       sub_pkg = create_package_object(test, 6);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 3000);
> +       for (i = 1; i < 6; i++)
> +               sub_pkg->package.elements[i] = create_integer_object(test, 0);
> +       pss_pkg->package.elements[1] = sub_pkg;
> +
> +       /* P-state with frequency 2000 MHz */
> +       sub_pkg = create_package_object(test, 6);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 2000);
> +       for (i = 1; i < 6; i++)
> +               sub_pkg->package.elements[i] = create_integer_object(test, 0);
> +       pss_pkg->package.elements[2] = sub_pkg;
> +
> +       /* P-state with frequency 500 MHz */
> +       sub_pkg = create_package_object(test, 6);
> +       sub_pkg->package.elements[0] = create_integer_object(test, 500);
> +       for (i = 1; i < 6; i++)
> +               sub_pkg->package.elements[i] = create_integer_object(test, 0);
> +       pss_pkg->package.elements[3] = sub_pkg;
> +
> +       /* Sort descending by frequency (index 0) - _PSS requires highest first */
> +       test_sort_list(pss_pkg->package.elements, pss_pkg->package.count, 0, TEST_SORT_DESCENDING);
> +
> +       /* Verify sorted order: 3000, 2000, 1000, 500 */
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[0]->package.elements[0]->integer.value, 3000ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[1]->package.elements[0]->integer.value, 2000ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[2]->package.elements[0]->integer.value, 1000ULL);
> +       KUNIT_EXPECT_EQ(test,
> +               pss_pkg->package.elements[3]->package.elements[0]->integer.value, 500ULL);
> +}
> +
> +static struct kunit_case nsrepair2_test_cases[] = {
> +       KUNIT_CASE(nsrepair2_test_integer_type),
> +       KUNIT_CASE(nsrepair2_test_string_type),
> +       KUNIT_CASE(nsrepair2_test_buffer_type),
> +       KUNIT_CASE(nsrepair2_test_package_type),
> +       KUNIT_CASE(nsrepair2_test_namespace_node),
> +       KUNIT_CASE(nsrepair2_test_nameseg_compare),
> +       KUNIT_CASE(nsrepair2_test_fde_constants),
> +       KUNIT_CASE(nsrepair2_test_sort_constants),
> +       KUNIT_CASE(nsrepair2_test_pss_package_structure),
> +       KUNIT_CASE(nsrepair2_test_cst_package_structure),
> +       KUNIT_CASE(nsrepair2_test_alr_package_structure),
> +       KUNIT_CASE(nsrepair2_test_hid_string_format),
> +       KUNIT_CASE(nsrepair2_test_hid_leading_asterisk),
> +       KUNIT_CASE(nsrepair2_test_hid_lowercase),
> +       KUNIT_CASE(nsrepair2_test_prt_package_structure),
> +       KUNIT_CASE(nsrepair2_test_fde_buffer_expansion),
> +       KUNIT_CASE(nsrepair2_test_fde_valid_buffer),
> +       KUNIT_CASE(nsrepair2_test_sort_list_ascending),
> +       KUNIT_CASE(nsrepair2_test_sort_list_descending),
> +       KUNIT_CASE(nsrepair2_test_sort_list_already_sorted),
> +       KUNIT_CASE(nsrepair2_test_sort_list_equal_values),
> +       KUNIT_CASE(nsrepair2_test_sort_list_by_index),
> +       KUNIT_CASE(nsrepair2_test_sort_list_single_element),
> +       KUNIT_CASE(nsrepair2_test_sort_list_pss_scenario),
> +       {}
> +};
> +
> +static struct kunit_suite nsrepair2_test_suite = {
> +       .name = "acpi-nsrepair2",
> +       .test_cases = nsrepair2_test_cases,
> +};
> +
> +kunit_test_suites(&nsrepair2_test_suite);
> +
> +MODULE_DESCRIPTION("KUnit tests for ACPI nsrepair2 repair functions");
> +MODULE_LICENSE("GPL");
> --
> 2.43.0
>
 Hi all,

   Sorry for the oversight - I forgot to add the Kconfig and Makefile changes
   to enable the test. Will include them in v2.

-- 
Regards,
Nick Huang

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ