Ctrl K
ComunidadGuías…

internal/config/shared_upstream_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package config

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"gopkg.in/yaml.v3"
)

func TestSharedUpstreamConfigSurvivesMigrationAndSnapshots(t *testing.T) {
	legacy := []byte(`auth-dir: client-auth
auth-auto-refresh-workers: 3
codex: {disable-codex-cloaking: true, stream-bootstrap-buffering: true, stream-bootstrap-timeout: 10s, orphan-delegation-compatibility: true, model-level-cooling: true, response-steering: true}
claude: {model-level-cooling: true}
claude-code: {disable-cloaking-model-list: true}
disable-claude-cloak-mode: true
claude-header-defaults: {user-agent: client-agent, package-version: 1.2.3, runtime-version: v22.1.0, os: Linux, arch: arm64, timeout: '123', timezone: Asia/Shanghai, stabilize-device-profile: true}
xai: {inject-x-search: true}
oauth: {auth-dir: client-auth, auth-auto-refresh-workers: 3, providers: {codex: {header-defaults: {user-agent: oauth-agent, beta-features: oauth-beta}}}}
api-keys: {codex: [{base-url: https://example.invalid, keys: [{api-key: test-key, disable-codex-cloaking: false}]}]}
`)
	canonical := []byte(`upstream:
  codex: {disable-codex-cloaking: true, stream-bootstrap-buffering: true, stream-bootstrap-timeout: 10s, orphan-delegation-compatibility: true, model-level-cooling: true, response-steering: true}
  claude:
    model-level-cooling: true
    disable-cloaking-model-list: true
    disable-claude-cloak-mode: true
    header-defaults: {user-agent: client-agent, package-version: 1.2.3, runtime-version: v22.1.0, os: Linux, arch: arm64, timeout: '123', timezone: Asia/Shanghai, stabilize-device-profile: true}
  xai: {inject-x-search: true}
oauth: {auth-dir: client-auth, auth-auto-refresh-workers: 3, providers: {codex: {header-defaults: {user-agent: oauth-agent, beta-features: oauth-beta}}}}
api-keys: {codex: [{base-url: https://example.invalid, keys: [{api-key: test-key, disable-codex-cloaking: false}]}]}
`)
	historical := []byte(`oauth:
  auth-dir: client-auth
  auth-auto-refresh-workers: 3
  providers:
    codex: {disable-codex-cloaking: true, stream-bootstrap-buffering: true, stream-bootstrap-timeout: 10s, orphan-delegation-compatibility: true, model-level-cooling: true, response-steering: true, header-defaults: {user-agent: oauth-agent, beta-features: oauth-beta}}
    claude:
      model-level-cooling: true
      claude-code: {disable-cloaking-model-list: true}
      disable-claude-cloak-mode: true
      header-defaults: {user-agent: client-agent, package-version: 1.2.3, runtime-version: v22.1.0, os: Linux, arch: arm64, timeout: '123', timezone: Asia/Shanghai, stabilize-device-profile: true}
    xai: {inject-x-search: true}
api-keys: {codex: [{base-url: https://example.invalid, keys: [{api-key: test-key, disable-codex-cloaking: false}]}]}
`)
	expected := []any{"client-auth", 3, true, true, "10s", true, true, true, true, true, true, "client-agent", "1.2.3", "v22.1.0", "Linux", "arm64", "123", "Asia/Shanghai", true, true}
	for _, tc := range []struct {
		name string
		raw  []byte
	}{
		{"legacy", legacy}, {"upstream", canonical}, {"historical OAuth", historical},
	} {
		t.Run(tc.name, func(t *testing.T) {
			cfg, errParse := ParseConfigBytes(tc.raw)
			if errParse != nil {
				t.Fatal(errParse)
			}
			migrated, _, errMigrate := NormalizeConfigLayout(tc.raw, true)
			if errMigrate != nil {
				t.Fatal(errMigrate)
			}
			if errValidate := ValidateV8Config(migrated); errValidate != nil {
				t.Fatal(errValidate)
			}
			var doc yaml.Node
			if errDecode := yaml.Unmarshal(migrated, &doc); errDecode != nil {
				t.Fatal(errDecode)
			}
			if yamlPath(doc.Content[0], "oauth.auth-dir") == nil || yamlPath(doc.Content[0], "upstream.claude.header-defaults.timezone") == nil || yamlPath(doc.Content[0], "oauth.providers.codex.header-defaults.user-agent") == nil {
				t.Fatal("migration did not separate shared upstream fields from OAuth headers")
			}
			for _, alias := range v8Aliases {
				if yamlPath(doc.Content[0], alias.old) != nil {
					t.Fatalf("historical alias %s survived migration", alias.old)
				}
			}
			snapshot, errMarshal := yaml.Marshal(cfg)
			if errMarshal != nil {
				t.Fatal(errMarshal)
			}
			path := filepath.Join(t.TempDir(), "config.yaml")
			if errWrite := os.WriteFile(path, tc.raw, 0600); errWrite != nil {
				t.Fatal(errWrite)
			}
			if errSave := SaveConfigPreserveComments(path, cfg, true); errSave != nil {
				t.Fatal(errSave)
			}
			saved, errRead := os.ReadFile(path)
			if errRead != nil {
				t.Fatal(errRead)
			}
			for name, raw := range map[string][]byte{"snapshot": snapshot, "migrated": migrated, "saved": saved} {
				restored, errParse := ParseConfigBytes(raw)
				if errParse != nil {
					t.Fatal(errParse)
				}
				for _, view := range []*Config{restored, restored.CloneForRuntime()} {
					for _, scoped := range []*Config{view, view.ForAPIKey()} {
						actual := []any{
							scoped.AuthDir, scoped.AuthAutoRefreshWorkers,
							scoped.Codex.DisableCodexCloaking, scoped.Codex.StreamBootstrapBuffering, scoped.Codex.StreamBootstrapTimeout,
							scoped.Codex.OrphanDelegationCompatibility, scoped.Codex.ModelLevelCooling, scoped.Codex.ResponseSteering,
							scoped.Claude.ModelLevelCooling, scoped.ClaudeCode.DisableCloakingModelList, scoped.DisableClaudeCloakMode,
							scoped.ClaudeHeaderDefaults.UserAgent, scoped.ClaudeHeaderDefaults.PackageVersion, scoped.ClaudeHeaderDefaults.RuntimeVersion,
							scoped.ClaudeHeaderDefaults.OS, scoped.ClaudeHeaderDefaults.Arch, scoped.ClaudeHeaderDefaults.Timeout, scoped.ClaudeHeaderDefaults.Timezone,
							scoped.ClaudeHeaderDefaults.StabilizeDeviceProfile != nil && *scoped.ClaudeHeaderDefaults.StabilizeDeviceProfile,
							scoped.XAI.InjectXSearch,
						}
						if !reflect.DeepEqual(actual, expected) {
							t.Fatalf("%s changed shared configuration: got %#v, want %#v", name, actual, expected)
						}
					}
					if view.ForAPIKey().CodexHeaderDefaults.UserAgent != "" || view.CodexHeaderDefaults.UserAgent != "oauth-agent" || len(view.CodexKey) != 1 || view.CodexKey[0].DisableCodexCloaking == nil || *view.CodexKey[0].DisableCodexCloaking {
						t.Fatal("OAuth-only headers or explicit key override lost their scope")
					}
				}
			}
		})
	}
}

