| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package specgen | |
| import ( | |
| "strings" | |
| "sync" | |
| "testing" | |
| ) | |
| var ( | |
| specPkg *specPackage | |
| specLoadErr error | |
| loadSpecOnce sync.Once | |
| ) | |
| func loadSpec(t *testing.T) *specPackage { | |
| loadSpecOnce.Do(func() { | |
| var root contextRoot | |
| ctx := context{root: &root} | |
| specPkg = loadSpecPackage(ctx, "../../../internal/spec", &LoadOptions{}) | |
| if err := root.gatherErrors(); err != nil { | |
| specLoadErr = err | |
| } | |
| }) | |
| if specLoadErr != nil { | |
| t.Fatalf("failed to load spec: %v", specLoadErr) | |
| } | |
| return specPkg | |
| } | |
| func TestLoadSpec(t *testing.T) { | |
| pkg := loadSpec(t) | |
| // Verify we parsed functions | |
| if len(pkg.Funcs) == 0 { | |
| t.Errorf("expected parsed functions, got 0") | |
| } | |
| var foundAdd, foundExtend bool | |
| for _, f := range pkg.Funcs { | |
| if f.Name == "Add" { | |
| foundAdd = true | |
| if len(f.TypeParams) != 2 { | |
| t.Errorf("Add should have 2 type parameters, got %d", len(f.TypeParams)) | |
| } else { | |
| if f.TypeParams[0].Obj().Name() != "E" || !strings.Contains(f.TypeParams[0].Constraint().String(), "Nums") { | |
| t.Errorf("unexpected Add type param 0: %s %s", f.TypeParams[0].Obj().Name(), f.TypeParams[0].Constraint()) | |
| } | |
| if f.TypeParams[1].Obj().Name() != "W" || !strings.Contains(f.TypeParams[1].Constraint().String(), "Width") { | |
| t.Errorf("unexpected Add type param 1: %s %s", f.TypeParams[1].Obj().Name(), f.TypeParams[1].Constraint()) | |
| } | |
| } | |
| if len(f.Params) != 2 { | |
| t.Errorf("Add should have 2 params, got %d", len(f.Params)) | |
| } else { | |
| if f.Params[0].Name() != "x" || !strings.Contains(f.Params[0].Type().String(), "Vec[") { | |
| t.Errorf("unexpected Add param 0: %s %s", f.Params[0].Name(), f.Params[0].Type()) | |
| } | |
| if f.Params[1].Name() != "y" || !strings.Contains(f.Params[1].Type().String(), "Vec[") { | |
| t.Errorf("unexpected Add param 1: %s %s", f.Params[1].Name(), f.Params[1].Type()) | |
| } | |
| } | |
| if len(f.Results) != 1 { | |
| t.Errorf("Add should have 1 result, got %d", len(f.Results)) | |
| } else { | |
| if !strings.Contains(f.Results[0].Type().String(), "Vec[") { | |
| t.Errorf("unexpected Add result type: %s", f.Results[0].Type()) | |
| } | |
| } | |
| } | |
| if f.Name == "ExtendLoLToZ" { | |
| foundExtend = true | |
| if len(f.Requirements) != 2 { | |
| t.Errorf("expected 2 requirements for ExtendLoLToZ, got %d", len(f.Requirements)) | |
| } else { | |
| if f.Requirements[0] == nil || f.Requirements[1] == nil { | |
| t.Errorf("expected non-nil parsed requirements") | |
| } | |
| } | |
| } | |
| } | |
| if !foundAdd { | |
| t.Errorf("failed to find function Add in parsed package") | |
| } | |
| if !foundExtend { | |
| t.Errorf("failed to find function ExtendLoLToZ in parsed package") | |
| } | |
| } | |
| func TestLoadSpecNameTmpl(t *testing.T) { | |
| pkg := loadSpec(t) | |
| var found bool | |
| for _, f := range pkg.Funcs { | |
| if f.Name == "MaskFromBits" { | |
| found = true | |
| want := "{{.z}}FromBits" | |
| if f.NameTmpl.raw != want { | |
| t.Errorf("MaskFromBits: expected NameTmpl.raw %q, got %q", want, f.NameTmpl.raw) | |
| } | |
| break | |
| } | |
| } | |
| if !found { | |
| t.Errorf("failed to find function MaskFromBits in parsed package") | |
| } | |
| } |