Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/local-app/pkg/selfupdate/selfupdate_test.go
2500 views
1
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package selfupdate
6
7
import (
8
"context"
9
"encoding/json"
10
"net/http"
11
"net/http/httptest"
12
"os"
13
"path/filepath"
14
"runtime"
15
"testing"
16
17
"github.com/Masterminds/semver/v3"
18
"github.com/google/go-cmp/cmp"
19
"github.com/opencontainers/go-digest"
20
)
21
22
func TestGenerateManifest(t *testing.T) {
23
type Expectation struct {
24
Error string
25
Manifest *Manifest
26
}
27
tests := []struct {
28
Name string
29
Expectation Expectation
30
Files []string
31
FilenameParser FilenameParserFunc
32
}{
33
{
34
Name: "happy path",
35
Expectation: Expectation{
36
Manifest: &Manifest{
37
Version: semver.MustParse("v1.0"),
38
Binaries: []Binary{
39
{
40
Filename: "gitpod-linux-amd64",
41
OS: "linux",
42
Arch: "amd64",
43
Digest: "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
44
},
45
},
46
},
47
},
48
Files: []string{
49
"gitpod-linux-amd64",
50
"nonsense",
51
},
52
FilenameParser: DefaultFilenameParser,
53
},
54
}
55
56
for _, test := range tests {
57
t.Run(test.Name, func(t *testing.T) {
58
var act Expectation
59
60
loc, err := os.MkdirTemp("", "selfupdate")
61
if err != nil {
62
t.Fatal(err)
63
}
64
t.Cleanup(func() {
65
os.RemoveAll(loc)
66
})
67
for _, f := range test.Files {
68
err = os.WriteFile(filepath.Join(loc, f), []byte("test"), 0644)
69
if err != nil {
70
t.Fatal(err)
71
}
72
}
73
74
res, err := GenerateManifest(semver.MustParse("v1.0"), loc, test.FilenameParser)
75
if err != nil {
76
act.Error = err.Error()
77
}
78
act.Manifest = res
79
80
if diff := cmp.Diff(test.Expectation, act); diff != "" {
81
t.Errorf("GenerateManifest() mismatch (-want +got):\n%s", diff)
82
}
83
})
84
}
85
}
86
87
func TestDownloadManifest(t *testing.T) {
88
marshal := func(mf *Manifest) []byte {
89
fc, err := json.Marshal(mf)
90
if err != nil {
91
t.Fatal(err)
92
}
93
return fc
94
}
95
96
type Expectation struct {
97
Error string
98
Manifest *Manifest
99
}
100
tests := []struct {
101
Name string
102
Expectation func(url string) Expectation
103
Manifest []byte
104
}{
105
{
106
Name: "happy path",
107
Manifest: marshal(&Manifest{
108
Version: semver.MustParse("0.2.0"),
109
Binaries: []Binary{
110
{
111
Filename: "gitpod-linux-amd64",
112
OS: "linux",
113
Arch: "amd64",
114
Digest: "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
115
},
116
},
117
}),
118
Expectation: func(url string) Expectation {
119
return Expectation{
120
Manifest: &Manifest{
121
Version: semver.MustParse("0.2.0"),
122
Binaries: []Binary{
123
{
124
URL: url + GitpodCLIBasePath + "/gitpod-linux-amd64",
125
Filename: "gitpod-linux-amd64",
126
OS: "linux",
127
Arch: "amd64",
128
Digest: "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
129
},
130
},
131
},
132
}
133
},
134
},
135
{
136
Name: "not found",
137
Expectation: func(url string) Expectation {
138
return Expectation{
139
Error: "cannot download manifest from " + url + GitpodCLIBasePath + "/manifest.json: 404 Not Found",
140
}
141
},
142
},
143
}
144
145
for _, test := range tests {
146
t.Run(test.Name, func(t *testing.T) {
147
mux := http.NewServeMux()
148
if test.Manifest != nil {
149
mux.Handle(filepath.Join(GitpodCLIBasePath, "/manifest.json"), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
150
_, _ = w.Write(test.Manifest)
151
}))
152
}
153
srv := httptest.NewServer(mux)
154
t.Cleanup(func() { srv.Close() })
155
156
var act Expectation
157
res, err := DownloadManifest(context.Background(), srv.URL)
158
if err != nil {
159
act.Error = err.Error()
160
}
161
act.Manifest = res
162
163
if diff := cmp.Diff(test.Expectation(srv.URL), act); diff != "" {
164
t.Errorf("DownloadManifest() mismatch (-want +got):\n%s", diff)
165
}
166
})
167
}
168
}
169
170
func TestReplaceSelf(t *testing.T) {
171
type File struct {
172
OS string
173
Arch string
174
Filename string
175
Content []byte
176
}
177
type Expectation struct {
178
Error string
179
}
180
tests := []struct {
181
Name string
182
Expectation Expectation
183
Files []File
184
}{
185
{
186
Name: "happy path",
187
Files: []File{
188
{
189
OS: runtime.GOOS,
190
Arch: runtime.GOARCH,
191
Filename: "gitpod-" + runtime.GOOS + "-" + runtime.GOARCH,
192
Content: []byte("#!/bin/sh"),
193
},
194
},
195
},
196
}
197
198
for _, test := range tests {
199
t.Run(test.Name, func(t *testing.T) {
200
var mf Manifest
201
mf.Version = semver.MustParse("v1.0")
202
for _, f := range test.Files {
203
mf.Binaries = append(mf.Binaries, Binary{
204
OS: f.OS,
205
Arch: f.Arch,
206
Filename: f.Filename,
207
Digest: digest.FromBytes(f.Content),
208
})
209
}
210
211
mux := http.NewServeMux()
212
mux.Handle(GitpodCLIBasePath+"/manifest.json", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
213
_ = json.NewEncoder(w).Encode(mf)
214
}))
215
for _, f := range test.Files {
216
mux.Handle(GitpodCLIBasePath+"/"+f.Filename, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
217
_, _ = w.Write(f.Content)
218
}))
219
}
220
srv := httptest.NewServer(mux)
221
t.Cleanup(func() { srv.Close() })
222
223
dlmf, err := DownloadManifest(context.Background(), srv.URL)
224
if err != nil {
225
t.Fatal(err)
226
}
227
228
var act Expectation
229
230
err = ReplaceSelf(context.Background(), dlmf)
231
if err != nil {
232
act.Error = err.Error()
233
}
234
235
if diff := cmp.Diff(test.Expectation, act); diff != "" {
236
t.Errorf("ReplaceSelf() mismatch (-want +got):\n%s", diff)
237
}
238
})
239
}
240
}
241
242