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: <20260201130334.3107-3-sef1548@gmail.com>
Date: Sun,  1 Feb 2026 13:03:34 +0000
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,
	Nick Huang <sef1548@...il.com>
Subject: [PATCH 2/2] ACPI: acpica: Add KUnit tests for nsrepair2 repair functions

   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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