iop/scripts/inventory-query/main_test.go

735 lines
19 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"gopkg.in/yaml.v3"
)
// fixtureYAML is a minimal inventory shape covering both dev and dev-corp patterns.
const fixtureYAML = `
test_env: dev
profile: dev-runtime-provider-pool
last_updated_at: "2026-07-13"
source:
remote_runner:
ssh: toki@toki-labs.com
edge:
id: edge-toki-labs-dev
build:
binaries:
edge: build/dev-runtime/bin/edge
model:
alias: ornith:35b
aliases:
gemma4:26b:
capacity_total: 5
providers:
- id: mac-mlx-vllm
served_model: mlx-community/gemma-4-26b-a4b-it-nvfp4
ornith:35b:
capacity_total: 8
providers:
- id: corp-dgx-spark-01-ornith
- id: corp-dgx-spark-02-ornith
active_edge_model_group:
providers:
gx10-vllm:
capacity_total: 4
qwen3_6_reference:
alias: qwen3.6:35b
id: qwen3-6-ref
provider: mac-mlx-vllm
nodes:
- id: mac-codex-node
alias: mac-codex
providers:
- id: mac-mlx-vllm
type: vllm-mlx
- id: gx10-vllm-node
alias: gx10-vllm
provider:
id: gx10-vllm
type: vllm
- id: onexplayer-lemonade-node
alias: onexplayer-lemonade
direct_providers:
- id: ornith-direct
family: spark_ornith
- id: node-3
alias: node-3
- id: node-4
alias: node-4
- id: node-5
alias: node-5
- id: node-6
alias: node-6
- id: node-7
alias: node-7
- id: node-8
alias: node-8
- id: node-9
alias: node-9
- id: node-10
alias: node-10
`
func parseFixture(t *testing.T) map[string]interface{} {
t.Helper()
var doc map[string]interface{}
if err := yaml.Unmarshal([]byte(fixtureYAML), &doc); err != nil {
t.Fatalf("failed to parse fixture YAML: %v", err)
}
return doc
}
func TestQueryEnvironmentProjectionIsBounded(t *testing.T) {
data := parseFixture(t)
proj := buildEnvProjection(data)
if proj.Env != "dev" {
t.Errorf("expected env=dev, got %q", proj.Env)
}
if proj.Profile != "dev-runtime-provider-pool" {
t.Errorf("expected profile=dev-runtime-provider-pool, got %q", proj.Profile)
}
if proj.LastUpdatedAt != "2026-07-13" {
t.Errorf("expected last_updated_at=2026-07-13, got %q", proj.LastUpdatedAt)
}
if proj.Source == nil {
t.Error("expected source to be present in projection")
}
if proj.Edge == nil {
t.Error("expected edge to be present in projection")
}
if proj.Build == nil {
t.Error("expected build to be present in projection")
}
// Ensure model and nodes are NOT in the projection.
jsonBytes, err := json.Marshal(proj)
if err != nil {
t.Fatalf("failed to marshal projection: %v", err)
}
jsonStr := string(jsonBytes)
if strings.Contains(jsonStr, `"model"`) {
t.Error("projection should not contain model key")
}
if strings.Contains(jsonStr, `"nodes"`) {
t.Error("projection should not contain nodes key")
}
}
func TestQueryNodeByIDAndAlias(t *testing.T) {
data := parseFixture(t)
// Match by id.
matches := queryNodes(data, "gx10-vllm-node")
if len(matches) != 1 {
t.Fatalf("expected 1 match for id=gx10-vllm-node, got %d: %+v", len(matches), matches)
}
if matches[0].Path != "nodes[1]" {
t.Errorf("expected path=nodes[1], got %q", matches[0].Path)
}
nodeObj, ok := matches[0].Value.(map[string]interface{})
if !ok {
t.Fatalf("expected map[string]interface{}, got %T", matches[0].Value)
}
if nodeObj["id"] != "gx10-vllm-node" {
t.Errorf("expected id=gx10-vllm-node, got %v", nodeObj["id"])
}
// Match by alias.
matches = queryNodes(data, "mac-codex")
if len(matches) != 1 {
t.Fatalf("expected 1 match for alias=mac-codex, got %d: %+v", len(matches), matches)
}
if matches[0].Path != "nodes[0]" {
t.Errorf("expected path=nodes[0], got %q", matches[0].Path)
}
}
func TestQueryModelAcrossAliasShapes(t *testing.T) {
data := parseFixture(t)
// Match by alias key in model.aliases.
matches := queryModels(data, "gemma4:26b")
if len(matches) == 0 {
t.Fatal("expected at least 1 match for alias key gemma4:26b")
}
found := false
for _, m := range matches {
if m.Path == "model.aliases.gemma4:26b" {
found = true
modelMap, ok := m.Value.(map[string]interface{})
if !ok {
t.Fatalf("expected map[string]interface{}, got %T", m.Value)
}
if modelMap["capacity_total"] != 5 {
t.Errorf("expected capacity_total=5, got %v", modelMap["capacity_total"])
}
break
}
}
if !found {
t.Errorf("expected match at model.aliases.gemma4:26b, got %+v", matches)
}
// Match by entity alias in model subtree.
matches = queryModels(data, "qwen3.6:35b")
if len(matches) == 0 {
t.Fatal("expected at least 1 match for entity alias qwen3.6:35b")
}
found = false
for _, m := range matches {
if m.Path == "model.qwen3_6_reference.alias" && m.Value == "qwen3.6:35b" {
found = true
break
}
}
if !found {
t.Errorf("expected match at model.qwen3_6_reference.alias, got %+v", matches)
}
// Match by entity id in model subtree.
matches = queryModels(data, "qwen3-6-ref")
if len(matches) == 0 {
t.Fatal("expected at least 1 match for entity id qwen3-6-ref")
}
found = false
for _, m := range matches {
if m.Path == "model.qwen3_6_reference.id" && m.Value == "qwen3-6-ref" {
found = true
break
}
}
if !found {
t.Errorf("expected match at model.qwen3_6_reference.id, got %+v", matches)
}
}
func TestQueryProviderSortsAndDeduplicatesMatches(t *testing.T) {
data := parseFixture(t)
matches := queryProviders(data, "mac-mlx-vllm")
if len(matches) == 0 {
t.Fatal("expected matches for provider mac-mlx-vllm")
}
// Check no duplicates.
paths := make(map[string]bool)
for _, m := range matches {
if paths[m.Path] {
t.Errorf("duplicate path found: %s", m.Path)
}
paths[m.Path] = true
}
// Check sorted by path.
for i := 1; i < len(matches); i++ {
if matches[i].Path < matches[i-1].Path {
t.Errorf("matches not sorted: %s < %s", matches[i].Path, matches[i-1].Path)
}
}
// Verify expected paths exist.
expectedPaths := map[string]bool{
"nodes[0].providers[0]": false,
"model.aliases.gemma4:26b.providers[0]": false,
"model.qwen3_6_reference.provider": false,
}
for _, m := range matches {
if _, ok := expectedPaths[m.Path]; ok {
expectedPaths[m.Path] = true
}
}
for p, found := range expectedPaths {
if !found {
t.Errorf("expected path %s not found in matches %+v", p, matches)
}
}
}
func TestQueryZeroMatch(t *testing.T) {
data := parseFixture(t)
matches := queryNodes(data, "nonexistent")
if len(matches) != 0 {
t.Errorf("expected 0 matches, got %d: %+v", len(matches), matches)
}
matches = queryProviders(data, "nonexistent-provider")
if len(matches) != 0 {
t.Errorf("expected 0 matches, got %d: %+v", len(matches), matches)
}
matches = queryModels(data, "nonexistent-model")
if len(matches) != 0 {
t.Errorf("expected 0 matches, got %d: %+v", len(matches), matches)
}
}
func TestParseFlagsRejectsInvalidCombinations(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
}{
{"missing env", []string{"--model", "x"}, true},
{"multiple selectors", []string{"--env", "dev", "--model", "x", "--node", "y"}, true},
{"unknown flag", []string{"--env", "dev", "--unknown"}, true},
{"env without value", []string{"--env"}, true},
{"model without value", []string{"--env", "dev", "--model"}, true},
{"invalid env value", []string{"--env", "invalid-env"}, true},
{"valid no selector", []string{"--env", "dev"}, false},
{"valid single selector", []string{"--env", "dev", "--node", "x"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := parseFlags(tt.args)
if tt.wantErr && err == nil {
t.Error("expected error but got nil")
}
if !tt.wantErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
})
}
}
func TestQueryIsDeterministic(t *testing.T) {
data := parseFixture(t)
var outputs []string
for i := 0; i < 5; i++ {
matches := queryProviders(data, "gx10-vllm")
out, err := json.Marshal(matches)
if err != nil {
t.Fatalf("json marshal error: %v", err)
}
outputs = append(outputs, string(out))
}
for i := 1; i < len(outputs); i++ {
if outputs[i] != outputs[0] {
t.Errorf("query not deterministic: output %d differs from output 0", i)
}
}
}
func TestQueryProviderInDirectProviders(t *testing.T) {
data := parseFixture(t)
matches := queryProviders(data, "ornith-direct")
if len(matches) != 1 {
t.Fatalf("expected 1 match for ornith-direct, got %d: %+v", len(matches), matches)
}
if matches[0].Path != "nodes[2].direct_providers[0]" {
t.Errorf("expected path=nodes[2].direct_providers[0], got %q", matches[0].Path)
}
}
func TestQueryModelAliasKey(t *testing.T) {
data := parseFixture(t)
matches := queryModels(data, "ornith:35b")
if len(matches) == 0 {
t.Fatal("expected matches for ornith:35b")
}
foundAliasKey := false
foundEntity := false
for _, m := range matches {
if m.Path == "model.aliases.ornith:35b" {
foundAliasKey = true
}
if m.Path == "model.alias" && m.Value == "ornith:35b" {
foundEntity = true
}
}
if !foundAliasKey {
t.Errorf("expected match at model.aliases.ornith:35b, got %+v", matches)
}
if !foundEntity {
t.Errorf("expected match at model.alias, got %+v", matches)
}
}
func TestQueryProviderInModelAliasesProviders(t *testing.T) {
data := parseFixture(t)
matches := queryProviders(data, "corp-dgx-spark-01-ornith")
if len(matches) != 1 {
t.Fatalf("expected 1 match for corp-dgx-spark-01-ornith, got %d: %+v", len(matches), matches)
}
if matches[0].Path != "model.aliases.ornith:35b.providers[0]" {
t.Errorf("expected path=model.aliases.ornith:35b.providers[0], got %q", matches[0].Path)
}
}
func TestEncodeJSONOutput(t *testing.T) {
var buf bytes.Buffer
proj := buildEnvProjection(parseFixture(t))
encodeJSON(&buf, proj)
if buf.Len() == 0 {
t.Error("expected non-empty JSON output")
}
var result envProjection
if err := json.Unmarshal(buf.Bytes(), &result); err != nil {
t.Fatalf("failed to unmarshal JSON output: %v\noutput: %s", err, buf.String())
}
if result.Env != "dev" {
t.Errorf("expected env=dev in JSON output, got %q", result.Env)
}
}
func TestQueryNodeReturnsEntityValue(t *testing.T) {
data := parseFixture(t)
matches := queryNodes(data, "gx10-vllm-node")
if len(matches) != 1 {
t.Fatalf("expected 1 match, got %d", len(matches))
}
nodeMap, ok := matches[0].Value.(map[string]interface{})
if !ok {
t.Fatalf("expected map[string]interface{}, got %T", matches[0].Value)
}
if nodeMap["id"] != "gx10-vllm-node" {
t.Errorf("expected id=gx10-vllm-node, got %v", nodeMap["id"])
}
}
func TestQueryModelAliasReturnsValueAtPath(t *testing.T) {
data := parseFixture(t)
matches := queryModels(data, "gemma4:26b")
if len(matches) != 1 {
t.Fatalf("expected 1 match, got %d", len(matches))
}
modelMap, ok := matches[0].Value.(map[string]interface{})
if !ok {
t.Fatalf("expected map[string]interface{}, got %T", matches[0].Value)
}
if modelMap["capacity_total"] != 5 {
t.Errorf("expected capacity_total=5, got %v", modelMap["capacity_total"])
}
}
func TestQueryProviderAcrossCanonicalShapes(t *testing.T) {
data := parseFixture(t)
matches := queryProviders(data, "gx10-vllm")
if len(matches) != 2 {
t.Fatalf("expected 2 matches, got %d: %+v", len(matches), matches)
}
paths := map[string]interface{}{
matches[0].Path: matches[0].Value,
matches[1].Path: matches[1].Value,
}
val1, ok := paths["model.active_edge_model_group.providers.gx10-vllm"]
if !ok {
t.Errorf("expected path model.active_edge_model_group.providers.gx10-vllm, got keys: %v", paths)
} else {
m, ok := val1.(map[string]interface{})
if !ok || m["capacity_total"] != 4 {
t.Errorf("expected map with capacity_total=4, got %T: %v", val1, val1)
}
}
val2, ok := paths["nodes[1].provider"]
if !ok {
t.Errorf("expected path nodes[1].provider, got keys: %v", paths)
} else {
m, ok := val2.(map[string]interface{})
if !ok || m["id"] != "gx10-vllm" {
t.Errorf("expected map with id=gx10-vllm, got %T: %v", val2, val2)
}
}
}
func TestQueryNodeSortsByPath(t *testing.T) {
data := parseFixture(t)
nodes, ok := data["nodes"].([]interface{})
if !ok {
t.Fatalf("nodes slice not found")
}
for i, n := range nodes {
obj, ok := n.(map[string]interface{})
if ok {
obj["alias"] = "target-node"
obj["id"] = fmt.Sprintf("node-id-%d", i)
}
}
matches := queryNodes(data, "target-node")
if len(matches) < 10 {
t.Fatalf("expected at least 10 matches, got %d", len(matches))
}
for i := 1; i < len(matches); i++ {
if matches[i].Path < matches[i-1].Path {
t.Errorf("matches not sorted by path: %s < %s", matches[i].Path, matches[i-1].Path)
}
}
}
func TestParseFlagsRejectsUnsupportedEnv(t *testing.T) {
_, err := parseFlags([]string{"--env", "unsupported"})
if err == nil {
t.Error("expected error for unsupported env, got nil")
}
}
func TestValidateInventoryRejectsIdentityMismatch(t *testing.T) {
data := parseFixture(t)
err := validateInventory(data, "dev-corp", "")
if err == nil {
t.Error("expected identity mismatch error, got nil")
}
}
func TestValidateInventoryRejectsInvalidProjectionTypes(t *testing.T) {
data := parseFixture(t)
delete(data, "profile")
err := validateInventory(data, "dev", "")
if err == nil {
t.Error("expected error for missing profile, got nil")
}
}
func TestRunClassifiesSchemaError(t *testing.T) {
data := parseFixture(t)
delete(data, "profile")
var stdout, stderr bytes.Buffer
loader := func(env string) (map[string]interface{}, error) {
return data, nil
}
code := run([]string{"--env", "dev"}, &stdout, &stderr, loader)
if code != exitError {
t.Errorf("expected exitError(2), got %d. stderr: %s", code, stderr.String())
}
}
func TestRunExitCodesAndStreams(t *testing.T) {
tests := []struct {
name string
args []string
modifyData func(map[string]interface{})
wantCode int
wantStdout bool
wantStderr bool
}{
{
name: "success env projection",
args: []string{"--env", "dev"},
wantCode: exitOK,
wantStdout: true,
wantStderr: false,
},
{
name: "success query match",
args: []string{"--env", "dev", "--node", "gx10-vllm-node"},
wantCode: exitOK,
wantStdout: true,
wantStderr: false,
},
{
name: "zero match",
args: []string{"--env", "dev", "--node", "definitely-not-a-node"},
wantCode: exitZeroMatch,
wantStdout: false,
wantStderr: true,
},
{
name: "flag error",
args: []string{"--env", "dev", "--model", "x", "--node", "y"},
wantCode: exitError,
wantStdout: false,
wantStderr: true,
},
{
name: "schema error (missing edge)",
args: []string{"--env", "dev"},
modifyData: func(d map[string]interface{}) { delete(d, "edge") },
wantCode: exitError,
wantStdout: false,
wantStderr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data := parseFixture(t)
if tt.modifyData != nil {
tt.modifyData(data)
}
loader := func(env string) (map[string]interface{}, error) {
return data, nil
}
var stdout, stderr bytes.Buffer
code := run(tt.args, &stdout, &stderr, loader)
if code != tt.wantCode {
t.Errorf("expected code %d, got %d. stderr: %s", tt.wantCode, code, stderr.String())
}
if tt.wantStdout && stdout.Len() == 0 {
t.Error("expected output in stdout, got empty")
}
if !tt.wantStdout && stdout.Len() > 0 {
t.Errorf("expected empty stdout, got %q", stdout.String())
}
if tt.wantStderr && stderr.Len() == 0 {
t.Error("expected output in stderr, got empty")
}
if !tt.wantStderr && stderr.Len() > 0 {
t.Errorf("expected empty stderr, got %q", stderr.String())
}
})
}
}
func TestValidateInventoryRejectsInvalidProjectionObjectTypes(t *testing.T) {
tests := []struct {
name string
modify func(map[string]interface{})
wantErr string
}{
{
name: "source is scalar",
modify: func(d map[string]interface{}) { d["source"] = "invalid" },
wantErr: "missing or invalid type for source",
},
{
name: "source is list",
modify: func(d map[string]interface{}) { d["source"] = []interface{}{"a"} },
wantErr: "missing or invalid type for source",
},
{
name: "edge is null",
modify: func(d map[string]interface{}) { d["edge"] = nil },
wantErr: "missing or invalid type for edge",
},
{
name: "build is scalar",
modify: func(d map[string]interface{}) { d["build"] = 42 },
wantErr: "missing or invalid type for build",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data := parseFixture(t)
tt.modify(data)
err := validateInventory(data, "dev", "")
if err == nil {
t.Error("expected error, got nil")
} else if err.Error() != tt.wantErr {
t.Errorf("expected error %q, got %q", tt.wantErr, err.Error())
}
})
}
}
func TestValidateInventoryRequiresProviderModelAndNodes(t *testing.T) {
data := parseFixture(t)
// Remove model for provider query.
delete(data, "model")
err := validateInventory(data, "dev", "provider")
if err == nil {
t.Error("expected error for missing model in provider query, got nil")
} else if err.Error() != "missing or invalid type for model" {
t.Errorf("expected model error, got %q", err.Error())
}
// Restore model but remove nodes for provider query.
data["model"] = map[string]interface{}{
"aliases": map[string]interface{}{},
}
delete(data, "nodes")
err = validateInventory(data, "dev", "provider")
if err == nil {
t.Error("expected error for missing nodes in provider query, got nil")
} else if err.Error() != "missing or invalid type for nodes" {
t.Errorf("expected nodes error, got %q", err.Error())
}
// nodes is wrong type for provider query.
data["nodes"] = "invalid"
err = validateInventory(data, "dev", "provider")
if err == nil {
t.Error("expected error for invalid nodes type in provider query, got nil")
}
// nodes is wrong type for node query.
delete(data, "model")
err = validateInventory(data, "dev", "node")
if err == nil {
t.Error("expected error for invalid nodes type in node query, got nil")
}
}
func TestRunClassifiesProviderSchemaError(t *testing.T) {
data := parseFixture(t)
delete(data, "model")
var stdout, stderr bytes.Buffer
loader := func(env string) (map[string]interface{}, error) {
return data, nil
}
code := run([]string{"--env", "dev", "--provider", "test"}, &stdout, &stderr, loader)
if code != exitError {
t.Errorf("expected exitError(2), got %d. stderr: %s", code, stderr.String())
}
if stdout.Len() > 0 {
t.Errorf("expected empty stdout, got %q", stdout.String())
}
if stderr.Len() == 0 {
t.Error("expected error message in stderr")
}
}
func TestRunHelpUsesInjectedStreams(t *testing.T) {
tests := []struct {
name string
args []string
}{
{"help flag", []string{"--env", "dev", "--help"}},
{"help short", []string{"--env", "dev", "-h"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data := parseFixture(t)
var stdout, stderr bytes.Buffer
loaderCalled := false
loader := func(env string) (map[string]interface{}, error) {
loaderCalled = true
return data, nil
}
code := run(tt.args, &stdout, &stderr, loader)
if code != exitOK {
t.Errorf("expected exitOK(0), got %d", code)
}
if loaderCalled {
t.Error("loader should not be called for help")
}
if stdout.Len() == 0 {
t.Error("expected usage output in stdout")
}
if !strings.Contains(stdout.String(), "usage:") {
t.Errorf("expected usage text in stdout, got %q", stdout.String())
}
if stderr.Len() > 0 {
t.Errorf("expected empty stderr, got %q", stderr.String())
}
})
}
}