package cmd
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"github.com/openeuler/Conch/internal/cli/client"
)
func TestPrintImageHelpListsImageCommands(t *testing.T) {
var buf bytes.Buffer
printImageHelp(&buf)
got := buf.String()
for _, want := range []string{
"conch image <command> [options]",
" pull ",
" push ",
" ls ",
" rm ",
"conch image <command> --help",
} {
if !strings.Contains(got, want) {
t.Fatalf("image help output missing %q:\n%s", want, got)
}
}
if strings.Contains(got, " unpack ") {
t.Fatalf("image help output still lists unpack:\n%s", got)
}
}
func TestRunImageListPrintsKind(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/api/image/list" {
http.NotFound(w, r)
return
}
_, _ = w.Write([]byte(`{"images":[{"name":"localhost/conch/demo:latest","target_digest":"sha256:demo","size":42,"kind":"boot-index-resume"}]}`))
}))
defer server.Close()
t.Setenv("CONCH_API_URL", server.URL)
w2Buf := &bytes.Buffer{}
oldStdout := os.Stdout
r2, w2, err := os.Pipe()
if err != nil {
t.Fatalf("Pipe2: %v", err)
}
os.Stdout = w2
defer func() { os.Stdout = oldStdout }()
if err := runImageList(context.Background(), nil); err != nil {
t.Fatalf("runImageList() error = %v", err)
}
_ = w2.Close()
if _, err := w2Buf.ReadFrom(r2); err != nil {
t.Fatalf("ReadFrom: %v", err)
}
output := w2Buf.String()
if !strings.HasPrefix(output, "NAME") {
t.Fatalf("output should put NAME first:\n%s", output)
}
if !strings.Contains(output, "boot-index-resume") {
t.Fatalf("output missing kind value:\n%s", output)
}
}
func TestRunImageListRejectsInvalidConfig(t *testing.T) {
configPath := t.TempDir() + "/config.yaml"
if err := os.WriteFile(configPath, []byte("server: [\n"), 0o600); err != nil {
t.Fatalf("WriteFile: %v", err)
}
t.Setenv("CONCH_API_URL", "http://127.0.0.1:4063")
err := runImageList(context.Background(), []string{"--config", configPath})
if err == nil {
t.Fatal("runImageList() error = nil")
}
if !strings.Contains(err.Error(), "failed to parse config file") {
t.Fatalf("runImageList() error = %v, want YAML parse error", err)
}
}
func TestPrintImageListHidesInternalRecordsByDefault(t *testing.T) {
images := []client.ImageRecord{
{Name: "localhost:5000/busybox:latest", TargetDigest: "sha256:source"},
{Name: "localhost/conch/busybox:latest", TargetDigest: "sha256:index", Kind: "boot-index-cold"},
{Name: "io.conch.template/localhost/conch/busybox:latest", TargetDigest: "sha256:index", Kind: "boot-index-cold"},
{Name: "conch-erofs-rootfs:build-1", TargetDigest: "sha256:rootfs"},
{Name: "localhost/conch/rootfs-component:rootfs", TargetDigest: "sha256:rootfs", Kind: "boot-component-rootfs"},
{Name: "localhost/conch/sandbox-component:sandbox", TargetDigest: "sha256:sandbox", Kind: "boot-component-sandbox"},
{Name: "localhost/conch/mem-snapshot-component:mem", TargetDigest: "sha256:mem", Kind: "boot-component-memory"},
}
var visible bytes.Buffer
if err := printImageList(&visible, images, false); err != nil {
t.Fatalf("printImageList(default) error = %v", err)
}
for _, want := range []string{"localhost:5000/busybox:latest", "localhost/conch/busybox:latest"} {
if !strings.Contains(visible.String(), want) {
t.Fatalf("default output missing %q:\n%s", want, visible.String())
}
}
for _, hidden := range []string{"io.conch.template/", "conch-erofs-rootfs:", "rootfs-component", "sandbox-component", "mem-snapshot-component"} {
if strings.Contains(visible.String(), hidden) {
t.Fatalf("default output unexpectedly contains %q:\n%s", hidden, visible.String())
}
}
var all bytes.Buffer
if err := printImageList(&all, images, true); err != nil {
t.Fatalf("printImageList(all) error = %v", err)
}
for _, want := range []string{"io.conch.template/", "conch-erofs-rootfs:", "rootfs-component", "sandbox-component", "mem-snapshot-component"} {
if !strings.Contains(all.String(), want) {
t.Fatalf("--all output missing %q:\n%s", want, all.String())
}
}
}
func TestDisplayImageKindDefaultsToOCIImage(t *testing.T) {
if got := displayImageKind(""); got != "oci-image" {
t.Fatalf("displayImageKind(empty) = %q, want oci-image", got)
}
}