Source file src/simd/archsimd/_gen/specgen/template_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package specgen
     6  
     7  import (
     8  	"simd/archsimd/_gen/specgen/specexpr"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestNewSpecTemplate(t *testing.T) {
    14  	tests := []struct {
    15  		tmpl    string
    16  		isTmpl  bool
    17  		wantErr bool
    18  	}{
    19  		{
    20  			tmpl:   "",
    21  			isTmpl: false,
    22  		},
    23  		{
    24  			tmpl:   "Convert",
    25  			isTmpl: false,
    26  		},
    27  		{
    28  			tmpl:   "Convert{{.zL}}To{{.zB}}{{.zN}}",
    29  			isTmpl: true,
    30  		},
    31  		{
    32  			tmpl:    "Convert{{.zL",
    33  			wantErr: true,
    34  		},
    35  		{
    36  			tmpl:    "Convert{{if}}",
    37  			wantErr: true,
    38  		},
    39  	}
    40  
    41  	for _, tc := range tests {
    42  		got, err := newSpecTemplate(tc.tmpl)
    43  		if (err != nil) != tc.wantErr {
    44  			t.Errorf("newSpecTemplate(%q) returned error: %v, wantErr: %v", tc.tmpl, err, tc.wantErr)
    45  			continue
    46  		}
    47  		if tc.wantErr {
    48  			continue
    49  		}
    50  		if got.raw != tc.tmpl {
    51  			t.Errorf("newSpecTemplate(%q) raw = %q, want %q", tc.tmpl, got.raw, tc.tmpl)
    52  		}
    53  		if (got.tmpl != nil) != tc.isTmpl {
    54  			t.Errorf("newSpecTemplate(%q) isTmpl = %v, want %v", tc.tmpl, got.tmpl != nil, tc.isTmpl)
    55  		}
    56  	}
    57  }
    58  
    59  func TestSpecTemplateExpand(t *testing.T) {
    60  	tmpl, err := newSpecTemplate("Convert{{.zL}}To{{.zB}}{{.zN}}")
    61  	if err != nil {
    62  		t.Fatalf("unexpected error parsing template: %v", err)
    63  	}
    64  
    65  	data := map[string]any{
    66  		"zL": specexpr.Int(4),
    67  		"zB": "Float",
    68  		"zN": specexpr.Int(32),
    69  	}
    70  
    71  	got, err := tmpl.expand(data)
    72  	if err != nil {
    73  		t.Fatalf("unexpected error expanding template: %v", err)
    74  	}
    75  	want := "Convert4ToFloat32"
    76  	if got != want {
    77  		t.Errorf("expected expanded string %q, got %q", want, got)
    78  	}
    79  }
    80  
    81  func TestSpecTemplateTitle(t *testing.T) {
    82  	tmpl, err := newSpecTemplate("ConvertTo{{.zE | title}}")
    83  	if err != nil {
    84  		t.Fatalf("unexpected error parsing template: %v", err)
    85  	}
    86  
    87  	data := map[string]any{
    88  		"zE": specexpr.Basic{Base: "float", Bits: 32},
    89  	}
    90  
    91  	got, err := tmpl.expand(data)
    92  	if err != nil {
    93  		t.Fatalf("unexpected error expanding template: %v", err)
    94  	}
    95  	want := "ConvertToFloat32"
    96  	if got != want {
    97  		t.Errorf("expected %q, got %q", want, got)
    98  	}
    99  }
   100  
   101  func TestSpecTemplateConditionals(t *testing.T) {
   102  	tmplStr := `Doc for {{.Name}}.
   103  {{if lt .zL .xL}}
   104  Upper elements of the result are zeroed.
   105  {{end}}`
   106  
   107  	tmpl, err := newSpecTemplate(tmplStr)
   108  	if err != nil {
   109  		t.Fatalf("unexpected error parsing template: %v", err)
   110  	}
   111  
   112  	// Case 1: zL < xL
   113  	data1 := map[string]any{
   114  		"Name": "ConvertLo4ToFloat32",
   115  		"zL":   specexpr.Int(4),
   116  		"xL":   specexpr.Int(8),
   117  	}
   118  	got1, err := tmpl.expand(data1)
   119  	if err != nil {
   120  		t.Fatalf("unexpected error: %v", err)
   121  	}
   122  	if !strings.Contains(got1, "Upper elements of the result are zeroed.") {
   123  		t.Errorf("expected conditional text when zL < xL, got: %q", got1)
   124  	}
   125  
   126  	// Case 2: zL >= xL
   127  	data2 := map[string]any{
   128  		"Name": "ConvertLo8ToFloat32",
   129  		"zL":   specexpr.Int(8),
   130  		"xL":   specexpr.Int(8),
   131  	}
   132  	got2, err := tmpl.expand(data2)
   133  	if err != nil {
   134  		t.Fatalf("unexpected error: %v", err)
   135  	}
   136  	if strings.Contains(got2, "Upper elements of the result are zeroed.") {
   137  		t.Errorf("expected no conditional text when zL == xL, got: %q", got2)
   138  	}
   139  }
   140  
   141  func TestSpecTemplateScalableWidthCompare(t *testing.T) {
   142  	tmpl, err := newSpecTemplate("{{if lt .zL .xL}}smaller{{else}}same-or-larger{{end}}")
   143  	if err != nil {
   144  		t.Fatalf("unexpected error: %v", err)
   145  	}
   146  
   147  	// zL = VW/32, xL = VW/16 => zL < xL
   148  	zL, err := specexpr.VW().Div(specexpr.Int(32))
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	xL, err := specexpr.VW().Div(specexpr.Int(16))
   153  	if err != nil {
   154  		t.Fatal(err)
   155  	}
   156  
   157  	data := map[string]any{
   158  		"zL": zL,
   159  		"xL": xL,
   160  	}
   161  	got, err := tmpl.expand(data)
   162  	if err != nil {
   163  		t.Fatalf("unexpected error: %v", err)
   164  	}
   165  	if got != "smaller" {
   166  		t.Errorf("expected 'smaller', got %q", got)
   167  	}
   168  }
   169  
   170  func TestSpecTemplateMissingKey(t *testing.T) {
   171  	tmpl, err := newSpecTemplate("Convert{{.missing}}")
   172  	if err != nil {
   173  		t.Fatalf("unexpected error: %v", err)
   174  	}
   175  
   176  	_, err = tmpl.expand(map[string]any{})
   177  	if err == nil {
   178  		t.Errorf("expected error on missing key, got nil")
   179  	}
   180  }
   181  
   182  func TestCleanDocNewlines(t *testing.T) {
   183  	tests := []struct {
   184  		input string
   185  		want  string
   186  	}{
   187  		{
   188  			input: "hello\n\n\n\nworld\n",
   189  			want:  "hello\n\nworld\n",
   190  		},
   191  		{
   192  			input: "hello\n\n\n",
   193  			want:  "hello\n",
   194  		},
   195  		{
   196  			input: "",
   197  			want:  "",
   198  		},
   199  	}
   200  
   201  	for _, tc := range tests {
   202  		got := cleanDocNewlines(tc.input)
   203  		if got != tc.want {
   204  			t.Errorf("cleanDocNewlines(%q) = %q, want %q", tc.input, got, tc.want)
   205  		}
   206  	}
   207  }
   208  

View as plain text