code.gitea.io/gitea@v1.22.3/modules/packages/debian/metadata_test.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package debian
     5  
     6  import (
     7  	"archive/tar"
     8  	"bytes"
     9  	"compress/gzip"
    10  	"io"
    11  	"testing"
    12  
    13  	"github.com/blakesmith/ar"
    14  	"github.com/klauspost/compress/zstd"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/ulikunitz/xz"
    17  )
    18  
    19  const (
    20  	packageName         = "gitea"
    21  	packageVersion      = "0:1.0.1-te~st"
    22  	packageArchitecture = "amd64"
    23  	packageAuthor       = "KN4CK3R"
    24  	description         = "Description with multiple lines."
    25  	projectURL          = "https://gitea.io"
    26  )
    27  
    28  func TestParsePackage(t *testing.T) {
    29  	createArchive := func(files map[string][]byte) io.Reader {
    30  		var buf bytes.Buffer
    31  		aw := ar.NewWriter(&buf)
    32  		aw.WriteGlobalHeader()
    33  		for filename, content := range files {
    34  			hdr := &ar.Header{
    35  				Name: filename,
    36  				Mode: 0o600,
    37  				Size: int64(len(content)),
    38  			}
    39  			aw.WriteHeader(hdr)
    40  			aw.Write(content)
    41  		}
    42  		return &buf
    43  	}
    44  
    45  	t.Run("MissingControlFile", func(t *testing.T) {
    46  		data := createArchive(map[string][]byte{"dummy.txt": {}})
    47  
    48  		p, err := ParsePackage(data)
    49  		assert.Nil(t, p)
    50  		assert.ErrorIs(t, err, ErrMissingControlFile)
    51  	})
    52  
    53  	t.Run("Compression", func(t *testing.T) {
    54  		t.Run("Unsupported", func(t *testing.T) {
    55  			data := createArchive(map[string][]byte{"control.tar.foo": {}})
    56  
    57  			p, err := ParsePackage(data)
    58  			assert.Nil(t, p)
    59  			assert.ErrorIs(t, err, ErrUnsupportedCompression)
    60  		})
    61  
    62  		var buf bytes.Buffer
    63  		tw := tar.NewWriter(&buf)
    64  		tw.WriteHeader(&tar.Header{
    65  			Name: "control",
    66  			Mode: 0o600,
    67  			Size: 50,
    68  		})
    69  		tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n"))
    70  		tw.Close()
    71  
    72  		cases := []struct {
    73  			Extension     string
    74  			WriterFactory func(io.Writer) io.WriteCloser
    75  		}{
    76  			{
    77  				Extension: "",
    78  				WriterFactory: func(w io.Writer) io.WriteCloser {
    79  					return nopCloser{w}
    80  				},
    81  			},
    82  			{
    83  				Extension: ".gz",
    84  				WriterFactory: func(w io.Writer) io.WriteCloser {
    85  					return gzip.NewWriter(w)
    86  				},
    87  			},
    88  			{
    89  				Extension: ".xz",
    90  				WriterFactory: func(w io.Writer) io.WriteCloser {
    91  					xw, _ := xz.NewWriter(w)
    92  					return xw
    93  				},
    94  			},
    95  			{
    96  				Extension: ".zst",
    97  				WriterFactory: func(w io.Writer) io.WriteCloser {
    98  					zw, _ := zstd.NewWriter(w)
    99  					return zw
   100  				},
   101  			},
   102  		}
   103  
   104  		for _, c := range cases {
   105  			t.Run(c.Extension, func(t *testing.T) {
   106  				var cbuf bytes.Buffer
   107  				w := c.WriterFactory(&cbuf)
   108  				w.Write(buf.Bytes())
   109  				w.Close()
   110  
   111  				data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()})
   112  
   113  				p, err := ParsePackage(data)
   114  				assert.NotNil(t, p)
   115  				assert.NoError(t, err)
   116  				assert.Equal(t, "gitea", p.Name)
   117  
   118  				t.Run("TrailingSlash", func(t *testing.T) {
   119  					data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()})
   120  
   121  					p, err := ParsePackage(data)
   122  					assert.NotNil(t, p)
   123  					assert.NoError(t, err)
   124  					assert.Equal(t, "gitea", p.Name)
   125  				})
   126  			})
   127  		}
   128  	})
   129  }
   130  
   131  type nopCloser struct {
   132  	io.Writer
   133  }
   134  
   135  func (nopCloser) Close() error {
   136  	return nil
   137  }
   138  
   139  func TestParseControlFile(t *testing.T) {
   140  	buildContent := func(name, version, architecture string) *bytes.Buffer {
   141  		var buf bytes.Buffer
   142  		buf.WriteString("Package: " + name + "\nVersion: " + version + "\nArchitecture: " + architecture + "\nMaintainer: " + packageAuthor + " <kn4ck3r@gitea.io>\nHomepage: " + projectURL + "\nDepends: a,\n b\nDescription: Description\n with multiple\n lines.")
   143  		return &buf
   144  	}
   145  
   146  	t.Run("InvalidName", func(t *testing.T) {
   147  		for _, name := range []string{"", "-cd"} {
   148  			p, err := ParseControlFile(buildContent(name, packageVersion, packageArchitecture))
   149  			assert.Nil(t, p)
   150  			assert.ErrorIs(t, err, ErrInvalidName)
   151  		}
   152  	})
   153  
   154  	t.Run("InvalidVersion", func(t *testing.T) {
   155  		for _, version := range []string{"", "1-", ":1.0", "1_0"} {
   156  			p, err := ParseControlFile(buildContent(packageName, version, packageArchitecture))
   157  			assert.Nil(t, p)
   158  			assert.ErrorIs(t, err, ErrInvalidVersion)
   159  		}
   160  	})
   161  
   162  	t.Run("InvalidArchitecture", func(t *testing.T) {
   163  		p, err := ParseControlFile(buildContent(packageName, packageVersion, ""))
   164  		assert.Nil(t, p)
   165  		assert.ErrorIs(t, err, ErrInvalidArchitecture)
   166  	})
   167  
   168  	t.Run("Valid", func(t *testing.T) {
   169  		content := buildContent(packageName, packageVersion, packageArchitecture)
   170  		full := content.String()
   171  
   172  		p, err := ParseControlFile(content)
   173  		assert.NoError(t, err)
   174  		assert.NotNil(t, p)
   175  
   176  		assert.Equal(t, packageName, p.Name)
   177  		assert.Equal(t, packageVersion, p.Version)
   178  		assert.Equal(t, packageArchitecture, p.Architecture)
   179  		assert.Equal(t, description, p.Metadata.Description)
   180  		assert.Equal(t, projectURL, p.Metadata.ProjectURL)
   181  		assert.Equal(t, packageAuthor, p.Metadata.Maintainer)
   182  		assert.Equal(t, []string{"a", "b"}, p.Metadata.Dependencies)
   183  		assert.Equal(t, full, p.Control)
   184  	})
   185  }