mirror of
https://github.com/coder/coder.git
synced 2026-10-31 02:43:21 +08:00
Phase 1 of the Scalable Approach for Adding New IDE Session Types RFC, tracked in #27410. Gives agent session accounting one canonical vocabulary for app names, so later work can report a count per app without the agent and the server disagreeing about what an app is called. - Adds codersdk/appname.go: NormalizeAppName for storage and lookup, and AppFamilyName for the places that need a bounded value, such as a Prometheus label or the Connection_Type enum. - agentssh.Server keeps session counters in a map keyed by normalized name instead of three fixed atomics, dropping entries at zero. - Drops MagicSessionType. Sessions carry plain app names, and unrecognized ones flow through as themselves rather than collapsing to unknown. Wire behavior is unchanged: the agent still reports the four session_count_* fields over Agent API 2.10.
86 lines
2.9 KiB
Go
86 lines
2.9 KiB
Go
package codersdk_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
// Duplicated from the package so the limit stays unexported.
|
|
const maxAppNameLength = 64
|
|
|
|
func TestNormalizeAppName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
}{
|
|
{"NormalizedPassthrough", "vscode", "vscode"},
|
|
{"KnownNameCaseInsensitive", "JetBrains", "jetbrains"},
|
|
{"LegacyAlias", "reconnecting-pty", "reconnecting_pty"},
|
|
{"HyphenatedKnownName", "vscode-insiders", "vscode_insiders"},
|
|
{"UnknownHyphensFolded", "my-future-ide", "my_future_ide"},
|
|
{"UnknownLowercased", "Cursor Nightly", "cursor nightly"},
|
|
{"UnknownPreservesUnicode", "エディタ", "エディタ"},
|
|
{"StripsNullBytes", "cur\x00sor", "cursor"},
|
|
{"TrimsWhitespace", " vscode\t", "vscode"},
|
|
{"Empty", "", "unknown"},
|
|
{"OnlyNullBytes", "\x00\x00", "unknown"},
|
|
{"OnlyWhitespace", " ", "unknown"},
|
|
{"TruncatesToMaxRunes", strings.Repeat("a", maxAppNameLength+10), strings.Repeat("a", maxAppNameLength)},
|
|
{"TruncatesMultibyteSafely", strings.Repeat("あ", maxAppNameLength+1), strings.Repeat("あ", maxAppNameLength)},
|
|
// Padding is trimmed before truncating, so it does not spend the budget.
|
|
{"TrimsPaddingBeforeTruncating", " " + strings.Repeat("a", maxAppNameLength) + " ", strings.Repeat("a", maxAppNameLength)},
|
|
{"TrimsWhitespaceLeftByTruncation", strings.Repeat("a", 60) + " tail", strings.Repeat("a", 60)},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
require.Equal(t, tc.want, codersdk.NormalizeAppName(tc.input))
|
|
})
|
|
}
|
|
}
|
|
|
|
// The usage-app vocabulary is declared independently of the normalized app
|
|
// names because its values are part of the HTTP API. This pins the two
|
|
// together so they cannot drift.
|
|
func TestUsageAppNamesAreNormalized(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for sdkName, want := range map[codersdk.UsageAppName]string{
|
|
codersdk.UsageAppNameVscode: "vscode",
|
|
codersdk.UsageAppNameJetbrains: "jetbrains",
|
|
codersdk.UsageAppNameReconnectingPty: "reconnecting_pty",
|
|
codersdk.UsageAppNameSSH: "ssh",
|
|
} {
|
|
require.Equal(t, want, codersdk.NormalizeAppName(string(sdkName)))
|
|
}
|
|
}
|
|
|
|
func TestAppNameFamily(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
input string
|
|
want codersdk.AppFamilyName
|
|
}{
|
|
{"VSCode", "vscode", codersdk.AppFamilyVSCode},
|
|
{"VSCodeFork", "cursor", codersdk.AppFamilyVSCode},
|
|
{"VSCodeInsidersHyphenated", "vscode-insiders", codersdk.AppFamilyVSCode},
|
|
{"CaseInsensitive", "JetBrains", codersdk.AppFamilyJetBrains},
|
|
{"SSHClientJoinsSSHFamily", "zed", codersdk.AppFamilySSH},
|
|
{"Alias", "reconnecting-pty", codersdk.AppFamilyReconnectingPTY},
|
|
{"Unknown", "SomeFutureIDE", codersdk.AppFamilyUnknown},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
require.Equal(t, tc.want, codersdk.AppNameFamily(tc.input))
|
|
})
|
|
}
|
|
}
|