Source file src/simd/_gen/unify/unify_test.go

     1  // Copyright 2025 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 unify
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"os"
    12  	"path/filepath"
    13  	"slices"
    14  	"strings"
    15  	"testing"
    16  
    17  	"gopkg.in/yaml.v3"
    18  )
    19  
    20  func TestUnify(t *testing.T) {
    21  	paths, err := filepath.Glob("testdata/*")
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	if len(paths) == 0 {
    26  		t.Fatal("no testdata found")
    27  	}
    28  	for _, path := range paths {
    29  		// Skip paths starting with _ so experimental files can be added.
    30  		base := filepath.Base(path)
    31  		if base[0] == '_' {
    32  			continue
    33  		}
    34  		if !strings.HasSuffix(base, ".yaml") {
    35  			t.Errorf("non-.yaml file in testdata: %s", base)
    36  			continue
    37  		}
    38  		base = strings.TrimSuffix(base, ".yaml")
    39  
    40  		t.Run(base, func(t *testing.T) {
    41  			testUnify(t, path)
    42  		})
    43  	}
    44  }
    45  
    46  func testUnify(t *testing.T, path string) {
    47  	f, err := os.Open(path)
    48  	if err != nil {
    49  		t.Fatal(err)
    50  	}
    51  	defer f.Close()
    52  
    53  	type testCase struct {
    54  		Skip  bool
    55  		Name  string
    56  		Unify []Closure
    57  		Want  yaml.Node
    58  		All   yaml.Node
    59  	}
    60  	dec := yaml.NewDecoder(f)
    61  
    62  	for i := 0; ; i++ {
    63  		var tc testCase
    64  		err := dec.Decode(&tc)
    65  		if err == io.EOF {
    66  			break
    67  		}
    68  		if err != nil {
    69  			t.Fatal(err)
    70  		}
    71  
    72  		name := tc.Name
    73  		if name == "" {
    74  			name = fmt.Sprint(i)
    75  		}
    76  
    77  		t.Run(name, func(t *testing.T) {
    78  			if tc.Skip {
    79  				t.Skip("skip: true set in test case")
    80  			}
    81  
    82  			defer func() {
    83  				p := recover()
    84  				if p != nil || t.Failed() {
    85  					// Redo with a trace
    86  					//
    87  					// TODO: Use t.Output() in Go 1.25.
    88  					var buf bytes.Buffer
    89  					Debug.UnifyLog = &buf
    90  					func() {
    91  						defer func() {
    92  							// If the original unify panicked, the second one
    93  							// probably will, too. Ignore it and let the first panic
    94  							// bubble.
    95  							recover()
    96  						}()
    97  						Unify(tc.Unify...)
    98  					}()
    99  					Debug.UnifyLog = nil
   100  					t.Logf("Trace:\n%s", buf.String())
   101  				}
   102  				if p != nil {
   103  					panic(p)
   104  				}
   105  			}()
   106  
   107  			// Unify the test cases
   108  			//
   109  			// TODO: Try reordering the inputs also
   110  			c, err := Unify(tc.Unify...)
   111  			if err != nil {
   112  				// TODO: Tests of errors
   113  				t.Fatal(err)
   114  			}
   115  
   116  			// Encode the result back to YAML so we can check if it's structurally
   117  			// equal.
   118  			clean := func(val any) *yaml.Node {
   119  				var node yaml.Node
   120  				node.Encode(val)
   121  				for n := range allYamlNodes(&node) {
   122  					// Canonicalize the style. There may be other style flags we need to
   123  					// muck with.
   124  					n.Style &^= yaml.FlowStyle
   125  					n.HeadComment = ""
   126  					n.LineComment = ""
   127  					n.FootComment = ""
   128  				}
   129  				return &node
   130  			}
   131  			check := func(gotVal any, wantNode *yaml.Node) {
   132  				got, err := yaml.Marshal(clean(gotVal))
   133  				if err != nil {
   134  					t.Fatalf("Encoding Value back to yaml failed: %s", err)
   135  				}
   136  				want, err := yaml.Marshal(clean(wantNode))
   137  				if err != nil {
   138  					t.Fatalf("Encoding Want back to yaml failed: %s", err)
   139  				}
   140  
   141  				if !bytes.Equal(got, want) {
   142  					t.Errorf("%s:%d:\nwant:\n%sgot\n%s", f.Name(), wantNode.Line, want, got)
   143  				}
   144  			}
   145  			if tc.Want.Kind != 0 {
   146  				check(c.val, &tc.Want)
   147  			}
   148  			if tc.All.Kind != 0 {
   149  				fVal := slices.Collect(c.All())
   150  				check(fVal, &tc.All)
   151  			}
   152  		})
   153  	}
   154  }
   155  

View as plain text