func TestSharedUpstreamPresenceWinsOverHistoricalAliases(t *testing.T) {
	for _, value := range []string{"false", "null"} {
		t.Run(value, func(t *testing.T) {
			raw := []byte("codex: {response-steering: true}\noauth: {providers: {codex: {response-steering: true}, claude: {header-defaults: {user-agent: historical-agent, stabilize-device-profile: true}}}}\nupstream: {codex: {response-steering: " + value + "}, claude: {header-defaults: {user-agent: '', stabilize-device-profile: " + value + "}}}\n")
			for _, migrate := range []bool{false, true} {
				data, _, errNormalize := NormalizeConfigLayout(raw, migrate)
				if errNormalize != nil {
					t.Fatal(errNormalize)
				}
				cfg, errParse := ParseConfigBytes(data)
				if errParse != nil {
					t.Fatal(errParse)
				}
				if cfg.Codex.ResponseSteering || cfg.ClaudeHeaderDefaults.UserAgent != "" || cfg.AuthAutoRefreshWorkers != 0 || (cfg.ClaudeHeaderDefaults.StabilizeDeviceProfile != nil && *cfg.ClaudeHeaderDefaults.StabilizeDeviceProfile) {
					t.Fatal("historical alias overrode an explicit shared zero value")
				}
				if migrate {
					if errValidate := ValidateV8Config(data); errValidate != nil {
						t.Fatal(errValidate)
					}
				}
			}
		})
	}
}

func TestSharedUpstreamEmptyHistoricalContainers(t *testing.T) {
	for _, tc := range []struct{ historical, current string }{
		{"oauth.providers.claude.header-defaults", "upstream.claude.header-defaults"},
		{"oauth.providers.claude.claude-code", "upstream.claude"},
		{"oauth.providers.claude", "upstream.claude"},
		{"oauth.providers.xai", "upstream.xai"},
	} {
		for _, value := range []string{"{}", "null"} {
			t.Run(tc.historical+"/"+value, func(t *testing.T) {
				var root, empty yaml.Node
				root.Kind, root.Tag = yaml.MappingNode, "!!map"
				if errDecode := yaml.Unmarshal([]byte(value), &empty); errDecode != nil {
					t.Fatal(errDecode)
				}
				setYAMLPath(&root, tc.historical, empty.Content[0])
				raw, errMarshal := yaml.Marshal(&root)
				if errMarshal != nil {
					t.Fatal(errMarshal)
				}
				migrated, _, errMigrate := NormalizeConfigLayout(raw, true)
				if errMigrate != nil {
					t.Fatal(errMigrate)
				}
				if errValidate := ValidateV8Config(migrated); errValidate != nil {
					t.Fatal(errValidate)
				}
				var doc yaml.Node
				if errDecode := yaml.Unmarshal(migrated, &doc); errDecode != nil {
					t.Fatal(errDecode)
				}
				if yamlPath(doc.Content[0], tc.historical) != nil || yamlPath(doc.Content[0], tc.current) == nil {
					t.Fatal("empty historical provider container was not migrated")
				}
			})
		}
	}
}