Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/editflags/editflags_test.go
2614 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package editflags
5
6
import (
7
"strings"
8
"testing"
9
10
"github.com/spf13/cobra"
11
"gotest.tools/v3/assert"
12
13
"github.com/lima-vm/lima/v2/pkg/localpathutil"
14
)
15
16
func TestCompleteCPUs(t *testing.T) {
17
assert.DeepEqual(t, []int{1}, completeCPUs(1))
18
assert.DeepEqual(t, []int{1, 2}, completeCPUs(2))
19
assert.DeepEqual(t, []int{1, 2, 4, 8}, completeCPUs(8))
20
assert.DeepEqual(t, []int{1, 2, 4, 8, 16, 20}, completeCPUs(20))
21
}
22
23
func TestCompleteMemoryGiB(t *testing.T) {
24
assert.DeepEqual(t, []float32{0.5}, completeMemoryGiB(1<<30))
25
assert.DeepEqual(t, []float32{1}, completeMemoryGiB(2<<30))
26
assert.DeepEqual(t, []float32{1, 2}, completeMemoryGiB(4<<30))
27
assert.DeepEqual(t, []float32{1, 2, 4}, completeMemoryGiB(8<<30))
28
assert.DeepEqual(t, []float32{1, 2, 4, 8, 10}, completeMemoryGiB(20<<30))
29
}
30
31
func TestBuildPortForwardExpression(t *testing.T) {
32
tests := []struct {
33
name string
34
portForwards []string
35
expected string
36
expectError bool
37
}{
38
{
39
name: "empty port forwards",
40
portForwards: []string{},
41
expected: "",
42
},
43
{
44
name: "single dynamic port forward",
45
portForwards: []string{"8080:80"},
46
expected: `.portForwards += [{"guestPort": "80", "hostPort": "8080", "static": false}]`,
47
},
48
{
49
name: "single static port forward",
50
portForwards: []string{"8080:80,static=true"},
51
expected: `.portForwards += [{"guestPort": "80", "hostPort": "8080", "static": true}]`,
52
},
53
{
54
name: "multiple mixed port forwards",
55
portForwards: []string{"8080:80", "2222:22,static=true", "3000:3000"},
56
expected: `.portForwards += [{"guestPort": "80", "hostPort": "8080", "static": false},{"guestPort": "22", "hostPort": "2222", "static": true},{"guestPort": "3000", "hostPort": "3000", "static": false}]`,
57
},
58
{
59
name: "invalid format - missing colon",
60
portForwards: []string{"8080"},
61
expectError: true,
62
},
63
{
64
name: "invalid format - too many colons",
65
portForwards: []string{"8080:80:extra"},
66
expectError: true,
67
},
68
{
69
name: "invalid static parameter",
70
portForwards: []string{"8080:80,invalid=true"},
71
expectError: true,
72
},
73
{
74
name: "too many parameters",
75
portForwards: []string{"8080:80,static=true,extra=value"},
76
expectError: true,
77
},
78
{
79
name: "whitespace handling",
80
portForwards: []string{" 8080 : 80 , static=true "},
81
expected: `.portForwards += [{"guestPort": "80", "hostPort": "8080", "static": true}]`,
82
},
83
}
84
85
for _, tt := range tests {
86
t.Run(tt.name, func(t *testing.T) {
87
result, err := BuildPortForwardExpression(tt.portForwards)
88
if tt.expectError {
89
assert.Check(t, err != nil)
90
} else {
91
assert.NilError(t, err)
92
assert.Equal(t, tt.expected, result)
93
}
94
})
95
}
96
}
97
98
func TestParsePortForward(t *testing.T) {
99
tests := []struct {
100
name string
101
spec string
102
hostPort string
103
guestPort string
104
isStatic bool
105
expectError bool
106
}{
107
{
108
name: "dynamic port forward",
109
spec: "8080:80",
110
hostPort: "8080",
111
guestPort: "80",
112
isStatic: false,
113
},
114
{
115
name: "static port forward",
116
spec: "8080:80,static=true",
117
hostPort: "8080",
118
guestPort: "80",
119
isStatic: true,
120
},
121
{
122
name: "whitespace handling",
123
spec: " 8080 : 80 , static=true ",
124
hostPort: "8080",
125
guestPort: "80",
126
isStatic: true,
127
},
128
{
129
name: "invalid format - missing colon",
130
spec: "8080",
131
expectError: true,
132
},
133
{
134
name: "invalid format - too many colons",
135
spec: "8080:80:extra",
136
expectError: true,
137
},
138
{
139
name: "invalid parameter",
140
spec: "8080:80,invalid=true",
141
expectError: true,
142
},
143
{
144
name: "too many parameters",
145
spec: "8080:80,static=true,extra=value",
146
expectError: true,
147
},
148
}
149
150
for _, tt := range tests {
151
t.Run(tt.name, func(t *testing.T) {
152
hostPort, guestPort, isStatic, err := ParsePortForward(tt.spec)
153
if tt.expectError {
154
assert.Check(t, err != nil)
155
} else {
156
assert.NilError(t, err)
157
assert.Equal(t, tt.hostPort, hostPort)
158
assert.Equal(t, tt.guestPort, guestPort)
159
assert.Equal(t, tt.isStatic, isStatic)
160
}
161
})
162
}
163
}
164
165
func TestYQExpressions(t *testing.T) {
166
expand := func(s string) string {
167
s, err := localpathutil.Expand(s)
168
assert.NilError(t, err)
169
// `D:\foo` -> `D:\\foo` (appears in YAML)
170
s = strings.ReplaceAll(s, "\\", "\\\\")
171
return s
172
}
173
tests := []struct {
174
name string
175
args []string
176
newInstance bool
177
expected []string
178
expectError string
179
}{
180
{
181
name: "mount",
182
args: []string{"--mount", "/foo", "--mount", "./bar:w"},
183
newInstance: false,
184
expected: []string{`.mounts = [{"location": "` + expand("./bar") + `", "mountPoint": "` + expand("./bar") + `", "writable": true},{"location": "` + expand("/foo") + `", "mountPoint": "` + expand("/foo") + `", "writable": false}] + .mounts`},
185
},
186
{
187
name: "mount-only",
188
args: []string{"--mount-only", "/foo", "--mount-only", "/bar:w"},
189
newInstance: false,
190
expected: []string{`.mounts = [{"location": "` + expand("/foo") + `", "mountPoint": "` + expand("/foo") + `", "writable": false},{"location": "` + expand("/bar") + `", "mountPoint": "` + expand("/bar") + `", "writable": true}]`},
191
},
192
{
193
name: "mixture of mount and mount-only",
194
args: []string{"--mount", "/foo", "--mount-only", "/bar:w"},
195
newInstance: false,
196
expectError: "flag `--mount` conflicts with `--mount-only`",
197
},
198
{
199
name: "dns",
200
args: []string{"--dns", "8.8.8.8", "--dns", "8.8.4.4", "--dns", "1.1.1.1"},
201
newInstance: false,
202
expected: []string{`.dns += ["8.8.8.8","8.8.4.4","1.1.1.1"] | .dns |= unique | .hostResolver.enabled=false`},
203
},
204
{
205
name: "network vzNAT",
206
args: []string{"--network", "vzNAT"},
207
newInstance: true,
208
expected: []string{`.networks += [{"vzNAT": true}] | .networks |= unique_by(.lima)`},
209
},
210
{
211
name: "network lima:shared",
212
args: []string{"--network", "lima:shared"},
213
newInstance: true,
214
expected: []string{`.networks += [{"lima": "shared"}] | .networks |= unique_by(.lima)`},
215
},
216
{
217
name: "multiple networks",
218
args: []string{"--network", "vzNAT", "--network", "lima:shared", "--network", "lima:bridged"},
219
newInstance: true,
220
expected: []string{`.networks += [{"vzNAT": true},{"lima": "shared"},{"lima": "bridged"}] | .networks |= unique_by(.lima)`},
221
},
222
{
223
name: "invalid network",
224
args: []string{"--network", "invalid"},
225
newInstance: true,
226
expectError: `network name must be "vzNAT" or "lima:*", got "invalid"`,
227
},
228
}
229
for _, tt := range tests {
230
t.Run(tt.name, func(t *testing.T) {
231
cmd := &cobra.Command{}
232
RegisterEdit(cmd, "")
233
assert.NilError(t, cmd.ParseFlags(tt.args))
234
expr, err := YQExpressions(cmd.Flags(), tt.newInstance)
235
if tt.expectError != "" {
236
assert.ErrorContains(t, err, tt.expectError)
237
} else {
238
assert.NilError(t, err)
239
assert.DeepEqual(t, tt.expected, expr)
240
}
241
})
242
}
243
}
244
245