2022-03-30 10:42:47 +02:00
// Copyright 2021 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2022-03-30 10:42:47 +02:00
2022-09-02 15:18:23 -04:00
package integration
2022-03-30 10:42:47 +02:00
import (
2024-06-17 16:42:46 +08:00
"archive/tar"
2022-03-30 10:42:47 +02:00
"bytes"
2024-06-17 16:42:46 +08:00
"compress/gzip"
"crypto/sha256"
"crypto/sha512"
2022-03-30 10:42:47 +02:00
"encoding/base64"
"fmt"
"mime/multipart"
"net/http"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/packages/rubygems"
2022-09-02 15:18:23 -04:00
"code.gitea.io/gitea/tests"
2022-03-30 10:42:47 +02:00
"github.com/stretchr/testify/assert"
)
2024-06-17 16:42:46 +08:00
type tarFile struct {
Name string
Data [ ] byte
}
func makeArchiveFileTar ( files [ ] * tarFile ) [ ] byte {
buf := new ( bytes . Buffer )
tarWriter := tar . NewWriter ( buf )
for _ , file := range files {
_ = tarWriter . WriteHeader ( & tar . Header {
Typeflag : tar . TypeReg ,
Name : file . Name ,
Mode : 0 o644 ,
Size : int64 ( len ( file . Data ) ) ,
} )
_ , _ = tarWriter . Write ( file . Data )
}
_ = tarWriter . Close ( )
return buf . Bytes ( )
}
func makeArchiveFileGz ( data [ ] byte ) [ ] byte {
buf := new ( bytes . Buffer )
gzWriter , _ := gzip . NewWriterLevel ( buf , gzip . NoCompression )
_ , _ = gzWriter . Write ( data )
_ = gzWriter . Close ( )
return buf . Bytes ( )
}
func makeRubyGem ( name , version string ) [ ] byte {
metadataContent := fmt . Sprintf ( ` -- - ! ruby / object : Gem : : Specification
name : % s
version : ! ruby / object : Gem : : Version
version : % s
platform : ruby
authors :
- Gitea
autorequire :
bindir : bin
cert_chain : [ ]
date : 2021 - 0 8 - 23 00 : 00 : 00.000000000 Z
dependencies :
- ! ruby / object : Gem : : Dependency
name : runtime - dep
requirement : ! ruby / object : Gem : : Requirement
requirements :
- - ">="
- ! ruby / object : Gem : : Version
version : 1.2 .0
- - "<"
- ! ruby / object : Gem : : Version
version : ' 2.0 '
type : : runtime
prerelease : false
version_requirements : ! ruby / object : Gem : : Requirement
requirements :
- - ">="
- ! ruby / object : Gem : : Version
version : 1.2 .0
- - "<"
- ! ruby / object : Gem : : Version
version : ' 2.0 '
- ! ruby / object : Gem : : Dependency
name : dev - dep
requirement : ! ruby / object : Gem : : Requirement
requirements :
- - "~>"
- ! ruby / object : Gem : : Version
version : ' 5.2 '
type : : development
prerelease : false
version_requirements : ! ruby / object : Gem : : Requirement
requirements :
- - "~>"
- ! ruby / object : Gem : : Version
version : ' 5.2 '
description : RubyGems package test
email : rubygems @ gitea . io
executables : [ ]
extensions : [ ]
extra_rdoc_files : [ ]
files :
- lib / gitea . rb
homepage : https : //gitea.io/
licenses :
- MIT
metadata : { }
post_install_message :
rdoc_options : [ ]
require_paths :
- lib
required_ruby_version : ! ruby / object : Gem : : Requirement
requirements :
- - ">="
- ! ruby / object : Gem : : Version
version : 2.3 .0
required_rubygems_version : ! ruby / object : Gem : : Requirement
requirements :
- - ">="
- ! ruby / object : Gem : : Version
version : ' 1.0 '
requirements : [ ]
rubyforge_project :
rubygems_version : 2.7 .6 .2
signing_key :
specification_version : 4
summary : Gitea package
test_files : [ ]
` , name , version )
metadataGz := makeArchiveFileGz ( [ ] byte ( metadataContent ) )
dataTarGz := makeArchiveFileGz ( makeArchiveFileTar ( [ ] * tarFile {
{
Name : "lib/gitea.rb" ,
Data : [ ] byte ( "class Gitea\nend" ) ,
} ,
} ) )
checksumsYaml := fmt . Sprintf ( ` -- -
SHA256 :
metadata . gz : % x
data . tar . gz : % x
SHA512 :
metadata . gz : % x
data . tar . gz : % x
` , sha256 . Sum256 ( metadataGz ) , sha256 . Sum256 ( dataTarGz ) , sha512 . Sum512 ( metadataGz ) , sha512 . Sum512 ( dataTarGz ) )
files := [ ] * tarFile {
{
Name : "data.tar.gz" ,
Data : dataTarGz ,
} ,
{
Name : "metadata.gz" ,
Data : metadataGz ,
} ,
{
Name : "checksums.yaml.gz" ,
Data : makeArchiveFileGz ( [ ] byte ( checksumsYaml ) ) ,
} ,
}
return makeArchiveFileTar ( files )
}
2022-03-30 10:42:47 +02:00
func TestPackageRubyGems ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2023-02-23 15:11:56 +01:00
2022-08-16 10:22:25 +08:00
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
testGemName := "gitea"
testGemVersion := "1.0.5"
testGemContent := makeRubyGem ( testGemName , testGemVersion )
testGemContentChecksum := fmt . Sprintf ( "%x" , sha256 . Sum256 ( testGemContent ) )
testAnotherGemName := "gitea-another"
testAnotherGemVersion := "0.99"
2022-03-30 10:42:47 +02:00
root := fmt . Sprintf ( "/api/packages/%s/rubygems" , user . Name )
2024-06-17 16:42:46 +08:00
uploadFile := func ( t * testing . T , content [ ] byte , expectedStatus int ) {
req := NewRequestWithBody ( t , "POST" , fmt . Sprintf ( "%s/api/v1/gems" , root ) , bytes . NewReader ( content ) ) .
2023-12-22 00:59:59 +01:00
AddBasicAuth ( user . Name )
2022-03-30 10:42:47 +02:00
MakeRequest ( t , req , expectedStatus )
}
t . Run ( "Upload" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
uploadFile ( t , testGemContent , http . StatusCreated )
2022-03-30 10:42:47 +02:00
pvs , err := packages . GetVersionsByPackageType ( db . DefaultContext , user . ID , packages . TypeRubyGems )
assert . NoError ( t , err )
assert . Len ( t , pvs , 1 )
pd , err := packages . GetPackageDescriptor ( db . DefaultContext , pvs [ 0 ] )
assert . NoError ( t , err )
assert . NotNil ( t , pd . SemVer )
assert . IsType ( t , & rubygems . Metadata { } , pd . Metadata )
2024-06-17 16:42:46 +08:00
assert . Equal ( t , testGemName , pd . Package . Name )
assert . Equal ( t , testGemVersion , pd . Version . Version )
2022-03-30 10:42:47 +02:00
pfs , err := packages . GetFilesByVersionID ( db . DefaultContext , pvs [ 0 ] . ID )
assert . NoError ( t , err )
assert . Len ( t , pfs , 1 )
2024-06-17 16:42:46 +08:00
assert . Equal ( t , fmt . Sprintf ( "%s-%s.gem" , testGemName , testGemVersion ) , pfs [ 0 ] . Name )
2022-03-30 10:42:47 +02:00
assert . True ( t , pfs [ 0 ] . IsLead )
pb , err := packages . GetBlobByID ( db . DefaultContext , pfs [ 0 ] . BlobID )
assert . NoError ( t , err )
2024-06-17 16:42:46 +08:00
assert . EqualValues ( t , len ( testGemContent ) , pb . Size )
2022-03-30 10:42:47 +02:00
} )
t . Run ( "UploadExists" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2024-06-17 16:42:46 +08:00
uploadFile ( t , testGemContent , http . StatusConflict )
2022-03-30 10:42:47 +02:00
} )
t . Run ( "Download" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/gems/%s-%s.gem" , root , testGemName , testGemVersion ) ) .
2023-12-22 00:59:59 +01:00
AddBasicAuth ( user . Name )
2022-03-30 10:42:47 +02:00
resp := MakeRequest ( t , req , http . StatusOK )
2024-06-17 16:42:46 +08:00
assert . Equal ( t , testGemContent , resp . Body . Bytes ( ) )
2022-03-30 10:42:47 +02:00
pvs , err := packages . GetVersionsByPackageType ( db . DefaultContext , user . ID , packages . TypeRubyGems )
assert . NoError ( t , err )
assert . Len ( t , pvs , 1 )
assert . Equal ( t , int64 ( 1 ) , pvs [ 0 ] . DownloadCount )
} )
t . Run ( "DownloadGemspec" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/quick/Marshal.4.8/%s-%s.gemspec.rz" , root , testGemName , testGemVersion ) ) .
2023-12-22 00:59:59 +01:00
AddBasicAuth ( user . Name )
2022-03-30 10:42:47 +02:00
resp := MakeRequest ( t , req , http . StatusOK )
b , _ := base64 . StdEncoding . DecodeString ( ` eJxi4Si1EndPzbWyCi5ITc5My0xOLMnMz2M8zMIRLeGpxGWsZ6RnzGbF5hqSyempxJWeWZKayGbN
EBJqJQjWFZZaVJyZnxfN5qnEZahnoGcKkjTwVBJyB6lUKEhMzk5MTwULGngqcRaVJlWCONEMBp5K
DGAWSKc7zFhPJamg0qRK99TcYphehZLU4hKInFhGSUlBsZW + PtgZepn5 + iDxECRzDUDGcfh6hoA4
gAAAAP //MS06Gw==`)
assert . Equal ( t , b , resp . Body . Bytes ( ) )
pvs , err := packages . GetVersionsByPackageType ( db . DefaultContext , user . ID , packages . TypeRubyGems )
assert . NoError ( t , err )
assert . Len ( t , pvs , 1 )
assert . Equal ( t , int64 ( 1 ) , pvs [ 0 ] . DownloadCount )
} )
t . Run ( "EnumeratePackages" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2022-03-30 10:42:47 +02:00
enumeratePackages := func ( t * testing . T , endpoint string , expectedContent [ ] byte ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/%s" , root , endpoint ) ) .
AddBasicAuth ( user . Name )
2022-03-30 10:42:47 +02:00
resp := MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , expectedContent , resp . Body . Bytes ( ) )
}
b , _ := base64 . StdEncoding . DecodeString ( ` H4sICAAAAAAA/3NwZWNzLjQuOABi4Yhmi+bwVOJKzyxJTWSzYnMNCbUSdE/NtbIKSy0qzszPi2bzVOIy1DPQM2WzZgjxVOIsKk2qBDEBAQAA///xOEYKOwAAAA== ` )
enumeratePackages ( t , "specs.4.8.gz" , b )
b , _ = base64 . StdEncoding . DecodeString ( ` H4sICAAAAAAA/2xhdGVzdF9zcGVjcy40LjgAYuGIZovm8FTiSs8sSU1ks2JzDQm1EnRPzbWyCkstKs7Mz4tm81TiMtQz0DNls2YI8VTiLCpNqgQxAQEAAP//8ThGCjsAAAA= ` )
enumeratePackages ( t , "latest_specs.4.8.gz" , b )
b , _ = base64 . StdEncoding . DecodeString ( ` H4sICAAAAAAA/3ByZXJlbGVhc2Vfc3BlY3MuNC44AGLhiGYABAAA//9snXr5BAAAAA== ` )
enumeratePackages ( t , "prerelease_specs.4.8.gz" , b )
} )
2024-06-17 16:42:46 +08:00
t . Run ( "UploadAnother" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
uploadFile ( t , makeRubyGem ( testAnotherGemName , testAnotherGemVersion ) , http . StatusCreated )
} )
t . Run ( "PackageInfo" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/info/%s" , root , testGemName ) ) . AddBasicAuth ( user . Name )
resp := MakeRequest ( t , req , http . StatusOK )
expected := fmt . Sprintf ( ` -- -
1.0 .5 runtime - dep : >= 1.2 .0 & < 2.0 | checksum : % s , ruby : >= 2.3 .0 , rubygems : >= 1.0
` , testGemContentChecksum )
assert . Equal ( t , expected , resp . Body . String ( ) )
} )
t . Run ( "Versions" , func ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrintCurrentTest ( t ) ( )
2024-06-17 16:42:46 +08:00
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/versions" , root ) ) . AddBasicAuth ( user . Name )
resp := MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , ` -- -
gitea 1.0 .5 0 8843 c2dd0ea19910e6b056b98e38f1c
gitea - another 0.99 8 b639e4048d282941485368ec42609be
` , resp . Body . String ( ) )
} )
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
deleteGemPackage := func ( t * testing . T , packageName , packageVersion string ) {
2022-03-30 10:42:47 +02:00
body := bytes . Buffer { }
writer := multipart . NewWriter ( & body )
2024-06-17 16:42:46 +08:00
_ = writer . WriteField ( "gem_name" , packageName )
_ = writer . WriteField ( "version" , packageVersion )
_ = writer . Close ( )
2023-12-22 00:59:59 +01:00
req := NewRequestWithBody ( t , "DELETE" , fmt . Sprintf ( "%s/api/v1/gems/yank" , root ) , & body ) .
SetHeader ( "Content-Type" , writer . FormDataContentType ( ) ) .
AddBasicAuth ( user . Name )
2022-03-30 10:42:47 +02:00
MakeRequest ( t , req , http . StatusOK )
2024-06-17 16:42:46 +08:00
}
2022-03-30 10:42:47 +02:00
2024-06-17 16:42:46 +08:00
t . Run ( "DeleteAll" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
deleteGemPackage ( t , testGemName , testGemVersion )
deleteGemPackage ( t , testAnotherGemName , testAnotherGemVersion )
2022-03-30 10:42:47 +02:00
pvs , err := packages . GetVersionsByPackageType ( db . DefaultContext , user . ID , packages . TypeRubyGems )
assert . NoError ( t , err )
assert . Empty ( t , pvs )
} )
2024-06-17 16:42:46 +08:00
t . Run ( "PackageInfoAfterDelete" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/info/%s" , root , testGemName ) ) . AddBasicAuth ( user . Name )
MakeRequest ( t , req , http . StatusNotFound )
} )
t . Run ( "VersionsAfterDelete" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/versions" , root ) ) . AddBasicAuth ( user . Name )
resp := MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , "---\n" , resp . Body . String ( ) )
} )
2022-03-30 10:42:47 +02:00
}