1package container
2
3import (
4 "strings"
5 "testing"
6
7 "github.com/stretchr/testify/assert"
8)
9
10func TestNormalizeImageRef(t *testing.T) {
11 testCases := []struct {
12 name string
13 input string
14 expected string
15 }{
16 {
17 name: "simple image with tag",
18 input: "nginx:latest",
19 expected: "docker.io/library/nginx:latest",
20 },
21 {
22 name: "image without tag",
23 input: "nginx",
24 expected: "docker.io/library/nginx:latest",
25 },
26 {
27 name: "registry with image and tag",
28 input: "registry.example.com/nginx:v1.0",
29 expected: "registry.example.com/nginx:v1.0",
30 },
31 {
32 name: "dockerhub image with user",
33 input: "user/repo:tag",
34 expected: "docker.io/user/repo:tag",
35 },
36 {
37 name: "official library image without tag",
38 input: "postgres",
39 expected: "docker.io/library/postgres:latest",
40 },
41 }
42
43 for _, tc := range testCases {
44 t.Run(tc.name, func(t *testing.T) {
45 result := normalizeImageRef(tc.input)
46 assert.Equal(t, tc.expected, result)
47 })
48 }
49}
50
51func TestGenerateVolumeName(t *testing.T) {
52 testCases := []struct {
53 name string
54 prefix string
55 domain string
56 path string
57 }{
58 {
59 name: "basic volume name",
60 prefix: "gordon",
61 domain: "app.example.com",
62 path: "/data",
63 },
64 {
65 name: "complex path",
66 prefix: "test",
67 domain: "my-app.domain.com",
68 path: "/var/www/html/uploads",
69 },
70 }
71
72 for _, tc := range testCases {
73 t.Run(tc.name, func(t *testing.T) {
74 result := generateVolumeName(tc.prefix, tc.domain, tc.path)
75
76 // Check that it starts with prefix
77 assert.True(t, strings.HasPrefix(result, tc.prefix+"-"))
78
79 // Check that it contains sanitized domain
80 sanitizedDomain := strings.ReplaceAll(strings.ToLower(tc.domain), ".", "-")
81 assert.Contains(t, result, sanitizedDomain)
82
83 // Volume names should be consistent for same inputs
84 result2 := generateVolumeName(tc.prefix, tc.domain, tc.path)
85 assert.Equal(t, result, result2)
86
87 // Volume names should be different for different paths
88 result3 := generateVolumeName(tc.prefix, tc.domain, tc.path+"/different")
89 assert.NotEqual(t, result, result3)
90 })
91 }
92}
93
94func TestMergeEnvironmentVariables(t *testing.T) {
95 testCases := []struct {
96 name string
97 dockerfileEnv []string
98 userEnv []string
99 expected []string
100 }{
101 {
102 name: "user env overrides dockerfile env",
103 dockerfileEnv: []string{"NODE_ENV=development", "PORT=3000"},
104 userEnv: []string{"NODE_ENV=production", "API_KEY=secret"},
105 expected: []string{"NODE_ENV=production", "PORT=3000", "API_KEY=secret"},
106 },
107 {
108 name: "only dockerfile env",
109 dockerfileEnv: []string{"NODE_ENV=development", "PORT=3000"},
110 userEnv: []string{},
111 expected: []string{"NODE_ENV=development", "PORT=3000"},
112 },
113 {
114 name: "only user env",
115 dockerfileEnv: []string{},
116 userEnv: []string{"API_KEY=secret", "DEBUG=true"},
117 expected: []string{"API_KEY=secret", "DEBUG=true"},
118 },
119 {
120 name: "empty environment",
121 dockerfileEnv: []string{},
122 userEnv: []string{},
123 expected: []string{},
124 },
125 }
126
127 for _, tc := range testCases {
128 t.Run(tc.name, func(t *testing.T) {
129 result := mergeEnvironmentVariables(tc.dockerfileEnv, tc.userEnv)
130 assert.Equal(t, len(tc.expected), len(result))
131
132 // Convert to map for easier comparison
133 resultMap := make(map[string]string)
134 for _, env := range result {
135 parts := splitEnvVar(env)
136 if len(parts) == 2 {
137 resultMap[parts[0]] = parts[1]
138 }
139 }
140
141 expectedMap := make(map[string]string)
142 for _, env := range tc.expected {
143 parts := splitEnvVar(env)
144 if len(parts) == 2 {
145 expectedMap[parts[0]] = parts[1]
146 }
147 }
148
149 assert.Equal(t, expectedMap, resultMap)
150 })
151 }
152}
153
154// Helper function to split environment variable string
155func splitEnvVar(env string) []string {
156 for i, c := range env {
157 if c == '=' {
158 return []string{env[:i], env[i+1:]}
159 }
160 }
161 return []string{env}
162}
163
164func TestSanitizeDomainForVolume(t *testing.T) {
165 testCases := []struct {
166 name string
167 input string
168 expected string
169 }{
170 {
171 name: "basic domain",
172 input: "app.example.com",
173 expected: "app-example-com",
174 },
175 {
176 name: "domain with port",
177 input: "localhost:3000",
178 expected: "localhost-3000",
179 },
180 {
181 name: "domain with special chars",
182 input: "my_app@example.com",
183 expected: "my-app-example-com",
184 },
185 {
186 name: "uppercase domain",
187 input: "API.EXAMPLE.COM",
188 expected: "api-example-com",
189 },
190 }
191
192 for _, tc := range testCases {
193 t.Run(tc.name, func(t *testing.T) {
194 result := sanitizeDomainForVolume(tc.input)
195 assert.Equal(t, tc.expected, result)
196 })
197 }
198}