Add a convenience method `DepsolvePackageSets()` to the `RPMMD` interface. The method is expected to depsolve all provided package sets in a chain or separately, based on the provided arguments, and return depsolved PackageSpecs sets. The intention is to have a single implementation of how are package sets depsolved and then use it from all places in composer (API and tools implementations). Adjust necessary mock implementations and add a unit test testing the new interface method implementation.
162 lines
6.2 KiB
Go
162 lines
6.2 KiB
Go
// This package contains tests related to dnf-json and rpmmd package.
|
|
|
|
// +build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
fedora "github.com/osbuild/osbuild-composer/internal/distro/fedora33"
|
|
rhel "github.com/osbuild/osbuild-composer/internal/distro/rhel86"
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
"github.com/osbuild/osbuild-composer/internal/test"
|
|
)
|
|
|
|
func TestFetchChecksum(t *testing.T) {
|
|
dir, err := test.SetUpTemporaryRepository()
|
|
fs := http.FileServer(http.Dir(dir))
|
|
go func() {
|
|
err := http.ListenAndServe(":9000", fs)
|
|
assert.Nilf(t, err, "Could not start the http server: %v", err)
|
|
}()
|
|
defer func(dir string) {
|
|
err := test.TearDownTemporaryRepository(dir)
|
|
assert.Nil(t, err, "Failed to clean up temporary repository.")
|
|
}(dir)
|
|
assert.Nilf(t, err, "Failed to set up temporary repository: %v", err)
|
|
|
|
repoCfg := rpmmd.RepoConfig{
|
|
Name: "repo",
|
|
BaseURL: "http://localhost:9000",
|
|
IgnoreSSL: true,
|
|
}
|
|
|
|
// use a fullpath to dnf-json, this allows this test to have an arbitrary
|
|
// working directory
|
|
rpmMetadata := rpmmd.NewRPMMD(path.Join(dir, "rpmmd"))
|
|
_, c, err := rpmMetadata.FetchMetadata([]rpmmd.RepoConfig{repoCfg}, "platform:f31", "x86_64", "31")
|
|
assert.Nilf(t, err, "Failed to fetch checksum: %v", err)
|
|
assert.NotEqual(t, "", c["repo"], "The checksum is empty")
|
|
}
|
|
|
|
// This test loads all the repositories available in /repositories directory
|
|
// and tries to run depsolve for each architecture. With N architectures available
|
|
// this should run cross-arch dependency solving N-1 times.
|
|
func TestCrossArchDepsolve(t *testing.T) {
|
|
// Load repositories from the definition we provide in the RPM package
|
|
repoDir := "/usr/share/tests/osbuild-composer"
|
|
|
|
// NOTE: we can add RHEL, but don't make it hard requirement because it will fail outside of VPN
|
|
for _, distroStruct := range []distro.Distro{fedora.NewF35()} {
|
|
t.Run(distroStruct.Name(), func(t *testing.T) {
|
|
|
|
// Run tests in parallel to speed up run times.
|
|
t.Parallel()
|
|
|
|
// Set up temporary directory for rpm/dnf cache
|
|
dir := t.TempDir()
|
|
|
|
// use a fullpath to dnf-json, this allows this test to have an arbitrary
|
|
// working directory
|
|
rpm := rpmmd.NewRPMMD(dir)
|
|
|
|
repos, err := rpmmd.LoadRepositories([]string{repoDir}, distroStruct.Name())
|
|
require.NoErrorf(t, err, "Failed to LoadRepositories %v", distroStruct.Name())
|
|
|
|
for _, archStr := range distroStruct.ListArches() {
|
|
t.Run(archStr, func(t *testing.T) {
|
|
arch, err := distroStruct.GetArch(archStr)
|
|
require.NoError(t, err)
|
|
|
|
for _, imgTypeStr := range arch.ListImageTypes() {
|
|
t.Run(imgTypeStr, func(t *testing.T) {
|
|
imgType, err := arch.GetImageType(imgTypeStr)
|
|
require.NoError(t, err)
|
|
|
|
packages := imgType.PackageSets(blueprint.Blueprint{})
|
|
|
|
_, _, err = rpm.Depsolve(packages["build-packages"], repos[archStr], distroStruct.ModulePlatformID(), archStr, distroStruct.Releasever())
|
|
assert.NoError(t, err)
|
|
|
|
_, _, err = rpm.Depsolve(packages["packages"], repos[archStr], distroStruct.ModulePlatformID(), archStr, distroStruct.Releasever())
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// This test loads all the repositories available in /repositories directory
|
|
// and tries to depsolve all package sets of one image type for one architecture.
|
|
func TestDepsolvePackageSets(t *testing.T) {
|
|
// Load repositories from the definition we provide in the RPM package
|
|
repoDir := "/usr/share/tests/osbuild-composer"
|
|
|
|
// NOTE: we can add RHEL, but don't make it hard requirement because it will fail outside of VPN
|
|
for _, distroStruct := range []distro.Distro{rhel.NewCentos()} {
|
|
t.Run(distroStruct.Name(), func(t *testing.T) {
|
|
|
|
// Run tests in parallel to speed up run times.
|
|
t.Parallel()
|
|
|
|
// Set up temporary directory for rpm/dnf cache
|
|
dir := t.TempDir()
|
|
|
|
// use a fullpath to dnf-json, this allows this test to have an arbitrary
|
|
// working directory
|
|
rpm := rpmmd.NewRPMMD(dir)
|
|
|
|
repos, err := rpmmd.LoadRepositories([]string{repoDir}, distroStruct.Name())
|
|
require.NoErrorf(t, err, "Failed to LoadRepositories %v", distroStruct.Name())
|
|
x86Repos, ok := repos[distro.X86_64ArchName]
|
|
require.Truef(t, ok, "failed to get %q repos for %q", distro.X86_64ArchName, distroStruct.Name())
|
|
|
|
x86Arch, err := distroStruct.GetArch(distro.X86_64ArchName)
|
|
require.Nilf(t, err, "failed to get %q arch of %q distro", distro.X86_64ArchName, distroStruct.Name())
|
|
|
|
qcow2ImageTypeName := "qcow2"
|
|
qcow2Image, err := x86Arch.GetImageType(qcow2ImageTypeName)
|
|
require.Nilf(t, err, "failed to get %q image type of %q/%q distro/arch", qcow2ImageTypeName, distroStruct.Name(), distro.X86_64ArchName)
|
|
|
|
imagePkgSets := qcow2Image.PackageSets(blueprint.Blueprint{Packages: []blueprint.Package{{Name: "bind"}}})
|
|
imagePkgSetChains := qcow2Image.PackageSetsChains()
|
|
require.NotEmptyf(t, imagePkgSetChains, "the %q image has no package set chains defined", qcow2ImageTypeName)
|
|
|
|
expectedPackageSpecsSetNames := func(pkgSets map[string]rpmmd.PackageSet, pkgSetChains map[string][]string) []string {
|
|
expectedPkgSpecsSetNames := make([]string, 0, len(pkgSets))
|
|
chainPkgSets := make(map[string]struct{}, len(pkgSets))
|
|
for name, pkgSetChain := range pkgSetChains {
|
|
expectedPkgSpecsSetNames = append(expectedPkgSpecsSetNames, name)
|
|
for _, pkgSetName := range pkgSetChain {
|
|
chainPkgSets[pkgSetName] = struct{}{}
|
|
}
|
|
}
|
|
for name := range pkgSets {
|
|
if _, ok := chainPkgSets[name]; ok {
|
|
continue
|
|
}
|
|
expectedPkgSpecsSetNames = append(expectedPkgSpecsSetNames, name)
|
|
}
|
|
return expectedPkgSpecsSetNames
|
|
}(imagePkgSets, imagePkgSetChains)
|
|
|
|
gotPackageSpecsSets, err := rpm.DepsolvePackageSets(imagePkgSetChains, imagePkgSets, x86Repos, nil, distroStruct.ModulePlatformID(), x86Arch.Name(), distroStruct.Releasever())
|
|
require.Nil(t, err)
|
|
require.EqualValues(t, len(expectedPackageSpecsSetNames), len(gotPackageSpecsSets))
|
|
for _, name := range expectedPackageSpecsSetNames {
|
|
_, ok := gotPackageSpecsSets[name]
|
|
assert.True(t, ok)
|
|
}
|
|
})
|
|
}
|
|
}
|