Skip to content
This repository was archived by the owner on Mar 16, 2024. It is now read-only.

Commit a292bb1

Browse files
refactor cli/run_test.go (#1422)
Signed-off-by: jacobdonenfeld <jedonenfeld@gmail.com>
1 parent f219d20 commit a292bb1

File tree

2 files changed

+228
-44
lines changed

2 files changed

+228
-44
lines changed

pkg/cli/run.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ func (s RunArgs) ToOpts() (client.AppRunOptions, error) {
208208
return opts, nil
209209
}
210210

211+
// isDirectory checks that the path from the provided directory
212+
// point to a directory. If it does not point to a directory and it points at a file,
213+
// it errors. Otherwise, the function returns false.
211214
func isDirectory(cwd string) (bool, error) {
212215
if s, err := os.Stat(cwd); os.IsNotExist(err) {
213216
return false, nil

pkg/cli/run_test.go

Lines changed: 225 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
package cli
22

33
import (
4+
"context"
5+
"fmt"
46
"io"
57
"os"
68
"strings"
79
"testing"
810

11+
"github.com/acorn-io/acorn/pkg/client"
12+
13+
apiv1 "github.com/acorn-io/acorn/pkg/apis/api.acorn.io/v1"
14+
v1 "github.com/acorn-io/acorn/pkg/apis/internal.acorn.io/v1"
15+
"github.com/acorn-io/acorn/pkg/mocks"
16+
"github.com/golang/mock/gomock"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+
919
"github.com/acorn-io/acorn/pkg/cli/testdata"
1020
"github.com/spf13/cobra"
1121

@@ -28,100 +38,271 @@ func TestRunArgs_Env(t *testing.T) {
2838
assert.Equal(t, "1", opts.Env[1].Value)
2939
}
3040

31-
func TestRunMemory(t *testing.T) {
41+
func TestRun(t *testing.T) {
42+
baseMock := func(f *mocks.MockClient) {
43+
f.EXPECT().AppGet(gomock.Any(), gomock.Any()).DoAndReturn(
44+
func(ctx context.Context, name string) (*apiv1.App, error) {
45+
switch name {
46+
case "dne":
47+
return nil, fmt.Errorf("error: app %s does not exist", name)
48+
case "found":
49+
return &apiv1.App{
50+
TypeMeta: metav1.TypeMeta{},
51+
ObjectMeta: metav1.ObjectMeta{Name: "found"},
52+
Spec: v1.AppInstanceSpec{Secrets: []v1.SecretBinding{{Secret: "found.secret", Target: "found"}}},
53+
Status: v1.AppInstanceStatus{Ready: true},
54+
}, nil
55+
case "found.container":
56+
return &apiv1.App{
57+
TypeMeta: metav1.TypeMeta{},
58+
ObjectMeta: metav1.ObjectMeta{Name: "found.container"},
59+
Spec: v1.AppInstanceSpec{Secrets: []v1.SecretBinding{{Secret: "found.secret", Target: "found"}}},
60+
Status: v1.AppInstanceStatus{},
61+
}, nil
62+
}
63+
return nil, nil
64+
}).AnyTimes()
65+
f.EXPECT().AppRun(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
66+
func(ctx context.Context, image string, opts *client.AppRunOptions) (*apiv1.App, error) {
67+
switch image {
68+
case "dne":
69+
return nil, fmt.Errorf("error: app %s does not exist", image)
70+
case "found":
71+
return &apiv1.App{
72+
TypeMeta: metav1.TypeMeta{},
73+
ObjectMeta: metav1.ObjectMeta{Name: "found"},
74+
Spec: v1.AppInstanceSpec{Secrets: []v1.SecretBinding{{Secret: "found.secret", Target: "found"}}},
75+
Status: v1.AppInstanceStatus{Ready: true},
76+
}, nil
77+
case "found.container":
78+
return &apiv1.App{
79+
TypeMeta: metav1.TypeMeta{},
80+
ObjectMeta: metav1.ObjectMeta{Name: "found.container"},
81+
Spec: v1.AppInstanceSpec{Secrets: []v1.SecretBinding{{Secret: "found.secret", Target: "found"}}},
82+
Status: v1.AppInstanceStatus{},
83+
}, nil
84+
}
85+
return nil, fmt.Errorf("error: app %s does not exist", image)
86+
}).AnyTimes()
87+
}
88+
3289
type fields struct {
33-
All bool
34-
Type []string
35-
Force bool
90+
Quiet bool
91+
Output string
92+
All bool
93+
Force bool
3694
}
3795
type args struct {
38-
cmd *cobra.Command
39-
args []string
40-
client *testdata.MockClient
96+
cmd *cobra.Command
97+
args []string
4198
}
42-
var _, w, _ = os.Pipe()
4399
tests := []struct {
44-
name string
45-
fields fields
46-
args args
47-
wantErr bool
48-
wantOut string
49-
commandContext CommandContext
100+
name string
101+
fields fields
102+
args args
103+
wantErr bool
104+
wantOut string
105+
prepare func(t *testing.T, f *mocks.MockClient)
50106
}{
51107
{
52108
name: "acorn run -h", fields: fields{
53109
All: false,
54-
Type: nil,
55110
Force: true,
56111
},
57-
commandContext: CommandContext{
58-
ClientFactory: &testdata.MockClientFactory{},
59-
StdOut: w,
60-
StdErr: w,
61-
StdIn: strings.NewReader(""),
62-
},
112+
63113
args: args{
64-
args: []string{"-h"},
65-
client: &testdata.MockClient{},
114+
args: []string{"-h"},
66115
},
67116
wantErr: false,
68117
wantOut: "./testdata/run/acorn_run_help.txt",
69118
},
70119
{
71120
name: "acorn run -m found.container=256Miii found ", fields: fields{
72121
All: false,
73-
Type: nil,
74122
Force: true,
75123
},
76-
commandContext: CommandContext{
77-
ClientFactory: &testdata.MockClientFactory{},
78-
StdOut: w,
79-
StdErr: w,
80-
StdIn: strings.NewReader(""),
81-
},
82124
args: args{
83-
args: []string{"-m found.container=256Miii", "found"},
84-
client: &testdata.MockClient{},
125+
args: []string{"-m found.container=256Miii", "found"},
126+
},
127+
prepare: func(t *testing.T, f *mocks.MockClient) {
128+
t.Helper()
129+
f.EXPECT().Info(gomock.Any()).Return(
130+
[]apiv1.Info{
131+
{
132+
TypeMeta: metav1.TypeMeta{},
133+
ObjectMeta: metav1.ObjectMeta{},
134+
Spec: apiv1.InfoSpec{},
135+
},
136+
}, nil)
85137
},
86138
wantErr: true,
87139
wantOut: "invalid number \"256Miii\"",
88140
},
89141
{
90142
name: "acorn run -m found.container=notallowed found ", fields: fields{
91143
All: false,
92-
Type: nil,
93144
Force: true,
94145
},
95-
commandContext: CommandContext{
96-
ClientFactory: &testdata.MockClientFactory{},
97-
StdOut: w,
98-
StdErr: w,
99-
StdIn: strings.NewReader(""),
100-
},
146+
101147
args: args{
102-
args: []string{"-m found.container=notallowed", "found"},
103-
client: &testdata.MockClient{},
148+
args: []string{"-m found.container=notallowed", "found"},
149+
},
150+
prepare: func(t *testing.T, f *mocks.MockClient) {
151+
t.Helper()
152+
f.EXPECT().Info(gomock.Any()).Return(
153+
[]apiv1.Info{
154+
{
155+
TypeMeta: metav1.TypeMeta{},
156+
ObjectMeta: metav1.ObjectMeta{},
157+
Spec: apiv1.InfoSpec{},
158+
},
159+
}, nil)
104160
},
105161
wantErr: true,
106162
wantOut: "illegal number start \"notallowed\"",
107163
},
164+
{
165+
name: "acorn run app name already in use", fields: fields{
166+
All: false,
167+
Force: true,
168+
},
169+
170+
args: args{
171+
args: []string{"-n=found", "run-name"},
172+
},
173+
prepare: func(t *testing.T, f *mocks.MockClient) {
174+
t.Helper()
175+
},
176+
wantErr: true,
177+
wantOut: "app \"found\" already exists",
178+
},
179+
{
180+
name: "acorn run ./folder but folder doesn't exist", fields: fields{
181+
All: false,
182+
Force: true,
183+
},
184+
185+
args: args{
186+
args: []string{"./folder"},
187+
},
188+
prepare: func(t *testing.T, f *mocks.MockClient) {
189+
t.Helper()
190+
f.EXPECT().Info(gomock.Any()).Return(
191+
[]apiv1.Info{
192+
{
193+
TypeMeta: metav1.TypeMeta{},
194+
ObjectMeta: metav1.ObjectMeta{},
195+
Spec: apiv1.InfoSpec{},
196+
},
197+
}, nil)
198+
},
199+
wantErr: true,
200+
wantOut: "error: app ./folder does not exist",
201+
},
202+
{
203+
name: "acorn_run_pointed_at_working_dir_without_acornfile", fields: fields{
204+
All: false,
205+
Force: true,
206+
},
207+
208+
args: args{
209+
args: []string{"."},
210+
},
211+
prepare: func(t *testing.T, f *mocks.MockClient) {
212+
t.Helper()
213+
f.EXPECT().Info(gomock.Any()).Return(
214+
[]apiv1.Info{
215+
{
216+
TypeMeta: metav1.TypeMeta{},
217+
ObjectMeta: metav1.ObjectMeta{},
218+
Spec: apiv1.InfoSpec{},
219+
},
220+
}, nil)
221+
},
222+
wantErr: true,
223+
wantOut: "open Acornfile: no such file or directory",
224+
},
225+
{
226+
name: "acorn_run_points_at_file", fields: fields{
227+
All: false,
228+
Force: true,
229+
},
230+
args: args{
231+
args: []string{"Acornfile_temp"},
232+
},
233+
prepare: func(t *testing.T, f *mocks.MockClient) {
234+
t.Helper()
235+
// Create a placeholder acorn file
236+
dir, err := os.Getwd()
237+
if err != nil {
238+
t.Fatalf("failed to get current working directory: %v", err)
239+
}
240+
file, err := os.Create(dir + "/Acornfile_temp")
241+
if err != nil {
242+
t.Fatalf("failed to get current working directory: %v", err)
243+
}
244+
t.Cleanup(func() { os.Remove(file.Name()) })
245+
246+
if _, err = file.Write([]byte("content")); err != nil {
247+
t.Fatal(err.Error())
248+
}
249+
if err = file.Close(); err != nil {
250+
t.Fatal(err)
251+
}
252+
if err != nil {
253+
t.Fatal()
254+
}
255+
256+
f.EXPECT().Info(gomock.Any()).Return(
257+
[]apiv1.Info{
258+
{
259+
TypeMeta: metav1.TypeMeta{},
260+
ObjectMeta: metav1.ObjectMeta{},
261+
Spec: apiv1.InfoSpec{},
262+
},
263+
}, nil)
264+
},
265+
wantErr: true,
266+
wantOut: "Acornfile_temp is not a directory",
267+
},
108268
}
109269
for _, tt := range tests {
110270
t.Run(tt.name, func(t *testing.T) {
271+
ctrl := gomock.NewController(t)
272+
//Mocked client for cli's client calls.
273+
mClient := mocks.NewMockClient(ctrl)
274+
275+
baseMock(mClient)
276+
if tt.prepare != nil {
277+
tt.prepare(t, mClient)
278+
}
279+
111280
r, w, _ := os.Pipe()
112281
os.Stdout = w
113-
tt.args.cmd = NewRun(tt.commandContext)
282+
// Mock client factory just returns the gomock client.
283+
tt.args.cmd = NewRun(CommandContext{
284+
ClientFactory: &testdata.MockClientFactoryManual{
285+
Client: mClient,
286+
},
287+
StdOut: w,
288+
StdErr: w,
289+
StdIn: strings.NewReader(""),
290+
})
114291
tt.args.cmd.SetArgs(tt.args.args)
115292
err := tt.args.cmd.Execute()
293+
116294
if err != nil && !tt.wantErr {
117295
assert.Failf(t, "got err when err not expected", "got err: %s", err.Error())
118296
} else if err != nil && tt.wantErr {
119297
assert.Equal(t, tt.wantOut, err.Error())
120298
} else {
121299
w.Close()
122300
out, _ := io.ReadAll(r)
123-
testOut, _ := os.ReadFile(tt.wantOut)
124-
assert.Equal(t, string(testOut), string(out))
301+
wantOut := tt.wantOut
302+
if testOut, err := os.ReadFile(tt.wantOut); err == nil {
303+
wantOut = string(testOut)
304+
}
305+
assert.Equal(t, wantOut, string(out))
125306
}
126307
})
127308
}

0 commit comments

Comments
 (0)