add test for the wall app

Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
GnomeZworc 2026-04-25 19:37:17 +02:00
commit 9e287e4e6a
Signed by: nicolas.boufideline
GPG key ID: 4406BBBF8845D632
15 changed files with 3022 additions and 1 deletions

355
internal/core/repo_test.go Normal file
View file

@ -0,0 +1,355 @@
package core_test
import (
"context"
"encoding/json"
"errors"
"testing"
aptclone "github.com/syonad/clonepack/internal/clone/apt"
"github.com/syonad/clonepack/internal/core"
"github.com/syonad/clonepack/internal/store"
)
// mockRepoStore is an in-memory implementation of store.RepoStore for tests.
type mockRepoStore struct {
repos map[int64]*store.Repo
nextID int64
}
func newMockRepoStore() *mockRepoStore {
return &mockRepoStore{repos: make(map[int64]*store.Repo), nextID: 1}
}
func (m *mockRepoStore) CreateRepo(_ context.Context, r *store.Repo) (int64, error) {
for _, existing := range m.repos {
if existing.Name == r.Name {
return 0, errors.New("UNIQUE constraint failed: repos.name")
}
}
id := m.nextID
m.nextID++
clone := *r
clone.ID = id
m.repos[id] = &clone
return id, nil
}
func (m *mockRepoStore) GetRepo(_ context.Context, id int64) (*store.Repo, error) {
r, ok := m.repos[id]
if !ok {
return nil, store.ErrNotFound
}
clone := *r
return &clone, nil
}
func (m *mockRepoStore) GetRepoByName(_ context.Context, name string) (*store.Repo, error) {
for _, r := range m.repos {
if r.Name == name {
clone := *r
return &clone, nil
}
}
return nil, store.ErrNotFound
}
func (m *mockRepoStore) ListRepos(_ context.Context) ([]store.Repo, error) {
out := make([]store.Repo, 0, len(m.repos))
for _, r := range m.repos {
out = append(out, *r)
}
return out, nil
}
func (m *mockRepoStore) DeleteRepo(_ context.Context, id int64) error {
if _, ok := m.repos[id]; !ok {
return store.ErrNotFound
}
delete(m.repos, id)
return nil
}
func (m *mockRepoStore) UpdateRepoSyncMode(_ context.Context, id int64, mode string) error {
r, ok := m.repos[id]
if !ok {
return store.ErrNotFound
}
r.SyncMode = mode
return nil
}
func (m *mockRepoStore) UpdateRepo(_ context.Context, id int64, sourceURL, syncMode, config string) error {
r, ok := m.repos[id]
if !ok {
return store.ErrNotFound
}
r.SourceURL = sourceURL
r.SyncMode = syncMode
r.Config = config
return nil
}
func newTestRepoService(t *testing.T) *core.RepoService {
t.Helper()
return core.NewRepoService(newMockRepoStore(), t.TempDir())
}
// --- Create tests ---
func TestCreate_validRPM(t *testing.T) {
svc := newTestRepoService(t)
repo, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "rocky9",
Type: "rpm",
SourceURL: "https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if repo.ID <= 0 {
t.Errorf("expected positive ID, got %d", repo.ID)
}
if repo.SyncMode != "auto" {
t.Errorf("default SyncMode: got %q, want auto", repo.SyncMode)
}
}
func TestCreate_validAPT(t *testing.T) {
svc := newTestRepoService(t)
repo, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "debian-bookworm",
Type: "apt",
SourceURL: "https://deb.debian.org/debian",
AptSuite: "bookworm",
AptComponents: []string{"main", "contrib"},
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Config should be valid JSON with suite set.
var cfg aptclone.Config
if err := json.Unmarshal([]byte(repo.Config), &cfg); err != nil {
t.Fatalf("Config is not valid JSON: %v", err)
}
if cfg.Suite != "bookworm" {
t.Errorf("cfg.Suite: got %q, want bookworm", cfg.Suite)
}
if len(cfg.Components) != 2 {
t.Errorf("cfg.Components: got %v, want [main contrib]", cfg.Components)
}
}
func TestCreate_aptDefaultsComponents(t *testing.T) {
svc := newTestRepoService(t)
repo, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "debian-minimal",
Type: "apt",
SourceURL: "https://deb.debian.org/debian",
AptSuite: "bookworm",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var cfg aptclone.Config
json.Unmarshal([]byte(repo.Config), &cfg)
if len(cfg.Components) == 0 {
t.Error("expected default components, got empty")
}
if len(cfg.Architectures) == 0 {
t.Error("expected default architectures, got empty")
}
}
func TestCreate_missingName(t *testing.T) {
svc := newTestRepoService(t)
_, err := svc.Create(context.Background(), core.CreateRepoInput{
Type: "rpm",
SourceURL: "https://example.com",
})
if err == nil {
t.Error("expected error for missing name, got nil")
}
}
func TestCreate_invalidType(t *testing.T) {
svc := newTestRepoService(t)
_, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "bad-type",
Type: "maven",
SourceURL: "https://example.com",
})
if err == nil {
t.Error("expected error for invalid type, got nil")
}
}
func TestCreate_missingSourceURL(t *testing.T) {
svc := newTestRepoService(t)
_, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "no-url",
Type: "rpm",
})
if err == nil {
t.Error("expected error for missing source_url, got nil")
}
}
func TestCreate_aptMissingSuite(t *testing.T) {
svc := newTestRepoService(t)
_, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "apt-no-suite",
Type: "apt",
SourceURL: "https://deb.debian.org/debian",
})
if err == nil {
t.Error("expected error for missing apt_suite, got nil")
}
}
func TestCreate_invalidSyncMode(t *testing.T) {
svc := newTestRepoService(t)
_, err := svc.Create(context.Background(), core.CreateRepoInput{
Name: "bad-mode",
Type: "rpm",
SourceURL: "https://example.com",
SyncMode: "cron",
})
if err == nil {
t.Error("expected error for invalid sync_mode, got nil")
}
}
// --- Update tests ---
func TestUpdate_changeSourceURL(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "rpm-repo",
Type: "rpm",
SourceURL: "https://old.example.com",
})
newURL := "https://new.example.com"
updated, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{SourceURL: &newURL})
if err != nil {
t.Fatalf("Update: %v", err)
}
if updated.SourceURL != newURL {
t.Errorf("SourceURL: got %q, want %q", updated.SourceURL, newURL)
}
}
func TestUpdate_changeSyncMode(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "rpm-repo-2",
Type: "rpm",
SourceURL: "https://example.com",
})
mode := "manual"
updated, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{SyncMode: &mode})
if err != nil {
t.Fatalf("Update: %v", err)
}
if updated.SyncMode != "manual" {
t.Errorf("SyncMode: got %q, want manual", updated.SyncMode)
}
}
func TestUpdate_aptComponents(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "apt-repo",
Type: "apt",
SourceURL: "https://deb.debian.org/debian",
AptSuite: "bookworm",
})
suite := "bookworm-backports"
updated, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{
AptSuite: &suite,
AptComponents: []string{"main", "contrib", "non-free"},
})
if err != nil {
t.Fatalf("Update: %v", err)
}
var cfg aptclone.Config
if err := json.Unmarshal([]byte(updated.Config), &cfg); err != nil {
t.Fatalf("Config JSON: %v", err)
}
if cfg.Suite != "bookworm-backports" {
t.Errorf("Suite: got %q, want bookworm-backports", cfg.Suite)
}
if len(cfg.Components) != 3 {
t.Errorf("Components: got %v", cfg.Components)
}
}
func TestUpdate_invalidSyncMode(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "rpm-repo-3",
Type: "rpm",
SourceURL: "https://example.com",
})
bad := "weekly"
_, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{SyncMode: &bad})
if err == nil {
t.Error("expected error for invalid sync_mode, got nil")
}
}
func TestUpdate_aptFieldsOnRPMRepo(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "rpm-repo-4",
Type: "rpm",
SourceURL: "https://example.com",
})
suite := "bookworm"
_, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{AptSuite: &suite})
if err == nil {
t.Error("expected error applying apt fields to rpm repo, got nil")
}
}
func TestUpdate_emptySourceURL(t *testing.T) {
svc := newTestRepoService(t)
ctx := context.Background()
repo, _ := svc.Create(ctx, core.CreateRepoInput{
Name: "rpm-repo-5",
Type: "rpm",
SourceURL: "https://example.com",
})
empty := ""
_, err := svc.Update(ctx, repo.ID, core.UpdateRepoInput{SourceURL: &empty})
if err == nil {
t.Error("expected error for empty source_url, got nil")
}
}
func TestUpdate_notFound(t *testing.T) {
svc := newTestRepoService(t)
url := "https://example.com"
_, err := svc.Update(context.Background(), 9999, core.UpdateRepoInput{SourceURL: &url})
if !errors.Is(err, store.ErrNotFound) {
t.Errorf("expected ErrNotFound, got %v", err)
}
}