267 lines · 9.6 KB · Go
RawDownload
// Copyright 2023 The Gitea Authors. All rights reserved.// SPDX-License-Identifier: MIT package integration import (	"archive/tar"	"bytes"	"compress/gzip"	"fmt"	"io"	"net/http"	"strings"	"testing" 	"forgejo.org/models/db"	"forgejo.org/models/packages"	"forgejo.org/models/unittest"	user_model "forgejo.org/models/user"	"forgejo.org/modules/base"	debian_module "forgejo.org/modules/packages/debian"	"forgejo.org/tests" 	"github.com/blakesmith/ar"	"github.com/stretchr/testify/assert"	"github.com/stretchr/testify/require") func TestPackageDebian(t *testing.T) {	defer tests.PrepareTestEnv(t)()	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 	packageName := "gitea"	packageVersion := "1.0.3"	packageVersion2 := "1.0.4"	packageDescription := "Package Description" 	createArchive := func(name, version, architecture string) io.Reader {		var cbuf bytes.Buffer		zw := gzip.NewWriter(&cbuf)		tw := tar.NewWriter(zw)		tw.WriteHeader(&tar.Header{			Name: "control",			Mode: 0o600,			Size: 50,		})		fmt.Fprintf(tw, "Package: %s\nVersion: %s\nArchitecture: %s\nDescription: %s\n", name, version, architecture, packageDescription)		tw.Close()		zw.Close() 		var buf bytes.Buffer		aw := ar.NewWriter(&buf)		aw.WriteGlobalHeader()		hdr := &ar.Header{			Name: "control.tar.gz",			Mode: 0o600,			Size: int64(cbuf.Len()),		}		aw.WriteHeader(hdr)		aw.Write(cbuf.Bytes())		return &buf	} 	distributions := []string{"test", "gitea"}	components := []string{"main", "stable"}	architectures := []string{"all", "amd64"} 	rootURL := fmt.Sprintf("/api/packages/%s/debian", user.Name) 	t.Run("RepositoryKey", func(t *testing.T) {		defer tests.PrintCurrentTest(t)() 		req := NewRequest(t, "GET", rootURL+"/repository.key")		resp := MakeRequest(t, req, http.StatusOK) 		assert.Equal(t, "application/pgp-keys", resp.Header().Get("Content-Type"))		assert.Contains(t, resp.Body.String(), "-----BEGIN PGP PUBLIC KEY BLOCK-----")	}) 	for _, distribution := range distributions {		t.Run(fmt.Sprintf("[Distribution:%s]", distribution), func(t *testing.T) {			for _, component := range components {				for _, architecture := range architectures {					t.Run(fmt.Sprintf("[Component:%s,Architecture:%s]", component, architecture), func(t *testing.T) {						uploadURL := fmt.Sprintf("%s/pool/%s/%s/upload", rootURL, distribution, component) 						t.Run("Upload", func(t *testing.T) {							defer tests.PrintCurrentTest(t)() 							req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{}))							MakeRequest(t, req, http.StatusUnauthorized) 							req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{})).								AddBasicAuth(user.Name)							MakeRequest(t, req, http.StatusBadRequest) 							req = NewRequestWithBody(t, "PUT", uploadURL, createArchive("", "", "")).								AddBasicAuth(user.Name)							MakeRequest(t, req, http.StatusBadRequest) 							req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture)).								AddBasicAuth(user.Name)							MakeRequest(t, req, http.StatusCreated) 							pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeDebian, packageName, packageVersion)							require.NoError(t, err) 							pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)							require.NoError(t, err)							assert.Nil(t, pd.SemVer)							assert.IsType(t, &debian_module.Metadata{}, pd.Metadata)							assert.Equal(t, packageName, pd.Package.Name)							assert.Equal(t, packageVersion, pd.Version.Version) 							pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pv.ID)							require.NoError(t, err)							assert.NotEmpty(t, pfs)							assert.Condition(t, func() bool {								seen := false								expectedFilename := fmt.Sprintf("%s_%s_%s.deb", packageName, packageVersion, architecture)								expectedCompositeKey := fmt.Sprintf("%s|%s", distribution, component)								for _, pf := range pfs {									if pf.Name == expectedFilename && pf.CompositeKey == expectedCompositeKey {										if seen {											return false										}										seen = true 										assert.True(t, pf.IsLead) 										pfps, err := packages.GetProperties(db.DefaultContext, packages.PropertyTypeFile, pf.ID)										require.NoError(t, err) 										for _, pfp := range pfps {											switch pfp.Name {											case debian_module.PropertyDistribution:												assert.Equal(t, distribution, pfp.Value)											case debian_module.PropertyComponent:												assert.Equal(t, component, pfp.Value)											case debian_module.PropertyArchitecture:												assert.Equal(t, architecture, pfp.Value)											}										}									}								}								return seen							}) 							req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture)).								AddBasicAuth(user.Name)							MakeRequest(t, req, http.StatusConflict)						}) 						t.Run("Download", func(t *testing.T) {							defer tests.PrintCurrentTest(t)() 							req := NewRequest(t, "GET", fmt.Sprintf("%s/pool/%s/%s/%s_%s_%s.deb", rootURL, distribution, component, packageName, packageVersion, architecture))							resp := MakeRequest(t, req, http.StatusOK) 							assert.Equal(t, "application/vnd.debian.binary-package", resp.Header().Get("Content-Type"))						}) 						t.Run("Packages", func(t *testing.T) {							defer tests.PrintCurrentTest(t)() 							req := NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion2, architecture)).								AddBasicAuth(user.Name)							MakeRequest(t, req, http.StatusCreated) 							url := fmt.Sprintf("%s/dists/%s/%s/binary-%s/Packages", rootURL, distribution, component, architecture) 							req = NewRequest(t, "GET", url)							resp := MakeRequest(t, req, http.StatusOK) 							body := resp.Body.String() 							assert.Contains(t, body, "Package: "+packageName+"\n")							assert.Contains(t, body, "Version: "+packageVersion+"\n")							assert.Contains(t, body, "Version: "+packageVersion2+"\n")							assert.Contains(t, body, "Architecture: "+architecture+"\n")							assert.Contains(t, body, fmt.Sprintf("Filename: pool/%s/%s/%s_%s_%s.deb\n", distribution, component, packageName, packageVersion, architecture))							assert.Contains(t, body, fmt.Sprintf("Filename: pool/%s/%s/%s_%s_%s.deb\n", distribution, component, packageName, packageVersion2, architecture)) 							req = NewRequest(t, "GET", url+".gz")							MakeRequest(t, req, http.StatusOK) 							req = NewRequest(t, "GET", url+".xz")							MakeRequest(t, req, http.StatusOK) 							url = fmt.Sprintf("%s/dists/%s/%s/%s/by-hash/SHA256/%s", rootURL, distribution, component, architecture, base.EncodeSha256(body))							req = NewRequest(t, "GET", url)							resp = MakeRequest(t, req, http.StatusOK) 							assert.Equal(t, body, resp.Body.String())						})					})				}			} 			t.Run("Release", func(t *testing.T) {				defer tests.PrintCurrentTest(t)() 				req := NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release", rootURL, distribution))				resp := MakeRequest(t, req, http.StatusOK) 				body := resp.Body.String() 				assert.Contains(t, body, "Components: "+strings.Join(components, " ")+"\n")				assert.Contains(t, body, "Architectures: "+strings.Join(architectures, " ")+"\n") 				for _, component := range components {					for _, architecture := range architectures {						assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages\n", component, architecture))						assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages.gz\n", component, architecture))						assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages.xz\n", component, architecture))					}				} 				req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/by-hash/SHA256/%s", rootURL, distribution, base.EncodeSha256(body)))				resp = MakeRequest(t, req, http.StatusOK) 				assert.Equal(t, body, resp.Body.String()) 				req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release.gpg", rootURL, distribution))				resp = MakeRequest(t, req, http.StatusOK) 				assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNATURE-----") 				req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/InRelease", rootURL, distribution))				resp = MakeRequest(t, req, http.StatusOK) 				assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNED MESSAGE-----")			})		})	} 	t.Run("Delete", func(t *testing.T) {		defer tests.PrintCurrentTest(t)() 		distribution := distributions[0]		architecture := architectures[0] 		for _, component := range components {			req := NewRequest(t, "DELETE", fmt.Sprintf("%s/pool/%s/%s/%s/%s/%s", rootURL, distribution, component, packageName, packageVersion, architecture))			MakeRequest(t, req, http.StatusUnauthorized) 			req = NewRequest(t, "DELETE", fmt.Sprintf("%s/pool/%s/%s/%s/%s/%s", rootURL, distribution, component, packageName, packageVersion, architecture)).				AddBasicAuth(user.Name)			MakeRequest(t, req, http.StatusNoContent) 			req = NewRequest(t, "DELETE", fmt.Sprintf("%s/pool/%s/%s/%s/%s/%s", rootURL, distribution, component, packageName, packageVersion2, architecture)).				AddBasicAuth(user.Name)			MakeRequest(t, req, http.StatusNoContent) 			req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/%s/binary-%s/Packages", rootURL, distribution, component, architecture))			MakeRequest(t, req, http.StatusNotFound)		} 		req := NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release", rootURL, distribution))		resp := MakeRequest(t, req, http.StatusOK) 		body := resp.Body.String() 		assert.Contains(t, body, "Components: "+strings.Join(components, " ")+"\n")		assert.Contains(t, body, "Architectures: "+architectures[1]+"\n")	})}