import { describe, expect, it } from "vitest";
import {
calculateBuildCacheStats,
calculateContainerStats,
calculateImageStats,
calculateVolumeStats,
} from "./stats-calculator.js";
describe("calculateImageStats", () => {
it("should calculate total, active, size, and reclaimable for images", (): void => {
const images = [
{ Size: 1000, SharedSize: 200, Containers: 2 },
{ Size: 2000, SharedSize: 500, Containers: 0 },
{ Size: 3000, SharedSize: 800, Containers: 1 },
];
const result = calculateImageStats(images);
expect(result.total).toBe(3);
expect(result.active).toBe(2); // 2 images with Containers > 0
expect(result.size).toBe(6000); // 1000 + 2000 + 3000
expect(result.reclaimable).toBe(4500); // 6000 - 1500 (total shared)
});
it("should handle empty image array", (): void => {
const result = calculateImageStats([]);
expect(result.total).toBe(0);
expect(result.active).toBe(0);
expect(result.size).toBe(0);
expect(result.reclaimable).toBe(0);
});
it("should handle images with missing Size or SharedSize", (): void => {
const images = [
{ Size: undefined, SharedSize: undefined, Containers: 1 },
{ Size: 1000, SharedSize: undefined, Containers: 0 },
];
const result = calculateImageStats(images);
expect(result.total).toBe(2);
expect(result.active).toBe(1);
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(1000);
});
it("should handle images with missing Containers field", (): void => {
const images = [{ Size: 1000, SharedSize: 200, Containers: undefined }];
const result = calculateImageStats(images);
expect(result.total).toBe(1);
expect(result.active).toBe(0); // undefined Containers means not active
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(800);
});
});
describe("calculateContainerStats", () => {
it("should calculate total, running, size, and rootfsSize for containers", (): void => {
const containers = [
{ SizeRw: 100, SizeRootFs: 500, State: "running" },
{ SizeRw: 200, SizeRootFs: 600, State: "exited" },
{ SizeRw: 150, SizeRootFs: 550, State: "running" },
];
const result = calculateContainerStats(containers);
expect(result.total).toBe(3);
expect(result.running).toBe(2); // 2 running containers
expect(result.size).toBe(450); // 100 + 200 + 150 (SizeRw)
expect(result.rootfsSize).toBe(1650); // 500 + 600 + 550 (SizeRootFs)
});
it("should handle empty container array", (): void => {
const result = calculateContainerStats([]);
expect(result.total).toBe(0);
expect(result.running).toBe(0);
expect(result.size).toBe(0);
expect(result.rootfsSize).toBe(0);
});
it("should handle containers with missing SizeRw or SizeRootFs", (): void => {
const containers = [
{ SizeRw: undefined, SizeRootFs: undefined, State: "running" },
{ SizeRw: 100, SizeRootFs: undefined, State: "exited" },
];
const result = calculateContainerStats(containers);
expect(result.total).toBe(2);
expect(result.running).toBe(1);
expect(result.size).toBe(100);
expect(result.rootfsSize).toBe(0);
});
it("should handle containers with missing State field", (): void => {
const containers = [{ SizeRw: 100, SizeRootFs: 500, State: undefined }];
const result = calculateContainerStats(containers);
expect(result.total).toBe(1);
expect(result.running).toBe(0); // undefined State means not running
expect(result.size).toBe(100);
expect(result.rootfsSize).toBe(500);
});
});
describe("calculateVolumeStats", () => {
it("should calculate total, active, size, and reclaimable for volumes", (): void => {
const volumes = [
{ UsageData: { Size: 1000, RefCount: 2 } },
{ UsageData: { Size: 2000, RefCount: 0 } },
{ UsageData: { Size: 3000, RefCount: 1 } },
];
const result = calculateVolumeStats(volumes);
expect(result.total).toBe(3);
expect(result.active).toBe(2); // 2 volumes with RefCount > 0
expect(result.size).toBe(6000); // 1000 + 2000 + 3000
expect(result.reclaimable).toBe(2000); // Only volume with RefCount = 0
});
it("should handle empty volume array", (): void => {
const result = calculateVolumeStats([]);
expect(result.total).toBe(0);
expect(result.active).toBe(0);
expect(result.size).toBe(0);
expect(result.reclaimable).toBe(0);
});
it("should handle volumes with missing UsageData", (): void => {
const volumes = [{ UsageData: undefined }, { UsageData: { Size: 1000, RefCount: 1 } }];
const result = calculateVolumeStats(volumes);
expect(result.total).toBe(2);
expect(result.active).toBe(1);
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(0); // No unused volumes
});
it("should handle volumes with missing Size or RefCount", (): void => {
const volumes = [
{ UsageData: { Size: undefined, RefCount: 1 } },
{ UsageData: { Size: 1000, RefCount: undefined } },
];
const result = calculateVolumeStats(volumes);
expect(result.total).toBe(2);
expect(result.active).toBe(1); // Only first volume has RefCount > 0
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(1000); // Second volume has no RefCount (unused)
});
});
describe("calculateBuildCacheStats", () => {
it("should calculate total, size, and reclaimable for build cache", (): void => {
const buildCache = [
{ Size: 1000, InUse: true },
{ Size: 2000, InUse: false },
{ Size: 3000, InUse: false },
];
const result = calculateBuildCacheStats(buildCache);
expect(result.total).toBe(3);
expect(result.size).toBe(6000); // 1000 + 2000 + 3000
expect(result.reclaimable).toBe(5000); // 2000 + 3000 (not in use)
});
it("should handle empty build cache array", (): void => {
const result = calculateBuildCacheStats([]);
expect(result.total).toBe(0);
expect(result.size).toBe(0);
expect(result.reclaimable).toBe(0);
});
it("should handle build cache with missing Size", (): void => {
const buildCache = [
{ Size: undefined, InUse: true },
{ Size: 1000, InUse: false },
];
const result = calculateBuildCacheStats(buildCache);
expect(result.total).toBe(2);
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(1000);
});
it("should handle build cache with missing InUse", (): void => {
const buildCache = [{ Size: 1000, InUse: undefined }];
const result = calculateBuildCacheStats(buildCache);
expect(result.total).toBe(1);
expect(result.size).toBe(1000);
expect(result.reclaimable).toBe(1000); // Treated as not in use when undefined
});
});