1
2
3
4
5 package specdoc
6
7 import (
8 "go/ast"
9 "go/parser"
10 "go/token"
11 "reflect"
12 "strings"
13 "testing"
14
15 "simd/archsimd/_gen/specgen/specexpr"
16 )
17
18 func mustParseExpr(t *testing.T, s string) ast.Expr {
19 t.Helper()
20 expr, err := parser.ParseExpr(s)
21 if err != nil {
22 t.Fatalf("parser.ParseExpr(%q): %v", s, err)
23 }
24 return expr
25 }
26
27 func TestParseTypeExpr(t *testing.T) {
28 tests := []struct {
29 expr string
30 want specexpr.Type
31 }{
32 {"int", specexpr.Basic{Base: "int", Bits: 0}},
33 {"uint32", specexpr.Basic{Base: "uint", Bits: 32}},
34 {"float64", specexpr.Basic{Base: "float", Bits: 64}},
35 {"bool", specexpr.Basic{Base: "bool", Bits: 0}},
36 {"Int32x4", specexpr.Vector{Elem: specexpr.Basic{Base: "int", Bits: 32}, Width: specexpr.Int(128)}},
37 {"Float64s", specexpr.Vector{Elem: specexpr.Basic{Base: "float", Bits: 64}, Width: specexpr.VW()}},
38 {"*int", specexpr.Pointer{Elem: specexpr.Basic{Base: "int", Bits: 0}}},
39 {"*Int32x4", specexpr.Pointer{Elem: specexpr.Vector{Elem: specexpr.Basic{Base: "int", Bits: 32}, Width: specexpr.Int(128)}}},
40 {"[]int8", specexpr.Slice{Elem: specexpr.Basic{Base: "int", Bits: 8}}},
41 {"[4]int32", specexpr.Array{Elem: specexpr.Basic{Base: "int", Bits: 32}, Len: specexpr.Int(4)}},
42 {"(int)", specexpr.Basic{Base: "int", Bits: 0}},
43 {"(*Int32x4)", specexpr.Pointer{Elem: specexpr.Vector{Elem: specexpr.Basic{Base: "int", Bits: 32}, Width: specexpr.Int(128)}}},
44 }
45
46 for _, tc := range tests {
47 t.Run(tc.expr, func(t *testing.T) {
48 expr := mustParseExpr(t, tc.expr)
49 got, err := parseTypeExpr(expr)
50 if err != nil {
51 t.Fatalf("parseTypeExpr(%q) unexpected error: %v", tc.expr, err)
52 }
53 if !reflect.DeepEqual(got, tc.want) {
54 t.Errorf("parseTypeExpr(%q) = %+v, want %+v", tc.expr, got, tc.want)
55 }
56 })
57 }
58 }
59
60 func TestParseTypeExprErrors(t *testing.T) {
61 bad := []struct {
62 name string
63 expr string
64 want string
65 }{
66 {"unknown identifier", "unknown", "unknown type name"},
67 {"any identifier", "any", "unknown type name"},
68 {"Mask scalar", "Mask", "unknown type name"},
69 {"w width form", "Int32w128", "unknown type name"},
70 {"pointer to invalid", "*unknown", "unknown type name"},
71 {"slice of invalid", "[]unknown", "unknown type name"},
72 {"array non-int bound identifier", "[N]int", "array bound is not an integer literal"},
73 {"array non-int bound expr", "[1+2]int", "array bound is not an integer literal"},
74 {"array negative bound", "[-1]int", "array bound is not an integer literal"},
75 {"array bound overflow", "[999999999999999999999999999999999999]int", "invalid array bound"},
76 {"array of invalid", "[4]unknown", "unknown type name"},
77 {"interface type", "interface{}", "unexpected type expression"},
78 {"struct type", "struct{}", "unexpected type expression"},
79 {"map type", "map[int]int", "unexpected type expression"},
80 {"func type", "func()", "unexpected type expression"},
81 {"channel type", "chan int", "unexpected type expression"},
82 }
83
84 for _, tc := range bad {
85 t.Run(tc.name, func(t *testing.T) {
86 expr := mustParseExpr(t, tc.expr)
87 got, err := parseTypeExpr(expr)
88 if err == nil {
89 t.Fatalf("parseTypeExpr(%q) = %+v, want error containing %q", tc.expr, got, tc.want)
90 }
91 if !strings.Contains(err.Error(), tc.want) {
92 t.Errorf("parseTypeExpr(%q) error = %q, want containing %q", tc.expr, err.Error(), tc.want)
93 }
94 })
95 }
96 }
97
98 func TestFieldListArgs(t *testing.T) {
99 fset := token.NewFileSet()
100 src := `package p
101 func f(a, b int, c *Int32x4) (Int32x4, int) {}
102 func g() (z Int32x4, err int) {}
103 `
104 file, err := parser.ParseFile(fset, "test.go", src, 0)
105 if err != nil {
106 t.Fatalf("parsing test.go: %v", err)
107 }
108 fd := file.Decls[0].(*ast.FuncDecl)
109
110 in, err := fieldListArgs(fd.Type.Params)
111 if err != nil {
112 t.Fatalf("fieldListArgs params unexpected error: %v", err)
113 }
114 if len(in) != 3 {
115 t.Fatalf("expected 3 params, got %d", len(in))
116 }
117 if in[0].Name != "a" || in[1].Name != "b" || in[2].Name != "c" {
118 t.Errorf("unexpected param names: %+v", in)
119 }
120
121 out, err := fieldListArgs(fd.Type.Results)
122 if err != nil {
123 t.Fatalf("fieldListArgs results unexpected error: %v", err)
124 }
125 if len(out) != 2 {
126 t.Fatalf("expected 2 results, got %d", len(out))
127 }
128 if out[0].Name != "" || out[1].Name != "" {
129 t.Errorf("unexpected result names: %+v", out)
130 }
131
132 fdG := file.Decls[1].(*ast.FuncDecl)
133 outG, err := fieldListArgs(fdG.Type.Results)
134 if err != nil {
135 t.Fatalf("fieldListArgs results unexpected error: %v", err)
136 }
137 if len(outG) != 2 {
138 t.Fatalf("expected 2 results, got %d", len(outG))
139 }
140 if outG[0].Name != "z" || outG[1].Name != "err" {
141 t.Errorf("unexpected result names: %+v", outG)
142 }
143
144
145 nilArgs, err := fieldListArgs(nil)
146 if err != nil || nilArgs != nil {
147 t.Errorf("fieldListArgs(nil) = (%+v, %v), want (nil, nil)", nilArgs, err)
148 }
149 }
150
View as plain text