test: generate a minimal RPM in pure Go instead of a committed fixture
Removes the committed .rpm binary (gitignored, so it broke clean checkouts) and the rpmbuild dependency. testsupport.MinimalRPM builds a valid-enough RPM header in-memory for cavaliergopher/rpm to parse, used by both the rpm provider test and the full-stack server repodata test.
This commit is contained in:
@@ -7,16 +7,14 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.unkin.net/unkin/artifactapi/internal/provider"
|
||||
"git.unkin.net/unkin/artifactapi/internal/testsupport"
|
||||
"git.unkin.net/unkin/artifactapi/pkg/models"
|
||||
)
|
||||
|
||||
const fixtureRPM = "testdata/e2e-testpkg-1.0-1.noarch.rpm"
|
||||
|
||||
type fakeBlobReader struct{ data []byte }
|
||||
|
||||
func (f fakeBlobReader) Download(_ context.Context, _ string) (io.ReadCloser, int64, error) {
|
||||
@@ -82,10 +80,7 @@ func TestRPMValidateUpload(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRPMAfterUpload(t *testing.T) {
|
||||
data, err := os.ReadFile(fixtureRPM)
|
||||
if err != nil {
|
||||
t.Fatalf("fixture: %v", err)
|
||||
}
|
||||
data := testsupport.MinimalRPM("e2e-testpkg", "1.0", "1", "noarch")
|
||||
store := &fakeMetaStore{}
|
||||
(&Provider{}).AfterUpload(context.Background(), "myrepo", "Packages/e2e-testpkg-1.0-1.noarch.rpm",
|
||||
"sha256:deadbeef", fakeBlobReader{data: data}, store)
|
||||
|
||||
@@ -301,10 +301,7 @@ func TestServerLocalPyPI(t *testing.T) {
|
||||
|
||||
func TestServerLocalRPMRepodata(t *testing.T) {
|
||||
requireStack(t)
|
||||
rpm, err := os.ReadFile("../provider/rpm/testdata/e2e-testpkg-1.0-1.noarch.rpm")
|
||||
if err != nil {
|
||||
t.Skipf("rpm fixture unavailable: %v", err)
|
||||
}
|
||||
rpm := testsupport.MinimalRPM("e2e-testpkg", "1.0", "1", "noarch")
|
||||
if resp, b := req(t, "POST", "/api/v2/remotes", `{"name":"srv-rpm","package_type":"rpm","repo_type":"local"}`); resp.StatusCode != 201 {
|
||||
t.Fatalf("create rpm local: %d %s", resp.StatusCode, b)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package testsupport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// MinimalRPM builds a valid-enough RPM package in pure Go (no committed binary
|
||||
// fixture, no external rpmbuild). It carries just the header tags the provider
|
||||
// reads: name/version/release/arch plus a single self Provides entry, which is
|
||||
// enough for cavaliergopher/rpm to parse and for repodata generation.
|
||||
func MinimalRPM(name, version, release, arch string) []byte {
|
||||
type tag struct {
|
||||
id, typ, count uint32
|
||||
data []byte
|
||||
}
|
||||
cstr := func(s string) []byte { return append([]byte(s), 0) }
|
||||
tags := []tag{
|
||||
{1000, 6, 1, cstr(name)}, // RPMTAG_NAME (STRING)
|
||||
{1001, 6, 1, cstr(version)}, // RPMTAG_VERSION
|
||||
{1002, 6, 1, cstr(release)}, // RPMTAG_RELEASE
|
||||
{1022, 6, 1, cstr(arch)}, // RPMTAG_ARCH
|
||||
{1047, 8, 1, cstr(name)}, // RPMTAG_PROVIDENAME (STRING_ARRAY)
|
||||
{1112, 4, 1, []byte{0, 0, 0, 0}}, // RPMTAG_PROVIDEFLAGS (INT32)
|
||||
{1113, 8, 1, cstr(version)}, // RPMTAG_PROVIDEVERSION (STRING_ARRAY)
|
||||
}
|
||||
|
||||
buildHeader := func(entries []tag) []byte {
|
||||
var index, store bytes.Buffer
|
||||
for _, e := range entries {
|
||||
off := uint32(store.Len())
|
||||
for _, v := range []uint32{e.id, e.typ, off, e.count} {
|
||||
binary.Write(&index, binary.BigEndian, v)
|
||||
}
|
||||
store.Write(e.data)
|
||||
}
|
||||
var b bytes.Buffer
|
||||
b.Write([]byte{0x8e, 0xad, 0xe8, 0x01, 0, 0, 0, 0}) // header magic + reserved
|
||||
binary.Write(&b, binary.BigEndian, uint32(len(entries)))
|
||||
binary.Write(&b, binary.BigEndian, uint32(store.Len()))
|
||||
b.Write(index.Bytes())
|
||||
b.Write(store.Bytes())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
lead := make([]byte, 96)
|
||||
copy(lead[0:4], []byte{0xed, 0xab, 0xee, 0xdb}) // lead magic
|
||||
lead[4] = 3 // major version
|
||||
binary.BigEndian.PutUint16(lead[8:10], 1) // archnum
|
||||
copy(lead[10:76], name) // name (66 bytes, null-padded)
|
||||
binary.BigEndian.PutUint16(lead[76:78], 1) // osnum
|
||||
binary.BigEndian.PutUint16(lead[78:80], 5) // signature type
|
||||
|
||||
var out bytes.Buffer
|
||||
out.Write(lead)
|
||||
out.Write(buildHeader(nil)) // empty signature header (16 bytes, 8-aligned)
|
||||
out.Write(buildHeader(tags))
|
||||
return out.Bytes()
|
||||
}
|
||||
Reference in New Issue
Block a user