253 lines
7.7 KiB
Nim
253 lines
7.7 KiB
Nim
## Property-Based Tests for NPK Manifest - TDD Approach
|
|
##
|
|
## **Feature:** 01-nip-unified-storage-and-formats
|
|
## **Property 3:** Manifesttrip
|
|
## **Validates:** Requirements 6.4
|
|
##
|
|
## **Property Statement:**
|
|
## For any NPK manifest, parsing and regenerating SHALL produce semantically equivalent KDL
|
|
##
|
|
## **TDD Strategy:**
|
|
## This test is written FIRST to expose gaps in the implementation.
|
|
## Test failures will drive the implementation of parseNPKManifest and generateNPKManifest.
|
|
## We use a MAXIMALLY POPULATED manifest to ensure ALL fields are tested.
|
|
|
|
import std/[unittest, times, options, strutils]
|
|
import nip/npk_manifest
|
|
import nip/manifest_parser
|
|
|
|
# ============================================================================
|
|
# Helper: Create Maximally Populated NPK Manifest
|
|
# ============================================================================
|
|
|
|
proc createFullNPKManifest*(): NPKManifest =
|
|
## Creates a maximally populated NPKManifest instance for roundtrip testing.
|
|
## This ensures we test ALL fields, not just the minimal required ones.
|
|
##
|
|
## **Philosophy:** Test the hardest case first. If this passes, simpler cases will too.
|
|
|
|
result = NPKManifest(
|
|
name: "nexus-base-pkg",
|
|
version: parseSemanticVersion("1.2.3-alpha.1+build.2"),
|
|
buildDate: parse("2025-11-20T14:00:00Z", "yyyy-MM-dd'T'HH:mm:ss'Z'"),
|
|
|
|
metadata: PackageInfo(
|
|
description: "Core dependency package for NexusOS.",
|
|
license: "Dual-ACUL-EUPL-1.2",
|
|
homepage: some("https://nexus.os/base"),
|
|
author: some("Markus Maiwald"),
|
|
maintainer: some("team@nexus.os"),
|
|
tags: @["core", "utility", "system"]
|
|
),
|
|
|
|
provenance: ProvenanceInfo(
|
|
source: "https://nexus.os/sources/base-1.2.3.tar.gz",
|
|
sourceHash: "xxh3-source123456789abc",
|
|
upstream: some("https://upstream.project.org"),
|
|
buildTimestamp: parse("2025-11-20T14:00:00Z", "yyyy-MM-dd'T'HH:mm:ss'Z'"),
|
|
builder: some("build-bot@nexus.os")
|
|
),
|
|
|
|
buildConfig: BuildConfiguration(
|
|
configureFlags: @["--prefix=/usr", "--enable-shared"],
|
|
compilerFlags: @["-O3", "-fno-lto", "-march=native"],
|
|
compilerVersion: "gcc-13.2.0",
|
|
targetArchitecture: "x86_64",
|
|
libc: "glibc",
|
|
allocator: "jemalloc",
|
|
buildSystem: "meson"
|
|
),
|
|
|
|
dependencies: @[
|
|
Dependency(
|
|
name: "zlib",
|
|
version: "1.2.13",
|
|
buildHash: "xxh3-zlib-build-hash",
|
|
optional: false
|
|
),
|
|
Dependency(
|
|
name: "openssl",
|
|
version: "3.0.0",
|
|
buildHash: "xxh3-openssl-build-hash",
|
|
optional: false
|
|
),
|
|
Dependency(
|
|
name: "gui-tools",
|
|
version: "2.0.0",
|
|
buildHash: "xxh3-gui-build-hash",
|
|
optional: true
|
|
)
|
|
],
|
|
|
|
casChunks: @[
|
|
ChunkReference(
|
|
hash: "xxh3-chunk1-binary",
|
|
size: 1048576,
|
|
chunkType: Binary,
|
|
path: "bin/nexus-base"
|
|
),
|
|
ChunkReference(
|
|
hash: "xxh3-chunk2-library",
|
|
size: 524288,
|
|
chunkType: Library,
|
|
path: "lib/libnexus.so"
|
|
),
|
|
ChunkReference(
|
|
hash: "xxh3-chunk3-config",
|
|
size: 4096,
|
|
chunkType: Config,
|
|
path: "etc/nexus.conf"
|
|
)
|
|
],
|
|
|
|
install: InstallPaths(
|
|
programsPath: "/Programs/NexusBase/1.2.3",
|
|
binPath: "/Programs/NexusBase/1.2.3/bin",
|
|
libPath: "/Programs/NexusBase/1.2.3/lib",
|
|
sharePath: "/Programs/NexusBase/1.2.3/share",
|
|
etcPath: "/Programs/NexusBase/1.2.3/etc"
|
|
),
|
|
|
|
system: SystemIntegration(
|
|
services: @[
|
|
ServiceSpec(
|
|
name: "nexus-base",
|
|
serviceType: "systemd",
|
|
enable: true,
|
|
startOnBoot: true
|
|
)
|
|
],
|
|
users: @[
|
|
UserSpec(
|
|
name: "nexus",
|
|
uid: some(1000),
|
|
system: true,
|
|
shell: "/bin/false",
|
|
home: some("/var/lib/nexus")
|
|
)
|
|
],
|
|
groups: @[
|
|
GroupSpec(
|
|
name: "nexus",
|
|
gid: some(1000),
|
|
system: true
|
|
)
|
|
],
|
|
systemPaths: @["/usr/bin/nexus-base"]
|
|
),
|
|
|
|
buildHash: "xxh3-build-config-hash",
|
|
|
|
signature: SignatureInfo(
|
|
algorithm: "ed25519",
|
|
keyId: "packager-2024-key",
|
|
signature: "base64-encoded-signature-placeholder"
|
|
)
|
|
)
|
|
|
|
# ============================================================================
|
|
# Property Tests - Written FIRST to Drive Implementation
|
|
# ============================================================================
|
|
|
|
suite "NPK Manifest Roundtrip Property Tests (Task 6.1)":
|
|
|
|
test "Property 3: KDL Generation - Verify output structure":
|
|
## **Phase 1:** Test that generateNPKManifest produces valid KDL
|
|
## This will fail initially and show us what's missing
|
|
|
|
let manifest = createFullNPKManifest()
|
|
let kdl = generateNPKManifest(manifest)
|
|
|
|
# Basic sanity checks
|
|
check kdl.len > 0
|
|
check "package" in kdl
|
|
check manifest.name in kdl
|
|
|
|
# Print generated KDL for inspection
|
|
echo "\n=== Generated KDL (Phase 1) ===\n"
|
|
echo kdl
|
|
echo "=== End KDL ===\n"
|
|
|
|
test "Property 3: Full Roundtrip - ALL FIELDS":
|
|
## **Phase 2:** Full roundtrip test
|
|
## This is the MAIN test that will expose all gaps
|
|
##
|
|
## **Feature: 01-nip-unified-storage-and-formats, Property 3: Manifest Roundtrip**
|
|
## **Validates: Requirements 6.4**
|
|
|
|
let originalManifest = createFullNPKManifest()
|
|
|
|
# Step 1: Generate KDL
|
|
let kdlString = generateNPKManifest(originalManifest)
|
|
check kdlString.len > 0
|
|
|
|
# Step 2: Parse KDL back
|
|
let parsedManifest = parseNPKManifest(kdlString)
|
|
|
|
# Step 3: Verify ALL fields preserved
|
|
if parsedManifest.name != originalManifest.name:
|
|
echo "Name mismatch: ", parsedManifest.name, " != ", originalManifest.name
|
|
check parsedManifest.name == originalManifest.name
|
|
|
|
if parsedManifest.version != originalManifest.version:
|
|
echo "Version mismatch:"
|
|
echo " Parsed: ", parsedManifest.version
|
|
echo " Original: ", originalManifest.version
|
|
check parsedManifest.version == originalManifest.version
|
|
|
|
if parsedManifest.buildHash != originalManifest.buildHash:
|
|
echo "BuildHash mismatch: ", parsedManifest.buildHash, " != ", originalManifest.buildHash
|
|
check parsedManifest.buildHash == originalManifest.buildHash
|
|
|
|
# Step 4: Verify deterministic generation
|
|
let kdlString2 = generateNPKManifest(parsedManifest)
|
|
if kdlString != kdlString2:
|
|
echo "KDL strings don't match!"
|
|
echo "=== Original KDL ==="
|
|
echo kdlString
|
|
echo "=== Regenerated KDL ==="
|
|
echo kdlString2
|
|
check kdlString == kdlString2
|
|
|
|
suite "NPK Manifest Validation Tests":
|
|
|
|
test "Validate manifest with valid xxh3 hashes":
|
|
let validManifest = NPKManifest(
|
|
name: "valid-pkg",
|
|
version: parseSemanticVersion("1.0.0"),
|
|
buildDate: now(),
|
|
metadata: PackageInfo(
|
|
description: "Valid package",
|
|
license: "MIT"
|
|
),
|
|
provenance: ProvenanceInfo(
|
|
source: "https://example.com/valid.tar.gz",
|
|
sourceHash: "xxh3-valid123",
|
|
buildTimestamp: now()
|
|
),
|
|
buildConfig: BuildConfiguration(
|
|
compilerVersion: "gcc-13.2.0",
|
|
targetArchitecture: "x86_64",
|
|
libc: "musl",
|
|
allocator: "default",
|
|
buildSystem: "cmake"
|
|
),
|
|
install: InstallPaths(
|
|
programsPath: "/Programs/Valid/1.0.0",
|
|
binPath: "/Programs/Valid/1.0.0/bin",
|
|
libPath: "/Programs/Valid/1.0.0/lib",
|
|
sharePath: "/Programs/Valid/1.0.0/share",
|
|
etcPath: "/Programs/Valid/1.0.0/etc"
|
|
),
|
|
system: SystemIntegration(),
|
|
buildHash: "xxh3-build123",
|
|
signature: SignatureInfo(
|
|
algorithm: "ed25519",
|
|
keyId: "test-key",
|
|
signature: "test-signature"
|
|
)
|
|
)
|
|
|
|
let issues = validateNPKManifest(validManifest)
|
|
check issues.len == 0
|