code.gitea.io/gitea@v1.21.7/tests/integration/api_packages_swift_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/zip"
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"mime/multipart"
    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  	swift_module "code.gitea.io/gitea/modules/packages/swift"
    21  	"code.gitea.io/gitea/modules/setting"
    22  	swift_router "code.gitea.io/gitea/routers/api/packages/swift"
    23  	"code.gitea.io/gitea/tests"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func TestPackageSwift(t *testing.T) {
    29  	defer tests.PrepareTestEnv(t)()
    30  
    31  	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
    32  
    33  	packageScope := "test-scope"
    34  	packageName := "test_package"
    35  	packageID := packageScope + "." + packageName
    36  	packageVersion := "1.0.3"
    37  	packageAuthor := "KN4CK3R"
    38  	packageDescription := "Gitea Test Package"
    39  	packageRepositoryURL := "https://gitea.io/gitea/gitea"
    40  	contentManifest1 := "// swift-tools-version:5.7\n//\n//  Package.swift"
    41  	contentManifest2 := "// swift-tools-version:5.6\n//\n//  Package@swift-5.6.swift"
    42  
    43  	url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
    44  
    45  	t.Run("CheckAcceptMediaType", func(t *testing.T) {
    46  		defer tests.PrintCurrentTest(t)()
    47  
    48  		for _, sub := range []string{
    49  			"/scope/package",
    50  			"/scope/package.json",
    51  			"/scope/package/1.0.0",
    52  			"/scope/package/1.0.0.json",
    53  			"/scope/package/1.0.0.zip",
    54  			"/scope/package/1.0.0/Package.swift",
    55  			"/identifiers",
    56  		} {
    57  			req := NewRequest(t, "GET", url+sub)
    58  			req.Header.Add("Accept", "application/unknown")
    59  			resp := MakeRequest(t, req, http.StatusBadRequest)
    60  
    61  			assert.Equal(t, "1", resp.Header().Get("Content-Version"))
    62  			assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
    63  		}
    64  
    65  		req := NewRequestWithBody(t, "PUT", url+"/scope/package/1.0.0", strings.NewReader(""))
    66  		req = AddBasicAuthHeader(req, user.Name)
    67  		req.Header.Add("Accept", "application/unknown")
    68  		resp := MakeRequest(t, req, http.StatusBadRequest)
    69  
    70  		assert.Equal(t, "1", resp.Header().Get("Content-Version"))
    71  		assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
    72  	})
    73  
    74  	t.Run("Upload", func(t *testing.T) {
    75  		defer tests.PrintCurrentTest(t)()
    76  
    77  		uploadPackage := func(t *testing.T, url string, expectedStatus int, sr io.Reader, metadata string) {
    78  			var body bytes.Buffer
    79  			mpw := multipart.NewWriter(&body)
    80  
    81  			part, _ := mpw.CreateFormFile("source-archive", "source-archive.zip")
    82  			io.Copy(part, sr)
    83  
    84  			if metadata != "" {
    85  				mpw.WriteField("metadata", metadata)
    86  			}
    87  
    88  			mpw.Close()
    89  
    90  			req := NewRequestWithBody(t, "PUT", url, &body)
    91  			req.Header.Add("Content-Type", mpw.FormDataContentType())
    92  			req.Header.Add("Accept", swift_router.AcceptJSON)
    93  			req = AddBasicAuthHeader(req, user.Name)
    94  			MakeRequest(t, req, expectedStatus)
    95  		}
    96  
    97  		createArchive := func(files map[string]string) *bytes.Buffer {
    98  			var buf bytes.Buffer
    99  			zw := zip.NewWriter(&buf)
   100  			for filename, content := range files {
   101  				w, _ := zw.Create(filename)
   102  				w.Write([]byte(content))
   103  			}
   104  			zw.Close()
   105  			return &buf
   106  		}
   107  
   108  		for _, triple := range []string{"/sc_ope/package/1.0.0", "/scope/pack~age/1.0.0", "/scope/package/1_0.0"} {
   109  			req := NewRequestWithBody(t, "PUT", url+triple, bytes.NewReader([]byte{}))
   110  			req = AddBasicAuthHeader(req, user.Name)
   111  			resp := MakeRequest(t, req, http.StatusBadRequest)
   112  
   113  			assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   114  			assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
   115  		}
   116  
   117  		uploadURL := fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion)
   118  
   119  		req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{}))
   120  		MakeRequest(t, req, http.StatusUnauthorized)
   121  
   122  		uploadPackage(
   123  			t,
   124  			uploadURL,
   125  			http.StatusCreated,
   126  			createArchive(map[string]string{
   127  				"Package.swift":           contentManifest1,
   128  				"Package@swift-5.6.swift": contentManifest2,
   129  			}),
   130  			`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`,
   131  		)
   132  
   133  		pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeSwift)
   134  		assert.NoError(t, err)
   135  		assert.Len(t, pvs, 1)
   136  
   137  		pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
   138  		assert.NoError(t, err)
   139  		assert.NotNil(t, pd.SemVer)
   140  		assert.Equal(t, packageID, pd.Package.Name)
   141  		assert.Equal(t, packageVersion, pd.Version.Version)
   142  		assert.IsType(t, &swift_module.Metadata{}, pd.Metadata)
   143  		metadata := pd.Metadata.(*swift_module.Metadata)
   144  		assert.Equal(t, packageDescription, metadata.Description)
   145  		assert.Len(t, metadata.Manifests, 2)
   146  		assert.Equal(t, contentManifest1, metadata.Manifests[""].Content)
   147  		assert.Equal(t, contentManifest2, metadata.Manifests["5.6"].Content)
   148  		assert.Len(t, pd.VersionProperties, 1)
   149  		assert.Equal(t, packageRepositoryURL, pd.VersionProperties.GetByName(swift_module.PropertyRepositoryURL))
   150  
   151  		pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
   152  		assert.NoError(t, err)
   153  		assert.Len(t, pfs, 1)
   154  		assert.Equal(t, fmt.Sprintf("%s-%s.zip", packageName, packageVersion), pfs[0].Name)
   155  		assert.True(t, pfs[0].IsLead)
   156  
   157  		uploadPackage(
   158  			t,
   159  			uploadURL,
   160  			http.StatusConflict,
   161  			createArchive(map[string]string{
   162  				"Package.swift": contentManifest1,
   163  			}),
   164  			"",
   165  		)
   166  	})
   167  
   168  	t.Run("Download", func(t *testing.T) {
   169  		defer tests.PrintCurrentTest(t)()
   170  
   171  		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.zip", url, packageScope, packageName, packageVersion))
   172  		req = AddBasicAuthHeader(req, user.Name)
   173  		req.Header.Add("Accept", swift_router.AcceptZip)
   174  		resp := MakeRequest(t, req, http.StatusOK)
   175  
   176  		assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   177  		assert.Equal(t, "application/zip", resp.Header().Get("Content-Type"))
   178  
   179  		pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion)
   180  		assert.NotNil(t, pv)
   181  		assert.NoError(t, err)
   182  
   183  		pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)
   184  		assert.NoError(t, err)
   185  		assert.Equal(t, "sha256="+pd.Files[0].Blob.HashSHA256, resp.Header().Get("Digest"))
   186  	})
   187  
   188  	t.Run("EnumeratePackageVersions", func(t *testing.T) {
   189  		defer tests.PrintCurrentTest(t)()
   190  
   191  		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", url, packageScope, packageName))
   192  		req = AddBasicAuthHeader(req, user.Name)
   193  		req.Header.Add("Accept", swift_router.AcceptJSON)
   194  		resp := MakeRequest(t, req, http.StatusOK)
   195  
   196  		versionURL := setting.AppURL + url[1:] + fmt.Sprintf("/%s/%s/%s", packageScope, packageName, packageVersion)
   197  
   198  		assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   199  		assert.Equal(t, fmt.Sprintf(`<%s>; rel="latest-version"`, versionURL), resp.Header().Get("Link"))
   200  
   201  		body := resp.Body.String()
   202  
   203  		var result *swift_router.EnumeratePackageVersionsResponse
   204  		DecodeJSON(t, resp, &result)
   205  
   206  		assert.Len(t, result.Releases, 1)
   207  		assert.Contains(t, result.Releases, packageVersion)
   208  		assert.Equal(t, versionURL, result.Releases[packageVersion].URL)
   209  
   210  		req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s.json", url, packageScope, packageName))
   211  		req = AddBasicAuthHeader(req, user.Name)
   212  		resp = MakeRequest(t, req, http.StatusOK)
   213  
   214  		assert.Equal(t, body, resp.Body.String())
   215  	})
   216  
   217  	t.Run("PackageVersionMetadata", func(t *testing.T) {
   218  		defer tests.PrintCurrentTest(t)()
   219  
   220  		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion))
   221  		req = AddBasicAuthHeader(req, user.Name)
   222  		req.Header.Add("Accept", swift_router.AcceptJSON)
   223  		resp := MakeRequest(t, req, http.StatusOK)
   224  
   225  		assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   226  
   227  		body := resp.Body.String()
   228  
   229  		var result *swift_router.PackageVersionMetadataResponse
   230  		DecodeJSON(t, resp, &result)
   231  
   232  		pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion)
   233  		assert.NotNil(t, pv)
   234  		assert.NoError(t, err)
   235  
   236  		pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)
   237  		assert.NoError(t, err)
   238  
   239  		assert.Equal(t, packageID, result.ID)
   240  		assert.Equal(t, packageVersion, result.Version)
   241  		assert.Len(t, result.Resources, 1)
   242  		assert.Equal(t, "source-archive", result.Resources[0].Name)
   243  		assert.Equal(t, "application/zip", result.Resources[0].Type)
   244  		assert.Equal(t, pd.Files[0].Blob.HashSHA256, result.Resources[0].Checksum)
   245  		assert.Equal(t, "SoftwareSourceCode", result.Metadata.Type)
   246  		assert.Equal(t, packageName, result.Metadata.Name)
   247  		assert.Equal(t, packageVersion, result.Metadata.Version)
   248  		assert.Equal(t, packageDescription, result.Metadata.Description)
   249  		assert.Equal(t, "Swift", result.Metadata.ProgrammingLanguage.Name)
   250  		assert.Equal(t, packageAuthor, result.Metadata.Author.GivenName)
   251  
   252  		req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.json", url, packageScope, packageName, packageVersion))
   253  		req = AddBasicAuthHeader(req, user.Name)
   254  		resp = MakeRequest(t, req, http.StatusOK)
   255  
   256  		assert.Equal(t, body, resp.Body.String())
   257  	})
   258  
   259  	t.Run("DownloadManifest", func(t *testing.T) {
   260  		manifestURL := fmt.Sprintf("%s/%s/%s/%s/Package.swift", url, packageScope, packageName, packageVersion)
   261  
   262  		t.Run("Default", func(t *testing.T) {
   263  			defer tests.PrintCurrentTest(t)()
   264  
   265  			req := NewRequest(t, "GET", manifestURL)
   266  			req = AddBasicAuthHeader(req, user.Name)
   267  			req.Header.Add("Accept", swift_router.AcceptSwift)
   268  			resp := MakeRequest(t, req, http.StatusOK)
   269  
   270  			assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   271  			assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type"))
   272  			assert.Equal(t, contentManifest1, resp.Body.String())
   273  		})
   274  
   275  		t.Run("DifferentVersion", func(t *testing.T) {
   276  			defer tests.PrintCurrentTest(t)()
   277  
   278  			req := NewRequest(t, "GET", manifestURL+"?swift-version=5.6")
   279  			req = AddBasicAuthHeader(req, user.Name)
   280  			resp := MakeRequest(t, req, http.StatusOK)
   281  
   282  			assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   283  			assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type"))
   284  			assert.Equal(t, contentManifest2, resp.Body.String())
   285  
   286  			req = NewRequest(t, "GET", manifestURL+"?swift-version=5.6.0")
   287  			req = AddBasicAuthHeader(req, user.Name)
   288  			MakeRequest(t, req, http.StatusOK)
   289  		})
   290  
   291  		t.Run("Redirect", func(t *testing.T) {
   292  			defer tests.PrintCurrentTest(t)()
   293  
   294  			req := NewRequest(t, "GET", manifestURL+"?swift-version=1.0")
   295  			req = AddBasicAuthHeader(req, user.Name)
   296  			resp := MakeRequest(t, req, http.StatusSeeOther)
   297  
   298  			assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   299  			assert.Equal(t, setting.AppURL+url[1:]+fmt.Sprintf("/%s/%s/%s/Package.swift", packageScope, packageName, packageVersion), resp.Header().Get("Location"))
   300  		})
   301  	})
   302  
   303  	t.Run("LookupPackageIdentifiers", func(t *testing.T) {
   304  		defer tests.PrintCurrentTest(t)()
   305  
   306  		req := NewRequest(t, "GET", url+"/identifiers")
   307  		req.Header.Add("Accept", swift_router.AcceptJSON)
   308  		resp := MakeRequest(t, req, http.StatusBadRequest)
   309  
   310  		assert.Equal(t, "1", resp.Header().Get("Content-Version"))
   311  		assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
   312  
   313  		req = NewRequest(t, "GET", url+"/identifiers?url=https://unknown.host/")
   314  		MakeRequest(t, req, http.StatusNotFound)
   315  
   316  		req = NewRequest(t, "GET", url+"/identifiers?url="+packageRepositoryURL)
   317  		req.Header.Add("Accept", swift_router.AcceptJSON)
   318  		resp = MakeRequest(t, req, http.StatusOK)
   319  
   320  		var result *swift_router.LookupPackageIdentifiersResponse
   321  		DecodeJSON(t, resp, &result)
   322  
   323  		assert.Len(t, result.Identifiers, 1)
   324  		assert.Equal(t, packageID, result.Identifiers[0])
   325  	})
   326  }