golang.org/x/tools@v0.21.0/go/packages/packagestest/export_test.go (about)

     1  // Copyright 2018 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 packagestest_test
     6  
     7  import (
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"sort"
    12  	"testing"
    13  
    14  	"golang.org/x/tools/go/packages/packagestest"
    15  )
    16  
    17  var testdata = []packagestest.Module{{
    18  	Name: "golang.org/fake1",
    19  	Files: map[string]interface{}{
    20  		"a.go": packagestest.Symlink("testdata/a.go"), // broken symlink
    21  		"b.go": "invalid file contents",
    22  	},
    23  	Overlay: map[string][]byte{
    24  		"b.go": []byte("package fake1"),
    25  		"c.go": []byte("package fake1"),
    26  	},
    27  }, {
    28  	Name: "golang.org/fake2",
    29  	Files: map[string]interface{}{
    30  		"other/a.go": "package fake2",
    31  	},
    32  }, {
    33  	Name: "golang.org/fake2/v2",
    34  	Files: map[string]interface{}{
    35  		"other/a.go": "package fake2",
    36  	},
    37  }, {
    38  	Name: "golang.org/fake3@v1.0.0",
    39  	Files: map[string]interface{}{
    40  		"other/a.go": "package fake3",
    41  	},
    42  }, {
    43  	Name: "golang.org/fake3@v1.1.0",
    44  	Files: map[string]interface{}{
    45  		"other/a.go": "package fake3",
    46  	},
    47  }}
    48  
    49  type fileTest struct {
    50  	module, fragment, expect string
    51  	check                    func(t *testing.T, exported *packagestest.Exported, filename string)
    52  }
    53  
    54  func checkFiles(t *testing.T, exported *packagestest.Exported, tests []fileTest) {
    55  	for _, test := range tests {
    56  		expect := filepath.Join(exported.Temp(), filepath.FromSlash(test.expect))
    57  		got := exported.File(test.module, test.fragment)
    58  		if got == "" {
    59  			t.Errorf("File %v missing from the output", expect)
    60  		} else if got != expect {
    61  			t.Errorf("Got file %v, expected %v", got, expect)
    62  		}
    63  		if test.check != nil {
    64  			test.check(t, exported, got)
    65  		}
    66  	}
    67  }
    68  
    69  func checkLink(expect string) func(t *testing.T, exported *packagestest.Exported, filename string) {
    70  	expect = filepath.FromSlash(expect)
    71  	return func(t *testing.T, exported *packagestest.Exported, filename string) {
    72  		if target, err := os.Readlink(filename); err != nil {
    73  			t.Errorf("Error checking link %v: %v", filename, err)
    74  		} else if target != expect {
    75  			t.Errorf("Link %v does not match, got %v expected %v", filename, target, expect)
    76  		}
    77  	}
    78  }
    79  
    80  func checkContent(expect string) func(t *testing.T, exported *packagestest.Exported, filename string) {
    81  	return func(t *testing.T, exported *packagestest.Exported, filename string) {
    82  		if content, err := exported.FileContents(filename); err != nil {
    83  			t.Errorf("Error reading %v: %v", filename, err)
    84  		} else if string(content) != expect {
    85  			t.Errorf("Content of %v does not match, got %v expected %v", filename, string(content), expect)
    86  		}
    87  	}
    88  }
    89  
    90  func TestGroupFilesByModules(t *testing.T) {
    91  	for _, tt := range []struct {
    92  		testdir string
    93  		want    []packagestest.Module
    94  	}{
    95  		{
    96  			testdir: "testdata/groups/one",
    97  			want: []packagestest.Module{
    98  				{
    99  					Name: "testdata/groups/one",
   100  					Files: map[string]interface{}{
   101  						"main.go": true,
   102  					},
   103  				},
   104  				{
   105  					Name: "example.com/extra",
   106  					Files: map[string]interface{}{
   107  						"help.go": true,
   108  					},
   109  				},
   110  			},
   111  		},
   112  		{
   113  			testdir: "testdata/groups/two",
   114  			want: []packagestest.Module{
   115  				{
   116  					Name: "testdata/groups/two",
   117  					Files: map[string]interface{}{
   118  						"main.go":           true,
   119  						"expect/yo.go":      true,
   120  						"expect/yo_test.go": true,
   121  					},
   122  				},
   123  				{
   124  					Name: "example.com/extra",
   125  					Files: map[string]interface{}{
   126  						"yo.go":        true,
   127  						"geez/help.go": true,
   128  					},
   129  				},
   130  				{
   131  					Name: "example.com/extra/v2",
   132  					Files: map[string]interface{}{
   133  						"me.go":        true,
   134  						"geez/help.go": true,
   135  					},
   136  				},
   137  				{
   138  					Name: "example.com/tempmod",
   139  					Files: map[string]interface{}{
   140  						"main.go": true,
   141  					},
   142  				},
   143  				{
   144  					Name: "example.com/what@v1.0.0",
   145  					Files: map[string]interface{}{
   146  						"main.go": true,
   147  					},
   148  				},
   149  				{
   150  					Name: "example.com/what@v1.1.0",
   151  					Files: map[string]interface{}{
   152  						"main.go": true,
   153  					},
   154  				},
   155  			},
   156  		},
   157  	} {
   158  		t.Run(tt.testdir, func(t *testing.T) {
   159  			got, err := packagestest.GroupFilesByModules(tt.testdir)
   160  			if err != nil {
   161  				t.Fatalf("could not group files %v", err)
   162  			}
   163  			if len(got) != len(tt.want) {
   164  				t.Fatalf("%s: wanted %d modules but got %d", tt.testdir, len(tt.want), len(got))
   165  			}
   166  			for i, w := range tt.want {
   167  				g := got[i]
   168  				if filepath.FromSlash(g.Name) != filepath.FromSlash(w.Name) {
   169  					t.Fatalf("%s: wanted module[%d].Name to be %s but got %s", tt.testdir, i, filepath.FromSlash(w.Name), filepath.FromSlash(g.Name))
   170  				}
   171  				for fh := range w.Files {
   172  					if _, ok := g.Files[fh]; !ok {
   173  						t.Fatalf("%s, module[%d]: wanted %s but could not find", tt.testdir, i, fh)
   174  					}
   175  				}
   176  				for fh := range g.Files {
   177  					if _, ok := w.Files[fh]; !ok {
   178  						t.Fatalf("%s, module[%d]: found unexpected file %s", tt.testdir, i, fh)
   179  					}
   180  				}
   181  			}
   182  		})
   183  	}
   184  }
   185  
   186  func TestMustCopyFiles(t *testing.T) {
   187  	// Create the following test directory structure in a temporary directory.
   188  	src := map[string]string{
   189  		// copies all files under the specified directory.
   190  		"go.mod": "module example.com",
   191  		"m.go":   "package m",
   192  		"a/a.go": "package a",
   193  		// contents from a nested module shouldn't be copied.
   194  		"nested/go.mod": "module example.com/nested",
   195  		"nested/m.go":   "package nested",
   196  		"nested/b/b.go": "package b",
   197  	}
   198  
   199  	tmpDir, err := os.MkdirTemp("", t.Name())
   200  	if err != nil {
   201  		t.Fatalf("failed to create a temporary directory: %v", err)
   202  	}
   203  	defer os.RemoveAll(tmpDir)
   204  
   205  	for fragment, contents := range src {
   206  		fullpath := filepath.Join(tmpDir, filepath.FromSlash(fragment))
   207  		if err := os.MkdirAll(filepath.Dir(fullpath), 0755); err != nil {
   208  			t.Fatal(err)
   209  		}
   210  		if err := os.WriteFile(fullpath, []byte(contents), 0644); err != nil {
   211  			t.Fatal(err)
   212  		}
   213  	}
   214  
   215  	copied := packagestest.MustCopyFileTree(tmpDir)
   216  	var got []string
   217  	for fragment := range copied {
   218  		got = append(got, filepath.ToSlash(fragment))
   219  	}
   220  	want := []string{"go.mod", "m.go", "a/a.go"}
   221  
   222  	sort.Strings(got)
   223  	sort.Strings(want)
   224  	if !reflect.DeepEqual(got, want) {
   225  		t.Errorf("packagestest.MustCopyFileTree = %v, want %v", got, want)
   226  	}
   227  
   228  	// packagestest.Export is happy.
   229  	exported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{{
   230  		Name:  "example.com",
   231  		Files: packagestest.MustCopyFileTree(tmpDir),
   232  	}})
   233  	defer exported.Cleanup()
   234  }