Skip to content

Commit df43bb1

Browse files
committed
this is sedia refactor
1 parent fb890be commit df43bb1

File tree

4 files changed

+190
-218
lines changed

4 files changed

+190
-218
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package updatetest
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
var arch = flag.String("arch", "amd64", "target architecture")
14+
15+
const dockerFile = "test.Dockerfile"
16+
const daemonHost = "127.0.0.1:8800"
17+
18+
func TestUpdatePackage(t *testing.T) {
19+
fmt.Printf("***** ARCH %s ***** \n", *arch)
20+
21+
t.Run("Stable To Current", func(t *testing.T) {
22+
t.Cleanup(func() { os.RemoveAll("build") })
23+
24+
tagAppCli := fetchDebPackageLatest(t, "build/stable", "arduino-app-cli")
25+
fetchDebPackageLatest(t, "build/stable", "arduino-router")
26+
majorTag := genMajorTag(t, tagAppCli)
27+
28+
fmt.Printf("Updating from stable version %s to unstable version %s \n", tagAppCli, majorTag)
29+
fmt.Printf("Building local deb version %s \n", majorTag)
30+
buildDebVersion(t, "build", majorTag, *arch)
31+
32+
const dockerImageName = "apt-test-update-image"
33+
fmt.Println("**** BUILD docker image *****")
34+
buildDockerImage(t, dockerFile, dockerImageName, *arch)
35+
//TODO: t cleanup remove docker image
36+
37+
t.Run("CLI Command", func(t *testing.T) {
38+
const containerName = "apt-test-update"
39+
t.Cleanup(func() { stopDockerContainer(t, containerName) })
40+
41+
fmt.Println("**** RUN docker image *****")
42+
startDockerContainer(t, containerName, dockerImageName)
43+
waitForPort(t, daemonHost, 5*time.Second)
44+
45+
preUpdateVersion := getAppCliVersion(t, containerName)
46+
require.Equal(t, "v"+preUpdateVersion, tagAppCli)
47+
runSystemUpdate(t, containerName)
48+
postUpdateVersion := getAppCliVersion(t, containerName)
49+
require.Equal(t, "v"+postUpdateVersion, majorTag)
50+
})
51+
52+
t.Run("HTTP Request", func(t *testing.T) {
53+
const containerName = "apt-test-update-http"
54+
t.Cleanup(func() { stopDockerContainer(t, containerName) })
55+
56+
startDockerContainer(t, containerName, dockerImageName)
57+
waitForPort(t, daemonHost, 5*time.Second)
58+
59+
preUpdateVersion := getAppCliVersion(t, containerName)
60+
require.Equal(t, "v"+preUpdateVersion, tagAppCli)
61+
62+
putUpdateRequest(t, daemonHost)
63+
waitForUpgrade(t, daemonHost)
64+
65+
postUpdateVersion := getAppCliVersion(t, containerName)
66+
require.Equal(t, "v"+postUpdateVersion, majorTag)
67+
})
68+
69+
})
70+
71+
t.Run("CurrentToStable", func(t *testing.T) {
72+
t.Cleanup(func() { os.RemoveAll("build") })
73+
74+
tagAppCli := fetchDebPackageLatest(t, "build", "arduino-app-cli")
75+
fetchDebPackageLatest(t, "build/stable", "arduino-router")
76+
minorTag := genMinorTag(t, tagAppCli)
77+
78+
fmt.Printf("Updating from unstable version %s to stable version %s \n", minorTag, tagAppCli)
79+
fmt.Printf("Building local deb version %s \n", minorTag)
80+
buildDebVersion(t, "build/stable", minorTag, *arch)
81+
82+
fmt.Println("**** BUILD docker image *****")
83+
const dockerImageName = "test-apt-update-unstable-image"
84+
85+
buildDockerImage(t, dockerFile, dockerImageName, *arch)
86+
//TODO: t cleanup remove docker image
87+
88+
t.Run("CLI Command", func(t *testing.T) {
89+
const containerName = "apt-test-update-unstable"
90+
t.Cleanup(func() { stopDockerContainer(t, containerName) })
91+
92+
fmt.Println("**** RUN docker image *****")
93+
startDockerContainer(t, containerName, dockerImageName)
94+
waitForPort(t, daemonHost, 5*time.Second)
95+
96+
preUpdateVersion := getAppCliVersion(t, containerName)
97+
require.Equal(t, "v"+preUpdateVersion, minorTag)
98+
runSystemUpdate(t, containerName)
99+
postUpdateVersion := getAppCliVersion(t, containerName)
100+
require.Equal(t, "v"+postUpdateVersion, tagAppCli)
101+
})
102+
103+
t.Run("HTTP Request", func(t *testing.T) {
104+
const containerName = "apt-test-update--unstable-http"
105+
t.Cleanup(func() { stopDockerContainer(t, containerName) })
106+
107+
startDockerContainer(t, containerName, dockerImageName)
108+
waitForPort(t, daemonHost, 5*time.Second)
109+
110+
preUpdateVersion := getAppCliVersion(t, containerName)
111+
require.Equal(t, "v"+preUpdateVersion, minorTag)
112+
113+
putUpdateRequest(t, daemonHost)
114+
waitForUpgrade(t, daemonHost)
115+
116+
postUpdateVersion := getAppCliVersion(t, containerName)
117+
require.Equal(t, "v"+postUpdateVersion, tagAppCli)
118+
})
119+
120+
})
121+
122+
}

