github.com/gernest/nezuko@v0.1.2/internal/module/module_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 module
     6  
     7  import "testing"
     8  
     9  var checkTests = []struct {
    10  	path    string
    11  	version string
    12  	ok      bool
    13  }{
    14  	{"rsc.io/quote", "0.1.0", false},
    15  	{"rsc io/quote", "v1.0.0", false},
    16  
    17  	{"github.com/go-yaml/yaml", "v0.8.0", true},
    18  	{"github.com/go-yaml/yaml", "v1.0.0", true},
    19  	{"github.com/go-yaml/yaml", "v2.0.0", false},
    20  	{"github.com/go-yaml/yaml", "v2.1.5", false},
    21  	{"github.com/go-yaml/yaml", "v3.0.0", false},
    22  
    23  	{"github.com/go-yaml/yaml/v2", "v1.0.0", false},
    24  	{"github.com/go-yaml/yaml/v2", "v2.0.0", true},
    25  	{"github.com/go-yaml/yaml/v2", "v2.1.5", true},
    26  	{"github.com/go-yaml/yaml/v2", "v3.0.0", false},
    27  
    28  	{"gopkg.in/yaml.v0", "v0.8.0", true},
    29  	{"gopkg.in/yaml.v0", "v1.0.0", false},
    30  	{"gopkg.in/yaml.v0", "v2.0.0", false},
    31  	{"gopkg.in/yaml.v0", "v2.1.5", false},
    32  	{"gopkg.in/yaml.v0", "v3.0.0", false},
    33  
    34  	{"gopkg.in/yaml.v1", "v0.8.0", false},
    35  	{"gopkg.in/yaml.v1", "v1.0.0", true},
    36  	{"gopkg.in/yaml.v1", "v2.0.0", false},
    37  	{"gopkg.in/yaml.v1", "v2.1.5", false},
    38  	{"gopkg.in/yaml.v1", "v3.0.0", false},
    39  
    40  	// For gopkg.in, .v1 means v1 only (not v0).
    41  	// But early versions of vgo still generated v0 pseudo-versions for it.
    42  	// Even though now we'd generate those as v1 pseudo-versions,
    43  	// we accept the old pseudo-versions to avoid breaking existing z.mod files.
    44  	// For example gopkg.in/yaml.v2@v2.2.1's z.mod requires check.v1 at a v0 pseudo-version.
    45  	{"gopkg.in/check.v1", "v0.0.0", false},
    46  	{"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true},
    47  
    48  	{"gopkg.in/yaml.v2", "v1.0.0", false},
    49  	{"gopkg.in/yaml.v2", "v2.0.0", true},
    50  	{"gopkg.in/yaml.v2", "v2.1.5", true},
    51  	{"gopkg.in/yaml.v2", "v3.0.0", false},
    52  
    53  	{"rsc.io/quote", "v17.0.0", false},
    54  	{"rsc.io/quote", "v17.0.0+incompatible", true},
    55  }
    56  
    57  func TestCheck(t *testing.T) {
    58  	for _, tt := range checkTests {
    59  		err := Check(tt.path, tt.version)
    60  		if tt.ok && err != nil {
    61  			t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err)
    62  		} else if !tt.ok && err == nil {
    63  			t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version)
    64  		}
    65  	}
    66  }
    67  
    68  var checkPathTests = []struct {
    69  	path     string
    70  	ok       bool
    71  	importOK bool
    72  	fileOK   bool
    73  }{
    74  	{"x.y/z", true, true, true},
    75  	{"x.y", true, true, true},
    76  
    77  	{"", false, false, false},
    78  	{"x.y/\xFFz", false, false, false},
    79  	{"/x.y/z", false, false, false},
    80  	{"x./z", false, false, false},
    81  	{".x/z", false, false, true},
    82  	{"-x/z", false, true, true},
    83  	{"x..y/z", false, false, false},
    84  	{"x.y/z/../../w", false, false, false},
    85  	{"x.y//z", false, false, false},
    86  	{"x.y/z//w", false, false, false},
    87  	{"x.y/z/", false, false, false},
    88  
    89  	{"x.y/z/v0", false, true, true},
    90  	{"x.y/z/v1", false, true, true},
    91  	{"x.y/z/v2", true, true, true},
    92  	{"x.y/z/v2.0", false, true, true},
    93  	{"X.y/z", false, true, true},
    94  
    95  	{"!x.y/z", false, false, true},
    96  	{"_x.y/z", false, true, true},
    97  	{"x.y!/z", false, false, true},
    98  	{"x.y\"/z", false, false, false},
    99  	{"x.y#/z", false, false, true},
   100  	{"x.y$/z", false, false, true},
   101  	{"x.y%/z", false, false, true},
   102  	{"x.y&/z", false, false, true},
   103  	{"x.y'/z", false, false, false},
   104  	{"x.y(/z", false, false, true},
   105  	{"x.y)/z", false, false, true},
   106  	{"x.y*/z", false, false, false},
   107  	{"x.y+/z", false, true, true},
   108  	{"x.y,/z", false, false, true},
   109  	{"x.y-/z", true, true, true},
   110  	{"x.y./zt", false, false, false},
   111  	{"x.y:/z", false, false, false},
   112  	{"x.y;/z", false, false, false},
   113  	{"x.y</z", false, false, false},
   114  	{"x.y=/z", false, false, true},
   115  	{"x.y>/z", false, false, false},
   116  	{"x.y?/z", false, false, false},
   117  	{"x.y@/z", false, false, true},
   118  	{"x.y[/z", false, false, true},
   119  	{"x.y\\/z", false, false, false},
   120  	{"x.y]/z", false, false, true},
   121  	{"x.y^/z", false, false, true},
   122  	{"x.y_/z", false, true, true},
   123  	{"x.y`/z", false, false, false},
   124  	{"x.y{/z", false, false, true},
   125  	{"x.y}/z", false, false, true},
   126  	{"x.y~/z", false, true, true},
   127  	{"x.y/z!", false, false, true},
   128  	{"x.y/z\"", false, false, false},
   129  	{"x.y/z#", false, false, true},
   130  	{"x.y/z$", false, false, true},
   131  	{"x.y/z%", false, false, true},
   132  	{"x.y/z&", false, false, true},
   133  	{"x.y/z'", false, false, false},
   134  	{"x.y/z(", false, false, true},
   135  	{"x.y/z)", false, false, true},
   136  	{"x.y/z*", false, false, false},
   137  	{"x.y/z+", true, true, true},
   138  	{"x.y/z,", false, false, true},
   139  	{"x.y/z-", true, true, true},
   140  	{"x.y/z.t", true, true, true},
   141  	{"x.y/z/t", true, true, true},
   142  	{"x.y/z:", false, false, false},
   143  	{"x.y/z;", false, false, false},
   144  	{"x.y/z<", false, false, false},
   145  	{"x.y/z=", false, false, true},
   146  	{"x.y/z>", false, false, false},
   147  	{"x.y/z?", false, false, false},
   148  	{"x.y/z@", false, false, true},
   149  	{"x.y/z[", false, false, true},
   150  	{"x.y/z\\", false, false, false},
   151  	{"x.y/z]", false, false, true},
   152  	{"x.y/z^", false, false, true},
   153  	{"x.y/z_", true, true, true},
   154  	{"x.y/z`", false, false, false},
   155  	{"x.y/z{", false, false, true},
   156  	{"x.y/z}", false, false, true},
   157  	{"x.y/z~", true, true, true},
   158  	{"x.y/x.foo", true, true, true},
   159  	{"x.y/aux.foo", false, false, false},
   160  	{"x.y/prn", false, false, false},
   161  	{"x.y/prn2", true, true, true},
   162  	{"x.y/com", true, true, true},
   163  	{"x.y/com1", false, false, false},
   164  	{"x.y/com1.txt", false, false, false},
   165  	{"x.y/calm1", true, true, true},
   166  	{"github.com/!123/logrus", false, false, true},
   167  
   168  	// TODO: CL 41822 allowed Unicode letters in old "go get"
   169  	// without due consideration of the implications, and only on github.com (!).
   170  	// For now, we disallow non-ASCII characters in module mode,
   171  	// in both module paths and general import paths,
   172  	// until we can get the implications right.
   173  	// When we do, we'll enable them everywhere, not just for GitHub.
   174  	{"github.com/user/unicode/испытание", false, false, true},
   175  
   176  	{"../x", false, false, false},
   177  	{"./y", false, false, false},
   178  	{"x:y", false, false, false},
   179  	{`\temp\foo`, false, false, false},
   180  	{".gitignore", false, false, true},
   181  	{".github/ISSUE_TEMPLATE", false, false, true},
   182  	{"x☺y", false, false, false},
   183  }
   184  
   185  func TestCheckPath(t *testing.T) {
   186  	for _, tt := range checkPathTests {
   187  		err := CheckPath(tt.path)
   188  		if tt.ok && err != nil {
   189  			t.Errorf("CheckPath(%q) = %v, wanted nil error", tt.path, err)
   190  		} else if !tt.ok && err == nil {
   191  			t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path)
   192  		}
   193  
   194  		err = CheckImportPath(tt.path)
   195  		if tt.importOK && err != nil {
   196  			t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err)
   197  		} else if !tt.importOK && err == nil {
   198  			t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path)
   199  		}
   200  
   201  		err = CheckFilePath(tt.path)
   202  		if tt.fileOK && err != nil {
   203  			t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err)
   204  		} else if !tt.fileOK && err == nil {
   205  			t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path)
   206  		}
   207  	}
   208  }
   209  
   210  var splitPathVersionTests = []struct {
   211  	pathPrefix string
   212  	version    string
   213  }{
   214  	{"x.y/z", ""},
   215  	{"x.y/z", "/v2"},
   216  	{"x.y/z", "/v3"},
   217  	{"x.y/v", ""},
   218  	{"gopkg.in/yaml", ".v0"},
   219  	{"gopkg.in/yaml", ".v1"},
   220  	{"gopkg.in/yaml", ".v2"},
   221  	{"gopkg.in/yaml", ".v3"},
   222  }
   223  
   224  func TestSplitPathVersion(t *testing.T) {
   225  	for _, tt := range splitPathVersionTests {
   226  		pathPrefix, version, ok := SplitPathVersion(tt.pathPrefix + tt.version)
   227  		if pathPrefix != tt.pathPrefix || version != tt.version || !ok {
   228  			t.Errorf("SplitPathVersion(%q) = %q, %q, %v, want %q, %q, true", tt.pathPrefix+tt.version, pathPrefix, version, ok, tt.pathPrefix, tt.version)
   229  		}
   230  	}
   231  
   232  	for _, tt := range checkPathTests {
   233  		pathPrefix, version, ok := SplitPathVersion(tt.path)
   234  		if pathPrefix+version != tt.path {
   235  			t.Errorf("SplitPathVersion(%q) = %q, %q, %v, doesn't add to input", tt.path, pathPrefix, version, ok)
   236  		}
   237  	}
   238  }
   239  
   240  var encodeTests = []struct {
   241  	path string
   242  	enc  string // empty means same as path
   243  }{
   244  	{path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-+/~_0123456789"},
   245  	{path: "github.com/GoogleCloudPlatform/omega", enc: "github.com/!google!cloud!platform/omega"},
   246  }
   247  
   248  func TestEncodePath(t *testing.T) {
   249  	// Check invalid paths.
   250  	for _, tt := range checkPathTests {
   251  		if !tt.ok {
   252  			_, err := EncodePath(tt.path)
   253  			if err == nil {
   254  				t.Errorf("EncodePath(%q): succeeded, want error (invalid path)", tt.path)
   255  			}
   256  		}
   257  	}
   258  
   259  	// Check encodings.
   260  	for _, tt := range encodeTests {
   261  		enc, err := EncodePath(tt.path)
   262  		if err != nil {
   263  			t.Errorf("EncodePath(%q): unexpected error: %v", tt.path, err)
   264  			continue
   265  		}
   266  		want := tt.enc
   267  		if want == "" {
   268  			want = tt.path
   269  		}
   270  		if enc != want {
   271  			t.Errorf("EncodePath(%q) = %q, want %q", tt.path, enc, want)
   272  		}
   273  	}
   274  }
   275  
   276  var badDecode = []string{
   277  	"github.com/GoogleCloudPlatform/omega",
   278  	"github.com/!google!cloud!platform!/omega",
   279  	"github.com/!0google!cloud!platform/omega",
   280  	"github.com/!_google!cloud!platform/omega",
   281  	"github.com/!!google!cloud!platform/omega",
   282  	"",
   283  }
   284  
   285  func TestDecodePath(t *testing.T) {
   286  	// Check invalid decodings.
   287  	for _, bad := range badDecode {
   288  		_, err := DecodePath(bad)
   289  		if err == nil {
   290  			t.Errorf("DecodePath(%q): succeeded, want error (invalid decoding)", bad)
   291  		}
   292  	}
   293  
   294  	// Check invalid paths (or maybe decodings).
   295  	for _, tt := range checkPathTests {
   296  		if !tt.ok {
   297  			path, err := DecodePath(tt.path)
   298  			if err == nil {
   299  				t.Errorf("DecodePath(%q) = %q, want error (invalid path)", tt.path, path)
   300  			}
   301  		}
   302  	}
   303  
   304  	// Check encodings.
   305  	for _, tt := range encodeTests {
   306  		enc := tt.enc
   307  		if enc == "" {
   308  			enc = tt.path
   309  		}
   310  		path, err := DecodePath(enc)
   311  		if err != nil {
   312  			t.Errorf("DecodePath(%q): unexpected error: %v", enc, err)
   313  			continue
   314  		}
   315  		if path != tt.path {
   316  			t.Errorf("DecodePath(%q) = %q, want %q", enc, path, tt.path)
   317  		}
   318  	}
   319  }