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 }