internal/testtools/test_deb_update/helpers.go renamed to internal/e2e/updatetest/helpers.go

Lines changed: 68 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package testtools
1+
package updatetest
22

33
import (
44
"bufio"
55
"bytes"
66
"context"
7+
"encoding/json"
78
"fmt"
8-
"io"
99
"iter"
1010
"log"
1111
"net"
@@ -17,9 +17,11 @@ import (
1717
"strings"
1818
"testing"
1919
"time"
20+
21+
"github.com/stretchr/testify/require"
2022
)
2123

22-
func FetchDebPackage(t *testing.T, path, repo, version, arch string) string {
24+
func fetchDebPackageLatest(t *testing.T, path, repo string) string {
2325
t.Helper()
2426

2527
cmd := exec.Command(
@@ -41,20 +43,13 @@ func FetchDebPackage(t *testing.T, path, repo, version, arch string) string {
4143
log.Fatal("could not parse tag from gh release list output")
4244
}
4345
tag := fields[0]
44-
tagPath := strings.TrimPrefix(tag, "v")
4546

46-
debFile := fmt.Sprintf("%s/%s_%s-1_%s.deb", path, repo, tagPath, arch)
47-
fmt.Println(debFile)
48-
if _, err := os.Stat(debFile); err == nil {
49-
fmt.Printf("✅ %s already exists, skipping download.\n", debFile)
50-
return tag
51-
}
5247
fmt.Println("Detected tag:", tag)
5348
cmd2 := exec.Command(
5449
"gh", "release", "download",
5550
tag,
5651
"--repo", "github.com/arduino/"+repo,
57-
"--pattern", "*",
52+
"--pattern", "*.deb",
5853
"--dir", path,
5954
)
6055

@@ -87,7 +82,7 @@ func buildDebVersion(t *testing.T, storePath, tagVersion, arch string) {
8782
}
8883
}
8984

90-
func majorTag(t *testing.T, tag string) string {
85+
func genMajorTag(t *testing.T, tag string) string {
9186
t.Helper()
9287

9388
parts := strings.Split(tag, ".")
@@ -102,7 +97,7 @@ func majorTag(t *testing.T, tag string) string {
10297
return newTag
10398
}
10499

105-
func minorTag(t *testing.T, tag string) string {
100+
func genMinorTag(t *testing.T, tag string) string {
106101
t.Helper()
107102

108103
parts := strings.Split(tag, ".")
@@ -133,7 +128,6 @@ func buildDockerImage(t *testing.T, dockerfile, name, arch string) {
133128
cmd.Stderr = &stderr
134129

135130
err := cmd.Run()
136-
137131
if err != nil {
138132
fmt.Printf("❌ Docker build failed: %v\n", err)
139133
fmt.Printf("---- STDERR ----\n%s\n", stderr.String())
@@ -142,11 +136,9 @@ func buildDockerImage(t *testing.T, dockerfile, name, arch string) {
142136
}
143137

144138
fmt.Println("✅ Docker build succeeded!")
145-
fmt.Println(out.String())
146-
147139
}
148140

149-
func runDockerContainer(t *testing.T, containerName string, containerImageName string) {
141+
func startDockerContainer(t *testing.T, containerName string, containerImageName string) {
150142
t.Helper()
151143

152144
cmd := exec.Command(
@@ -168,64 +160,66 @@ func runDockerContainer(t *testing.T, containerName string, containerImageName s
168160

169161
}
170162

171-
func runDockerSystemVersion(t *testing.T, containerName string) string {
163+
func getAppCliVersion(t *testing.T, containerName string) string {
172164
t.Helper()
173165

174166
cmd := exec.Command(
175167
"docker", "exec",
176168
"--user", "arduino",
177169
containerName,
178-
"arduino-app-cli", "version",
170+
"arduino-app-cli", "version", "--format", "json",
179171
)
180-
181172
output, err := cmd.CombinedOutput()
182173
if err != nil {
183174
log.Fatalf("command failed: %v\nOutput: %s", err, output)
184175
}
185176

186-
return string(output)
187-
188-
}
189-
190-
func runDockerSystemUpdate(t *testing.T, containerName string) {
191-
t.Helper()
192-
var buf bytes.Buffer
193-
194-
cmd := exec.Command(
195-
"docker", "exec",
196-
containerName,
197-
"sh", "-lc",
198-
`su - arduino -c "yes | arduino-app-cli system update"`,
199-
)
200-
201-
cmd.Stdout = io.MultiWriter(os.Stdout, &buf)
202-
203-
if err := cmd.Run(); err != nil {
204-
fmt.Fprintf(os.Stderr, "Error running system update: %v\n", err)
205-
os.Exit(1)
177+
var version struct {
178+
Version string `json:"version"`
179+
DaemonVersion string `json:"daemon_version"`
206180
}
181+
err = json.Unmarshal(output, &version)
182+
require.NoError(t, err)
183+
//TODO to enable after 0.6.7
184+
//require.Equal(t, version.Version, version.DaemonVersion, "client and daemon versions should match")
185+
require.NotEmpty(t, version.Version)
186+
return version.Version
207187

208188
}
209189

210-
func runDockerDaemon(t *testing.T, containerName string) string {
190+
func runSystemUpdate(t *testing.T, containerName string) {
211191
t.Helper()
212192

213193
cmd := exec.Command(
214194
"docker", "exec",
215-
"-d",
216195
"--user", "arduino",
217196
containerName,
218-
"systemctl", "start", "arduino-app-cli",
197+
"arduino-app-cli", "system", "update", "--yes",
219198
)
220199
output, err := cmd.CombinedOutput()
221-
if err != nil {
222-
log.Fatalf("command failed: %v\n Output: %s", err, output)
223-
}
224-
225-
return string(output)
200+
require.NoError(t, err, "system update failed: %s", output)
201+
t.Logf("system update output: %s", output)
226202
}
227203

228-
func runDockerCleanUp(t *testing.T, containerName string) {
204+
// func runDockerDaemon(t *testing.T, containerName string) string {
205+
// t.Helper()
206+
207+
// cmd := exec.Command(
208+
// "docker", "exec",
209+
// "-d",
210+
// "--user", "arduino",
211+
// containerName,
212+
// "systemctl", "start", "arduino-app-cli",
213+
// )
214+
// output, err := cmd.CombinedOutput()
215+
// if err != nil {
216+
// log.Fatalf("command failed: %v\n Output: %s", err, output)
217+
// }
218+
219+
// return string(output)
220+
// }
221+
222+
func stopDockerContainer(t *testing.T, containerName string) {
229223
t.Helper()
230224

231225
cleanupCmd := exec.Command("docker", "rm", "-f", containerName)
@@ -288,10 +282,12 @@ func rm(t *testing.T, pathFile string) {
288282

289283
}
290284

291-
func putUpdateRequest(t *testing.T, url string) string {
285+
func putUpdateRequest(t *testing.T, host string) {
292286

293287
t.Helper()
294288

289+
url := fmt.Sprintf("http://%s/v1/system/update/apply", host)
290+
295291
req, err := http.NewRequest(http.MethodPut, url, nil)
296292
if err != nil {
297293
log.Fatalf("Error creating request: %v", err)
@@ -306,30 +302,8 @@ func putUpdateRequest(t *testing.T, url string) string {
306302
}
307303
defer resp.Body.Close()
308304

309-
return resp.Status
310-
}
311-
312-
func rmrf(t *testing.T, pathFile string) {
313-
t.Helper()
314-
// Check if the folder exists
315-
if _, err := os.Stat(pathFile); os.IsNotExist(err) {
316-
fmt.Println("No build directory found.")
317-
return
318-
}
319-
320-
// Run the Linux command to remove it
321-
cmd := exec.Command("rm", "-rf", pathFile)
322-
cmd.Stdout = os.Stdout
323-
cmd.Stderr = os.Stderr
324-
325-
fmt.Println("Removing build directory...")
305+
require.Equal(t, 202, resp.StatusCode)
326306

327-
if err := cmd.Run(); err != nil {
328-
fmt.Fprintf(os.Stderr, "Error removing build folder: %v\n", err)
329-
os.Exit(1)
330-
}
331-
332-
fmt.Println("Build directory removed successfully.")
333307
}
334308

335309
func NewSSEClient(ctx context.Context, method, url string) iter.Seq2[Event, error] {
@@ -387,20 +361,35 @@ type Event struct {
387361
Data []byte // json
388362
}
389363

390-
// WaitForPort waits until a TCP port is open or fails after timeout.
391-
func WaitForPort(t *testing.T, host string, port string, timeout time.Duration) {
364+
// waitForPort waits until a TCP port is open or fails after timeout.
365+
func waitForPort(t *testing.T, host string, timeout time.Duration) {
392366
t.Helper()
393-
addr := fmt.Sprintf("%s:%s", host, port)
394367

395368
deadline := time.Now().Add(timeout)
396369
for time.Now().Before(deadline) {
397-
conn, err := net.DialTimeout("tcp", addr, 500*time.Millisecond)
370+
conn, err := net.DialTimeout("tcp", host, 500*time.Millisecond)
398371
if err == nil {
399372
_ = conn.Close()
400-
t.Logf("Server is up on %s", addr)
373+
t.Logf("Server is up on %s", host)
401374
return
402375
}
403376
time.Sleep(200 * time.Millisecond)
404377
}
405-
t.Fatalf("Server at %s did not start within %v", addr, timeout)
378+
t.Fatalf("Server at %s did not start within %v", host, timeout)
379+
}
380+
381+
func waitForUpgrade(t *testing.T, host string) {
382+
t.Helper()
383+
384+
url := fmt.Sprintf("http://%s/v1/system/update/events", host)
385+
386+
itr := NewSSEClient(t.Context(), "GET", url)
387+
for event, err := range itr {
388+
require.NoError(t, err)
389+
t.Logf("Received event: ID=%s, Event=%s, Data=%s\n", event.ID, event.Event, string(event.Data))
390+
if event.Event == "restarting" {
391+
break
392+
}
393+
}
394+
406395
}

0 commit comments

Comments
 (0)