github.com/opentofu/opentofu@v1.7.1/internal/registry/regsrc/module_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package regsrc
     7  
     8  import (
     9  	"testing"
    10  )
    11  
    12  func TestModule(t *testing.T) {
    13  	tests := []struct {
    14  		name        string
    15  		source      string
    16  		wantString  string
    17  		wantDisplay string
    18  		wantNorm    string
    19  		wantErr     bool
    20  	}{
    21  		{
    22  			name:        "public registry",
    23  			source:      "hashicorp/consul/aws",
    24  			wantString:  "hashicorp/consul/aws",
    25  			wantDisplay: "hashicorp/consul/aws",
    26  			wantNorm:    "hashicorp/consul/aws",
    27  			wantErr:     false,
    28  		},
    29  		{
    30  			name:        "public registry, submodule",
    31  			source:      "hashicorp/consul/aws//foo",
    32  			wantString:  "hashicorp/consul/aws//foo",
    33  			wantDisplay: "hashicorp/consul/aws//foo",
    34  			wantNorm:    "hashicorp/consul/aws//foo",
    35  			wantErr:     false,
    36  		},
    37  		{
    38  			name:        "public registry, explicit host",
    39  			source:      "registry.opentofu.org/hashicorp/consul/aws",
    40  			wantString:  "registry.opentofu.org/hashicorp/consul/aws",
    41  			wantDisplay: "hashicorp/consul/aws",
    42  			wantNorm:    "hashicorp/consul/aws",
    43  			wantErr:     false,
    44  		},
    45  		{
    46  			name:        "public registry, mixed case",
    47  			source:      "HashiCorp/Consul/aws",
    48  			wantString:  "HashiCorp/Consul/aws",
    49  			wantDisplay: "hashicorp/consul/aws",
    50  			wantNorm:    "hashicorp/consul/aws",
    51  			wantErr:     false,
    52  		},
    53  		{
    54  			name:        "private registry, custom port",
    55  			source:      "Example.com:1234/HashiCorp/Consul/aws",
    56  			wantString:  "Example.com:1234/HashiCorp/Consul/aws",
    57  			wantDisplay: "example.com:1234/hashicorp/consul/aws",
    58  			wantNorm:    "example.com:1234/hashicorp/consul/aws",
    59  			wantErr:     false,
    60  		},
    61  		{
    62  			name:        "IDN registry",
    63  			source:      "Испытание.com/HashiCorp/Consul/aws",
    64  			wantString:  "Испытание.com/HashiCorp/Consul/aws",
    65  			wantDisplay: "испытание.com/hashicorp/consul/aws",
    66  			wantNorm:    "xn--80akhbyknj4f.com/hashicorp/consul/aws",
    67  			wantErr:     false,
    68  		},
    69  		{
    70  			name:       "IDN registry, submodule, custom port",
    71  			source:     "Испытание.com:1234/HashiCorp/Consul/aws//Foo",
    72  			wantString: "Испытание.com:1234/HashiCorp/Consul/aws//Foo",
    73  			// Note we DO lowercase submodule names. This might causes issues on
    74  			// some filesystems (e.g. HFS+) that are case-sensitive where
    75  			////modules/Foo and //modules/foo describe different paths, but
    76  			// it's less confusing in general just to not support that. Any user
    77  			// with a module with submodules in both cases is already asking for
    78  			// portability issues, and tofu can ensure it does
    79  			// case-insensitive search for the dir in those cases.
    80  			wantDisplay: "испытание.com:1234/hashicorp/consul/aws//foo",
    81  			wantNorm:    "xn--80akhbyknj4f.com:1234/hashicorp/consul/aws//foo",
    82  			wantErr:     false,
    83  		},
    84  		{
    85  			name:    "invalid host",
    86  			source:  "---.com/HashiCorp/Consul/aws",
    87  			wantErr: true,
    88  		},
    89  		{
    90  			name:    "invalid format",
    91  			source:  "foo/var/baz/qux",
    92  			wantErr: true,
    93  		},
    94  		{
    95  			name:    "invalid suffix",
    96  			source:  "foo/var/baz?otherthing",
    97  			wantErr: true,
    98  		},
    99  		{
   100  			name:    "valid host, invalid format",
   101  			source:  "foo.com/var/baz?otherthing",
   102  			wantErr: true,
   103  		},
   104  		{
   105  			name:    "disallow github",
   106  			source:  "github.com/HashiCorp/Consul/aws",
   107  			wantErr: true,
   108  		},
   109  		{
   110  			name:    "disallow bitbucket",
   111  			source:  "bitbucket.org/HashiCorp/Consul/aws",
   112  			wantErr: true,
   113  		},
   114  	}
   115  	for _, tt := range tests {
   116  		t.Run(tt.name, func(t *testing.T) {
   117  			got, err := ParseModuleSource(tt.source)
   118  
   119  			if (err != nil) != tt.wantErr {
   120  				t.Fatalf("ParseModuleSource() error = %v, wantErr %v", err, tt.wantErr)
   121  			}
   122  
   123  			if err != nil {
   124  				return
   125  			}
   126  
   127  			if v := got.String(); v != tt.wantString {
   128  				t.Fatalf("String() = %v, want %v", v, tt.wantString)
   129  			}
   130  			if v := got.Display(); v != tt.wantDisplay {
   131  				t.Fatalf("Display() = %v, want %v", v, tt.wantDisplay)
   132  			}
   133  			if v := got.Normalized(); v != tt.wantNorm {
   134  				t.Fatalf("Normalized() = %v, want %v", v, tt.wantNorm)
   135  			}
   136  
   137  			gotDisplay, err := ParseModuleSource(tt.wantDisplay)
   138  			if err != nil {
   139  				t.Fatalf("ParseModuleSource(wantDisplay) error = %v", err)
   140  			}
   141  			if !got.Equal(gotDisplay) {
   142  				t.Fatalf("Equal() failed for %s and %s", tt.source, tt.wantDisplay)
   143  			}
   144  		})
   145  	}
   146  }