import std/[unittest, times, json, options, strutils] import ../src/nip/metadata suite "Package Metadata Generation": test "generateMetadata creates complete metadata for NPK": # Requirement 7.1: source origin, maintainer, upstream URL, build timestamp let source = SourceInfo( origin: "https://github.com/example/package", maintainer: "John Doe ", upstreamUrl: "https://example.com/package", sourceHash: "xxh3-abc123" ) # Requirement 7.2: compiler version, flags, target architecture, build hash let buildInfo = BuildInfo( compilerVersion: "gcc-13.2.0", compilerFlags: @["-O2", "-march=native"], targetArchitecture: "x86_64", buildHash: "xxh3-def456", buildTimestamp: now() ) let metadata = generateMetadata( packageName = "nginx", version = "1.24.0", formatType = FormatType.NPK, source = source, buildInfo = buildInfo ) check metadata.packageName == "nginx" check metadata.version == "1.24.0" check metadata.formatType == FormatType.NPK check metadata.source.origin == "https://github.com/example/package" check metadata.source.maintainer == "John Doe " check metadata.buildInfo.compilerVersion == "gcc-13.2.0" check metadata.buildInfo.buildHash == "xxh3-def456" test "generateMetadata creates complete metadata for NIP": let source = SourceInfo( origin: "https://flathub.org/apps/firefox", maintainer: "Mozilla Foundation", upstreamUrl: "https://www.mozilla.org/firefox/", sourceHash: "xxh3-xyz789" ) let buildInfo = BuildInfo( compilerVersion: "clang-16.0.0", compilerFlags: @["-O3", "-flto"], targetArchitecture: "x86_64", buildHash: "xxh3-ghi012", buildTimestamp: now() ) let metadata = generateMetadata( packageName = "firefox", version = "120.0", formatType = FormatType.NIP, source = source, buildInfo = buildInfo ) check metadata.formatType == FormatType.NIP check metadata.source.upstreamUrl == "https://www.mozilla.org/firefox/" test "generateMetadata creates complete metadata for NEXTER": let source = SourceInfo( origin: "https://hub.docker.com/_/nginx", maintainer: "NGINX Team", upstreamUrl: "https://nginx.org/", sourceHash: "xxh3-jkl345" ) let buildInfo = BuildInfo( compilerVersion: "gcc-12.3.0", compilerFlags: @["-O2"], targetArchitecture: "aarch64", buildHash: "xxh3-mno678", buildTimestamp: now() ) let metadata = generateMetadata( packageName = "nginx-container", version = "1.24.0", formatType = FormatType.NEXTER, source = source, buildInfo = buildInfo ) check metadata.formatType == FormatType.NEXTER check metadata.buildInfo.targetArchitecture == "aarch64" test "metadata includes provenance chain": # Requirement 7.3: complete chain from source to installation let source = SourceInfo( origin: "https://github.com/example/package", maintainer: "John Doe ", upstreamUrl: "https://example.com/package", sourceHash: "xxh3-abc123" ) let buildInfo = BuildInfo( compilerVersion: "gcc-13.2.0", compilerFlags: @["-O2"], targetArchitecture: "x86_64", buildHash: "xxh3-def456", buildTimestamp: now() ) let provenance = ProvenanceChain( sourceDownload: ProvenanceStep( timestamp: now(), action: "source_download", hash: "xxh3-abc123", verifiedBy: "nip-0.2.0" ), build: ProvenanceStep( timestamp: now(), action: "build", hash: "xxh3-def456", verifiedBy: "nip-0.2.0" ), installation: ProvenanceStep( timestamp: now(), action: "installation", hash: "xxh3-ghi789", verifiedBy: "nip-0.2.0" ) ) let metadata = generateMetadata( packageName = "test-package", version = "1.0.0", formatType = FormatType.NPK, source = source, buildInfo = buildInfo, provenance = some(provenance) ) check metadata.provenance.isSome check metadata.provenance.get().sourceDownload.action == "source_download" check metadata.provenance.get().build.action == "build" check metadata.provenance.get().installation.action == "installation" test "metadata can be serialized to JSON": # Requirement 7.4: metadata can be queried let source = SourceInfo( origin: "https://github.com/example/package", maintainer: "John Doe ", upstreamUrl: "https://example.com/package", sourceHash: "xxh3-abc123" ) let buildInfo = BuildInfo( compilerVersion: "gcc-13.2.0", compilerFlags: @["-O2", "-march=native"], targetArchitecture: "x86_64", buildHash: "xxh3-def456", buildTimestamp: now() ) let metadata = generateMetadata( packageName = "nginx", version = "1.24.0", formatType = FormatType.NPK, source = source, buildInfo = buildInfo ) let jsonStr = toJson(metadata) check jsonStr.len > 0 # Verify JSON contains required fields let parsed = parseJson(jsonStr) check parsed.hasKey("packageName") check parsed.hasKey("version") check parsed.hasKey("formatType") check parsed.hasKey("source") check parsed.hasKey("buildInfo") check parsed["source"].hasKey("origin") check parsed["source"].hasKey("maintainer") check parsed["source"].hasKey("upstreamUrl") check parsed["buildInfo"].hasKey("compilerVersion") check parsed["buildInfo"].hasKey("buildHash") test "metadata can be deserialized from JSON": let jsonStr = """ { "packageName": "nginx", "version": "1.24.0", "formatType": "NPK", "source": { "origin": "https://github.com/example/package", "maintainer": "John Doe ", "upstreamUrl": "https://example.com/package", "sourceHash": "xxh3-abc123" }, "buildInfo": { "compilerVersion": "gcc-13.2.0", "compilerFlags": ["-O2", "-march=native"], "targetArchitecture": "x86_64", "buildHash": "xxh3-def456", "buildTimestamp": "2025-11-20T10:30:00Z" }, "dependencies": [], "createdAt": "2025-11-20T10:30:00Z" } """ let metadata = fromJson(jsonStr) check metadata.packageName == "nginx" check metadata.version == "1.24.0" check metadata.formatType == FormatType.NPK check metadata.source.origin == "https://github.com/example/package" check metadata.buildInfo.compilerVersion == "gcc-13.2.0" test "metadata uses xxh3 for build hashes": # Requirement 7.5: use xxh3 for build hashes let source = SourceInfo( origin: "https://github.com/example/package", maintainer: "John Doe ", upstreamUrl: "https://example.com/package", sourceHash: "xxh3-abc123" ) let buildInfo = BuildInfo( compilerVersion: "gcc-13.2.0", compilerFlags: @["-O2"], targetArchitecture: "x86_64", buildHash: "xxh3-def456", # Must use xxh3 prefix buildTimestamp: now() ) let metadata = generateMetadata( packageName = "test-package", version = "1.0.0", formatType = FormatType.NPK, source = source, buildInfo = buildInfo ) check metadata.buildInfo.buildHash.startsWith("xxh3-") check metadata.source.sourceHash.startsWith("xxh3-") test "metadata includes dependencies with build hashes": let source = SourceInfo( origin: "https://github.com/example/package", maintainer: "John Doe ", upstreamUrl: "https://example.com/package", sourceHash: "xxh3-abc123" ) let buildInfo = BuildInfo( compilerVersion: "gcc-13.2.0", compilerFlags: @["-O2"], targetArchitecture: "x86_64", buildHash: "xxh3-def456", buildTimestamp: now() ) let dependencies = @[ DependencyInfo( name: "openssl", version: "3.0.0", buildHash: "xxh3-dep001" ), DependencyInfo( name: "zlib", version: "1.2.13", buildHash: "xxh3-dep002" ) ] let metadata = generateMetadata( packageName = "nginx", version = "1.24.0", formatType = FormatType.NPK, source = source, buildInfo = buildInfo, dependencies = dependencies ) check metadata.dependencies.len == 2 check metadata.dependencies[0].name == "openssl" check metadata.dependencies[0].buildHash == "xxh3-dep001" check metadata.dependencies[1].name == "zlib" check metadata.dependencies[1].buildHash == "xxh3-dep002"