@@ -10,6 +10,7 @@ import (
1010 "net/http/httptest"
1111 "os"
1212 "path/filepath"
13+ "runtime"
1314 "testing"
1415)
1516
@@ -278,6 +279,95 @@ func TestReplaceBinary(t *testing.T) {
278279 }
279280}
280281
282+ func TestApplyUpdate_SkipsServerBinaries (t * testing.T ) {
283+ tmpDir := t .TempDir ()
284+ installDir := filepath .Join (tmpDir , "bin" )
285+ os .MkdirAll (installDir , 0755 )
286+
287+ // Seed existing binaries (client + server).
288+ os .WriteFile (filepath .Join (installDir , "daemon" ), []byte ("old-daemon" ), 0755 )
289+ os .WriteFile (filepath .Join (installDir , "registry" ), []byte ("old-registry" ), 0755 )
290+ os .WriteFile (filepath .Join (installDir , "beacon" ), []byte ("old-beacon" ), 0755 )
291+ os .WriteFile (filepath .Join (installDir , ".pilot-version" ), []byte ("v1.0.0\n " ), 0644 )
292+
293+ // Build an archive with both client and server binaries.
294+ archiveDir := t .TempDir ()
295+ archiveName := fmt .Sprintf ("pilot-%s-%s.tar.gz" , runtime .GOOS , runtime .GOARCH )
296+ archivePath := filepath .Join (archiveDir , archiveName )
297+ createTestTarGz (t , archivePath , map [string ]string {
298+ "daemon" : "new-daemon" ,
299+ "pilotctl" : "new-pilotctl" ,
300+ "gateway" : "new-gateway" ,
301+ "updater" : "new-updater" ,
302+ "registry" : "new-registry" ,
303+ "beacon" : "new-beacon" ,
304+ "rendezvous" : "new-rendezvous" ,
305+ "nameserver" : "new-nameserver" ,
306+ })
307+ archiveContent , _ := os .ReadFile (archivePath )
308+ archiveHash := sha256 .Sum256 (archiveContent )
309+ checksumsContent := fmt .Sprintf ("%x %s\n " , archiveHash , archiveName )
310+
311+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
312+ switch r .URL .Path {
313+ case "/download/" + archiveName :
314+ w .Write (archiveContent )
315+ case "/download/checksums.txt" :
316+ w .Write ([]byte (checksumsContent ))
317+ default :
318+ http .NotFound (w , r )
319+ }
320+ }))
321+ defer srv .Close ()
322+
323+ u := & Updater {
324+ config : Config {InstallDir : installDir },
325+ client : srv .Client (),
326+ stopCh : make (chan struct {}),
327+ }
328+
329+ release := & GitHubRelease {
330+ TagName : "v1.1.0" ,
331+ Assets : []GitHubAsset {
332+ {Name : archiveName , BrowserDownloadURL : srv .URL + "/download/" + archiveName },
333+ {Name : "checksums.txt" , BrowserDownloadURL : srv .URL + "/download/checksums.txt" },
334+ },
335+ }
336+
337+ if err := u .applyUpdate (release ); err != nil {
338+ t .Fatalf ("applyUpdate: %v" , err )
339+ }
340+
341+ // Client binaries should be updated.
342+ for _ , name := range []string {"daemon" , "pilotctl" , "gateway" , "updater" } {
343+ data , err := os .ReadFile (filepath .Join (installDir , name ))
344+ if err != nil {
345+ t .Fatalf ("read %s: %v" , name , err )
346+ }
347+ if string (data ) != "new-" + name {
348+ t .Errorf ("%s = %q, want %q" , name , string (data ), "new-" + name )
349+ }
350+ }
351+
352+ // Server binaries should NOT be updated.
353+ for _ , name := range []string {"registry" , "beacon" } {
354+ data , err := os .ReadFile (filepath .Join (installDir , name ))
355+ if err != nil {
356+ t .Fatalf ("read %s: %v" , name , err )
357+ }
358+ if string (data ) != "old-" + name {
359+ t .Errorf ("%s = %q, want %q (should be unchanged)" , name , string (data ), "old-" + name )
360+ }
361+ }
362+
363+ // Server binaries not previously present should NOT be created.
364+ for _ , name := range []string {"rendezvous" , "nameserver" } {
365+ if _ , err := os .Stat (filepath .Join (installDir , name )); err == nil {
366+ t .Errorf ("%s should not have been created" , name )
367+ }
368+ }
369+ }
370+
281371// createTestTarGz creates a tar.gz archive with the given file name→content map.
282372func createTestTarGz (t * testing.T , path string , files map [string ]string ) {
283373 t .Helper ()
0 commit comments