From 2d854e0d76de2d87bc58ca31adf082b4c09ff92e Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 17 Jun 2026 11:57:24 +0000 Subject: [PATCH] 0706 nwnss: audit queue sharedsrc runtime --- nwnss-audit.md | 9 +- tests/nwnss/CMakeLists.txt | 1 + tests/nwnss/que/CMakeLists.txt | 4 + tests/nwnss/que/test_nwnss_que.c | 317 +++++++++++++++++++++++++++++++ 4 files changed, 327 insertions(+), 4 deletions(-) create mode 100644 tests/nwnss/que/CMakeLists.txt create mode 100644 tests/nwnss/que/test_nwnss_que.c diff --git a/nwnss-audit.md b/nwnss-audit.md index 1d3d617..1ea4726 100644 --- a/nwnss-audit.md +++ b/nwnss-audit.md @@ -114,6 +114,7 @@ still stay original and remain listed, because later imports may rely on them. | PARTIAL | `src/nwnss/comn/common/ndp_messagehandler.c` | ORIG wrapper | link smoke | Novell wrapper name/pattern; full audit open. | | TEMP | `src/nwnss/comn/comnModule.c` | TEMP | link smoke | Transition module identity bridge; should disappear later. | | AUDITED | `src/nwnss/library/bit.c` | PORT | nwnss.bit, nwnss.bitmap | No original provider found beyond bit.h/libNSS.imp; native-NINT semantics fixed/tested in 0698. | +| AUDITED | `src/nwnss/library/que.c` + `src/nwnss/sharedsrc/que.c.h` + `include/nwnss/library/que.h` | ORIG wrapper + ORIG+FIX sharedsrc/header | nwnss.que | Wrapper matches Novell sharedsrc pattern; header and sharedsrc compared with original. Abweichungen sind Include-Pfad-Fixes, legacy callback casts and whitespace/diff-check cleanup only; STK/SQ/CIR/DQ/SET semantics tested in 0706. | | AUDITED | `src/nwnss/library/misc/rand.c` | PORT | nwnss.rand, nwnss.namespace | No original provider found beyond rand.h/libNSS.imp/callers; seed-deterministic PRNG port checked in 0700/0701; libsodium only initializes default state before explicit seeding. | | AUDITED | `src/nwnss/library/misc/rbpTree.c` | PORT | nwnss.rbpTree | No original provider found beyond rbpTree.h/libNSS.imp/callers; CLRS-style algorithmic port checked against header contract in 0703 and strengthened in 0705 with explicit red/black, parent-link, binary-search-order, black-height, and Coin3D-style insertion/deletion stress coverage. Coin3D rbptree.cpp was checked only as an external BSD-licensed CLRS comparison and was not imported. | | TODO | `src/nwnss/library/os/currentTime.c` | PORT | nwnss.utc | Userspace time port; full audit open. | @@ -303,9 +304,9 @@ even if it already compiles or has indirect test coverage. | TODO | ORIG header? | not yet classified | `include/nwnss/library/intlatch.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `include/nwnss/library/nssDebug.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `include/nwnss/library/omni.h` | Must be compared against original source and classified. | -| TODO | ORIG header? | not yet classified | `include/nwnss/library/que.h` | Must be compared against original source and classified. | +| AUDITED | ORIG+FIX | nwnss.que | `include/nwnss/library/que.h` | Compared with original `shared/sdk/library/que.h`; complete header kept. Differences are include path normalization (``) and whitespace-only cleanup; extensive header-documented STK/SQ/CIR/DQ/SET contracts tested in 0706. | | AUDITED | ORIG | nwnss.rand | `include/nwnss/library/rand.h` | Byte-identical to shared/sdk/library/rand.h; audited with rand.c in 0700. | -| AUDITED | ORIG header | nwnss.rbpTree | `include/nwnss/library/rbpTree.h` | Byte-identical to original shared/sdk/library/rbpTree.h; complete header kept. Header itself cites CLRS/Sedgewick and defines the RBP parent-pointer contract. | +| AUDITED | ORIG header | nwnss.rbpTree | `include/nwnss/library/rbpTree.h` | Byte-identical to original shared/sdk/library/rbpTree.h; complete header kept. Header itself cites CLRS/Sedgewick and defines the RBP parent-pointer contract. | | TODO | ORIG header? | not yet classified | `include/nwnss/library/size_t.h` | Must be compared against original source and classified. | | AUDITED | ORIG+FIX | nwnss.xstring | `include/nwnss/library/string.h` | Compared with original; MARS userspace include_next/strings.h branch only. | | AUDITED | ORIG | nwnss.xctype | `include/nwnss/library/xCtype.h` | Byte-identical to original. | @@ -562,7 +563,7 @@ even if it already compiles or has indirect test coverage. | AUDITED | PORT | nwnss.bit, nwnss.bitmap | `src/nwnss/library/bit.c` | No original provider found beyond bit.h/libNSS.imp; native-NINT semantics fixed/tested in 0698. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/functionPtrs.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/qdiv.c` | Must be compared against original source and classified. | -| TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/que.c` | Must be compared against original source and classified. | +| AUDITED | ORIG wrapper | nwnss.que | `src/nwnss/library/que.c` | Wrapper translation unit for original sharedsrc `que.c.h`; matches Novell sharedsrc-wrapper pattern. | | AUDITED | PORT | nwnss.xctype | `src/nwnss/library/xCtype.c` | No original provider found beyond xCtype.h/libNSS.imp; ASCII table/toupper/tolower semantics tested in 0698. | | AUDITED | PORT/ORIG+FIX | nwnss.xstring | `src/nwnss/library/xString.c` | LB_stricmp uses original sharedsrc; no original provider found for remaining libNSS.imp helpers; baseline semantics tested in 0698. | @@ -795,7 +796,7 @@ even if it already compiles or has indirect test coverage. | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/ndp_messagehandler.c.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/otherErrorTables.c.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/parseDSObjectName.c.h` | Must be compared against original source and classified. | -| TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/que.c.h` | Must be compared against original source and classified. | +| AUDITED | ORIG+FIX | nwnss.que | `src/nwnss/sharedsrc/que.c.h` | Compared with original `public_core/sharedsrc/que.c.h`; differences limited to include paths, legacy callback casts for modern compiler types, and whitespace/diff-check cleanup. | | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/stricmp.c.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/sysimp.c.h` | Must be compared against original source and classified. | | TODO | ORIG header? | not yet classified | `src/nwnss/sharedsrc/uni2utf.c.h` | Must be compared against original source and classified. | diff --git a/tests/nwnss/CMakeLists.txt b/tests/nwnss/CMakeLists.txt index e5947e5..958bf37 100644 --- a/tests/nwnss/CMakeLists.txt +++ b/tests/nwnss/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(pssmpk) add_subdirectory(register) add_subdirectory(rbpTree) add_subdirectory(qdiv) +add_subdirectory(que) add_subdirectory(rand) add_subdirectory(schedule) add_subdirectory(slab) diff --git a/tests/nwnss/que/CMakeLists.txt b/tests/nwnss/que/CMakeLists.txt new file mode 100644 index 0000000..a09f452 --- /dev/null +++ b/tests/nwnss/que/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(test_nwnss_que test_nwnss_que.c) +target_compile_features(test_nwnss_que PRIVATE c_std_99) +target_link_libraries(test_nwnss_que PRIVATE mars_nwe::nwnss) +add_test(NAME nwnss.que COMMAND test_nwnss_que) diff --git a/tests/nwnss/que/test_nwnss_que.c b/tests/nwnss/que/test_nwnss_que.c new file mode 100644 index 0000000..5cd6170 --- /dev/null +++ b/tests/nwnss/que/test_nwnss_que.c @@ -0,0 +1,317 @@ +#include "library/que.h" + +#include + +#define CHECK(expr) \ + do { \ + if (!(expr)) { \ + fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #expr); \ + return 1; \ + } \ + } while (0) + +typedef struct QueNode_s { + int id; + struct STKlink_s stk; + struct SQlink_s sq; + struct CIRlink_s cir; + DQlink_t dq; + SETlink_t set; +} QueNode; + +static void init_node(QueNode *node, int id) +{ + node->id = id; + node->stk.next = NULL; + node->sq.next = NULL; + node->cir.next = NULL; + node->dq.next = NULL; + node->dq.prev = NULL; + node->set.next = NULL; + node->set.prev = NULL; + node->set.setNum = 0; +} + +static void init_nodes(QueNode *nodes, int count) +{ + int i; + for (i = 0; i < count; ++i) { + init_node(&nodes[i], i + 1); + } +} + +static STATUS apply_sum(SETlink_t *link, void *arg) +{ + QueNode *node = STRUCT(link, QueNode, set); + int *sum = (int *)arg; + *sum += node->id; + return zOK; +} + +static int test_stack(void) +{ + QueNode nodes[4]; + STKtop_t top; + QueNode *item; + + init_nodes(nodes, 4); + STK_INIT(top); + CHECK(STK_EMPTY(top)); + CHECK(!STK_NOT_EMPTY(top)); + + STK_PUSH(top, &nodes[0], stk); + STK_PUSH(top, &nodes[1], stk); + STK_PUSH(top, &nodes[2], stk); + CHECK(STK_NOT_EMPTY(top)); + STK_PEEK(top, item, QueNode, stk); + CHECK(item == &nodes[2]); + + CHECK(STK_RMV(top, &nodes[1], stk) == TRUE); + CHECK(nodes[1].stk.next == NULL); + + STK_POP(top, item, QueNode, stk); + CHECK(item == &nodes[2]); + CHECK(nodes[2].stk.next == NULL); + STK_POP_NO_CHECK(top, item, QueNode, stk); + CHECK(item == &nodes[0]); + CHECK(STK_EMPTY(top)); + + STK_POP(top, item, QueNode, stk); + CHECK(item == NULL); + + init_nodes(nodes, 4); + STK_INIT_ELEMENTS(top, nodes, 4, QueNode, stk); + CHECK(!STK_EMPTY(top)); + CHECK(STK_RMV(top, &nodes[2], stk) == TRUE); + CHECK(STK_RMV(top, &nodes[2], stk) == FALSE); + return 0; +} + +static int test_singly_linked_queue(void) +{ + QueNode nodes[6]; + SQhead_t head; + SQhead_t other; + QueNode *item; + + init_nodes(nodes, 6); + SQ_INIT(&head); + CHECK(SQ_EMPTY(&head)); + CHECK(SQ_CNT(&head) == 0); + + SQ_ENQ(&head, &nodes[0], sq); + SQ_ENQ(&head, &nodes[1], sq); + SQ_PUSH(&head, &nodes[2], sq); + CHECK(SQ_CNT(&head) == 3); + CHECK(SQ_FIND(&head, &nodes[1], sq) == TRUE); + CHECK(SQ_FIND(&head, &nodes[3], sq) == FALSE); + + SQ_PEEK(&head, item, QueNode, sq); + CHECK(item == &nodes[2]); + SQ_DEQ(&head, item, QueNode, sq); + CHECK(item == &nodes[2]); + CHECK(nodes[2].sq.next == NULL); + + CHECK(SQ_RMV(&head, &nodes[1], sq) == TRUE); + CHECK(nodes[1].sq.next == NULL); + SQ_DEQ_NO_CHECK(&head, item, QueNode, sq); + CHECK(item == &nodes[0]); + CHECK(SQ_EMPTY(&head)); + + SQ_INIT(&head); + SQ_INIT(&other); + SQ_ENQ(&head, &nodes[0], sq); + SQ_ENQ(&head, &nodes[1], sq); + SQ_ENQ(&other, &nodes[2], sq); + SQ_ENQ(&other, &nodes[3], sq); + SQ_APPEND(&head, &other); + CHECK(SQ_EMPTY(&other)); + CHECK(SQ_CNT(&head) == 4); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[0]); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[1]); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[2]); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[3]); + CHECK(SQ_EMPTY(&head)); + + init_nodes(nodes, 6); + SQ_INIT(&head); + SQ_INIT(&other); + SQ_ENQ(&head, &nodes[4], sq); + SQ_ENQ(&other, &nodes[0], sq); + SQ_ENQ(&other, &nodes[1], sq); + SQ_PREPEND(&head, &other); + CHECK(SQ_EMPTY(&other)); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[0]); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[1]); + SQ_DEQ(&head, item, QueNode, sq); CHECK(item == &nodes[4]); + CHECK(SQ_EMPTY(&head)); + return 0; +} + +static int test_circular_queue(void) +{ + QueNode nodes[6]; + CIRhead_t head; + CIRhead_t other; + QueNode *item; + + init_nodes(nodes, 6); + CIR_INIT(head); + CHECK(CIR_EMPTY(head)); + CHECK(CIR_CNT(head) == 0); + + CIR_ENQ(head, &nodes[0], cir); + CIR_ENQ(head, &nodes[1], cir); + CIR_PUSH(head, &nodes[2], cir); + CHECK(CIR_CNT(head) == 3); + CHECK(CIR_FIND(head, &nodes[1], cir) == TRUE); + CHECK(CIR_FIND(head, &nodes[4], cir) == FALSE); + CIR_PEEK(head, item, QueNode, cir); + CHECK(item == &nodes[2]); + + CHECK(CIR_RMV(head, &nodes[1], cir) == TRUE); + CHECK(nodes[1].cir.next == NULL); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[2]); + CIR_DEQ_NO_CHECK(head, item, QueNode, cir); CHECK(item == &nodes[0]); + CHECK(CIR_EMPTY(head)); + + init_nodes(nodes, 6); + CIR_INIT(head); + CIR_INIT(other); + CIR_ENQ(head, &nodes[0], cir); + CIR_ENQ(head, &nodes[1], cir); + CIR_ENQ(other, &nodes[2], cir); + CIR_ENQ(other, &nodes[3], cir); + CIR_APPEND(head, other); + CHECK(CIR_EMPTY(other)); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[0]); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[1]); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[2]); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[3]); + CHECK(CIR_EMPTY(head)); + + init_nodes(nodes, 6); + CIR_INIT(head); + CIR_INIT(other); + CIR_ENQ(head, &nodes[4], cir); + CIR_ENQ(other, &nodes[0], cir); + CIR_ENQ(other, &nodes[1], cir); + CIR_PREPEND(head, other); + CHECK(CIR_EMPTY(other)); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[0]); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[1]); + CIR_DEQ(head, item, QueNode, cir); CHECK(item == &nodes[4]); + CHECK(CIR_EMPTY(head)); + return 0; +} + +static int test_doubly_linked_queue(void) +{ + QueNode nodes[6]; + DQhead_t head; + DQhead_t other; + QueNode *item; + + init_nodes(nodes, 6); + DQ_INIT(&head); + CHECK(DQ_EMPTY(&head)); + CHECK(DQ_CNT(&head) == 0); + CHECK(LBQ_DQaudit(&head) == 0); + + DQ_ENQ(&head, &nodes[0], dq); + DQ_ENQ(&head, &nodes[1], dq); + DQ_PUSH(&head, &nodes[2], dq); + CHECK(DQ_CNT(&head) == 3); + CHECK(DQ_FIND(&head, &nodes[1], dq) == TRUE); + CHECK(DQ_FIND(&head, &nodes[4], dq) == FALSE); + CHECK(LBQ_DQaudit(&head) == 3); + DQ_PEEK(&head, item, QueNode, dq); CHECK(item == &nodes[2]); + DQ_PEEK_END(&head, item, QueNode, dq); CHECK(item == &nodes[1]); + + DQ_RMV(&nodes[0], dq); + CHECK(nodes[0].dq.next == NULL); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[2]); + DQ_TAKE(&head, item, QueNode, dq); CHECK(item == &nodes[1]); + CHECK(DQ_EMPTY(&head)); + + init_nodes(nodes, 6); + DQ_INIT(&head); + DQ_INIT(&other); + DQ_ENQ(&head, &nodes[0], dq); + DQ_ENQ(&head, &nodes[1], dq); + DQ_ENQ(&other, &nodes[2], dq); + DQ_ENQ(&other, &nodes[3], dq); + DQ_APPEND(&head, &other); + CHECK(DQ_EMPTY(&other)); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[0]); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[1]); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[2]); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[3]); + CHECK(DQ_EMPTY(&head)); + + init_nodes(nodes, 6); + DQ_INIT(&head); + DQ_INIT(&other); + DQ_ENQ(&head, &nodes[4], dq); + DQ_ENQ(&other, &nodes[0], dq); + DQ_ENQ(&other, &nodes[1], dq); + DQ_PREPEND(&head, &other); + CHECK(DQ_EMPTY(&other)); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[0]); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[1]); + DQ_DEQ(&head, item, QueNode, dq); CHECK(item == &nodes[4]); + CHECK(DQ_EMPTY(&head)); + return 0; +} + +static int test_ordered_set(void) +{ + QueNode nodes[6]; + SEThead_t head; + QueNode *item; + int sum = 0; + + init_nodes(nodes, 6); + SET_INIT(&head); + CHECK(SET_EMPTY(&head)); + CHECK(SET_CNT(&head) == 0); + + SET_ENQ(&head, &nodes[0], set); + SET_ENQ(&head, &nodes[1], set); + SET_PUSH(&head, &nodes[2], set); + CHECK(SET_CNT(&head) == 3); + CHECK(nodes[2].set.setNum < nodes[0].set.setNum); + CHECK(nodes[0].set.setNum < nodes[1].set.setNum); + CHECK(SET_FIND(&head, &nodes[1], set) == TRUE); + CHECK(SET_FIND(&head, &nodes[4], set) == FALSE); + + SET_PEEK(&head, item, QueNode, set); CHECK(item == &nodes[2]); + SET_PEEK_END(&head, item, QueNode, set); CHECK(item == &nodes[1]); + CHECK(SET_APPLY(&head, (statusfunc_t)apply_sum, &sum) == zOK); + CHECK(sum == (nodes[2].id + nodes[0].id + nodes[1].id)); + + SET_RMV(&nodes[0], set); + CHECK(nodes[0].set.next == NULL); + SET_DEQ(&head, item, QueNode, set); CHECK(item == &nodes[2]); + SET_TAKE(&head, item, QueNode, set); CHECK(item == &nodes[1]); + CHECK(SET_EMPTY(&head)); + + init_nodes(nodes, 6); + SET_INIT(&head); + SET_ENQ(&head, &nodes[0], set); + SET_ENQ(&head, &nodes[1], set); + SET_DEQ_NO_CHECK(&head, item, QueNode, set); CHECK(item == &nodes[0]); + SET_DROP(&head, &nodes[1], set); + CHECK(SET_EMPTY(&head)); + return 0; +} + +int main(void) +{ + CHECK(test_stack() == 0); + CHECK(test_singly_linked_queue() == 0); + CHECK(test_circular_queue() == 0); + CHECK(test_doubly_linked_queue() == 0); + CHECK(test_ordered_set() == 0); + return 0; +}