// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package verify import ( "testing" ) func TestParseParamsExported(t *testing.T) { tests := []struct { input string names []string types []string isPtr []bool }{ { input: "dst []byte, src []byte", names: []string{"dst", "src"}, types: []string{"[]byte", "[]byte"}, isPtr: []bool{true, true}, }, { input: "dst, src []byte", names: []string{"dst", "src"}, types: []string{"[]byte", "[]byte"}, isPtr: []bool{true, true}, }, { input: "a, b int", names: []string{"a", "b"}, types: []string{"int", "int"}, isPtr: []bool{false, false}, }, { input: "src []byte, dst []byte", names: []string{"src", "dst"}, types: []string{"[]byte", "[]byte"}, isPtr: []bool{true, true}, }, { input: "swin []int32, dstP []uint32, hist *[32]uint16", names: []string{"swin", "dstP", "hist"}, types: []string{"[]int32", "[]uint32", "*[32]uint16"}, isPtr: []bool{true, true, true}, }, { input: "n int, code int", names: []string{"n", "code"}, types: []string{"int", "int"}, isPtr: []bool{false, false}, }, } for _, tt := range tests { params := parseParamsExported(tt.input) if len(params) != len(tt.names) { t.Errorf("parseParamsExported(%q): got %d params, want %d", tt.input, len(params), len(tt.names)) continue } for i, p := range params { if p.Name != tt.names[i] { t.Errorf("parseParamsExported(%q)[%d].Name = %q, want %q", tt.input, i, p.Name, tt.names[i]) } if p.Typ != tt.types[i] { t.Errorf("parseParamsExported(%q)[%d].Typ = %q, want %q", tt.input, i, p.Typ, tt.types[i]) } if p.IsPointer() != tt.isPtr[i] { t.Errorf("parseParamsExported(%q)[%d].IsPointer() = %v, want %v", tt.input, i, p.IsPointer(), tt.isPtr[i]) } } } } func TestParseBufSpec(t *testing.T) { t.Run("empty", func(t *testing.T) { specs, err := ParseBufSpec("") if err != nil || len(specs) != 0 { t.Errorf("ParseBufSpec(\"\") = %v, %v; want nil, nil", specs, err) } }) t.Run("single", func(t *testing.T) { specs, err := ParseBufSpec("dst:64:zero") if err != nil { t.Fatal(err) } if len(specs) != 1 || specs[0].Name != "dst" || specs[0].Size != 64 || specs[0].Pattern != "zero" { t.Errorf("ParseBufSpec(\"dst:64:zero\") = %+v; want [{dst 64 zero}]", specs) } }) t.Run("multiple", func(t *testing.T) { specs, err := ParseBufSpec("dst:64:zero,src:128:seq") if err != nil { t.Fatal(err) } if len(specs) != 2 { t.Fatalf("got %d specs, want 2", len(specs)) } if specs[0].Name != "dst" || specs[1].Name != "src" { t.Errorf("names = %s, %s; want dst, src", specs[0].Name, specs[1].Name) } }) t.Run("invalid", func(t *testing.T) { _, err := ParseBufSpec("bad") if err == nil { t.Error("ParseBufSpec(\"bad\") should error") } }) t.Run("zero-size", func(t *testing.T) { _, err := ParseBufSpec("dst:0:zero") if err == nil { t.Error("ParseBufSpec(\"dst:0:zero\") should error on zero size") } }) t.Run("trailing-garbage-size", func(t *testing.T) { // fmt.Sscanf("%d") accepted "1024abc" as 1024; the strict parse // must reject the whole field. if _, err := ParseBufSpec("dst:1024abc:zero"); err == nil { t.Error("ParseBufSpec(\"dst:1024abc:zero\") should reject a size with trailing garbage") } }) t.Run("hex-size", func(t *testing.T) { if _, err := ParseBufSpec("dst:0x40:zero"); err == nil { t.Error("ParseBufSpec(\"dst:0x40:zero\") should reject a non-decimal size") } }) t.Run("unknown-pattern", func(t *testing.T) { if _, err := ParseBufSpec("dst:64:wibble"); err == nil { t.Error("ParseBufSpec(\"dst:64:wibble\") should reject an unknown pattern") } }) t.Run("bad-hex-pattern", func(t *testing.T) { if _, err := ParseBufSpec("dst:64:zz"); err == nil { t.Error("ParseBufSpec(\"dst:64:zz\") should reject undecodable hex") } }) t.Run("empty-pattern", func(t *testing.T) { if _, err := ParseBufSpec("dst:64:"); err == nil { t.Error("ParseBufSpec(\"dst:64:\") should reject an empty pattern") } }) t.Run("hex-pattern", func(t *testing.T) { specs, err := ParseBufSpec("dst:6:deadbeef") if err != nil { t.Fatal(err) } if len(specs) != 1 || specs[0].Pattern != "deadbeef" { t.Errorf("ParseBufSpec(\"dst:6:deadbeef\") = %+v", specs) } }) } func TestBufPoolBuildArgs(t *testing.T) { specs, err := ParseBufSpec("dst:64:seq,src:128:zero") if err != nil { t.Fatal(err) } var pool BufPool if err := pool.Alloc(specs); err != nil { t.Fatal(err) } defer pool.Close() // Layout for wideCopyAVX2(dst, src []byte): dst at 0, src at 24. layout := []ArgOffset{ {Name: "dst", Typ: "[]byte", Offset: 0, Size: 24, IsPtr: true}, {Name: "src", Typ: "[]byte", Offset: 24, Size: 24, IsPtr: true}, } args := pool.BuildArgs(layout, 48) // dst.ptr should be non-zero. if args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0 { t.Error("dst.ptr is zero; expected a buffer address") } // dst.len should be 64 (0x40). if args[8] != 0x40 { t.Errorf("dst.len = %d, want 64", args[8]) } // dst.cap should be 64. if args[16] != 0x40 { t.Errorf("dst.cap = %d, want 64", args[16]) } // src.ptr should be non-zero. if args[24] == 0 && args[25] == 0 && args[26] == 0 && args[27] == 0 { t.Error("src.ptr is zero; expected a buffer address") } // src.len should be 128 (0x80). if args[32] != 0x80 { t.Errorf("src.len = %d, want 128", args[32]) } } func TestParseScalarArgs(t *testing.T) { m, err := ParseScalarArgs("n=57,base=0x1f,x= 12 ") if err != nil { t.Fatal(err) } if m["n"] != 57 || m["base"] != 0x1f || m["x"] != 12 { t.Fatalf("parsed %+v", m) } if _, err := ParseScalarArgs("n"); err == nil { t.Error("name-only spec must fail") } if _, err := ParseScalarArgs("n=zz"); err == nil { t.Error("bad value must fail") } } func TestApplyScalarArgs(t *testing.T) { layout := []ArgOffset{ {Name: "text", Typ: "*byte", Offset: 0, Size: 8, IsPtr: true}, {Name: "n", Typ: "int", Offset: 8, Size: 8, IsPtr: false}, } args := make([]byte, 16) if err := ApplyScalarArgs(args, layout, map[string]uint64{"n": 0x1f}); err != nil { t.Fatal(err) } if got := args[8]; got != 0x1f { t.Fatalf("args[8] = %d, want 31", got) } // Pointer parameters reject scalar writes. if err := ApplyScalarArgs(args, layout, map[string]uint64{"text": 5}); err == nil { t.Fatal("pointer param must reject a scalar write") } // Unknown names reject. if err := ApplyScalarArgs(args, layout, map[string]uint64{"nope": 1}); err == nil { t.Fatal("unknown param must reject") } }