add test for the wall app
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
c4776d81dd
commit
9e287e4e6a
15 changed files with 3022 additions and 1 deletions
284
internal/clone/rpm/metadata_gen_test.go
Normal file
284
internal/clone/rpm/metadata_gen_test.go
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
package rpm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// buildPrimaryGz creates a gzipped primary.xml with the given packages.
|
||||
// Each entry is {name, locationHref}.
|
||||
func buildPrimaryGz(t *testing.T, pkgs []struct{ name, href string }) []byte {
|
||||
t.Helper()
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(`<?xml version="1.0" encoding="UTF-8"?>`)
|
||||
fmt.Fprintf(&buf, `<metadata xmlns="http://linux.duke.edu/metadata/common" packages="%d">`, len(pkgs))
|
||||
for _, p := range pkgs {
|
||||
fmt.Fprintf(&buf,
|
||||
`<package type="rpm"><name>%s</name><location href="%s"/></package>`,
|
||||
p.name, p.href)
|
||||
}
|
||||
buf.WriteString(`</metadata>`)
|
||||
|
||||
var gz bytes.Buffer
|
||||
gzw := gzip.NewWriter(&gz)
|
||||
gzw.Write(buf.Bytes())
|
||||
gzw.Close()
|
||||
return gz.Bytes()
|
||||
}
|
||||
|
||||
// buildRepoMD creates a minimal repomd.xml pointing to the given primary href.
|
||||
func buildRepoMD(t *testing.T, primaryHref string) []byte {
|
||||
t.Helper()
|
||||
repomd := RepoMD{
|
||||
Data: []RepoMDEntry{{
|
||||
Type: "primary",
|
||||
Location: RepoMDLocation{Href: primaryHref},
|
||||
Checksum: RepoMDChecksum{Type: "sha256", Value: "placeholder"},
|
||||
OpenChecksum: RepoMDChecksum{Type: "sha256", Value: "placeholder"},
|
||||
}},
|
||||
}
|
||||
out, err := xml.MarshalIndent(repomd, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("marshal repomd: %v", err)
|
||||
}
|
||||
return append([]byte(xml.Header), out...)
|
||||
}
|
||||
|
||||
// setupRepo creates a local repo dir with a primary.xml.gz, a .primary-source
|
||||
// marker and a repomd.xml. It creates the given rpm files on disk.
|
||||
func setupRepo(t *testing.T, pkgs []struct{ name, href string }, presentOnDisk []string) string {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
repodata := filepath.Join(dir, "repodata")
|
||||
os.MkdirAll(repodata, 0o755)
|
||||
|
||||
// Upstream primary at a hashed path (mimics real layout).
|
||||
upstreamPrimary := "repodata/upstream-primary.xml.gz"
|
||||
if err := os.WriteFile(filepath.Join(dir, upstreamPrimary), buildPrimaryGz(t, pkgs), 0o644); err != nil {
|
||||
t.Fatalf("write upstream primary: %v", err)
|
||||
}
|
||||
|
||||
// .primary-source marker.
|
||||
if err := os.WriteFile(filepath.Join(repodata, PrimarySourceFile), []byte(upstreamPrimary), 0o644); err != nil {
|
||||
t.Fatalf("write .primary-source: %v", err)
|
||||
}
|
||||
|
||||
// repomd.xml pointing at local primary (which doesn't exist yet — regen will create it).
|
||||
if err := os.WriteFile(filepath.Join(repodata, "repomd.xml"), buildRepoMD(t, localPrimaryHref), 0o644); err != nil {
|
||||
t.Fatalf("write repomd.xml: %v", err)
|
||||
}
|
||||
|
||||
// Create selected rpm files on disk.
|
||||
for _, href := range presentOnDisk {
|
||||
dest := filepath.Join(dir, filepath.FromSlash(href))
|
||||
os.MkdirAll(filepath.Dir(dest), 0o755)
|
||||
if err := os.WriteFile(dest, []byte("fake-rpm"), 0o644); err != nil {
|
||||
t.Fatalf("write rpm %s: %v", href, err)
|
||||
}
|
||||
}
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
// parsePrimaryGz decompresses and parses a primary.xml.gz, returning package hrefs.
|
||||
func parsePrimaryGz(t *testing.T, path string) []string {
|
||||
t.Helper()
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read primary.xml.gz: %v", err)
|
||||
}
|
||||
gz, err := gzip.NewReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
t.Fatalf("open gzip: %v", err)
|
||||
}
|
||||
defer gz.Close()
|
||||
var meta filterableMetadata
|
||||
if err := xml.NewDecoder(gz).Decode(&meta); err != nil {
|
||||
t.Fatalf("parse primary.xml: %v", err)
|
||||
}
|
||||
hrefs := make([]string, len(meta.Packages))
|
||||
for i, p := range meta.Packages {
|
||||
hrefs[i] = p.Location.Href
|
||||
}
|
||||
return hrefs
|
||||
}
|
||||
|
||||
// --- InitEmptyRepo ---
|
||||
|
||||
func TestInitEmptyRepo_createsStructure(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := InitEmptyRepo(dir); err != nil {
|
||||
t.Fatalf("InitEmptyRepo: %v", err)
|
||||
}
|
||||
|
||||
for _, path := range []string{
|
||||
filepath.Join(dir, "repodata"),
|
||||
filepath.Join(dir, "Packages"),
|
||||
filepath.Join(dir, "repodata", "repomd.xml"),
|
||||
filepath.Join(dir, localPrimaryHref),
|
||||
} {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
t.Errorf("expected %s to exist: %v", path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitEmptyRepo_repomdIsValid(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
InitEmptyRepo(dir)
|
||||
|
||||
data, _ := os.ReadFile(filepath.Join(dir, "repodata", "repomd.xml"))
|
||||
var repomd RepoMD
|
||||
if err := xml.Unmarshal(data, &repomd); err != nil {
|
||||
t.Fatalf("repomd.xml is not valid XML: %v", err)
|
||||
}
|
||||
if len(repomd.Data) == 0 {
|
||||
t.Error("expected at least one entry in repomd.xml")
|
||||
}
|
||||
if repomd.Data[0].Type != "primary" {
|
||||
t.Errorf("first entry type: got %q, want primary", repomd.Data[0].Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitEmptyRepo_primaryIsEmpty(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
InitEmptyRepo(dir)
|
||||
|
||||
hrefs := parsePrimaryGz(t, filepath.Join(dir, localPrimaryHref))
|
||||
if len(hrefs) != 0 {
|
||||
t.Errorf("expected 0 packages in empty repo, got %d", len(hrefs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitEmptyRepo_idempotent(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
InitEmptyRepo(dir)
|
||||
|
||||
repomdBefore, _ := os.ReadFile(filepath.Join(dir, "repodata", "repomd.xml"))
|
||||
InitEmptyRepo(dir) // second call
|
||||
repomdAfter, _ := os.ReadFile(filepath.Join(dir, "repodata", "repomd.xml"))
|
||||
|
||||
if !bytes.Equal(repomdBefore, repomdAfter) {
|
||||
t.Error("second InitEmptyRepo modified repomd.xml")
|
||||
}
|
||||
}
|
||||
|
||||
// --- RegenerateMetadata ---
|
||||
|
||||
func TestRegenerateMetadata_keepsOnlyPresentFiles(t *testing.T) {
|
||||
allPkgs := []struct{ name, href string }{
|
||||
{"curl", "Packages/curl-7.88-1.x86_64.rpm"},
|
||||
{"wget", "Packages/wget-1.21-1.x86_64.rpm"},
|
||||
{"vim", "Packages/vim-9.0-1.x86_64.rpm"},
|
||||
}
|
||||
// Only curl and vim are on disk.
|
||||
presentOnDisk := []string{"Packages/curl-7.88-1.x86_64.rpm", "Packages/vim-9.0-1.x86_64.rpm"}
|
||||
|
||||
dir := setupRepo(t, allPkgs, presentOnDisk)
|
||||
|
||||
if err := RegenerateMetadata(dir); err != nil {
|
||||
t.Fatalf("RegenerateMetadata: %v", err)
|
||||
}
|
||||
|
||||
hrefs := parsePrimaryGz(t, filepath.Join(dir, localPrimaryHref))
|
||||
if len(hrefs) != 2 {
|
||||
t.Fatalf("expected 2 packages, got %d: %v", len(hrefs), hrefs)
|
||||
}
|
||||
hrefSet := map[string]bool{hrefs[0]: true, hrefs[1]: true}
|
||||
if !hrefSet["Packages/curl-7.88-1.x86_64.rpm"] {
|
||||
t.Error("expected curl in output")
|
||||
}
|
||||
if !hrefSet["Packages/vim-9.0-1.x86_64.rpm"] {
|
||||
t.Error("expected vim in output")
|
||||
}
|
||||
if hrefSet["Packages/wget-1.21-1.x86_64.rpm"] {
|
||||
t.Error("wget should have been filtered out (not on disk)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegenerateMetadata_allAbsent(t *testing.T) {
|
||||
allPkgs := []struct{ name, href string }{
|
||||
{"curl", "Packages/curl-7.88-1.x86_64.rpm"},
|
||||
{"wget", "Packages/wget-1.21-1.x86_64.rpm"},
|
||||
}
|
||||
dir := setupRepo(t, allPkgs, nil) // nothing on disk
|
||||
|
||||
if err := RegenerateMetadata(dir); err != nil {
|
||||
t.Fatalf("RegenerateMetadata: %v", err)
|
||||
}
|
||||
|
||||
hrefs := parsePrimaryGz(t, filepath.Join(dir, localPrimaryHref))
|
||||
if len(hrefs) != 0 {
|
||||
t.Errorf("expected 0 packages, got %d", len(hrefs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegenerateMetadata_updatesRepoMD(t *testing.T) {
|
||||
allPkgs := []struct{ name, href string }{
|
||||
{"curl", "Packages/curl-7.88-1.x86_64.rpm"},
|
||||
}
|
||||
dir := setupRepo(t, allPkgs, []string{"Packages/curl-7.88-1.x86_64.rpm"})
|
||||
|
||||
if err := RegenerateMetadata(dir); err != nil {
|
||||
t.Fatalf("RegenerateMetadata: %v", err)
|
||||
}
|
||||
|
||||
data, _ := os.ReadFile(filepath.Join(dir, "repodata", "repomd.xml"))
|
||||
var repomd RepoMD
|
||||
xml.Unmarshal(data, &repomd)
|
||||
|
||||
var primary *RepoMDEntry
|
||||
for i := range repomd.Data {
|
||||
if repomd.Data[i].Type == "primary" {
|
||||
primary = &repomd.Data[i]
|
||||
}
|
||||
}
|
||||
if primary == nil {
|
||||
t.Fatal("no primary entry in repomd.xml after regen")
|
||||
}
|
||||
if primary.Location.Href != localPrimaryHref {
|
||||
t.Errorf("Location.Href: got %q, want %q", primary.Location.Href, localPrimaryHref)
|
||||
}
|
||||
if primary.Checksum.Type != "sha256" {
|
||||
t.Errorf("Checksum.Type: got %q, want sha256", primary.Checksum.Type)
|
||||
}
|
||||
if primary.Checksum.Value == "placeholder" {
|
||||
t.Error("checksum was not updated from placeholder")
|
||||
}
|
||||
if primary.Size == 0 {
|
||||
t.Error("Size should be non-zero after regen")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegenerateMetadata_alwaysFiltersFromUpstream(t *testing.T) {
|
||||
// Simulates two successive approvals — regen must always read upstream, not the
|
||||
// previously-filtered local primary.
|
||||
allPkgs := []struct{ name, href string }{
|
||||
{"curl", "Packages/curl-7.88-1.x86_64.rpm"},
|
||||
{"wget", "Packages/wget-1.21-1.x86_64.rpm"},
|
||||
{"vim", "Packages/vim-9.0-1.x86_64.rpm"},
|
||||
}
|
||||
dir := setupRepo(t, allPkgs, []string{"Packages/curl-7.88-1.x86_64.rpm"})
|
||||
|
||||
// First regen: only curl on disk.
|
||||
RegenerateMetadata(dir)
|
||||
hrefs := parsePrimaryGz(t, filepath.Join(dir, localPrimaryHref))
|
||||
if len(hrefs) != 1 {
|
||||
t.Fatalf("after first regen: expected 1, got %d", len(hrefs))
|
||||
}
|
||||
|
||||
// Add wget to disk, regen again — vim still absent.
|
||||
dest := filepath.Join(dir, "Packages", "wget-1.21-1.x86_64.rpm")
|
||||
os.WriteFile(dest, []byte("fake"), 0o644)
|
||||
|
||||
RegenerateMetadata(dir)
|
||||
hrefs = parsePrimaryGz(t, filepath.Join(dir, localPrimaryHref))
|
||||
if len(hrefs) != 2 {
|
||||
t.Fatalf("after second regen: expected 2, got %d: %v", len(hrefs), hrefs)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue