code.gitea.io/gitea@v1.21.7/tests/integration/api_packages_debian_test.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "archive/tar" 8 "bytes" 9 "compress/gzip" 10 "fmt" 11 "io" 12 "net/http" 13 "strings" 14 "testing" 15 16 "code.gitea.io/gitea/models/db" 17 "code.gitea.io/gitea/models/packages" 18 "code.gitea.io/gitea/models/unittest" 19 user_model "code.gitea.io/gitea/models/user" 20 "code.gitea.io/gitea/modules/base" 21 debian_module "code.gitea.io/gitea/modules/packages/debian" 22 "code.gitea.io/gitea/tests" 23 24 "github.com/blakesmith/ar" 25 "github.com/stretchr/testify/assert" 26 ) 27 28 func TestPackageDebian(t *testing.T) { 29 defer tests.PrepareTestEnv(t)() 30 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 31 32 packageName := "gitea" 33 packageVersion := "1.0.3" 34 packageDescription := "Package Description" 35 36 createArchive := func(name, version, architecture string) io.Reader { 37 var cbuf bytes.Buffer 38 zw := gzip.NewWriter(&cbuf) 39 tw := tar.NewWriter(zw) 40 tw.WriteHeader(&tar.Header{ 41 Name: "control", 42 Mode: 0o600, 43 Size: 50, 44 }) 45 fmt.Fprintf(tw, "Package: %s\nVersion: %s\nArchitecture: %s\nDescription: %s\n", name, version, architecture, packageDescription) 46 tw.Close() 47 zw.Close() 48 49 var buf bytes.Buffer 50 aw := ar.NewWriter(&buf) 51 aw.WriteGlobalHeader() 52 hdr := &ar.Header{ 53 Name: "control.tar.gz", 54 Mode: 0o600, 55 Size: int64(cbuf.Len()), 56 } 57 aw.WriteHeader(hdr) 58 aw.Write(cbuf.Bytes()) 59 return &buf 60 } 61 62 distributions := []string{"test", "gitea"} 63 components := []string{"main", "stable"} 64 architectures := []string{"all", "amd64"} 65 66 rootURL := fmt.Sprintf("/api/packages/%s/debian", user.Name) 67 68 t.Run("RepositoryKey", func(t *testing.T) { 69 defer tests.PrintCurrentTest(t)() 70 71 req := NewRequest(t, "GET", rootURL+"/repository.key") 72 resp := MakeRequest(t, req, http.StatusOK) 73 74 assert.Equal(t, "application/pgp-keys", resp.Header().Get("Content-Type")) 75 assert.Contains(t, resp.Body.String(), "-----BEGIN PGP PUBLIC KEY BLOCK-----") 76 }) 77 78 for _, distribution := range distributions { 79 t.Run(fmt.Sprintf("[Distribution:%s]", distribution), func(t *testing.T) { 80 for _, component := range components { 81 for _, architecture := range architectures { 82 t.Run(fmt.Sprintf("[Component:%s,Architecture:%s]", component, architecture), func(t *testing.T) { 83 t.Run("Upload", func(t *testing.T) { 84 defer tests.PrintCurrentTest(t)() 85 86 uploadURL := fmt.Sprintf("%s/pool/%s/%s/upload", rootURL, distribution, component) 87 88 req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{})) 89 MakeRequest(t, req, http.StatusUnauthorized) 90 91 req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{})) 92 AddBasicAuthHeader(req, user.Name) 93 MakeRequest(t, req, http.StatusBadRequest) 94 95 req = NewRequestWithBody(t, "PUT", uploadURL, createArchive("", "", "")) 96 AddBasicAuthHeader(req, user.Name) 97 MakeRequest(t, req, http.StatusBadRequest) 98 99 req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture)) 100 AddBasicAuthHeader(req, user.Name) 101 MakeRequest(t, req, http.StatusCreated) 102 103 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeDebian) 104 assert.NoError(t, err) 105 assert.Len(t, pvs, 1) 106 107 pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) 108 assert.NoError(t, err) 109 assert.Nil(t, pd.SemVer) 110 assert.IsType(t, &debian_module.Metadata{}, pd.Metadata) 111 assert.Equal(t, packageName, pd.Package.Name) 112 assert.Equal(t, packageVersion, pd.Version.Version) 113 114 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) 115 assert.NoError(t, err) 116 assert.NotEmpty(t, pfs) 117 assert.Condition(t, func() bool { 118 seen := false 119 expectedFilename := fmt.Sprintf("%s_%s_%s.deb", packageName, packageVersion, architecture) 120 expectedCompositeKey := fmt.Sprintf("%s|%s", distribution, component) 121 for _, pf := range pfs { 122 if pf.Name == expectedFilename && pf.CompositeKey == expectedCompositeKey { 123 if seen { 124 return false 125 } 126 seen = true 127 128 assert.True(t, pf.IsLead) 129 130 pfps, err := packages.GetProperties(db.DefaultContext, packages.PropertyTypeFile, pf.ID) 131 assert.NoError(t, err) 132 133 for _, pfp := range pfps { 134 switch pfp.Name { 135 case debian_module.PropertyDistribution: 136 assert.Equal(t, distribution, pfp.Value) 137 case debian_module.PropertyComponent: 138 assert.Equal(t, component, pfp.Value) 139 case debian_module.PropertyArchitecture: 140 assert.Equal(t, architecture, pfp.Value) 141 } 142 } 143 } 144 } 145 return seen 146 }) 147 148 req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture)) 149 AddBasicAuthHeader(req, user.Name) 150 MakeRequest(t, req, http.StatusBadRequest) 151 }) 152 153 t.Run("Download", func(t *testing.T) { 154 defer tests.PrintCurrentTest(t)() 155 156 req := NewRequest(t, "GET", fmt.Sprintf("%s/pool/%s/%s/%s_%s_%s.deb", rootURL, distribution, component, packageName, packageVersion, architecture)) 157 resp := MakeRequest(t, req, http.StatusOK) 158 159 assert.Equal(t, "application/vnd.debian.binary-package", resp.Header().Get("Content-Type")) 160 }) 161 162 t.Run("Packages", func(t *testing.T) { 163 defer tests.PrintCurrentTest(t)() 164 165 url := fmt.Sprintf("%s/dists/%s/%s/binary-%s/Packages", rootURL, distribution, component, architecture) 166 167 req := NewRequest(t, "GET", url) 168 resp := MakeRequest(t, req, http.StatusOK) 169 170 body := resp.Body.String() 171 172 assert.Contains(t, body, "Package: "+packageName) 173 assert.Contains(t, body, "Version: "+packageVersion) 174 assert.Contains(t, body, "Architecture: "+architecture) 175 assert.Contains(t, body, fmt.Sprintf("Filename: pool/%s/%s/%s_%s_%s.deb", distribution, component, packageName, packageVersion, architecture)) 176 177 req = NewRequest(t, "GET", url+".gz") 178 MakeRequest(t, req, http.StatusOK) 179 180 req = NewRequest(t, "GET", url+".xz") 181 MakeRequest(t, req, http.StatusOK) 182 183 url = fmt.Sprintf("%s/dists/%s/%s/%s/by-hash/SHA256/%s", rootURL, distribution, component, architecture, base.EncodeSha256(body)) 184 req = NewRequest(t, "GET", url) 185 resp = MakeRequest(t, req, http.StatusOK) 186 187 assert.Equal(t, body, resp.Body.String()) 188 }) 189 }) 190 } 191 } 192 193 t.Run("Release", func(t *testing.T) { 194 defer tests.PrintCurrentTest(t)() 195 196 req := NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release", rootURL, distribution)) 197 resp := MakeRequest(t, req, http.StatusOK) 198 199 body := resp.Body.String() 200 201 assert.Contains(t, body, "Components: "+strings.Join(components, " ")) 202 assert.Contains(t, body, "Architectures: "+strings.Join(architectures, " ")) 203 204 for _, component := range components { 205 for _, architecture := range architectures { 206 assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages", component, architecture)) 207 assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages.gz", component, architecture)) 208 assert.Contains(t, body, fmt.Sprintf("%s/binary-%s/Packages.xz", component, architecture)) 209 } 210 } 211 212 req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/by-hash/SHA256/%s", rootURL, distribution, base.EncodeSha256(body))) 213 resp = MakeRequest(t, req, http.StatusOK) 214 215 assert.Equal(t, body, resp.Body.String()) 216 217 req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release.gpg", rootURL, distribution)) 218 resp = MakeRequest(t, req, http.StatusOK) 219 220 assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNATURE-----") 221 222 req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/InRelease", rootURL, distribution)) 223 resp = MakeRequest(t, req, http.StatusOK) 224 225 assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNED MESSAGE-----") 226 }) 227 }) 228 } 229 230 t.Run("Delete", func(t *testing.T) { 231 defer tests.PrintCurrentTest(t)() 232 233 distribution := distributions[0] 234 architecture := architectures[0] 235 236 for _, component := range components { 237 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/pool/%s/%s/%s/%s/%s", rootURL, distribution, component, packageName, packageVersion, architecture)) 238 MakeRequest(t, req, http.StatusUnauthorized) 239 240 req = NewRequest(t, "DELETE", fmt.Sprintf("%s/pool/%s/%s/%s/%s/%s", rootURL, distribution, component, packageName, packageVersion, architecture)) 241 AddBasicAuthHeader(req, user.Name) 242 MakeRequest(t, req, http.StatusNoContent) 243 244 req = NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/%s/binary-%s/Packages", rootURL, distribution, component, architecture)) 245 MakeRequest(t, req, http.StatusNotFound) 246 } 247 248 req := NewRequest(t, "GET", fmt.Sprintf("%s/dists/%s/Release", rootURL, distribution)) 249 resp := MakeRequest(t, req, http.StatusOK) 250 251 body := resp.Body.String() 252 253 assert.Contains(t, body, "Components: "+strings.Join(components, " ")) 254 assert.Contains(t, body, "Architectures: "+architectures[1]) 255 }) 256 }