cmd/vet: add subtestnames analyzer; fix all existing violations

Add a new vet analyzer that checks t.Run subtest names don't contain
characters requiring quoting when re-running via "go test -run". This
enforces the style guide rule: don't use spaces or punctuation in
subtest names.

The analyzer flags:
- Direct t.Run calls with string literal names containing spaces,
  regex metacharacters, quotes, or other problematic characters
- Table-driven t.Run(tt.name, ...) calls where tt ranges over a
  slice/map literal with bad name field values

Also fix all 978 existing violations across 81 test files, replacing
spaces with hyphens and shortening long sentence-like names to concise
hyphenated forms.

Updates #19242

Change-Id: Ib0ad96a111bd8e764582d1d4902fe2599454ab65
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
main
Brad Fitzpatrick 2 weeks ago committed by Brad Fitzpatrick
parent 0f02c20c5e
commit 5ef3713c9f
  1. 4
      .github/workflows/vet.yml
  2. 24
      client/freedesktop/freedesktop_test.go
  3. 4
      client/tailscale/tailscale_test.go
  4. 30
      client/web/web_test.go
  5. 75
      clientupdate/clientupdate_test.go
  6. 34
      clientupdate/distsign/distsign_test.go
  7. 18
      cmd/containerboot/kube_test.go
  8. 12
      cmd/derper/derper_test.go
  9. 4
      cmd/gitops-pusher/gitops-pusher_test.go
  10. 30
      cmd/k8s-nameserver/main_test.go
  11. 12
      cmd/k8s-operator/nameserver_test.go
  12. 18
      cmd/k8s-operator/operator_test.go
  13. 24
      cmd/k8s-operator/sts_test.go
  14. 2
      cmd/k8s-operator/tsrecorder_specs_test.go
  15. 8
      cmd/tailscale/cli/cli_test.go
  16. 2
      cmd/tailscale/cli/configure-kube_test.go
  17. 6
      cmd/tailscale/cli/configure-synology-cert_test.go
  18. 4
      cmd/tailscale/cli/exitnode_test.go
  19. 89
      cmd/tailscale/cli/serve_v2_test.go
  20. 4
      cmd/tailscaled/tailscaled_test.go
  21. 123
      cmd/tsidp/tsidp_test.go
  22. 227
      cmd/vet/subtestnames/analyzer.go
  23. 15
      cmd/vet/subtestnames/analyzer_test.go
  24. 112
      cmd/vet/subtestnames/testdata/src/example/example_test.go
  25. 3
      cmd/vet/vet.go
  26. 8
      control/controlclient/map_test.go
  27. 4
      derp/derp_test.go
  28. 56
      derp/xdp/xdp_linux_test.go
  29. 22
      drive/driveimpl/dirfs/dirfs_test.go
  30. 10
      drive/driveimpl/drive_test.go
  31. 16
      feature/identityfederation/identityfederation_test.go
  32. 18
      feature/oauthkey/oauthkey_test.go
  33. 38
      feature/relayserver/relayserver_test.go
  34. 2
      flake.nix
  35. 2
      go.mod.sri
  36. 16
      health/health_test.go
  37. 2
      ipn/ipnlocal/c2n_test.go
  38. 12
      ipn/ipnlocal/cert_test.go
  39. 222
      ipn/ipnlocal/local_test.go
  40. 14
      ipn/ipnlocal/network-lock_test.go
  41. 44
      ipn/ipnlocal/serve_test.go
  42. 6
      ipn/ipnlocal/serve_unix_test.go
  43. 10
      ipn/prefs_test.go
  44. 4
      ipn/serve_test.go
  45. 6
      k8s-operator/reconciler/proxygrouppolicy/proxygrouppolicy_test.go
  46. 18
      k8s-operator/reconciler/tailnet/tailnet_test.go
  47. 10
      log/sockstatlog/logger_test.go
  48. 44
      net/batching/conn_linux_test.go
  49. 6
      net/dns/manager_linux_test.go
  50. 8
      net/dns/resolver/forwarder_test.go
  51. 2
      net/netcheck/netcheck_test.go
  52. 4
      net/netmon/netmon_linux_test.go
  53. 4
      net/speedtest/speedtest_test.go
  54. 8
      net/stun/stun_test.go
  55. 14
      net/tshttpproxy/tshttpproxy_synology_test.go
  56. 10
      net/tshttpproxy/tshttpproxy_test.go
  57. 14
      net/udprelay/endpoint/endpoint_test.go
  58. 6
      net/udprelay/server_test.go
  59. 70
      safeweb/http_test.go
  60. 6
      sessionrecording/connect_test.go
  61. 2
      shell.nix
  62. 8
      ssh/tailssh/accept_env_test.go
  63. 6
      syncs/shardedint_test.go
  64. 16
      tailcfg/proto_port_range_test.go
  65. 4
      tailcfg/tailcfg_test.go
  66. 14
      tka/tailchonk_test.go
  67. 17
      tsconsensus/authorization_test.go
  68. 34
      tsnet/tsnet_test.go
  69. 130
      tstest/clock_test.go
  70. 4
      tstest/integration/vms/vms_test.go
  71. 26
      tstest/resource_test.go
  72. 44
      tsweb/tsweb_test.go
  73. 12
      types/dnstype/dnstype_test.go
  74. 46
      util/cmpver/version_test.go
  75. 8
      util/deephash/deephash_test.go
  76. 46
      util/eventbus/eventbustest/eventbustest_test.go
  77. 12
      util/linuxfw/nftables_runner_test.go
  78. 12
      util/syspolicy/setting/policy_scope_test.go
  79. 58
      util/syspolicy/syspolicy_test.go
  80. 34
      wgengine/magicsock/endpoint_test.go
  81. 6
      wgengine/magicsock/magicsock_linux_test.go
  82. 106
      wgengine/magicsock/magicsock_test.go
  83. 16
      wgengine/magicsock/relaymanager_test.go
  84. 32
      wgengine/router/osrouter/router_linux_test.go
  85. 6
      wgengine/watchdog_test.go
  86. 14
      wgengine/wgcfg/device_test.go

@ -36,8 +36,10 @@ jobs:
- name: Run 'go vet'
working-directory: src
# Use listpkgs --ignore-3p to skip tempfork/ packages, which
# intentionally match upstream and may not follow our style rules.
# Must use ./... instead of tailscale.com/... because the latter will
# include the v2 go client (tailscale.com/client/tailscale/v2) if it's
# a dependency in our go.mod file. Possibly a go vet bug, but avoid
# cross-repo vetting for now so we can safely add the dependency.
run: ./tool/go vet -vettool=/tmp/vettool ./...
run: ./tool/go vet -vettool=/tmp/vettool $(./tool/go run ./tool/listpkgs --ignore-3p ./...)

@ -13,12 +13,12 @@ func TestEscape(t *testing.T) {
name, input, want string
}{
{
name: "no illegal chars",
name: "no-illegal-chars",
input: "/home/user",
want: "/home/user",
},
{
name: "empty string",
name: "empty-string",
input: "",
want: "\"\"",
},
@ -38,12 +38,12 @@ func TestEscape(t *testing.T) {
want: "\"\n\"",
},
{
name: "double quote",
name: "double-quote",
input: "\"",
want: "\"\\\"\"",
},
{
name: "single quote",
name: "single-quote",
input: "'",
want: "\"'\"",
},
@ -53,12 +53,12 @@ func TestEscape(t *testing.T) {
want: "\"\\\\\"",
},
{
name: "greater than",
name: "greater-than",
input: ">",
want: "\">\"",
},
{
name: "less than",
name: "less-than",
input: "<",
want: "\"<\"",
},
@ -93,7 +93,7 @@ func TestEscape(t *testing.T) {
want: "\"*\"",
},
{
name: "question mark",
name: "question-mark",
input: "?",
want: "\"?\"",
},
@ -103,12 +103,12 @@ func TestEscape(t *testing.T) {
want: "\"#\"",
},
{
name: "open paren",
name: "open-paren",
input: "(",
want: "\"(\"",
},
{
name: "close paren",
name: "close-paren",
input: ")",
want: "\")\"",
},
@ -118,17 +118,17 @@ func TestEscape(t *testing.T) {
want: "\"\\`\"",
},
{
name: "char without escape",
name: "char-without-escape",
input: "/home/user\t",
want: "\"/home/user\t\"",
},
{
name: "char with escape",
name: "char-with-escape",
input: "/home/user\\",
want: "\"/home/user\\\\\"",
},
{
name: "all illegal chars",
name: "all-illegal-chars",
input: "/home/user" + needsEscape,
want: "\"/home/user \t\n\\\"'\\\\><~|&;\\$*?#()\\`\"",
},

@ -31,7 +31,7 @@ func TestClientBuildURL(t *testing.T) {
want: `http://127.0.0.1:1234/api/v2/tailnet/example%20dot%20com%3Ffoo=bar`,
},
{
desc: "url.Values",
desc: "url-Values",
elements: []any{"tailnet", "example.com", "acl", url.Values{"details": {"1"}}},
want: `http://127.0.0.1:1234/api/v2/tailnet/example.com/acl?details=1`,
},
@ -71,7 +71,7 @@ func TestClientBuildTailnetURL(t *testing.T) {
want: `http://127.0.0.1:1234/api/v2/tailnet/example.com/foo%20bar%3Fbaz=qux`,
},
{
desc: "url.Values",
desc: "url-Values",
elements: []any{"acl", url.Values{"details": {"1"}}},
want: `http://127.0.0.1:1234/api/v2/tailnet/example.com/acl?details=1`,
},

@ -41,37 +41,37 @@ func TestQnapAuthnURL(t *testing.T) {
want string
}{
{
name: "localhost http",
name: "localhost-http",
in: "http://localhost:8088/",
want: "http://localhost:8088/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "localhost https",
name: "localhost-https",
in: "https://localhost:5000/",
want: "https://localhost:5000/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "IP http",
name: "IP-http",
in: "http://10.1.20.4:80/",
want: "http://10.1.20.4:80/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "IP6 https",
name: "IP6-https",
in: "https://[ff7d:0:1:2::1]/",
want: "https://[ff7d:0:1:2::1]/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "hostname https",
name: "hostname-https",
in: "https://qnap.example.com/",
want: "https://qnap.example.com/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "invalid URL",
name: "invalid-URL",
in: "This is not a URL, it is a really really really really really really really really really really really really long string to exercise the URL truncation code in the error path.",
want: "http://localhost/cgi-bin/authLogin.cgi?qtoken=token",
},
{
name: "err != nil",
name: "err-not-nil",
in: "http://192.168.0.%31/",
want: "http://localhost/cgi-bin/authLogin.cgi?qtoken=token",
},
@ -1516,47 +1516,47 @@ func TestCSRFProtect(t *testing.T) {
wantError bool
}{
{
name: "GET requests with no header are allowed",
name: "GET-no-header-allowed", // GET requests with no header are allowed
method: "GET",
},
{
name: "POST requests with same-origin are allowed",
name: "POST-same-origin-allowed",
method: "POST",
secFetchSite: "same-origin",
},
{
name: "POST requests with cross-site are not allowed",
name: "POST-cross-site-rejected",
method: "POST",
secFetchSite: "cross-site",
wantError: true,
},
{
name: "POST requests with unknown sec-fetch-site values are not allowed",
name: "POST-unknown-sec-fetch-site-rejected",
method: "POST",
secFetchSite: "new-unknown-value",
wantError: true,
},
{
name: "POST requests with none are not allowed",
name: "POST-sec-fetch-none-rejected",
method: "POST",
secFetchSite: "none",
wantError: true,
},
{
name: "POST requests with no sec-fetch-site header but matching host and origin are allowed",
name: "POST-no-sec-fetch-site-matching-host-origin", // no sec-fetch-site header but matching host and origin are allowed
method: "POST",
host: "example.com",
origin: "https://example.com",
},
{
name: "POST requests with no sec-fetch-site and non-matching host and origin are not allowed",
name: "POST-no-sec-fetch-site-mismatched-host-origin-rejected",
method: "POST",
host: "example.com",
origin: "https://example.net",
wantError: true,
},
{
name: "POST requests with no sec-fetch-site and and origin that matches the override are allowed",
name: "POST-no-sec-fetch-site-origin-override-allowed",
method: "POST",
originOverride: "example.net",
host: "internal.example.foo", // Host can be changed by reverse proxies

@ -148,27 +148,27 @@ func TestUpdateYUMRepoTrack(t *testing.T) {
wantErr bool
}{
{
desc: "same track",
desc: "same-track",
before: YUMRepos[StableTrack],
track: StableTrack,
after: YUMRepos[StableTrack],
},
{
desc: "change track",
desc: "change-track",
before: YUMRepos[StableTrack],
track: UnstableTrack,
after: YUMRepos[UnstableTrack],
rewrote: true,
},
{
desc: "change track RC",
desc: "change-track-RC",
before: YUMRepos[StableTrack],
track: ReleaseCandidateTrack,
after: YUMRepos[ReleaseCandidateTrack],
rewrote: true,
},
{
desc: "non-tailscale repo file",
desc: "non-tailscale-repo-file",
before: YUMRepos["FakeRepo"],
track: StableTrack,
wantErr: true,
@ -215,7 +215,7 @@ func TestParseAlpinePackageVersion(t *testing.T) {
wantErr bool
}{
{
desc: "valid version",
desc: "valid-version",
out: `
tailscale-1.44.2-r0 description:
The easiest, most secure way to use WireGuard and 2FA
@ -229,7 +229,7 @@ tailscale-1.44.2-r0 installed size:
want: "1.44.2",
},
{
desc: "wrong package output",
desc: "wrong-package-output",
out: `
busybox-1.36.1-r0 description:
Size optimized toolbox of many common UNIX utilities
@ -243,7 +243,7 @@ busybox-1.36.1-r0 installed size:
wantErr: true,
},
{
desc: "missing version",
desc: "missing-version",
out: `
tailscale description:
The easiest, most secure way to use WireGuard and 2FA
@ -257,12 +257,12 @@ tailscale installed size:
wantErr: true,
},
{
desc: "empty output",
desc: "empty-output",
out: "",
wantErr: true,
},
{
desc: "multiple versions",
desc: "multiple-versions",
out: `
tailscale-1.54.1-r0 description:
The easiest, most secure way to use WireGuard and 2FA
@ -322,14 +322,14 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
track string
}{
{
name: "Up to date",
name: "up-to-date",
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
latestHTTPVersion: "1.95.3",
latestApkVersion: "1.95.3",
track: "unstable",
},
{
name: "Behind unstable",
name: "behind-unstable",
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
latestHTTPVersion: "1.95.4",
latestApkVersion: "1.95.3",
@ -339,7 +339,7 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
track: "unstable",
},
{
name: "Behind stable",
name: "behind-stable",
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v2.40/main",
latestHTTPVersion: "1.94.3",
latestApkVersion: "1.92.1",
@ -349,7 +349,7 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
track: "stable",
},
{
name: "Nothing in dist file",
name: "nothing-in-dist-file",
fileContent: "",
latestHTTPVersion: "1.94.3",
latestApkVersion: "1.92.1",
@ -505,14 +505,14 @@ unique=synology_88f6281_213air
want: "88f6281",
},
{
desc: "missing unique",
desc: "missing-unique",
content: `
company_title="Synology"
`,
wantErr: true,
},
{
desc: "empty unique",
desc: "empty-unique",
content: `
company_title="Synology"
unique=
@ -520,7 +520,7 @@ unique=
wantErr: true,
},
{
desc: "empty unique double-quoted",
desc: "empty-unique-double-quoted",
content: `
company_title="Synology"
unique=""
@ -528,7 +528,7 @@ unique=""
wantErr: true,
},
{
desc: "empty unique single-quoted",
desc: "empty-unique-single-quoted",
content: `
company_title="Synology"
unique=''
@ -536,7 +536,7 @@ unique=''
wantErr: true,
},
{
desc: "malformed unique",
desc: "malformed-unique",
content: `
company_title="Synology"
unique="synology_88f6281"
@ -544,12 +544,12 @@ unique="synology_88f6281"
wantErr: true,
},
{
desc: "empty file",
desc: "empty-file",
content: ``,
wantErr: true,
},
{
desc: "empty lines and comments",
desc: "empty-lines-and-comments",
content: `
# In a file named synoinfo? Shocking!
@ -613,7 +613,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
},
},
{
desc: "don't touch unrelated files",
desc: "skip-unrelated-files", // don't touch unrelated files
before: map[string]string{
"tailscale": "v1",
"tailscaled": "v1",
@ -645,7 +645,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
},
},
{
desc: "ignore extra tarball files",
desc: "ignore-extra-tarball-files",
before: map[string]string{
"tailscale": "v1",
"tailscaled": "v1",
@ -661,7 +661,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
},
},
{
desc: "tarball missing tailscaled",
desc: "tarball-missing-tailscaled",
before: map[string]string{
"tailscale": "v1",
"tailscaled": "v1",
@ -677,7 +677,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
wantErr: true,
},
{
desc: "duplicate tailscale binary",
desc: "duplicate-tailscale-binary",
before: map[string]string{
"tailscale": "v1",
"tailscaled": "v1",
@ -696,7 +696,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
wantErr: true,
},
{
desc: "empty archive",
desc: "empty-archive",
before: map[string]string{
"tailscale": "v1",
"tailscaled": "v1",
@ -952,17 +952,18 @@ func TestCleanupOldDownloads(t *testing.T) {
func TestParseUnraidPluginVersion(t *testing.T) {
tests := []struct {
name string
plgPath string
wantVer string
wantErr string
}{
{plgPath: "testdata/tailscale-1.52.0.plg", wantVer: "1.52.0"},
{plgPath: "testdata/tailscale-1.54.0.plg", wantVer: "1.54.0"},
{plgPath: "testdata/tailscale-nover.plg", wantErr: "version not found in plg file"},
{plgPath: "testdata/tailscale-nover-path-mentioned.plg", wantErr: "version not found in plg file"},
{name: "v1_52_0", plgPath: "testdata/tailscale-1.52.0.plg", wantVer: "1.52.0"},
{name: "v1_54_0", plgPath: "testdata/tailscale-1.54.0.plg", wantVer: "1.54.0"},
{name: "nover", plgPath: "testdata/tailscale-nover.plg", wantErr: "version not found in plg file"},
{name: "nover-path-mentioned", plgPath: "testdata/tailscale-nover-path-mentioned.plg", wantErr: "version not found in plg file"},
}
for _, tt := range tests {
t.Run(tt.plgPath, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got, err := parseUnraidPluginVersion(tt.plgPath)
if got != tt.wantVer {
t.Errorf("got version: %q, want %q", got, tt.wantVer)
@ -992,7 +993,7 @@ func TestConfirm(t *testing.T) {
want bool
}{
{
desc: "on latest stable",
desc: "on-latest-stable",
fromTrack: StableTrack,
toTrack: StableTrack,
fromVer: "1.66.0",
@ -1000,7 +1001,7 @@ func TestConfirm(t *testing.T) {
want: false,
},
{
desc: "stable upgrade",
desc: "stable-upgrade",
fromTrack: StableTrack,
toTrack: StableTrack,
fromVer: "1.66.0",
@ -1008,7 +1009,7 @@ func TestConfirm(t *testing.T) {
want: true,
},
{
desc: "unstable upgrade",
desc: "unstable-upgrade",
fromTrack: UnstableTrack,
toTrack: UnstableTrack,
fromVer: "1.67.1",
@ -1016,7 +1017,7 @@ func TestConfirm(t *testing.T) {
want: true,
},
{
desc: "from stable to unstable",
desc: "from-stable-to-unstable",
fromTrack: StableTrack,
toTrack: UnstableTrack,
fromVer: "1.66.0",
@ -1024,7 +1025,7 @@ func TestConfirm(t *testing.T) {
want: true,
},
{
desc: "from unstable to stable",
desc: "from-unstable-to-stable",
fromTrack: UnstableTrack,
toTrack: StableTrack,
fromVer: "1.67.1",
@ -1032,7 +1033,7 @@ func TestConfirm(t *testing.T) {
want: true,
},
{
desc: "confirm callback rejects",
desc: "confirm-callback-rejects",
fromTrack: StableTrack,
toTrack: StableTrack,
fromVer: "1.66.0",
@ -1043,7 +1044,7 @@ func TestConfirm(t *testing.T) {
want: false,
},
{
desc: "confirm callback allows",
desc: "confirm-callback-allows",
fromTrack: StableTrack,
toTrack: StableTrack,
fromVer: "1.66.0",

@ -30,7 +30,7 @@ func TestDownload(t *testing.T) {
wantErr bool
}{
{
desc: "missing file",
desc: "missing-file",
before: func(*testing.T) {},
src: "hello",
wantErr: true,
@ -44,7 +44,7 @@ func TestDownload(t *testing.T) {
want: []byte("world"),
},
{
desc: "no signature",
desc: "no-signature",
before: func(*testing.T) {
srv.add("hello", []byte("world"))
},
@ -52,7 +52,7 @@ func TestDownload(t *testing.T) {
wantErr: true,
},
{
desc: "bad signature",
desc: "bad-signature",
before: func(*testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", []byte("potato"))
@ -61,7 +61,7 @@ func TestDownload(t *testing.T) {
wantErr: true,
},
{
desc: "signed with untrusted key",
desc: "signed-untrusted-key",
before: func(t *testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
@ -70,7 +70,7 @@ func TestDownload(t *testing.T) {
wantErr: true,
},
{
desc: "signed with root key",
desc: "signed-with-root-key",
before: func(t *testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", ed25519.Sign(srv.roots[0].k, []byte("world")))
@ -79,7 +79,7 @@ func TestDownload(t *testing.T) {
wantErr: true,
},
{
desc: "bad signing key signature",
desc: "bad-signing-key-signature",
before: func(t *testing.T) {
srv.add("distsign.pub.sig", []byte("potato"))
srv.addSigned("hello", []byte("world"))
@ -130,7 +130,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr bool
}{
{
desc: "missing file",
desc: "missing-file",
before: func(*testing.T) {},
src: "hello",
wantErr: true,
@ -143,7 +143,7 @@ func TestValidateLocalBinary(t *testing.T) {
src: "hello",
},
{
desc: "contents changed",
desc: "contents-changed",
before: func(*testing.T) {
srv.addSigned("hello", []byte("new world"))
},
@ -151,7 +151,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr: true,
},
{
desc: "no signature",
desc: "no-signature",
before: func(*testing.T) {
srv.add("hello", []byte("world"))
},
@ -159,7 +159,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr: true,
},
{
desc: "bad signature",
desc: "bad-signature",
before: func(*testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", []byte("potato"))
@ -168,7 +168,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr: true,
},
{
desc: "signed with untrusted key",
desc: "signed-untrusted-key",
before: func(t *testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
@ -177,7 +177,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr: true,
},
{
desc: "signed with root key",
desc: "signed-with-root-key",
before: func(t *testing.T) {
srv.add("hello", []byte("world"))
srv.add("hello.sig", ed25519.Sign(srv.roots[0].k, []byte("world")))
@ -186,7 +186,7 @@ func TestValidateLocalBinary(t *testing.T) {
wantErr: true,
},
{
desc: "bad signing key signature",
desc: "bad-signing-key-signature",
before: func(t *testing.T) {
srv.add("distsign.pub.sig", []byte("potato"))
srv.addSigned("hello", []byte("world"))
@ -341,7 +341,7 @@ func TestParseRootKey(t *testing.T) {
wantErr: true,
},
{
desc: "invalid PEM tag",
desc: "invalid-PEM-tag",
generate: func() ([]byte, []byte, error) {
priv, pub, err := GenerateRootKey()
priv = bytes.Replace(priv, []byte("ROOT "), nil, -1)
@ -350,7 +350,7 @@ func TestParseRootKey(t *testing.T) {
wantErr: true,
},
{
desc: "not PEM",
desc: "not-PEM",
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
wantErr: true,
},
@ -399,7 +399,7 @@ func TestParseSigningKey(t *testing.T) {
wantErr: true,
},
{
desc: "invalid PEM tag",
desc: "invalid-PEM-tag",
generate: func() ([]byte, []byte, error) {
priv, pub, err := GenerateSigningKey()
priv = bytes.Replace(priv, []byte("SIGNING "), nil, -1)
@ -408,7 +408,7 @@ func TestParseSigningKey(t *testing.T) {
wantErr: true,
},
{
desc: "not PEM",
desc: "not-PEM",
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
wantErr: true,
},

@ -31,7 +31,7 @@ func TestSetupKube(t *testing.T) {
kc *kubeClient
}{
{
name: "TS_AUTHKEY set, state Secret exists",
name: "authkey-set-secret-exists",
cfg: &settings{
AuthKey: "foo",
KubeSecret: "foo",
@ -50,7 +50,7 @@ func TestSetupKube(t *testing.T) {
},
},
{
name: "TS_AUTHKEY set, state Secret does not exist, we have permissions to create it",
name: "authkey-set-secret-missing-can-create",
cfg: &settings{
AuthKey: "foo",
KubeSecret: "foo",
@ -69,7 +69,7 @@ func TestSetupKube(t *testing.T) {
},
},
{
name: "TS_AUTHKEY set, state Secret does not exist, we do not have permissions to create it",
name: "authkey-set-secret-missing-cannot-create",
cfg: &settings{
AuthKey: "foo",
KubeSecret: "foo",
@ -89,7 +89,7 @@ func TestSetupKube(t *testing.T) {
wantErr: true,
},
{
name: "TS_AUTHKEY set, we encounter a non-404 error when trying to retrieve the state Secret",
name: "authkey-set-get-secret-non-404-error",
cfg: &settings{
AuthKey: "foo",
KubeSecret: "foo",
@ -109,7 +109,7 @@ func TestSetupKube(t *testing.T) {
wantErr: true,
},
{
name: "TS_AUTHKEY set, we encounter a non-404 error when trying to check Secret permissions",
name: "authkey-set-check-perms-error",
cfg: &settings{
AuthKey: "foo",
KubeSecret: "foo",
@ -127,7 +127,7 @@ func TestSetupKube(t *testing.T) {
},
{
// Interactive login using URL in Pod logs
name: "TS_AUTHKEY not set, state Secret does not exist, we have permissions to create it",
name: "no-authkey-secret-missing-can-create",
cfg: &settings{
KubeSecret: "foo",
},
@ -145,7 +145,7 @@ func TestSetupKube(t *testing.T) {
},
{
// Interactive login using URL in Pod logs
name: "TS_AUTHKEY not set, state Secret exists, but does not contain auth key",
name: "no-authkey-secret-exists-no-key",
cfg: &settings{
KubeSecret: "foo",
},
@ -162,7 +162,7 @@ func TestSetupKube(t *testing.T) {
}},
},
{
name: "TS_AUTHKEY not set, state Secret contains auth key, we do not have RBAC to patch it",
name: "no-authkey-secret-has-key-cannot-patch",
cfg: &settings{
KubeSecret: "foo",
},
@ -180,7 +180,7 @@ func TestSetupKube(t *testing.T) {
wantErr: true,
},
{
name: "TS_AUTHKEY not set, state Secret contains auth key, we have RBAC to patch it",
name: "no-authkey-secret-has-key-can-patch",
cfg: &settings{
KubeSecret: "foo",
},

@ -46,30 +46,30 @@ func TestNoContent(t *testing.T) {
want string
}{
{
name: "no challenge",
name: "no-challenge",
},
{
name: "valid challenge",
name: "valid-challenge",
input: "input",
want: "response input",
},
{
name: "valid challenge hostname",
name: "valid-challenge-hostname",
input: "ts_derp99b.tailscale.com",
want: "response ts_derp99b.tailscale.com",
},
{
name: "invalid challenge",
name: "invalid-challenge",
input: "foo\x00bar",
want: "",
},
{
name: "whitespace invalid challenge",
name: "whitespace-invalid-challenge",
input: "foo bar",
want: "",
},
{
name: "long challenge",
name: "long-challenge",
input: strings.Repeat("x", 65),
want: "",
},

@ -30,7 +30,7 @@ func TestEmbeddedTypeUnmarshal(t *testing.T) {
},
}
t.Run("unmarshal gitops type from acl type", func(t *testing.T) {
t.Run("unmarshal-gitops-from-acl", func(t *testing.T) {
b, _ := json.Marshal(aclTestErr)
var e ACLGitopsTestError
err := json.Unmarshal(b, &e)
@ -41,7 +41,7 @@ func TestEmbeddedTypeUnmarshal(t *testing.T) {
t.Fatalf("user heading for 'ACLError' not found in gitops error: %v", e.Error())
}
})
t.Run("unmarshal acl type from gitops type", func(t *testing.T) {
t.Run("unmarshal-acl-from-gitops", func(t *testing.T) {
b, _ := json.Marshal(gitopsErr)
var e tailscale.ACLTestError
err := json.Unmarshal(b, &e)

@ -24,7 +24,7 @@ func TestNameserver(t *testing.T) {
wantResp *dns.Msg
}{
{
name: "A record query, record exists",
name: "A-record-exists",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeA}},
@ -46,7 +46,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "A record query, record does not exist",
name: "A-record-not-exists",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "baz.bar.com", Qtype: dns.TypeA}},
@ -64,7 +64,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "A record query, but the name is not a valid FQDN",
name: "A-record-invalid-FQDN",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "foo..bar.com", Qtype: dns.TypeA}},
@ -80,7 +80,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "AAAA record query, A record exists",
name: "AAAA-query-A-record-exists",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeAAAA}},
@ -97,7 +97,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "AAAA record query, A record does not exist",
name: "AAAA-query-A-record-not-exists",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "baz.bar.com", Qtype: dns.TypeAAAA}},
@ -114,7 +114,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "AAAA record query with IPv6 record",
name: "AAAA-query-ipv6-record",
ip6: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {net.ParseIP("2001:db8::1")}},
query: &dns.Msg{
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeAAAA}},
@ -136,7 +136,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "Dual-stack: both A and AAAA records exist",
name: "dual-stack-A-and-AAAA",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("dual.bar.com."): {{10, 0, 0, 1}}},
ip6: map[dnsname.FQDN][]net.IP{dnsname.FQDN("dual.bar.com."): {net.ParseIP("2001:db8::1")}},
query: &dns.Msg{
@ -157,7 +157,7 @@ func TestNameserver(t *testing.T) {
}},
},
{
name: "CNAME record query",
name: "CNAME-query",
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
query: &dns.Msg{
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeCNAME}},
@ -200,20 +200,20 @@ func TestResetRecords(t *testing.T) {
wantsErr bool
}{
{
name: "previously empty nameserver.ip4 gets set",
name: "previously-empty-nameserver-ip4-gets-set",
config: []byte(`{"version": "v1alpha1", "ip4": {"foo.bar.com": ["1.2.3.4"]}}`),
wantsIp4: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {{1, 2, 3, 4}}},
wantsIp6: make(map[dnsname.FQDN][]net.IP),
},
{
name: "nameserver.ip4 gets reset",
name: "nameserver-ip4-gets-reset",
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
config: []byte(`{"version": "v1alpha1", "ip4": {"foo.bar.com": ["1.2.3.4"]}}`),
wantsIp4: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {{1, 2, 3, 4}}},
wantsIp6: make(map[dnsname.FQDN][]net.IP),
},
{
name: "configuration with incompatible version",
name: "configuration-with-incompatible-version",
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
config: []byte(`{"version": "v1beta1", "ip4": {"foo.bar.com": ["1.2.3.4"]}}`),
wantsIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
@ -221,26 +221,26 @@ func TestResetRecords(t *testing.T) {
wantsErr: true,
},
{
name: "nameserver.ip4 gets reset to empty config when no configuration is provided",
name: "nameserver-ip4-gets-reset-to-empty-config-when-no-configuration-is-provided",
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
wantsIp4: make(map[dnsname.FQDN][]net.IP),
wantsIp6: make(map[dnsname.FQDN][]net.IP),
},
{
name: "nameserver.ip4 gets reset to empty config when the provided configuration is empty",
name: "nameserver-ip4-gets-reset-to-empty-config-when-the-provided-configuration-is-empty",
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
config: []byte(`{"version": "v1alpha1", "ip4": {}}`),
wantsIp4: make(map[dnsname.FQDN][]net.IP),
wantsIp6: make(map[dnsname.FQDN][]net.IP),
},
{
name: "nameserver.ip6 gets set",
name: "nameserver-ip6-gets-set",
config: []byte(`{"version": "v1alpha1", "ip6": {"foo.bar.com": ["2001:db8::1"]}}`),
wantsIp4: make(map[dnsname.FQDN][]net.IP),
wantsIp6: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {net.ParseIP("2001:db8::1")}},
},
{
name: "dual-stack configuration",
name: "dual-stack-configuration",
config: []byte(`{"version": "v1alpha1", "ip4": {"dual.bar.com": ["10.0.0.1"]}, "ip6": {"dual.bar.com": ["2001:db8::1"]}}`),
wantsIp4: map[dnsname.FQDN][]net.IP{"dual.bar.com.": {{10, 0, 0, 1}}},
wantsIp6: map[dnsname.FQDN][]net.IP{"dual.bar.com.": {net.ParseIP("2001:db8::1")}},

@ -80,7 +80,7 @@ func TestNameserverReconciler(t *testing.T) {
nameserverLabels := nameserverResourceLabels(dnsConfig.Name, tsNamespace)
wantsDeploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "nameserver", Namespace: tsNamespace}, TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.Identifier()}}
t.Run("deployment has expected fields", func(t *testing.T) {
t.Run("deployment-expected-fields", func(t *testing.T) {
if err = yaml.Unmarshal(deployYaml, wantsDeploy); err != nil {
t.Fatalf("unmarshalling yaml: %v", err)
}
@ -102,7 +102,7 @@ func TestNameserverReconciler(t *testing.T) {
})
wantsSvc := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "nameserver", Namespace: tsNamespace}, TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.Identifier()}}
t.Run("service has expected fields", func(t *testing.T) {
t.Run("service-expected-fields", func(t *testing.T) {
if err = yaml.Unmarshal(svcYaml, wantsSvc); err != nil {
t.Fatalf("unmarshalling yaml: %v", err)
}
@ -113,7 +113,7 @@ func TestNameserverReconciler(t *testing.T) {
expectEqual(t, fc, wantsSvc)
})
t.Run("dns config status is set", func(t *testing.T) {
t.Run("dns-config-status-set", func(t *testing.T) {
// Verify that DNSConfig advertizes the nameserver's Service IP address,
// has the ready status condition and tailscale finalizer.
mustUpdate(t, fc, "tailscale", "nameserver", func(svc *corev1.Service) {
@ -136,7 +136,7 @@ func TestNameserverReconciler(t *testing.T) {
expectEqual(t, fc, dnsConfig)
})
t.Run("nameserver image can be updated", func(t *testing.T) {
t.Run("nameserver-image-updated", func(t *testing.T) {
// Verify that nameserver image gets updated to match DNSConfig spec.
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {
dnsCfg.Spec.Nameserver.Image.Tag = "v0.0.2"
@ -146,7 +146,7 @@ func TestNameserverReconciler(t *testing.T) {
expectEqual(t, fc, wantsDeploy)
})
t.Run("reconciler does not overwrite custom configuration", func(t *testing.T) {
t.Run("reconciler-preserves-custom-config", func(t *testing.T) {
// Verify that when another actor sets ConfigMap data, it does not get
// overwritten by nameserver reconciler.
dnsRecords := &operatorutils.Records{Version: "v1alpha1", IP4: map[string][]string{"foo.ts.net": {"1.2.3.4"}}}
@ -175,7 +175,7 @@ func TestNameserverReconciler(t *testing.T) {
expectEqual(t, fc, wantCm)
})
t.Run("uses default nameserver image", func(t *testing.T) {
t.Run("uses-default-nameserver-image", func(t *testing.T) {
// Verify that if dnsconfig.spec.nameserver.image.{repo,tag} are unset,
// the nameserver image defaults to tailscale/k8s-nameserver:unstable.
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {

@ -1498,24 +1498,28 @@ func TestProxyFirewallMode(t *testing.T) {
func Test_isMagicDNSName(t *testing.T) {
tests := []struct {
name string
in string
want bool
}{
{
name: "foo-tail4567-ts-net",
in: "foo.tail4567.ts.net",
want: true,
},
{
name: "foo-tail4567-ts-net-trailing-dot",
in: "foo.tail4567.ts.net.",
want: true,
},
{
name: "foo-tail4567",
in: "foo.tail4567",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
if got := isMagicDNSName(tt.in); got != tt.want {
t.Errorf("isMagicDNSName(%q) = %v, want %v", tt.in, got, tt.want)
}
@ -1756,7 +1760,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want string
}{
{
name: "success- custom domain",
name: "success-custom-domain",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "department.org.io")},
},
@ -1764,7 +1768,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want: "department.org.io",
},
{
name: "success- default domain",
name: "success-default-domain",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.cluster.local."), toFQDN(t, "svc.cluster.local."), toFQDN(t, "cluster.local.")},
},
@ -1772,7 +1776,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want: "cluster.local",
},
{
name: "only two search domains found",
name: "only-two-search-domains",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "svc.department.org.io"), toFQDN(t, "department.org.io")},
},
@ -1780,7 +1784,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want: "cluster.local",
},
{
name: "first search domain does not match the expected structure",
name: "first-search-domain-mismatch",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.bar.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "some.other.fqdn")},
},
@ -1788,7 +1792,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want: "cluster.local",
},
{
name: "second search domain does not match the expected structure",
name: "second-search-domain-mismatch",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "foo.department.org.io"), toFQDN(t, "some.other.fqdn")},
},
@ -1796,7 +1800,7 @@ func Test_clusterDomainFromResolverConf(t *testing.T) {
want: "cluster.local",
},
{
name: "third search domain does not match the expected structure",
name: "third-search-domain-mismatch",
conf: &resolvconffile.Config{
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "some.other.fqdn")},
},

@ -324,76 +324,76 @@ func Test_mergeStatefulSetLabelsOrAnnots(t *testing.T) {
want map[string]string
}{
{
name: "no custom labels specified and none present in current labels, return current labels",
name: "no-custom-labels-none-present",
current: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
want: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
managed: tailscaleManagedLabels,
},
{
name: "no custom labels specified, but some present in current labels, return tailscale managed labels only from the current labels",
name: "no-custom-labels-some-present",
current: map[string]string{"foo": "bar", "something.io/foo": "bar", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
want: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
managed: tailscaleManagedLabels,
},
{
name: "custom labels specified, current labels only contain tailscale managed labels, return a union of both",
name: "custom-labels-with-managed-only",
current: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
want: map[string]string{"foo": "bar", "something.io/foo": "bar", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
managed: tailscaleManagedLabels,
},
{
name: "custom labels specified, current labels contain tailscale managed labels and custom labels, some of which re not present in the new custom labels, return a union of managed labels and the desired custom labels",
name: "custom-labels-stale-removed",
current: map[string]string{"foo": "bar", "bar": "baz", "app": "1234", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
want: map[string]string{"foo": "bar", "something.io/foo": "bar", "app": "1234", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
managed: tailscaleManagedLabels,
},
{
name: "no current labels present, return custom labels only",
name: "no-current-labels-return-custom",
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
managed: tailscaleManagedLabels,
},
{
name: "no current labels present, no custom labels specified, return empty map",
name: "no-current-no-custom-return-empty",
want: map[string]string{},
managed: tailscaleManagedLabels,
},
{
name: "no custom annots specified and none present in current annots, return current annots",
name: "no-custom-annots-none-present",
current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
managed: tailscaleManagedAnnotations,
},
{
name: "no custom annots specified, but some present in current annots, return tailscale managed annots only from the current annots",
name: "no-custom-annots-some-present",
current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
managed: tailscaleManagedAnnotations,
},
{
name: "custom annots specified, current annots only contain tailscale managed annots, return a union of both",
name: "custom-annots-with-managed-only",
current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
want: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
managed: tailscaleManagedAnnotations,
},
{
name: "custom annots specified, current annots contain tailscale managed annots and custom annots, some of which are not present in the new custom annots, return a union of managed annots and the desired custom annots",
name: "custom-annots-stale-removed",
current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
custom: map[string]string{"something.io/foo": "bar"},
want: map[string]string{"something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
managed: tailscaleManagedAnnotations,
},
{
name: "no current annots present, return custom annots only",
name: "no-current-annots-return-custom",
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
managed: tailscaleManagedAnnotations,
},
{
name: "no current labels present, no custom labels specified, return empty map",
name: "no-current-annots-no-custom-return-empty",
want: map[string]string{},
managed: tailscaleManagedAnnotations,
},

@ -17,7 +17,7 @@ import (
)
func TestRecorderSpecs(t *testing.T) {
t.Run("ensure spec fields are passed through correctly", func(t *testing.T) {
t.Run("spec-fields-passthrough", func(t *testing.T) {
tsr := &tsapi.Recorder{
ObjectMeta: metav1.ObjectMeta{
Name: "test",

@ -1533,13 +1533,13 @@ func TestParseNLArgs(t *testing.T) {
parseDisablements: true,
},
{
name: "key no votes",
name: "key-no-votes",
input: []string{"nlpub:" + strings.Repeat("00", 32)},
parseKeys: true,
wantKeys: []tka.Key{{Kind: tka.Key25519, Votes: 1, Public: bytes.Repeat([]byte{0}, 32)}},
},
{
name: "key with votes",
name: "key-with-votes",
input: []string{"nlpub:" + strings.Repeat("01", 32) + "?5"},
parseKeys: true,
wantKeys: []tka.Key{{Kind: tka.Key25519, Votes: 5, Public: bytes.Repeat([]byte{1}, 32)}},
@ -1551,13 +1551,13 @@ func TestParseNLArgs(t *testing.T) {
wantDisablements: [][]byte{bytes.Repeat([]byte{2}, 32), bytes.Repeat([]byte{3}, 32)},
},
{
name: "disablements not allowed",
name: "disablements-not-allowed",
input: []string{"disablement:" + strings.Repeat("02", 32)},
parseKeys: true,
wantErr: fmt.Errorf("parsing key 1: key hex string doesn't have expected type prefix tlpub:"),
},
{
name: "keys not allowed",
name: "keys-not-allowed",
input: []string{"nlpub:" + strings.Repeat("02", 32)},
parseDisablements: true,
wantErr: fmt.Errorf("parsing argument 1: expected value with \"disablement:\" or \"disablement-secret:\" prefix, got %q", "nlpub:0202020202020202020202020202020202020202020202020202020202020202"),

@ -76,7 +76,7 @@ users:
token: unused`,
},
{
name: "all configs, clusters, users have been deleted",
name: "all-configs-clusters-users-deleted",
in: `apiVersion: v1
clusters: null
contexts: null

@ -30,7 +30,7 @@ func Test_listCerts(t *testing.T) {
wantErr bool
}{
{
name: "normal response",
name: "normal-response",
caller: fakeAPICaller{
Data: json.RawMessage(`{
"certificates" : [
@ -117,12 +117,12 @@ func Test_listCerts(t *testing.T) {
},
},
{
name: "call error",
name: "call-error",
caller: fakeAPICaller{nil, fmt.Errorf("caller failed")},
wantErr: true,
},
{
name: "payload decode error",
name: "payload-decode-error",
caller: fakeAPICaller{json.RawMessage("This isn't JSON!"), nil},
wantErr: true,
},

@ -14,7 +14,7 @@ import (
)
func TestFilterFormatAndSortExitNodes(t *testing.T) {
t.Run("without filter", func(t *testing.T) {
t.Run("without-filter", func(t *testing.T) {
ps := []*ipnstate.PeerStatus{
{
HostName: "everest-1",
@ -139,7 +139,7 @@ func TestFilterFormatAndSortExitNodes(t *testing.T) {
}
})
t.Run("with country filter", func(t *testing.T) {
t.Run("with-country-filter", func(t *testing.T) {
ps := []*ipnstate.PeerStatus{
{
HostName: "baker-1",

@ -1056,49 +1056,49 @@ func TestSrcTypeFromFlags(t *testing.T) {
expectedErr bool
}{
{
name: "only http set",
name: "only-http-set",
env: &serveEnv{http: 80},
expectedType: serveTypeHTTP,
expectedPort: 80,
expectedErr: false,
},
{
name: "only https set",
name: "only-https-set",
env: &serveEnv{https: 10000},
expectedType: serveTypeHTTPS,
expectedPort: 10000,
expectedErr: false,
},
{
name: "only tcp set",
name: "only-tcp-set",
env: &serveEnv{tcp: 8000},
expectedType: serveTypeTCP,
expectedPort: 8000,
expectedErr: false,
},
{
name: "only tls-terminated-tcp set",
name: "only-tls-terminated-tcp-set",
env: &serveEnv{tlsTerminatedTCP: 8080},
expectedType: serveTypeTLSTerminatedTCP,
expectedPort: 8080,
expectedErr: false,
},
{
name: "defaults to https, port 443",
name: "defaults-to-https-443",
env: &serveEnv{},
expectedType: serveTypeHTTPS,
expectedPort: 443,
expectedErr: false,
},
{
name: "defaults to https, port 443 for service",
name: "defaults-to-https-443-for-service",
env: &serveEnv{service: "svc:foo"},
expectedType: serveTypeHTTPS,
expectedPort: 443,
expectedErr: false,
},
{
name: "multiple types set",
name: "multiple-types-set",
env: &serveEnv{http: 80, https: 443},
expectedPort: 0,
expectedErr: true,
@ -1235,19 +1235,20 @@ func TestAcceptSetAppCapsFlag(t *testing.T) {
func TestCleanURLPath(t *testing.T) {
tests := []struct {
name string
input string
expected string
wantErr bool
}{
{input: "", expected: "/"},
{input: "/", expected: "/"},
{input: "/foo", expected: "/foo"},
{input: "/foo/", expected: "/foo/"},
{input: "/../bar", wantErr: true},
{name: "empty", input: "", expected: "/"},
{name: "slash", input: "/", expected: "/"},
{name: "foo", input: "/foo", expected: "/foo"},
{name: "foo-trailing-slash", input: "/foo/", expected: "/foo/"},
{name: "dotdot-bar", input: "/../bar", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
actual, err := cleanURLPath(tt.input)
if tt.wantErr == true && err == nil {
@ -1275,18 +1276,18 @@ func TestAddServiceToPrefs(t *testing.T) {
expected []string
}{
{
name: "add service to empty prefs",
name: "add-service-to-empty-prefs",
svcName: "svc:foo",
expected: []string{"svc:foo"},
},
{
name: "add service to existing prefs",
name: "add-service-to-existing-prefs",
svcName: "svc:bar",
startServices: []string{"svc:foo"},
expected: []string{"svc:foo", "svc:bar"},
},
{
name: "add existing service to prefs",
name: "add-existing-service-to-prefs",
svcName: "svc:foo",
startServices: []string{"svc:foo"},
expected: []string{"svc:foo"},
@ -1323,18 +1324,18 @@ func TestRemoveServiceFromPrefs(t *testing.T) {
expected []string
}{
{
name: "remove service from empty prefs",
name: "remove-service-from-empty-prefs",
svcName: "svc:foo",
expected: []string{},
},
{
name: "remove existing service from prefs",
name: "remove-existing-service-from-prefs",
svcName: "svc:foo",
startServices: []string{"svc:foo"},
expected: []string{},
},
{
name: "remove service not in prefs",
name: "remove-service-not-in-prefs",
svcName: "svc:bar",
startServices: []string{"svc:foo"},
expected: []string{"svc:foo"},
@ -1446,7 +1447,7 @@ func TestMessageForPort(t *testing.T) {
}, "\n"),
},
{
name: "serve service http",
name: "serve-service-http",
subcmd: serve,
serveConfig: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1490,7 +1491,7 @@ func TestMessageForPort(t *testing.T) {
}, "\n"),
},
{
name: "serve service no capmap",
name: "serve-service-no-capmap",
subcmd: serve,
serveConfig: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1534,7 +1535,7 @@ func TestMessageForPort(t *testing.T) {
}, "\n"),
},
{
name: "serve service https non-default port",
name: "serve-service-https-non-default-port",
subcmd: serve,
serveConfig: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1576,7 +1577,7 @@ func TestMessageForPort(t *testing.T) {
}, "\n"),
},
{
name: "serve service TCPForward",
name: "serve-service-TCPForward",
subcmd: serve,
serveConfig: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1613,7 +1614,7 @@ func TestMessageForPort(t *testing.T) {
}, "\n"),
},
{
name: "serve service Tun",
name: "serve-service-Tun",
subcmd: serve,
serveConfig: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1790,7 +1791,7 @@ func TestSetServe(t *testing.T) {
expectErr bool
}{
{
name: "add new handler",
name: "add-new-handler",
desc: "add a new http handler to empty config",
cfg: &ipn.ServeConfig{},
dnsName: "foo.test.ts.net",
@ -1810,7 +1811,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "update http handler",
name: "update-http-handler",
desc: "update an existing http handler on the same port to same type",
cfg: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}},
@ -1839,7 +1840,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "update TCP handler",
name: "update-TCP-handler",
desc: "update an existing TCP handler on the same port to a http handler",
cfg: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{80: {TCPForward: "http://localhost:3000"}},
@ -1852,7 +1853,7 @@ func TestSetServe(t *testing.T) {
expectErr: true,
},
{
name: "add new service handler",
name: "add-new-service-handler",
desc: "add a new service TCP handler to empty config",
cfg: &ipn.ServeConfig{},
@ -1869,7 +1870,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "update service handler",
name: "update-service-handler",
desc: "update an existing service TCP handler on the same port to same type",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1891,7 +1892,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "update service handler",
name: "update-service-handler",
desc: "update an existing service TCP handler on the same port to a http handler",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1908,7 +1909,7 @@ func TestSetServe(t *testing.T) {
expectErr: true,
},
{
name: "add new service handler",
name: "add-new-service-handler",
desc: "add a new service HTTP handler to empty config",
cfg: &ipn.ServeConfig{},
dnsName: "svc:bar",
@ -1932,7 +1933,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "update existing service handler",
name: "update-existing-service-handler",
desc: "update an existing service HTTP handler",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1969,7 +1970,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "add new service handler",
name: "add-new-service-handler",
desc: "add a new service HTTP handler to existing service config",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2014,7 +2015,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "add new service mount",
name: "add-new-service-mount",
desc: "add a new service mount to existing service config",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2054,7 +2055,7 @@ func TestSetServe(t *testing.T) {
},
},
{
name: "add new service handler",
name: "add-new-service-handler",
desc: "add a new service handler in tun mode to empty config",
cfg: &ipn.ServeConfig{},
dnsName: "svc:bar",
@ -2103,7 +2104,7 @@ func TestUnsetServe(t *testing.T) {
expectErr bool
}{
{
name: "unset http handler",
name: "unset-http-handler",
desc: "remove an existing http handler",
cfg: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -2128,7 +2129,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: false,
},
{
name: "unset service handler",
name: "unset-service-handler",
desc: "remove an existing service TCP handler",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2157,7 +2158,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: false,
},
{
name: "unset service handler tun",
name: "unset-service-handler-tun",
desc: "remove an existing service handler in tun mode",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2175,7 +2176,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: false,
},
{
name: "unset service handler tcp",
name: "unset-service-handler-tcp",
desc: "remove an existing service TCP handler",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2196,7 +2197,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: false,
},
{
name: "unset http handler not found",
name: "unset-http-handler-not-found",
desc: "try to remove a non-existing http handler",
cfg: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -2221,7 +2222,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: true,
},
{
name: "unset service handler not found",
name: "unset-service-handler-not-found",
desc: "try to remove a non-existing service TCP handler",
cfg: &ipn.ServeConfig{
@ -2253,7 +2254,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: true,
},
{
name: "unset service doesn't exist",
name: "unset-service-doesnt-exist",
desc: "try to remove a non-existing service's handler",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -2273,7 +2274,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: true,
},
{
name: "unset tcp while port is in use",
name: "unset-tcp-while-port-in-use",
desc: "try to remove a TCP handler while the port is used for web",
cfg: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -2297,7 +2298,7 @@ func TestUnsetServe(t *testing.T) {
expectErr: true,
},
{
name: "unset service tcp while port is in use",
name: "unset-service-tcp-while-port-in-use",
desc: "try to remove a service TCP handler while the port is used for web",
cfg: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{

@ -58,7 +58,7 @@ func TestStateStoreError(t *testing.T) {
args.statedir = t.TempDir()
args.tunname = "userspace-networking"
t.Run("new state", func(t *testing.T) {
t.Run("new-state", func(t *testing.T) {
sys := tsd.NewSystem()
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
lb, err := getLocalBackend(t.Context(), t.Logf, logID.Public(), sys)
@ -70,7 +70,7 @@ func TestStateStoreError(t *testing.T) {
t.Errorf("StateStoreHealth is unhealthy on fresh LocalBackend:\n%s", strings.Join(lb.HealthTracker().Strings(), "\n"))
}
})
t.Run("corrupt state", func(t *testing.T) {
t.Run("corrupt-state", func(t *testing.T) {
sys := tsd.NewSystem()
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
// Populate the state file with something that will fail to parse to

@ -137,14 +137,14 @@ func TestFlattenExtraClaims(t *testing.T) {
expected map[string]any
}{
{
name: "empty extra claims",
name: "empty-extra-claims",
input: []capRule{
{ExtraClaims: map[string]any{}},
},
expected: map[string]any{},
},
{
name: "string and number values",
name: "string-and-number-values",
input: []capRule{
{
ExtraClaims: map[string]any{
@ -159,7 +159,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "slice of strings and ints",
name: "slice-of-strings-and-ints",
input: []capRule{
{
ExtraClaims: map[string]any{
@ -172,7 +172,8 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "duplicate values deduplicated (slice input)",
// duplicate values deduplicated via slice input
name: "dedup-slice-input",
input: []capRule{
{
ExtraClaims: map[string]any{
@ -190,7 +191,8 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "ignore unsupported map type, keep valid scalar",
// ignore unsupported map type, keep valid scalar
name: "ignore-unsupported-map-keep-scalar",
input: []capRule{
{
ExtraClaims: map[string]any{
@ -204,7 +206,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "scalar first, slice second",
name: "scalar-first-slice-second",
input: []capRule{
{ExtraClaims: map[string]any{"foo": "bar"}},
{ExtraClaims: map[string]any{"foo": []any{"baz"}}},
@ -214,7 +216,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "conflicting scalar and unsupported map",
name: "conflicting-scalar-and-unsupported-map",
input: []capRule{
{ExtraClaims: map[string]any{"foo": "bar"}},
{ExtraClaims: map[string]any{"foo": map[string]any{"bad": "entry"}}},
@ -224,7 +226,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "multiple slices with overlap",
name: "multiple-slices-with-overlap",
input: []capRule{
{ExtraClaims: map[string]any{"roles": []any{"admin", "user"}}},
{ExtraClaims: map[string]any{"roles": []any{"admin", "guest"}}},
@ -234,7 +236,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "slice with unsupported values",
name: "slice-with-unsupported-values",
input: []capRule{
{ExtraClaims: map[string]any{
"mixed": []any{"ok", 42, map[string]string{"oops": "fail"}},
@ -245,7 +247,7 @@ func TestFlattenExtraClaims(t *testing.T) {
},
},
{
name: "duplicate scalar value",
name: "duplicate-scalar-value",
input: []capRule{
{ExtraClaims: map[string]any{"env": "prod"}},
{ExtraClaims: map[string]any{"env": "prod"}},
@ -279,7 +281,7 @@ func TestExtraClaims(t *testing.T) {
expectError bool
}{
{
name: "extra claim",
name: "extra-claim",
claim: tailscaleClaims{
Claims: jwt.Claims{},
Nonce: "foobar",
@ -312,7 +314,7 @@ func TestExtraClaims(t *testing.T) {
},
},
{
name: "duplicate claim distinct values",
name: "duplicate-claim-distinct-values",
claim: tailscaleClaims{
Claims: jwt.Claims{},
Nonce: "foobar",
@ -350,7 +352,7 @@ func TestExtraClaims(t *testing.T) {
},
},
{
name: "multiple extra claims",
name: "multiple-extra-claims",
claim: tailscaleClaims{
Claims: jwt.Claims{},
Nonce: "foobar",
@ -389,7 +391,7 @@ func TestExtraClaims(t *testing.T) {
},
},
{
name: "overwrite claim",
name: "overwrite-claim",
claim: tailscaleClaims{
Claims: jwt.Claims{},
Nonce: "foobar",
@ -422,7 +424,7 @@ func TestExtraClaims(t *testing.T) {
expectError: true,
},
{
name: "empty extra claims",
name: "empty-extra-claims",
claim: tailscaleClaims{
Claims: jwt.Claims{},
Nonce: "foobar",
@ -496,21 +498,21 @@ func TestServeToken(t *testing.T) {
expected map[string]any
}{
{
name: "GET not allowed",
name: "GET-not-allowed",
method: "GET",
grantType: "authorization_code",
strictMode: false,
expectError: true,
},
{
name: "unsupported grant type",
name: "unsupported-grant-type",
method: "POST",
grantType: "pkcs",
strictMode: false,
expectError: true,
},
{
name: "invalid code",
name: "invalid-code",
method: "POST",
grantType: "authorization_code",
code: "invalid-code",
@ -518,7 +520,7 @@ func TestServeToken(t *testing.T) {
expectError: true,
},
{
name: "omit code from form",
name: "omit-code-from-form",
method: "POST",
grantType: "authorization_code",
omitCode: true,
@ -526,7 +528,7 @@ func TestServeToken(t *testing.T) {
expectError: true,
},
{
name: "invalid redirect uri",
name: "invalid-redirect-uri",
method: "POST",
grantType: "authorization_code",
code: "valid-code",
@ -536,7 +538,7 @@ func TestServeToken(t *testing.T) {
expectError: true,
},
{
name: "invalid remoteAddr",
name: "invalid-remoteAddr",
method: "POST",
grantType: "authorization_code",
redirectURI: "https://rp.example.com/callback",
@ -546,7 +548,7 @@ func TestServeToken(t *testing.T) {
expectError: true,
},
{
name: "extra claim included (non-strict)",
name: "extra-claim-included-non-strict",
method: "POST",
grantType: "authorization_code",
redirectURI: "https://rp.example.com/callback",
@ -568,7 +570,8 @@ func TestServeToken(t *testing.T) {
},
},
{
name: "attempt to overwrite protected claim (non-strict)",
// attempt to overwrite protected claim in non-strict mode
name: "overwrite-protected-claim-non-strict",
method: "POST",
grantType: "authorization_code",
redirectURI: "https://rp.example.com/callback",
@ -708,7 +711,7 @@ func TestExtraUserInfo(t *testing.T) {
expectError bool
}{
{
name: "extra claim",
name: "extra-claim",
tokenValidTill: time.Now().Add(1 * time.Minute),
caps: tailcfg.PeerCapMap{
tailcfg.PeerCapabilityTsIDP: {
@ -725,7 +728,7 @@ func TestExtraUserInfo(t *testing.T) {
},
},
{
name: "duplicate claim distinct values",
name: "duplicate-claim-distinct-values",
tokenValidTill: time.Now().Add(1 * time.Minute),
caps: tailcfg.PeerCapMap{
tailcfg.PeerCapabilityTsIDP: {
@ -742,7 +745,7 @@ func TestExtraUserInfo(t *testing.T) {
},
},
{
name: "multiple extra claims",
name: "multiple-extra-claims",
tokenValidTill: time.Now().Add(1 * time.Minute),
caps: tailcfg.PeerCapMap{
tailcfg.PeerCapabilityTsIDP: {
@ -761,13 +764,13 @@ func TestExtraUserInfo(t *testing.T) {
},
},
{
name: "empty extra claims",
name: "empty-extra-claims",
caps: tailcfg.PeerCapMap{},
tokenValidTill: time.Now().Add(1 * time.Minute),
expected: map[string]any{},
},
{
name: "attempt to overwrite protected claim",
name: "overwrite-protected-claim",
tokenValidTill: time.Now().Add(1 * time.Minute),
caps: tailcfg.PeerCapMap{
tailcfg.PeerCapabilityTsIDP: {
@ -783,7 +786,7 @@ func TestExtraUserInfo(t *testing.T) {
expectError: true,
},
{
name: "extra claim omitted",
name: "extra-claim-omitted",
tokenValidTill: time.Now().Add(1 * time.Minute),
caps: tailcfg.PeerCapMap{
tailcfg.PeerCapabilityTsIDP: {
@ -798,7 +801,7 @@ func TestExtraUserInfo(t *testing.T) {
expected: map[string]any{},
},
{
name: "expired token",
name: "expired-token",
caps: tailcfg.PeerCapMap{},
tokenValidTill: time.Now().Add(-1 * time.Minute),
expected: map[string]any{},
@ -1131,19 +1134,22 @@ func TestGetAllowInsecureRegistration(t *testing.T) {
expectAllowInsecureRegistration bool
}{
{
name: "flag explicitly set to false - insecure registration disabled (strict mode)",
// flag explicitly set to false - insecure registration disabled (strict mode)
name: "flag-false-insecure-disabled",
flagSet: true,
flagValue: false,
expectAllowInsecureRegistration: false,
},
{
name: "flag explicitly set to true - insecure registration enabled",
// flag explicitly set to true - insecure registration enabled
name: "flag-true-insecure-enabled",
flagSet: true,
flagValue: true,
expectAllowInsecureRegistration: true,
},
{
name: "flag unset - insecure registration enabled (default for backward compatibility)",
// flag unset - insecure registration enabled (default for backward compatibility)
name: "flag-unset-insecure-enabled-default",
flagSet: false,
flagValue: false, // not used when unset
expectAllowInsecureRegistration: true,
@ -1192,7 +1198,7 @@ func TestMigrateOAuthClients(t *testing.T) {
expectOldRenamed bool
}{
{
name: "migrate from old file to new file",
name: "migrate-old-to-new",
setupOldFile: true,
oldFileContent: map[string]*funnelClient{
"old-client": {
@ -1206,7 +1212,7 @@ func TestMigrateOAuthClients(t *testing.T) {
expectOldRenamed: true,
},
{
name: "new file already exists - no migration",
name: "new-file-exists-no-migration",
setupNewFile: true,
newFileContent: map[string]*funnelClient{
"existing-client": {
@ -1220,12 +1226,12 @@ func TestMigrateOAuthClients(t *testing.T) {
expectOldRenamed: false,
},
{
name: "neither file exists - create empty new file",
name: "neither-exists-create-empty",
expectNewFileExists: true,
expectOldRenamed: false,
},
{
name: "both files exist - prefer new file",
name: "both-exist-prefer-new",
setupOldFile: true,
setupNewFile: true,
oldFileContent: map[string]*funnelClient{
@ -1373,19 +1379,19 @@ func TestGetConfigFilePath(t *testing.T) {
expectError bool
}{
{
name: "file exists in current directory - use current directory",
name: "file-in-cwd-use-cwd",
fileName: "test-config.json",
createInCwd: true,
expectInCwd: true,
},
{
name: "file does not exist - use root path",
name: "file-missing-use-root",
fileName: "test-config.json",
createInCwd: false,
expectInCwd: false,
},
{
name: "file exists in both - prefer current directory",
name: "file-in-both-prefer-cwd",
fileName: "test-config.json",
createInCwd: true,
createInRoot: true,
@ -1472,7 +1478,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
}{
// Security boundary test: funnel rejection
{
name: "funnel requests are always rejected for security",
name: "funnel-rejected",
strictMode: true,
clientID: "test-client",
redirectURI: "https://rp.example.com/callback",
@ -1487,7 +1493,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
// Strict mode parameter validation tests (non-funnel)
{
name: "strict mode - missing client_id",
name: "strict-missing-client_id",
strictMode: true,
clientID: "",
redirectURI: "https://rp.example.com/callback",
@ -1496,7 +1502,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "strict mode - missing redirect_uri",
name: "strict-missing-redirect_uri",
strictMode: true,
clientID: "test-client",
redirectURI: "",
@ -1507,7 +1513,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
// Strict mode client validation tests (non-funnel)
{
name: "strict mode - invalid client_id",
name: "strict-invalid-client_id",
strictMode: true,
clientID: "invalid-client",
redirectURI: "https://rp.example.com/callback",
@ -1517,7 +1523,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "strict mode - redirect_uri mismatch",
name: "strict-redirect_uri-mismatch",
strictMode: true,
clientID: "test-client",
redirectURI: "https://wrong.example.com/callback",
@ -1666,7 +1672,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectIDToken bool
}{
{
name: "strict mode - valid token exchange with form credentials",
name: "strict-token-exchange-form-creds",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1680,7 +1686,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectIDToken: true,
},
{
name: "strict mode - valid token exchange with basic auth",
name: "strict-token-exchange-basic-auth",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1695,7 +1701,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectIDToken: true,
},
{
name: "strict mode - missing client credentials",
name: "strict-missing-client-creds",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1708,7 +1714,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectCode: http.StatusUnauthorized,
},
{
name: "strict mode - client_id mismatch",
name: "strict-client_id-mismatch",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1722,7 +1728,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "strict mode - invalid client secret",
name: "strict-invalid-client-secret",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1737,7 +1743,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectCode: http.StatusUnauthorized,
},
{
name: "strict mode - redirect_uri mismatch",
name: "strict-redirect_uri-mismatch",
strictMode: true,
method: "POST",
grantType: "authorization_code",
@ -1752,7 +1758,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "non-strict mode - no client validation required",
name: "non-strict-no-client-validation",
strictMode: false,
method: "POST",
grantType: "authorization_code",
@ -1913,7 +1919,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectUserInfo bool
}{
{
name: "strict mode - valid token with existing client",
name: "strict-valid-token-existing-client",
strictMode: true,
setupToken: true,
setupClient: true,
@ -1923,7 +1929,8 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectUserInfo: true,
},
{
name: "strict mode - valid token but client no longer exists",
// valid token but client no longer exists
name: "strict-token-client-deleted",
strictMode: true,
setupToken: true,
setupClient: false,
@ -1934,7 +1941,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectCode: http.StatusUnauthorized,
},
{
name: "strict mode - expired token",
name: "strict-expired-token",
strictMode: true,
setupToken: true,
setupClient: true,
@ -1945,7 +1952,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "strict mode - invalid token",
name: "strict-invalid-token",
strictMode: true,
setupToken: false,
token: "invalid-token",
@ -1953,7 +1960,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "strict mode - token without client association",
name: "strict-token-no-client-assoc",
strictMode: true,
setupToken: true,
setupClient: false,
@ -1964,7 +1971,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
expectCode: http.StatusBadRequest,
},
{
name: "non-strict mode - no client validation required",
name: "non-strict-no-client-validation",
strictMode: false,
setupToken: true,
setupClient: false,

@ -0,0 +1,227 @@
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package subtestnames checks that t.Run subtest names don't contain characters
// that require quoting or escaping when re-running via "go test -run".
//
// Go's testing package rewrites subtest names: spaces become underscores,
// non-printable characters get escaped, and regex metacharacters require
// escaping in -run patterns. This makes it hard to re-run specific subtests
// or search for them in code.
//
// This analyzer flags:
// - Direct t.Run calls with string literal names containing bad characters
// - t.Run calls using tt.name (or similar) where tt ranges over a slice/map
// of test cases with string literal names containing bad characters
package subtestnames
import (
"go/ast"
"go/token"
"strconv"
"strings"
"unicode"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
// Analyzer checks that t.Run subtest names are clean for use with "go test -run".
var Analyzer = &analysis.Analyzer{
Name: "subtestnames",
Doc: "check that t.Run subtest names don't require quoting when re-running via go test -run",
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: run,
}
// badChars are characters that are problematic in subtest names.
// Spaces are rewritten to underscores by testing.rewrite, and regex
// metacharacters require escaping in -run patterns.
const badChars = " \t\n\r^$.*+?()[]{}|\\'\"#"
// hasBadChar reports whether s contains any character that would be
// problematic in a subtest name.
func hasBadChar(s string) bool {
return strings.ContainsAny(s, badChars) || strings.ContainsFunc(s, func(r rune) bool {
return !unicode.IsPrint(r)
})
}
// hasBadDash reports whether s starts or ends with a dash, which is
// problematic in subtest names because "go test -run" may interpret a
// leading dash as a flag, and trailing dashes are confusing.
func hasBadDash(s string) bool {
return strings.HasPrefix(s, "-") || strings.HasSuffix(s, "-")
}
func run(pass *analysis.Pass) (any, error) {
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
// Build a stack of enclosing nodes so we can find the RangeStmt
// enclosing a given t.Run call.
nodeFilter := []ast.Node{
(*ast.RangeStmt)(nil),
(*ast.CallExpr)(nil),
}
var rangeStack []*ast.RangeStmt
insp.Nodes(nodeFilter, func(n ast.Node, push bool) bool {
switch n := n.(type) {
case *ast.RangeStmt:
if push {
rangeStack = append(rangeStack, n)
} else {
rangeStack = rangeStack[:len(rangeStack)-1]
}
return true
case *ast.CallExpr:
if !push {
return true
}
checkCallExpr(pass, n, rangeStack)
return true
}
return true
})
return nil, nil
}
func checkCallExpr(pass *analysis.Pass, call *ast.CallExpr, rangeStack []*ast.RangeStmt) {
// Check if this is a t.Run(...) or b.Run(...) call.
sel, ok := call.Fun.(*ast.SelectorExpr)
if !ok || sel.Sel.Name != "Run" || len(call.Args) < 2 {
return
}
// Verify the receiver is *testing.T, *testing.B, or *testing.F.
if !isTestingTBF(pass, sel) {
return
}
nameArg := call.Args[0]
// Case 1: Direct string literal, e.g. t.Run("foo bar", ...)
if lit, ok := nameArg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
val, err := strconv.Unquote(lit.Value)
if err != nil {
return
}
if hasBadChar(val) {
pass.Reportf(lit.Pos(), "subtest name %s contains characters that require quoting in go test -run patterns", lit.Value)
} else if hasBadDash(val) {
pass.Reportf(lit.Pos(), "subtest name %s starts or ends with '-' which is problematic in go test -run patterns", lit.Value)
}
return
}
// Case 2: Selector expression like tt.name, tc.name, etc.
// where tt is a range variable over a slice/map of test cases.
selExpr, ok := nameArg.(*ast.SelectorExpr)
if !ok {
return
}
ident, ok := selExpr.X.(*ast.Ident)
if !ok {
return
}
// Find the enclosing range statement where ident is the value variable.
for i := len(rangeStack) - 1; i >= 0; i-- {
rs := rangeStack[i]
valIdent, ok := rs.Value.(*ast.Ident)
if !ok || valIdent.Obj != ident.Obj {
continue
}
// Found the range statement. Check the source being iterated.
checkRangeSource(pass, rs.X, selExpr.Sel)
return
}
}
// isTestingTBF checks whether sel looks like a method call on *testing.T, *testing.B, or *testing.F.
func isTestingTBF(pass *analysis.Pass, sel *ast.SelectorExpr) bool {
typ := pass.TypesInfo.TypeOf(sel.X)
if typ != nil {
s := typ.String()
return s == "*testing.T" || s == "*testing.B" || s == "*testing.F"
}
return false
}
// checkRangeSource examines the expression being ranged over and checks
// composite literal elements for bad subtest name fields.
func checkRangeSource(pass *analysis.Pass, rangeExpr ast.Expr, fieldName *ast.Ident) {
switch x := rangeExpr.(type) {
case *ast.Ident:
if x.Obj == nil {
return
}
switch decl := x.Obj.Decl.(type) {
case *ast.AssignStmt:
// e.g. tests := []struct{...}{...}
for _, rhs := range decl.Rhs {
checkCompositeLit(pass, rhs, fieldName)
}
case *ast.ValueSpec:
// e.g. var tests = []struct{...}{...}
for _, val := range decl.Values {
checkCompositeLit(pass, val, fieldName)
}
}
case *ast.CompositeLit:
checkCompositeLit(pass, x, fieldName)
}
}
// checkCompositeLit checks a composite literal (slice/map) for elements
// that have a field with a bad subtest name.
func checkCompositeLit(pass *analysis.Pass, expr ast.Expr, fieldName *ast.Ident) {
comp, ok := expr.(*ast.CompositeLit)
if !ok {
return
}
for _, elt := range comp.Elts {
// For map literals, check the value.
if kv, ok := elt.(*ast.KeyValueExpr); ok {
elt = kv.Value
}
checkStructLitField(pass, elt, fieldName)
}
}
// checkStructLitField checks a struct literal for a field with the given name
// that contains a bad subtest name string.
func checkStructLitField(pass *analysis.Pass, expr ast.Expr, fieldName *ast.Ident) {
comp, ok := expr.(*ast.CompositeLit)
if !ok {
return
}
for _, elt := range comp.Elts {
kv, ok := elt.(*ast.KeyValueExpr)
if !ok {
continue
}
key, ok := kv.Key.(*ast.Ident)
if !ok || key.Name != fieldName.Name {
continue
}
lit, ok := kv.Value.(*ast.BasicLit)
if !ok || lit.Kind != token.STRING {
continue
}
val, err := strconv.Unquote(lit.Value)
if err != nil {
continue
}
if hasBadChar(val) {
pass.Reportf(lit.Pos(), "subtest name %s contains characters that require quoting in go test -run patterns", lit.Value)
} else if hasBadDash(val) {
pass.Reportf(lit.Pos(), "subtest name %s starts or ends with '-' which is problematic in go test -run patterns", lit.Value)
}
}
}

@ -0,0 +1,15 @@
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package subtestnames
import (
"testing"
"golang.org/x/tools/go/analysis/analysistest"
)
func TestAnalyzer(t *testing.T) {
testdata := analysistest.TestData()
analysistest.Run(t, testdata, Analyzer, "example")
}

@ -0,0 +1,112 @@
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package example
import "testing"
func TestDirect(t *testing.T) {
// Bad: spaces
t.Run("that everything's cool", func(t *testing.T) {}) // want `subtest name "that everything's cool" contains characters that require quoting`
// Bad: apostrophe
t.Run("it's working", func(t *testing.T) {}) // want `subtest name "it's working" contains characters that require quoting`
// Bad: regex metacharacters
t.Run("test(foo)", func(t *testing.T) {}) // want `subtest name "test\(foo\)" contains characters that require quoting`
t.Run("test[0]", func(t *testing.T) {}) // want `subtest name "test\[0\]" contains characters that require quoting`
t.Run("a|b", func(t *testing.T) {}) // want `subtest name "a\|b" contains characters that require quoting`
t.Run("a*b", func(t *testing.T) {}) // want `subtest name "a\*b" contains characters that require quoting`
t.Run("a+b", func(t *testing.T) {}) // want `subtest name "a\+b" contains characters that require quoting`
t.Run("a.b", func(t *testing.T) {}) // want `subtest name "a\.b" contains characters that require quoting`
t.Run("^start", func(t *testing.T) {}) // want `subtest name "\^start" contains characters that require quoting`
t.Run("end$", func(t *testing.T) {}) // want `subtest name "end\$" contains characters that require quoting`
t.Run("a{2}", func(t *testing.T) {}) // want `subtest name "a\{2\}" contains characters that require quoting`
t.Run("a?b", func(t *testing.T) {}) // want `subtest name "a\?b" contains characters that require quoting`
t.Run("a\\b", func(t *testing.T) {}) // want `subtest name "a\\\\b" contains characters that require quoting`
// Bad: double quotes
t.Run("say \"hello\"", func(t *testing.T) {}) // want `subtest name "say \\"hello\\"" contains characters that require quoting`
// Bad: hash
t.Run("comment#1", func(t *testing.T) {}) // want `subtest name "comment#1" contains characters that require quoting`
// Bad: leading/trailing dash
t.Run("-leading-dash", func(t *testing.T) {}) // want `subtest name "-leading-dash" starts or ends with '-' which is problematic`
t.Run("trailing-dash-", func(t *testing.T) {}) // want `subtest name "trailing-dash-" starts or ends with '-' which is problematic`
t.Run("-both-", func(t *testing.T) {}) // want `subtest name "-both-" starts or ends with '-' which is problematic`
// Good: clean names
t.Run("zero-passes", func(t *testing.T) {})
t.Run("simple_test", func(t *testing.T) {})
t.Run("CamelCase", func(t *testing.T) {})
t.Run("with-dashes", func(t *testing.T) {})
t.Run("123", func(t *testing.T) {})
t.Run("comma,separated", func(t *testing.T) {})
t.Run("colon:value", func(t *testing.T) {})
t.Run("slash/path", func(t *testing.T) {})
t.Run("equals=sign", func(t *testing.T) {})
}
func TestTableDriven(t *testing.T) {
tests := []struct {
name string
val int
}{
{name: "bad space name", val: 1}, // want `subtest name "bad space name" contains characters that require quoting`
{name: "good-name", val: 2},
{name: "also(bad)", val: 3}, // want `subtest name "also\(bad\)" contains characters that require quoting`
{name: "it's-bad", val: 4}, // want `subtest name "it's-bad" contains characters that require quoting`
{name: "clean-name", val: 5},
{name: "-leading-dash", val: 6}, // want `subtest name "-leading-dash" starts or ends with '-' which is problematic`
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {})
}
}
func TestTableDrivenVar(t *testing.T) {
var tests = []struct {
name string
val int
}{
{name: "has spaces", val: 1}, // want `subtest name "has spaces" contains characters that require quoting`
{name: "ok-name", val: 2},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {})
}
}
func TestTableDrivenMap(t *testing.T) {
tests := map[string]struct {
name string
val int
}{
"key1": {name: "bad name here", val: 1}, // want `subtest name "bad name here" contains characters that require quoting`
"key2": {name: "ok-name", val: 2},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {})
}
}
func TestNotTesting(t *testing.T) {
// Not a t.Run call, should not trigger.
s := struct{ Run func(string, func()) }{}
s.Run("bad name here", func() {})
}
func TestDynamicName(t *testing.T) {
// Dynamic name, not a string literal — should not trigger.
name := getName()
t.Run(name, func(t *testing.T) {})
}
func getName() string { return "foo" }
func BenchmarkDirect(b *testing.B) {
// Also check b.Run.
b.Run("bad name here", func(b *testing.B) {}) // want `subtest name "bad name here" contains characters that require quoting`
b.Run("good-name", func(b *testing.B) {})
}

@ -9,6 +9,7 @@ import (
"golang.org/x/tools/go/analysis/unitchecker"
"tailscale.com/cmd/vet/jsontags"
"tailscale.com/cmd/vet/subtestnames"
)
//go:embed jsontags_allowlist
@ -20,5 +21,5 @@ func init() {
}
func main() {
unitchecker.Main(jsontags.Analyzer)
unitchecker.Main(jsontags.Analyzer, subtestnames.Analyzer)
}

@ -801,7 +801,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
expectNewDisco bool
}{
{
name: "disco key wired through when newer lastSeen",
name: "disco-key-newer-lastSeen",
initialOnline: false,
initialLastSeen: oldTime,
updateOnline: false,
@ -809,7 +809,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
expectNewDisco: true,
},
{
name: "disco key NOT wired through when older lastSeen",
name: "disco-key-older-lastSeen",
initialOnline: false,
initialLastSeen: now,
updateOnline: false,
@ -817,7 +817,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
expectNewDisco: false,
},
{
name: "disco key wired through when newer lastSeen, going offline",
name: "disco-key-newer-lastSeen-going-offline",
initialOnline: true,
initialLastSeen: oldTime,
updateOnline: false,
@ -825,7 +825,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
expectNewDisco: true,
},
{
name: "online flip with newer lastSeen",
name: "online-flip-newer-lastSeen",
initialOnline: false,
initialLastSeen: oldTime,
updateOnline: true,

@ -616,13 +616,13 @@ func TestSendFreeze(t *testing.T) {
}
}
t.Run("initial send", func(t *testing.T) {
t.Run("initial-send", func(t *testing.T) {
drain(t, "bob")
drain(t, "cathy")
isEmpty(t, "alice")
})
t.Run("block cathy", func(t *testing.T) {
t.Run("block-cathy", func(t *testing.T) {
// Block cathy. Now the cathyConn buffer will fill up quickly,
// and the derp server will back up.
cathyConn.SetReadBlock(true)

@ -447,7 +447,7 @@ func TestXDP(t *testing.T) {
wantMetrics map[bpfCountersKey]uint64
}{
{
name: "ipv4 STUN Binding Request Drop STUN",
name: "ipv4-STUN-Binding-Request-Drop-STUN",
dropSTUN: true,
packetIn: ipv4STUNBindingReqTX,
wantCode: xdpActionDrop,
@ -466,7 +466,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request Drop STUN",
name: "ipv6-STUN-Binding-Request-Drop-STUN",
dropSTUN: true,
packetIn: ipv6STUNBindingReqTX,
wantCode: xdpActionDrop,
@ -485,7 +485,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request TX",
name: "ipv4-STUN-Binding-Request-TX",
packetIn: ipv4STUNBindingReqTX,
wantCode: xdpActionTX,
wantPacketOut: getIPv4STUNBindingResp(),
@ -503,7 +503,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request TX",
name: "ipv6-STUN-Binding-Request-TX",
packetIn: ipv6STUNBindingReqTX,
wantCode: xdpActionTX,
wantPacketOut: getIPv6STUNBindingResp(),
@ -521,7 +521,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request invalid ip csum PASS",
name: "ipv4-STUN-Binding-Request-invalid-ip-csum-PASS",
packetIn: ipv4STUNBindingReqIPCsumPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqIPCsumPass,
@ -539,7 +539,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request ihl PASS",
name: "ipv4-STUN-Binding-Request-ihl-PASS",
packetIn: ipv4STUNBindingReqIHLPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqIHLPass,
@ -557,7 +557,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request ip version PASS",
name: "ipv4-STUN-Binding-Request-ip-version-PASS",
packetIn: ipv4STUNBindingReqIPVerPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqIPVerPass,
@ -575,7 +575,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request ip proto PASS",
name: "ipv4-STUN-Binding-Request-ip-proto-PASS",
packetIn: ipv4STUNBindingReqIPProtoPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqIPProtoPass,
@ -593,7 +593,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request frag offset PASS",
name: "ipv4-STUN-Binding-Request-frag-offset-PASS",
packetIn: ipv4STUNBindingReqFragOffsetPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqFragOffsetPass,
@ -611,7 +611,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request flags mf PASS",
name: "ipv4-STUN-Binding-Request-flags-mf-PASS",
packetIn: ipv4STUNBindingReqFlagsMFPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqFlagsMFPass,
@ -629,7 +629,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request tot len PASS",
name: "ipv4-STUN-Binding-Request-tot-len-PASS",
packetIn: ipv4STUNBindingReqTotLenPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqTotLenPass,
@ -647,7 +647,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request ip version PASS",
name: "ipv6-STUN-Binding-Request-ip-version-PASS",
packetIn: ipv6STUNBindingReqIPVerPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqIPVerPass,
@ -665,7 +665,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request next hdr PASS",
name: "ipv6-STUN-Binding-Request-next-hdr-PASS",
packetIn: ipv6STUNBindingReqNextHdrPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqNextHdrPass,
@ -683,7 +683,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request payload len PASS",
name: "ipv6-STUN-Binding-Request-payload-len-PASS",
packetIn: ipv6STUNBindingReqPayloadLenPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqPayloadLenPass,
@ -701,7 +701,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request UDP csum PASS",
name: "ipv4-STUN-Binding-Request-UDP-csum-PASS",
packetIn: ipv4STUNBindingReqUDPCsumPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqUDPCsumPass,
@ -719,7 +719,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request UDP csum PASS",
name: "ipv6-STUN-Binding-Request-UDP-csum-PASS",
packetIn: ipv6STUNBindingReqUDPCsumPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqUDPCsumPass,
@ -737,7 +737,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request STUN type PASS",
name: "ipv4-STUN-Binding-Request-STUN-type-PASS",
packetIn: ipv4STUNBindingReqSTUNTypePass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqSTUNTypePass,
@ -755,7 +755,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request STUN type PASS",
name: "ipv6-STUN-Binding-Request-STUN-type-PASS",
packetIn: ipv6STUNBindingReqSTUNTypePass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqSTUNTypePass,
@ -773,7 +773,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request STUN magic PASS",
name: "ipv4-STUN-Binding-Request-STUN-magic-PASS",
packetIn: ipv4STUNBindingReqSTUNMagicPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqSTUNMagicPass,
@ -791,7 +791,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request STUN magic PASS",
name: "ipv6-STUN-Binding-Request-STUN-magic-PASS",
packetIn: ipv6STUNBindingReqSTUNMagicPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqSTUNMagicPass,
@ -809,7 +809,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request STUN attrs len PASS",
name: "ipv4-STUN-Binding-Request-STUN-attrs-len-PASS",
packetIn: ipv4STUNBindingReqSTUNAttrsLenPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqSTUNAttrsLenPass,
@ -827,7 +827,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request STUN attrs len PASS",
name: "ipv6-STUN-Binding-Request-STUN-attrs-len-PASS",
packetIn: ipv6STUNBindingReqSTUNAttrsLenPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqSTUNAttrsLenPass,
@ -845,7 +845,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request STUN SW val PASS",
name: "ipv4-STUN-Binding-Request-STUN-SW-val-PASS",
packetIn: ipv4STUNBindingReqSTUNSWValPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqSTUNSWValPass,
@ -863,7 +863,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request STUN SW val PASS",
name: "ipv6-STUN-Binding-Request-STUN-SW-val-PASS",
packetIn: ipv6STUNBindingReqSTUNSWValPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqSTUNSWValPass,
@ -881,7 +881,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 STUN Binding Request STUN first attr PASS",
name: "ipv4-STUN-Binding-Request-STUN-first-attr-PASS",
packetIn: ipv4STUNBindingReqSTUNFirstAttrPass,
wantCode: xdpActionPass,
wantPacketOut: ipv4STUNBindingReqSTUNFirstAttrPass,
@ -899,7 +899,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 STUN Binding Request STUN first attr PASS",
name: "ipv6-STUN-Binding-Request-STUN-first-attr-PASS",
packetIn: ipv6STUNBindingReqSTUNFirstAttrPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqSTUNFirstAttrPass,
@ -917,7 +917,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv4 UDP zero csum TX",
name: "ipv4-UDP-zero-csum-TX",
packetIn: ipv4STUNBindingReqUDPZeroCsumTx,
wantCode: xdpActionTX,
wantPacketOut: getIPv4STUNBindingResp(),
@ -935,7 +935,7 @@ func TestXDP(t *testing.T) {
},
},
{
name: "ipv6 UDP zero csum PASS",
name: "ipv6-UDP-zero-csum-PASS",
packetIn: ipv6STUNBindingReqUDPZeroCsumPass,
wantCode: xdpActionPass,
wantPacketOut: ipv6STUNBindingReqUDPZeroCsumPass,

@ -29,7 +29,7 @@ func TestStat(t *testing.T) {
err error
}{
{
label: "root folder",
label: "root-folder",
name: "",
expected: &shared.StaticFileInfo{
Named: "",
@ -40,7 +40,7 @@ func TestStat(t *testing.T) {
},
},
{
label: "static root folder",
label: "static-root-folder",
name: "/domain",
expected: &shared.StaticFileInfo{
Named: "domain",
@ -73,7 +73,7 @@ func TestStat(t *testing.T) {
},
},
{
label: "non-existent remote",
label: "non-existent-remote",
name: "remote3",
err: os.ErrNotExist,
},
@ -108,7 +108,7 @@ func TestListDir(t *testing.T) {
err error
}{
{
label: "root folder",
label: "root-folder",
name: "",
expected: []fs.FileInfo{
&shared.StaticFileInfo{
@ -121,7 +121,7 @@ func TestListDir(t *testing.T) {
},
},
{
label: "static root folder",
label: "static-root-folder",
name: "/domain",
expected: []fs.FileInfo{
&shared.StaticFileInfo{
@ -189,19 +189,19 @@ func TestMkdir(t *testing.T) {
err error
}{
{
label: "attempt to create root folder",
label: "create-root-folder",
name: "/",
},
{
label: "attempt to create static root folder",
label: "create-static-root-folder",
name: "/domain",
},
{
label: "attempt to create remote",
label: "create-remote",
name: "/domain/remote1",
},
{
label: "attempt to create non-existent remote",
label: "create-non-existent-remote",
name: "/domain/remote3",
err: os.ErrPermission,
},
@ -231,7 +231,7 @@ func TestRemoveAll(t *testing.T) {
err error
}{
{
label: "attempt to remove root folder",
label: "remove-root-folder",
name: "/",
err: os.ErrPermission,
},
@ -258,7 +258,7 @@ func TestRename(t *testing.T) {
err error
}{
{
label: "attempt to move root folder",
label: "move-root-folder",
oldName: "/",
newName: "/domain/remote2/copy.txt",
err: os.ErrPermission,

@ -156,27 +156,27 @@ func TestMissingPaths(t *testing.T) {
wantStatus int
}{
{
name: "empty path",
name: "empty-path",
path: "",
wantStatus: http.StatusForbidden,
},
{
name: "single slash",
name: "single-slash",
path: "/",
wantStatus: http.StatusForbidden,
},
{
name: "only token",
name: "only-token",
path: "/" + secretToken,
wantStatus: http.StatusBadRequest,
},
{
name: "token with trailing slash",
name: "token-trailing-slash",
path: "/" + secretToken + "/",
wantStatus: http.StatusBadRequest,
},
{
name: "token and invalid share",
name: "token-invalid-share",
path: "/" + secretToken + "/nonexistentshare",
wantStatus: http.StatusNotFound,
},

@ -31,7 +31,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErr: "",
},
{
name: "missing client id short-circuits without error",
name: "missing-client-id-noop",
clientID: "",
idToken: "token",
audience: "api://tailscale-wif",
@ -40,7 +40,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErr: "",
},
{
name: "missing id token and audience",
name: "missing-id-token-and-audience",
clientID: "client-123",
idToken: "",
audience: "",
@ -48,7 +48,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErr: "federated identity requires either an ID token or an audience",
},
{
name: "missing tags",
name: "missing-tags",
clientID: "client-123",
idToken: "token",
audience: "api://tailscale-wif",
@ -56,7 +56,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErr: "federated identity authkeys require --advertise-tags",
},
{
name: "invalid client id attributes",
name: "invalid-client-id-attrs",
clientID: "client-123?invalid=value",
idToken: "token",
audience: "api://tailscale-wif",
@ -99,7 +99,7 @@ func TestParseOptionalAttributes(t *testing.T) {
wantErr string
}{
{
name: "default values",
name: "default-values",
clientID: "client-123",
wantClientID: "client-123",
wantEphemeral: true,
@ -107,7 +107,7 @@ func TestParseOptionalAttributes(t *testing.T) {
wantErr: "",
},
{
name: "custom values",
name: "custom-values",
clientID: "client-123?ephemeral=false&preauthorized=true",
wantClientID: "client-123",
wantEphemeral: false,
@ -115,7 +115,7 @@ func TestParseOptionalAttributes(t *testing.T) {
wantErr: "",
},
{
name: "unknown attribute",
name: "unknown-attribute",
clientID: "client-123?unknown=value",
wantClientID: "",
wantEphemeral: false,
@ -123,7 +123,7 @@ func TestParseOptionalAttributes(t *testing.T) {
wantErr: `unknown optional config attribute "unknown"`,
},
{
name: "invalid value",
name: "invalid-value",
clientID: "client-123?ephemeral=invalid",
wantClientID: "",
wantEphemeral: false,

@ -20,42 +20,42 @@ func TestResolveAuthKey(t *testing.T) {
wantErr bool
}{
{
name: "keys without client secret prefix pass through unchanged",
name: "non-client-secret-passthrough",
clientID: "tskey-auth-regular",
tags: []string{"tag:test"},
wantAuthKey: "tskey-auth-regular",
wantErr: false,
},
{
name: "client secret without advertised tags",
name: "client-secret-no-tags",
clientID: "tskey-client-abc",
tags: nil,
wantAuthKey: "",
wantErr: true,
},
{
name: "client secret with default attributes",
name: "client-secret-default-attrs",
clientID: "tskey-client-abc",
tags: []string{"tag:test"},
wantAuthKey: "tskey-auth-xyz",
wantErr: false,
},
{
name: "client secret with custom attributes",
name: "client-secret-custom-attrs",
clientID: "tskey-client-abc?ephemeral=false&preauthorized=true",
tags: []string{"tag:test"},
wantAuthKey: "tskey-auth-xyz",
wantErr: false,
},
{
name: "client secret with unknown attribute",
name: "client-secret-unknown-attr",
clientID: "tskey-client-abc?unknown=value",
tags: []string{"tag:test"},
wantAuthKey: "",
wantErr: true,
},
{
name: "oauth client secret with invalid attribute value",
name: "client-secret-invalid-attr-value",
clientID: "tskey-client-abc?ephemeral=invalid",
tags: []string{"tag:test"},
wantAuthKey: "",
@ -111,7 +111,7 @@ func TestResolveAuthKeyAttributes(t *testing.T) {
wantBaseURL string
}{
{
name: "default values",
name: "default-values",
clientSecret: "tskey-client-abc",
wantEphemeral: true,
wantPreauth: false,
@ -132,14 +132,14 @@ func TestResolveAuthKeyAttributes(t *testing.T) {
wantBaseURL: "https://api.tailscale.com",
},
{
name: "baseURL=https://api.example.com",
name: "baseURL-custom",
clientSecret: "tskey-client-abc?baseURL=https://api.example.com",
wantEphemeral: true,
wantPreauth: false,
wantBaseURL: "https://api.example.com",
},
{
name: "all custom values",
name: "all-custom-values",
clientSecret: "tskey-client-abc?ephemeral=false&preauthorized=true&baseURL=https://api.example.com",
wantEphemeral: false,
wantPreauth: true,

@ -48,7 +48,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantEndpoints []netip.AddrPort
}{
{
name: "no changes non-nil port previously running",
name: "no-changes-non-nil-port-running",
fields: fields{
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -62,7 +62,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "set addr ports unchanged port previously running",
name: "set-addr-ports-unchanged-running",
fields: fields{
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -77,7 +77,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
},
{
name: "set addr ports not previously running",
name: "set-addr-ports-not-running",
fields: fields{
port: nil,
rs: nil,
@ -92,7 +92,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
},
{
name: "clear addr ports unchanged port previously running",
name: "clear-addr-ports-unchanged-running",
fields: fields{
port: new(uint16(1)),
staticEndpoints: views.SliceOf(prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints),
@ -108,7 +108,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantEndpoints: nil,
},
{
name: "prefs port nil",
name: "prefs-port-nil",
fields: fields{
port: new(uint16(1)),
},
@ -121,7 +121,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "prefs port nil previously running",
name: "prefs-port-nil-running",
fields: fields{
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -135,7 +135,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "prefs port changed",
name: "prefs-port-changed",
fields: fields{
port: new(uint16(2)),
},
@ -148,7 +148,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "prefs port changed previously running",
name: "prefs-port-changed-running",
fields: fields{
port: new(uint16(2)),
rs: mockRelayServerNotZeroVal(),
@ -162,7 +162,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "sameNode false",
name: "sameNode-false",
fields: fields{
port: new(uint16(1)),
},
@ -175,7 +175,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "sameNode false previously running",
name: "sameNode-false-running",
fields: fields{
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -189,7 +189,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "prefs port non-nil extension port nil",
name: "prefs-port-non-nil-ext-nil",
fields: fields{
port: nil,
},
@ -277,7 +277,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated bool
}{
{
name: "want running",
name: "want-running",
shutdown: false,
port: new(uint16(1)),
hasNodeAttrDisableRelayServer: false,
@ -285,7 +285,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "want running previously running",
name: "want-running-previously-running",
shutdown: false,
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -294,7 +294,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "shutdown true",
name: "shutdown-true",
shutdown: true,
port: new(uint16(1)),
hasNodeAttrDisableRelayServer: false,
@ -302,7 +302,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "shutdown true previously running",
name: "shutdown-true-previously-running",
shutdown: true,
port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(),
@ -311,7 +311,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "port nil",
name: "port-nil",
shutdown: false,
port: nil,
hasNodeAttrDisableRelayServer: false,
@ -319,7 +319,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "port nil previously running",
name: "port-nil-previously-running",
shutdown: false,
port: nil,
rs: mockRelayServerNotZeroVal(),
@ -328,7 +328,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: true,
},
{
name: "hasNodeAttrDisableRelayServer true",
name: "hasNodeAttrDisableRelayServer-true",
shutdown: false,
port: nil,
hasNodeAttrDisableRelayServer: true,
@ -336,7 +336,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
wantRelayServerFieldMutated: false,
},
{
name: "hasNodeAttrDisableRelayServer true previously running",
name: "hasNodeAttrDisableRelayServer-true-running",
shutdown: false,
port: nil,
rs: mockRelayServerNotZeroVal(),

@ -163,4 +163,4 @@
});
};
}
# nix-direnv cache busting line: sha256-39axT5Q0+fNTcMgZCMLMNfJEJN46wMaaKDgfI+Uj+Ps=
# nix-direnv cache busting line: sha256-VsVMvTEblVx/HNbuCVxC9UgKpriRwixswUSKVGLMf3Q=

@ -1 +1 @@
sha256-39axT5Q0+fNTcMgZCMLMNfJEJN46wMaaKDgfI+Uj+Ps=
sha256-VsVMvTEblVx/HNbuCVxC9UgKpriRwixswUSKVGLMf3Q=

@ -388,7 +388,7 @@ func TestShowUpdateWarnable(t *testing.T) {
wantShow bool
}{
{
desc: "nil ClientVersion",
desc: "nil-ClientVersion",
check: true,
cv: nil,
wantWarnable: nil,
@ -402,35 +402,35 @@ func TestShowUpdateWarnable(t *testing.T) {
wantShow: false,
},
{
desc: "no LatestVersion",
desc: "no-LatestVersion",
check: true,
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: ""},
wantWarnable: nil,
wantShow: false,
},
{
desc: "show regular update",
desc: "show-regular-update",
check: true,
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
wantWarnable: updateAvailableWarnable,
wantShow: true,
},
{
desc: "show security update",
desc: "show-security-update",
check: true,
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3", UrgentSecurityUpdate: true},
wantWarnable: securityUpdateAvailableWarnable,
wantShow: true,
},
{
desc: "update check disabled",
desc: "update-check-disabled",
check: false,
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
wantWarnable: nil,
wantShow: false,
},
{
desc: "hide update with auto-updates",
desc: "hide-update-with-auto-updates",
check: true,
apply: opt.NewBool(true),
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
@ -438,7 +438,7 @@ func TestShowUpdateWarnable(t *testing.T) {
wantShow: false,
},
{
desc: "show security update with auto-updates",
desc: "show-security-update-with-auto-updates",
check: true,
apply: opt.NewBool(true),
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3", UrgentSecurityUpdate: true},
@ -622,7 +622,7 @@ func TestControlHealth(t *testing.T) {
}
})
t.Run("Strings()", func(t *testing.T) {
t.Run("Strings", func(t *testing.T) {
wantStrs := []string{
"Control health message: Extra help.",
"Control health message: Extra help. Learn more: http://www.example.com",

@ -63,7 +63,7 @@ func TestHandleC2NTLSCertStatus(t *testing.T) {
want *tailcfg.C2NTLSCertInfo
}{
{
name: "no domain",
name: "no-domain",
wantStatus: 400,
wantError: "no 'domain'\n",
},

@ -39,25 +39,29 @@ func TestCertRequest(t *testing.T) {
}
tests := []struct {
name string
domain string
wantSANs []string
}{
{
name: "example-com",
domain: "example.com",
wantSANs: []string{"example.com"},
},
{
name: "wildcard-example-com",
domain: "*.example.com",
wantSANs: []string{"*.example.com", "example.com"},
},
{
name: "wildcard-foo-bar-com",
domain: "*.foo.bar.com",
wantSANs: []string{"*.foo.bar.com", "foo.bar.com"},
},
}
for _, tt := range tests {
t.Run(tt.domain, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
csrDER, err := certRequest(key, tt.domain, nil)
if err != nil {
t.Fatalf("certRequest: %v", err)
@ -365,19 +369,19 @@ func TestShouldStartDomainRenewal(t *testing.T) {
wantErr string
}{
{
name: "should renew",
name: "should-renew",
notBefore: now.AddDate(0, 0, -89),
lifetime: 90 * 24 * time.Hour,
want: true,
},
{
name: "short-lived renewal",
name: "short-lived-renewal",
notBefore: now.AddDate(0, 0, -7),
lifetime: 10 * 24 * time.Hour,
want: true,
},
{
name: "no renew",
name: "no-renew",
notBefore: now.AddDate(0, 0, -59), // 59 days ago == not 2/3rds of the way through 90 days yet
lifetime: 90 * 24 * time.Hour,
want: false,

@ -3035,20 +3035,20 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
lastSuggestedExitNode tailcfg.StableNodeID
}{
{
name: "ExitNodeID key is set",
name: "exitNodeID-set",
exitNodeIDKey: true,
exitNodeID: "123",
exitNodeIDWant: "123",
prefsChanged: true,
},
{
name: "ExitNodeID key not set",
name: "exitNodeID-not-set",
exitNodeIDKey: true,
exitNodeIDWant: "",
prefsChanged: false,
},
{
name: "ExitNodeID key set, ExitNodeIP preference set",
name: "exitNodeID-set-exitNodeIP-pref-set",
exitNodeIDKey: true,
exitNodeID: "123",
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
@ -3056,7 +3056,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: true,
},
{
name: "ExitNodeID key not set, ExitNodeIP key set",
name: "exitNodeID-not-set-exitNodeIP-set",
exitNodeIPKey: true,
exitNodeIP: "127.0.0.1",
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
@ -3064,7 +3064,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: false,
},
{
name: "ExitNodeIP key set, existing ExitNodeIP pref",
name: "exitNodeIP-set-existing-pref",
exitNodeIPKey: true,
exitNodeIP: "127.0.0.1",
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
@ -3072,7 +3072,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: false,
},
{
name: "existing preferences match policy",
name: "existing-prefs-match-policy",
exitNodeIDKey: true,
exitNodeID: "123",
prefs: &ipn.Prefs{ExitNodeID: tailcfg.StableNodeID("123")},
@ -3080,7 +3080,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: false,
},
{
name: "ExitNodeIP set if net map does not have corresponding node",
// ExitNodeIP is set when net map does not have a corresponding node.
name: "exitNodeIP-set-no-matching-node",
exitNodeIPKey: true,
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
exitNodeIP: "127.0.0.1",
@ -3116,7 +3117,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
},
},
{
name: "ExitNodeIP cleared if net map has corresponding node - policy matches prefs",
// ExitNodeIP cleared when net map has corresponding node and policy matches prefs.
name: "exitNodeIP-cleared-matching-node-policy-matches",
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
exitNodeIPKey: true,
exitNodeIP: "127.0.0.1",
@ -3156,7 +3158,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
},
},
{
name: "ExitNodeIP cleared if net map has corresponding node - no policy set",
// ExitNodeIP cleared when net map has corresponding node and no policy is set.
name: "exitNodeIP-cleared-matching-node-no-policy",
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
exitNodeIPWant: "",
exitNodeIDWant: "123",
@ -3194,7 +3197,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
},
},
{
name: "ExitNodeIP cleared if net map has corresponding node - different exit node IP in policy",
// ExitNodeIP cleared when net map has corresponding node but policy has different exit node IP.
name: "exitNodeIP-cleared-matching-node-different-policy-IP",
exitNodeIPKey: true,
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
exitNodeIP: "100.64.5.6",
@ -3234,7 +3238,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
},
},
{
name: "ExitNodeID key is set to auto:any and last suggested exit node is populated",
name: "exitNodeID-auto-any-last-suggested-populated",
exitNodeIDKey: true,
exitNodeID: "auto:any",
lastSuggestedExitNode: "123",
@ -3243,7 +3247,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: true,
},
{
name: "ExitNodeID key is set to auto:any and last suggested exit node is not populated",
name: "exitNodeID-auto-any-last-suggested-not-populated",
exitNodeIDKey: true,
exitNodeID: "auto:any",
exitNodeIDWant: "auto:any",
@ -3251,7 +3255,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: true,
},
{
name: "ExitNodeID key is set to auto:foo and last suggested exit node is populated",
name: "exitNodeID-auto-foo-last-suggested-populated",
exitNodeIDKey: true,
exitNodeID: "auto:foo",
lastSuggestedExitNode: "123",
@ -3260,7 +3264,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
prefsChanged: true,
},
{
name: "ExitNodeID key is set to auto:foo and last suggested exit node is not populated",
name: "exitNodeID-auto-foo-last-suggested-not-populated",
exitNodeIDKey: true,
exitNodeID: "auto:foo",
exitNodeIDWant: "auto:any", // should be "auto:any" for compatibility with existing clients
@ -3645,10 +3649,10 @@ func TestApplySysPolicy(t *testing.T) {
stringPolicies map[pkey.Key]string
}{
{
name: "empty prefs without policies",
name: "empty-prefs-no-policies",
},
{
name: "prefs set without policies",
name: "prefs-set-no-policies",
prefs: ipn.Prefs{
ControlURL: "1",
ShieldsUp: true,
@ -3667,7 +3671,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "empty prefs with policies",
name: "empty-prefs-with-policies",
wantPrefs: ipn.Prefs{
ControlURL: "1",
ShieldsUp: true,
@ -3687,7 +3691,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "prefs set with matching policies",
name: "prefs-set-matching-policies",
prefs: ipn.Prefs{
ControlURL: "1",
ShieldsUp: true,
@ -3708,7 +3712,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "prefs set with conflicting policies",
name: "prefs-set-conflicting-policies",
prefs: ipn.Prefs{
ControlURL: "1",
ShieldsUp: true,
@ -3736,7 +3740,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "prefs set with neutral policies",
name: "prefs-set-neutral-policies",
prefs: ipn.Prefs{
ControlURL: "1",
ShieldsUp: true,
@ -3772,7 +3776,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "enable AutoUpdate apply does not unset check",
name: "enable-apply-keeps-check",
prefs: ipn.Prefs{
AutoUpdate: ipn.AutoUpdatePrefs{
Check: true,
@ -3791,7 +3795,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "disable AutoUpdate apply does not unset check",
name: "disable-apply-keeps-check",
prefs: ipn.Prefs{
AutoUpdate: ipn.AutoUpdatePrefs{
Check: true,
@ -3810,7 +3814,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "enable AutoUpdate check does not unset apply",
name: "enable-check-keeps-apply",
prefs: ipn.Prefs{
AutoUpdate: ipn.AutoUpdatePrefs{
Check: false,
@ -3829,7 +3833,7 @@ func TestApplySysPolicy(t *testing.T) {
},
},
{
name: "disable AutoUpdate check does not unset apply",
name: "disable-check-keeps-apply",
prefs: ipn.Prefs{
AutoUpdate: ipn.AutoUpdatePrefs{
Check: true,
@ -3879,7 +3883,7 @@ func TestApplySysPolicy(t *testing.T) {
}
})
t.Run("status update", func(t *testing.T) {
t.Run("status-update", func(t *testing.T) {
// Profile manager fills in blank ControlURL but it's not set
// in most test cases to avoid cluttering them, so adjust for
// that.
@ -3919,75 +3923,75 @@ func TestPreferencePolicyInfo(t *testing.T) {
policyError error
}{
{
name: "force enable modify",
name: "force-enable-modify",
initialValue: false,
wantValue: true,
wantChange: true,
policyValue: "always",
},
{
name: "force enable unchanged",
name: "force-enable-unchanged",
initialValue: true,
wantValue: true,
policyValue: "always",
},
{
name: "force disable modify",
name: "force-disable-modify",
initialValue: true,
wantValue: false,
wantChange: true,
policyValue: "never",
},
{
name: "force disable unchanged",
name: "force-disable-unchanged",
initialValue: false,
wantValue: false,
policyValue: "never",
},
{
name: "unforced enabled",
name: "unforced-enabled",
initialValue: true,
wantValue: true,
policyValue: "user-decides",
},
{
name: "unforced disabled",
name: "unforced-disabled",
initialValue: false,
wantValue: false,
policyValue: "user-decides",
},
{
name: "blank enabled",
name: "blank-enabled",
initialValue: true,
wantValue: true,
policyValue: "",
},
{
name: "blank disabled",
name: "blank-disabled",
initialValue: false,
wantValue: false,
policyValue: "",
},
{
name: "unset enabled",
name: "unset-enabled",
initialValue: true,
wantValue: true,
policyError: syspolicy.ErrNoSuchKey,
},
{
name: "unset disabled",
name: "unset-disabled",
initialValue: false,
wantValue: false,
policyError: syspolicy.ErrNoSuchKey,
},
{
name: "error enabled",
name: "error-enabled",
initialValue: true,
wantValue: true,
policyError: errors.New("test error"),
},
{
name: "error disabled",
name: "error-disabled",
initialValue: false,
wantValue: false,
policyError: errors.New("test error"),
@ -4113,53 +4117,62 @@ func TestOnTailnetDefaultAutoUpdate(t *testing.T) {
func TestTCPHandlerForDst(t *testing.T) {
b := newTestBackend(t)
tests := []struct {
name string
desc string
dst string
intercept bool
}{
{
name: "100_100_100_100-port80",
desc: "intercept port 80 (Web UI) on quad100 IPv4",
dst: "100.100.100.100:80",
intercept: true,
},
{
name: "fd7a-115c-a1e0--53-port80",
desc: "intercept port 80 (Web UI) on quad100 IPv6",
dst: "[fd7a:115c:a1e0::53]:80",
intercept: true,
},
{
name: "100_100_103_100-port80",
desc: "don't intercept port 80 on local ip",
dst: "100.100.103.100:80",
intercept: false,
},
{
name: "fd7a-115c-a1e0--53-port8080",
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
dst: "[fd7a:115c:a1e0::53]:8080",
intercept: true,
},
{
name: "100_100_103_100-port8080",
desc: "don't intercept port 8080 on local ip",
dst: "100.100.103.100:8080",
intercept: false,
},
{
name: "100_100_100_100-port9080",
desc: "don't intercept port 9080 on quad100 IPv4",
dst: "100.100.100.100:9080",
intercept: false,
},
{
name: "fd7a-115c-a1e0--53-port9080",
desc: "don't intercept port 9080 on quad100 IPv6",
dst: "[fd7a:115c:a1e0::53]:9080",
intercept: false,
},
{
name: "100_100_103_100-port9080",
desc: "don't intercept port 9080 on local ip",
dst: "100.100.103.100:9080",
intercept: false,
},
}
for _, tt := range tests {
t.Run(tt.dst, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Log(tt.desc)
src := netip.MustParseAddrPort("100.100.102.100:51234")
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
@ -4258,122 +4271,146 @@ func TestTCPHandlerForDstWithVIPService(t *testing.T) {
}
tests := []struct {
name string
desc string
dst string
intercept bool
}{
{
name: "100_100_100_100-port80",
desc: "intercept port 80 (Web UI) on quad100 IPv4",
dst: "100.100.100.100:80",
intercept: true,
},
{
name: "fd7a-115c-a1e0--53-port80",
desc: "intercept port 80 (Web UI) on quad100 IPv6",
dst: "[fd7a:115c:a1e0::53]:80",
intercept: true,
},
{
name: "100_100_103_100-port80",
desc: "don't intercept port 80 on local ip",
dst: "100.100.103.100:80",
intercept: false,
},
{
name: "100_100_100_100-port8080",
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
dst: "100.100.100.100:8080",
intercept: true,
},
{
name: "fd7a-115c-a1e0--53-port8080",
desc: "intercept port 8080 (Taildrive) on quad100 IPv6",
dst: "[fd7a:115c:a1e0::53]:8080",
intercept: true,
},
{
name: "100_100_103_100-port8080",
desc: "don't intercept port 8080 on local ip",
dst: "100.100.103.100:8080",
intercept: false,
},
{
name: "100_100_100_100-port9080",
desc: "don't intercept port 9080 on quad100 IPv4",
dst: "100.100.100.100:9080",
intercept: false,
},
{
name: "fd7a-115c-a1e0--53-port9080",
desc: "don't intercept port 9080 on quad100 IPv6",
dst: "[fd7a:115c:a1e0::53]:9080",
intercept: false,
},
{
name: "100_100_103_100-port9080",
desc: "don't intercept port 9080 on local ip",
dst: "100.100.103.100:9080",
intercept: false,
},
// VIP service destinations
{
name: "100_101_101_101-port882",
desc: "intercept port 882 (HTTP) on service foo IPv4",
dst: "100.101.101.101:882",
intercept: true,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port882",
desc: "intercept port 882 (HTTP) on service foo IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:882",
intercept: true,
},
{
name: "100_101_101_101-port883",
desc: "intercept port 883 (HTTPS) on service foo IPv4",
dst: "100.101.101.101:883",
intercept: true,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port883",
desc: "intercept port 883 (HTTPS) on service foo IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:883",
intercept: true,
},
{
name: "100_99_99_99-port990",
desc: "intercept port 990 (TCPForward) on service bar IPv4",
dst: "100.99.99.99:990",
intercept: true,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port990",
desc: "intercept port 990 (TCPForward) on service bar IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
intercept: true,
},
{
name: "100_99_99_99-port990-terminateTLS",
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv4",
dst: "100.99.99.99:990",
intercept: true,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port990-terminateTLS",
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
intercept: true,
},
{
name: "100_101_101_101-port4444",
desc: "don't intercept port 4444 on service foo IPv4",
dst: "100.101.101.101:4444",
intercept: false,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port4444",
desc: "don't intercept port 4444 on service foo IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:4444",
intercept: false,
},
{
name: "100_22_22_22-port883",
desc: "don't intercept port 600 on unknown service IPv4",
dst: "100.22.22.22:883",
intercept: false,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port883",
desc: "don't intercept port 600 on unknown service IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:883",
intercept: false,
},
{
name: "100_133_133_133-port600",
desc: "don't intercept port 600 (HTTPS) on service baz IPv4",
dst: "100.133.133.133:600",
intercept: false,
},
{
name: "fd7a-115c-a1e0-ab12-4843-cd96-8585-8585-port600",
desc: "don't intercept port 600 (HTTPS) on service baz IPv6",
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:8585:8585]:600",
intercept: false,
@ -4381,7 +4418,7 @@ func TestTCPHandlerForDstWithVIPService(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.dst, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Log(tt.desc)
src := netip.MustParseAddrPort("100.100.102.100:51234")
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
@ -4664,14 +4701,14 @@ func TestRoundTraffic(t *testing.T) {
bytes int64
want float64
}{
{name: "under 5 bytes", bytes: 4, want: 4},
{name: "under 1000 bytes", bytes: 987, want: 990},
{name: "under 10_000 bytes", bytes: 8875, want: 8900},
{name: "under 100_000 bytes", bytes: 77777, want: 78000},
{name: "under 1_000_000 bytes", bytes: 666523, want: 670000},
{name: "under 10_000_000 bytes", bytes: 22556677, want: 23000000},
{name: "under 1_000_000_000 bytes", bytes: 1234234234, want: 1200000000},
{name: "under 1_000_000_000 bytes", bytes: 123423423499, want: 123400000000},
{name: "under-5B", bytes: 4, want: 4},
{name: "under-1000B", bytes: 987, want: 990},
{name: "under-10000B", bytes: 8875, want: 8900},
{name: "under-100000B", bytes: 77777, want: 78000},
{name: "under-1000000B", bytes: 666523, want: 670000},
{name: "under-10000000B", bytes: 22556677, want: 23000000},
{name: "under-1000000000B", bytes: 1234234234, want: 1200000000},
{name: "over-1000000000B", bytes: 123423423499, want: 123400000000},
}
for _, tt := range tests {
@ -5033,7 +5070,7 @@ func TestSuggestExitNode(t *testing.T) {
wantError error
}{
{
name: "2 exit nodes in same region",
name: "2-exits-same-region",
lastReport: preferred1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5051,7 +5088,7 @@ func TestSuggestExitNode(t *testing.T) {
wantID: "stable1",
},
{
name: "2 exit nodes different regions unknown latency",
name: "2-exits-different-regions-unknown-latency",
lastReport: noLatency1Report,
netMap: defaultNetmap,
wantRegions: []int{1, 3}, // the only regions with peers
@ -5060,7 +5097,7 @@ func TestSuggestExitNode(t *testing.T) {
wantID: "stable2",
},
{
name: "2 derp based exit nodes, different regions, equal latency",
name: "2-derp-exits-different-regions-equal-latency",
lastReport: &netcheck.Report{
RegionLatency: map[int]time.Duration{
1: 10,
@ -5083,7 +5120,7 @@ func TestSuggestExitNode(t *testing.T) {
wantID: "stable1",
},
{
name: "mullvad nodes, no derp based exit nodes",
name: "mullvad-no-derp-exits",
lastReport: noLatency1Report,
netMap: locationNetmap,
wantID: "stable5",
@ -5091,7 +5128,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "Dallas",
},
{
name: "nearby mullvad nodes with different priorities",
name: "nearby-mullvad-different-priorities",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5107,7 +5144,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "Fort Worth",
},
{
name: "nearby mullvad nodes with same priorities",
name: "nearby-mullvad-same-priorities",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5124,7 +5161,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "Dallas",
},
{
name: "mullvad nodes, remaining node is not in preferred derp",
name: "mullvad-remaining-not-in-preferred-derp",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5140,7 +5177,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "peer4",
},
{
name: "no peers",
name: "no-peers",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5148,13 +5185,13 @@ func TestSuggestExitNode(t *testing.T) {
},
},
{
name: "nil report",
name: "nil-report",
lastReport: nil,
netMap: largeNetmap,
wantError: ErrNoPreferredDERP,
},
{
name: "no preferred derp region",
name: "no-preferred-derp-region",
lastReport: preferredNoneReport,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5163,13 +5200,13 @@ func TestSuggestExitNode(t *testing.T) {
wantError: ErrNoPreferredDERP,
},
{
name: "nil netmap",
name: "nil-netmap",
lastReport: noLatency1Report,
netMap: nil,
wantError: ErrNoPreferredDERP,
},
{
name: "nil derpmap",
name: "nil-derpmap",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5181,7 +5218,7 @@ func TestSuggestExitNode(t *testing.T) {
wantError: ErrNoPreferredDERP,
},
{
name: "missing suggestion capability",
name: "missing-suggestion-capability",
lastReport: noLatency1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5193,7 +5230,7 @@ func TestSuggestExitNode(t *testing.T) {
},
},
{
name: "prefer last node",
name: "prefer-last-node",
lastReport: preferred1Report,
netMap: &netmap.NetworkMap{
SelfNode: selfNode.View(),
@ -5212,7 +5249,7 @@ func TestSuggestExitNode(t *testing.T) {
wantID: "stable2",
},
{
name: "found better derp node",
name: "found-better-derp-node",
lastSuggestion: "stable3",
lastReport: preferred1Report,
netMap: defaultNetmap,
@ -5220,7 +5257,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "peer2",
},
{
name: "prefer last mullvad node",
name: "prefer-last-mullvad-node",
lastSuggestion: "stable2",
lastReport: preferred1Report,
netMap: &netmap.NetworkMap{
@ -5238,7 +5275,7 @@ func TestSuggestExitNode(t *testing.T) {
wantLocation: dallas.View(),
},
{
name: "prefer better mullvad node",
name: "prefer-better-mullvad-node",
lastSuggestion: "stable2",
lastReport: preferred1Report,
netMap: &netmap.NetworkMap{
@ -5256,7 +5293,7 @@ func TestSuggestExitNode(t *testing.T) {
wantLocation: fortWorth.View(),
},
{
name: "large netmap",
name: "large-netmap",
lastReport: preferred1Report,
netMap: largeNetmap,
wantNodes: []tailcfg.StableNodeID{"stable1", "stable2"},
@ -5264,13 +5301,13 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "peer2",
},
{
name: "no allowed suggestions",
name: "no-allowed-suggestions",
lastReport: preferred1Report,
netMap: largeNetmap,
allowPolicy: []tailcfg.StableNodeID{},
},
{
name: "only derp suggestions",
name: "only-derp-suggestions",
lastReport: preferred1Report,
netMap: largeNetmap,
allowPolicy: []tailcfg.StableNodeID{"stable1", "stable2", "stable3"},
@ -5279,7 +5316,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "peer2",
},
{
name: "only mullvad suggestions",
name: "only-mullvad-suggestions",
lastReport: preferred1Report,
netMap: largeNetmap,
allowPolicy: []tailcfg.StableNodeID{"stable5", "stable6", "stable7"},
@ -5288,7 +5325,7 @@ func TestSuggestExitNode(t *testing.T) {
wantLocation: fortWorth.View(),
},
{
name: "only worst derp",
name: "only-worst-derp",
lastReport: preferred1Report,
netMap: largeNetmap,
allowPolicy: []tailcfg.StableNodeID{"stable3"},
@ -5296,7 +5333,7 @@ func TestSuggestExitNode(t *testing.T) {
wantName: "peer3",
},
{
name: "only worst mullvad",
name: "only-worst-mullvad",
lastReport: preferred1Report,
netMap: largeNetmap,
allowPolicy: []tailcfg.StableNodeID{"stable6"},
@ -5306,7 +5343,7 @@ func TestSuggestExitNode(t *testing.T) {
},
{
// Regression test for https://github.com/tailscale/tailscale/issues/17661
name: "exit nodes with no home DERP, randomly selected",
name: "exits-no-home-DERP-random-selection",
lastReport: &netcheck.Report{
RegionLatency: map[int]time.Duration{
1: 10,
@ -5388,7 +5425,7 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
wantIDs []tailcfg.StableNodeID
}{
{
name: "different priorities",
name: "different-priorities",
candidates: []tailcfg.NodeView{
makePeer(2, withExitRoutes(), withLocation(location20.View())),
makePeer(3, withExitRoutes(), withLocation(location10.View())),
@ -5396,7 +5433,7 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
wantIDs: []tailcfg.StableNodeID{"stable2"},
},
{
name: "same priorities",
name: "same-priorities",
candidates: []tailcfg.NodeView{
makePeer(2, withExitRoutes(), withLocation(location10.View())),
makePeer(3, withExitRoutes(), withLocation(location10.View())),
@ -5404,11 +5441,11 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
wantIDs: []tailcfg.StableNodeID{"stable2", "stable3"},
},
{
name: "<1 candidates",
name: "lt1-candidates",
candidates: []tailcfg.NodeView{},
},
{
name: "1 candidate",
name: "1-candidate",
candidates: []tailcfg.NodeView{
makePeer(2, withExitRoutes(), withLocation(location20.View())),
},
@ -5444,7 +5481,7 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
want float64
}{
{
name: "zero values",
name: "zero-values",
fromLat: 0,
fromLong: 0,
toLat: 0,
@ -5452,7 +5489,7 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
want: 0,
},
{
name: "valid values",
name: "valid-values",
fromLat: 40.73061,
fromLong: -73.935242,
toLat: 37.3382082,
@ -5460,7 +5497,8 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
want: 4117266.873301274,
},
{
name: "valid values, locations in north and south of equator",
// Locations in north and south of equator.
name: "valid-values-cross-equator",
fromLat: 40.73061,
fromLong: -73.935242,
toLat: -33.861481,
@ -5865,13 +5903,13 @@ func TestMinLatencyDERPregion(t *testing.T) {
wantRegion int
}{
{
name: "regions, no latency values",
name: "regions-no-latency",
regions: []int{1, 2, 3},
wantRegion: 0,
report: &netcheck.Report{},
},
{
name: "regions, different latency values",
name: "regions-different-latency",
regions: []int{1, 2, 3},
wantRegion: 2,
report: &netcheck.Report{
@ -5883,7 +5921,7 @@ func TestMinLatencyDERPregion(t *testing.T) {
},
},
{
name: "regions, same values",
name: "regions-same-latency",
regions: []int{1, 2, 3},
wantRegion: 1,
report: &netcheck.Report{
@ -6030,7 +6068,7 @@ func TestFillAllowedSuggestions(t *testing.T) {
want: []tailcfg.StableNodeID{"one", "three", "four", "two"}, // order should not matter
},
{
name: "preserve case",
name: "preserve-case",
allowPolicy: []string{"ABC", "def", "gHiJ"},
want: []tailcfg.StableNodeID{"ABC", "def", "gHiJ"},
},
@ -6184,61 +6222,61 @@ func TestNotificationTargetMatch(t *testing.T) {
wantMatch: false,
},
{
name: "FilterByUID+CID/Nil",
name: "FilterByUID-CID/Nil",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4"},
actor: nil,
wantMatch: false,
},
{
name: "FilterByUID+CID/NoUID/NoCID",
name: "FilterByUID-CID/NoUID/NoCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{},
wantMatch: false,
},
{
name: "FilterByUID+CID/NoUID/SameCID",
name: "FilterByUID-CID/NoUID/SameCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("A")},
wantMatch: false,
},
{
name: "FilterByUID+CID/NoUID/DifferentCID",
name: "FilterByUID-CID/NoUID/DifferentCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("B")},
wantMatch: false,
},
{
name: "FilterByUID+CID/SameUID/NoCID",
name: "FilterByUID-CID/SameUID/NoCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4"},
wantMatch: false,
},
{
name: "FilterByUID+CID/SameUID/SameCID",
name: "FilterByUID-CID/SameUID/SameCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4", CID: ipnauth.ClientIDFrom("A")},
wantMatch: true,
},
{
name: "FilterByUID+CID/SameUID/DifferentCID",
name: "FilterByUID-CID/SameUID/DifferentCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4", CID: ipnauth.ClientIDFrom("B")},
wantMatch: false,
},
{
name: "FilterByUID+CID/DifferentUID/NoCID",
name: "FilterByUID-CID/DifferentUID/NoCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8"},
wantMatch: false,
},
{
name: "FilterByUID+CID/DifferentUID/SameCID",
name: "FilterByUID-CID/DifferentUID/SameCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8", CID: ipnauth.ClientIDFrom("A")},
wantMatch: false,
},
{
name: "FilterByUID+CID/DifferentUID/DifferentCID",
name: "FilterByUID-CID/DifferentUID/DifferentCID",
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8", CID: ipnauth.ClientIDFrom("B")},
wantMatch: false,

@ -300,9 +300,9 @@ func TestTKASync(t *testing.T) {
}
tcs := []tkaSyncScenario{
{name: "up to date"},
{name: "up-to-date"},
{
name: "control has an update",
name: "control-has-an-update",
controlAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
b := a.NewUpdater(signer)
if err := b.RemoveKey(someKey.MustID()); err != nil {
@ -317,7 +317,7 @@ func TestTKASync(t *testing.T) {
},
{
// AKA 'control data loss' scenario
name: "node has an update",
name: "node-has-an-update",
nodeAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
b := a.NewUpdater(signer)
if err := b.RemoveKey(someKey.MustID()); err != nil {
@ -332,7 +332,7 @@ func TestTKASync(t *testing.T) {
},
{
// AKA 'control data loss + update in the meantime' scenario
name: "node and control diverge",
name: "node-and-control-diverge",
controlAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
b := a.NewUpdater(signer)
if err := b.SetKeyMeta(someKey.MustID(), map[string]string{"ye": "swiggity"}); err != nil {
@ -1020,7 +1020,7 @@ func TestTKAAffectedSigs(t *testing.T) {
wantErr string
}{
{
"no error",
"no-error",
func() *tka.NodeKeySignature {
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
return sig
@ -1028,7 +1028,7 @@ func TestTKAAffectedSigs(t *testing.T) {
"",
},
{
"signature for different keyID",
"signature-for-different-keyID",
func() *tka.NodeKeySignature {
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, untrustedKey)
return sig
@ -1036,7 +1036,7 @@ func TestTKAAffectedSigs(t *testing.T) {
fmt.Sprintf("got signature with keyID %X from request for %X", untrustedKey.KeyID(), nlPriv.KeyID()),
},
{
"invalid signature",
"invalid-signature",
func() *tka.NodeKeySignature {
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
copy(sig.Signature, []byte{1, 2, 3, 4, 5, 6}) // overwrite with trash to invalid signature

@ -619,49 +619,49 @@ func TestServeHTTPProxyPath(t *testing.T) {
wantRequestPath string
}{
{
name: "/foo -> /foo, with mount point and path /foo",
name: "foo-to-foo-mount-foo",
mountPoint: "/foo",
proxyPath: "/foo",
requestPath: "/foo",
wantRequestPath: "/foo",
},
{
name: "/foo/ -> /foo/, with mount point and path /foo",
name: "foo-slash-to-foo-slash-mount-foo",
mountPoint: "/foo",
proxyPath: "/foo",
requestPath: "/foo/",
wantRequestPath: "/foo/",
},
{
name: "/foo -> /foo/, with mount point and path /foo/",
name: "foo-to-foo-slash-mount-foo-slash",
mountPoint: "/foo/",
proxyPath: "/foo/",
requestPath: "/foo",
wantRequestPath: "/foo/",
},
{
name: "/-> /, with mount point and path /",
name: "root-to-root-mount-root",
mountPoint: "/",
proxyPath: "/",
requestPath: "/",
wantRequestPath: "/",
},
{
name: "/foo -> /foo, with mount point and path /",
name: "foo-to-foo-mount-root",
mountPoint: "/",
proxyPath: "/",
requestPath: "/foo",
wantRequestPath: "/foo",
},
{
name: "/foo/bar -> /foo/bar, with mount point and path /foo",
name: "foo-bar-to-foo-bar-mount-foo",
mountPoint: "/foo",
proxyPath: "/foo",
requestPath: "/foo/bar",
wantRequestPath: "/foo/bar",
},
{
name: "/foo/bar/baz -> /foo/bar/baz, with mount point and path /foo",
name: "foo-bar-baz-to-foo-bar-baz-mount-foo",
mountPoint: "/foo",
proxyPath: "/foo",
requestPath: "/foo/bar/baz",
@ -1457,7 +1457,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError bool
}{
{
name: "empty existing config",
name: "empty-existing-config",
description: "should be able to update with empty existing config",
existing: &ipn.ServeConfig{},
incoming: &ipn.ServeConfig{
@ -1468,7 +1468,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "no existing config",
name: "no-existing-config",
description: "should be able to update with no existing config",
existing: nil,
incoming: &ipn.ServeConfig{
@ -1479,7 +1479,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "empty incoming config",
name: "empty-incoming-config",
description: "wiping config should work",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1490,7 +1490,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "no incoming config",
name: "no-incoming-config",
description: "missing incoming config should not result in an error",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1501,7 +1501,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "non-overlapping update",
name: "non-overlapping-update",
description: "non-overlapping update should work",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1516,7 +1516,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "overwriting background port",
name: "overwriting-background-port",
description: "should be able to overwrite a background port",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1535,7 +1535,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "broken existing config",
name: "broken-existing-config",
description: "broken existing config should not prevent new config updates",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1573,7 +1573,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "services same port as background",
name: "services-same-port-as-background",
description: "services should be able to use the same port as background listeners",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1592,7 +1592,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: false,
},
{
name: "services tun mode",
name: "services-tun-mode",
description: "TUN mode should be mutually exclusive with TCP or web handlers for new Services",
existing: &ipn.ServeConfig{},
incoming: &ipn.ServeConfig{
@ -1608,7 +1608,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "new foreground listener",
name: "new-foreground-listener",
description: "new foreground listeners must be on open ports",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1627,7 +1627,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "new background listener",
name: "new-background-listener",
description: "new background listers cannot overwrite foreground listeners",
existing: &ipn.ServeConfig{
Foreground: map[string]*ipn.ServeConfig{
@ -1646,7 +1646,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "serve type overwrite",
name: "serve-type-overwrite",
description: "incoming configuration cannot change the serve type in use by a port",
existing: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
@ -1665,7 +1665,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "serve type overwrite services",
name: "serve-type-overwrite-services",
description: "incoming Services configuration cannot change the serve type in use by a port",
existing: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1692,7 +1692,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "tun mode with handlers",
name: "tun-mode-with-handlers",
description: "Services cannot enable TUN mode if L4 or L7 handlers already exist",
existing: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
@ -1720,7 +1720,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
wantError: true,
},
{
name: "handlers with tun mode",
name: "handlers-with-tun-mode",
description: "Services cannot add L4 or L7 handlers if TUN mode is already enabled",
existing: &ipn.ServeConfig{
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{

@ -23,26 +23,30 @@ import (
func TestExpandProxyArgUnix(t *testing.T) {
tests := []struct {
name string
input string
wantURL string
wantInsecure bool
}{
{
name: "unix-tmp-sock",
input: "unix:/tmp/test.sock",
wantURL: "unix:/tmp/test.sock",
},
{
name: "unix-var-run-docker-sock",
input: "unix:/var/run/docker.sock",
wantURL: "unix:/var/run/docker.sock",
},
{
name: "unix-relative-sock",
input: "unix:./relative.sock",
wantURL: "unix:./relative.sock",
},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
gotURL, gotInsecure := expandProxyArg(tt.input)
if gotURL != tt.wantURL {
t.Errorf("expandProxyArg(%q) url = %q, want %q", tt.input, gotURL, tt.wantURL)

@ -458,7 +458,7 @@ func TestPrefsFromBytesPreservesOldValues(t *testing.T) {
want: Prefs{ControlURL: "https://foo", RouteAll: true},
},
{
name: "opt.Bool", // test that we don't normalize it early
name: "opt-Bool", // test that we don't normalize it early
old: Prefs{Sync: "unset"},
json: []byte(`{}`),
want: Prefs{Sync: "unset"},
@ -1236,13 +1236,13 @@ func TestParseAutoExitNodeString(t *testing.T) {
wantExpr ExitNodeExpression
}{
{
name: "empty expr",
name: "empty-expr",
exitNodeID: "",
wantOk: false,
wantExpr: "",
},
{
name: "no auto prefix",
name: "no-auto-prefix",
exitNodeID: "foo",
wantOk: false,
wantExpr: "",
@ -1260,13 +1260,13 @@ func TestParseAutoExitNodeString(t *testing.T) {
wantExpr: "foo",
},
{
name: "auto prefix but empty suffix",
name: "auto-prefix-empty-suffix",
exitNodeID: "auto:",
wantOk: false,
wantExpr: "",
},
{
name: "auto prefix no colon",
name: "auto-prefix-no-colon",
exitNodeID: "auto",
wantOk: false,
wantExpr: "",

@ -283,11 +283,11 @@ func TestExpandProxyTargetDev(t *testing.T) {
wantErr bool
}{
{name: "port-only", input: "8080", expected: "http://127.0.0.1:8080"},
{name: "hostname+port", input: "localhost:8080", expected: "http://localhost:8080"},
{name: "hostname-and-port", input: "localhost:8080", expected: "http://localhost:8080"},
{name: "no-change", input: "http://127.0.0.1:8080", expected: "http://127.0.0.1:8080"},
{name: "include-path", input: "http://127.0.0.1:8080/foo", expected: "http://127.0.0.1:8080/foo"},
{name: "https-scheme", input: "https://localhost:8080", expected: "https://localhost:8080"},
{name: "https+insecure-scheme", input: "https+insecure://localhost:8080", expected: "https+insecure://localhost:8080"},
{name: "https-insecure-scheme", input: "https+insecure://localhost:8080", expected: "https+insecure://localhost:8080"},
{name: "change-default-scheme", input: "localhost:8080", defaultScheme: "https", expected: "https://localhost:8080"},
{name: "change-supported-schemes", input: "localhost:8080", defaultScheme: "tcp", supportedSchemes: []string{"tcp"}, expected: "tcp://localhost:8080"},
{name: "remote-target", input: "https://example.com:8080", expected: "https://example.com:8080"},

@ -30,7 +30,7 @@ func TestReconciler_Reconcile(t *testing.T) {
ExpectsError bool
}{
{
Name: "single policy, denies all",
Name: "single-policy-denies-all",
ExpectedPolicyCount: 2,
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
@ -53,7 +53,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "multiple policies merged",
Name: "multiple-policies-merged",
ExpectedPolicyCount: 2,
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
@ -89,7 +89,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "no policies, no child resources",
Name: "no-policies-no-child-resources",
ExpectedPolicyCount: 0,
Request: reconcile.Request{
NamespacedName: types.NamespacedName{

@ -39,7 +39,7 @@ func TestReconciler_Reconcile(t *testing.T) {
ClientFunc func(*tsapi.Tailnet, *corev1.Secret) tailnet.TailscaleClient
}{
{
Name: "ignores unknown tailnet requests",
Name: "ignores-unknown-tailnet-requests",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -47,7 +47,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for missing secret",
Name: "invalid-status-missing-secret",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -73,7 +73,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for empty secret",
Name: "invalid-status-empty-secret",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -105,7 +105,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for missing client id",
Name: "invalid-status-missing-client-id",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -140,7 +140,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for missing client secret",
Name: "invalid-status-missing-client-secret",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -175,7 +175,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for bad devices scope",
Name: "invalid-status-bad-devices-scope",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -214,7 +214,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for bad services scope",
Name: "invalid-status-bad-services-scope",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -253,7 +253,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "invalid status for bad keys scope",
Name: "invalid-status-bad-keys-scope",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "test",
@ -292,7 +292,7 @@ func TestReconciler_Reconcile(t *testing.T) {
},
},
{
Name: "ready when valid and scopes are correct",
Name: "ready-valid-scopes-correct",
Request: reconcile.Request{
NamespacedName: types.NamespacedName{
Name: "default",

@ -39,19 +39,19 @@ func TestDelta(t *testing.T) {
wantStats map[sockstats.Label]deltaStat
}{
{
name: "nil a stat",
name: "nil-a-stat",
a: nil,
b: &sockstats.SockStats{},
wantStats: nil,
},
{
name: "nil b stat",
name: "nil-b-stat",
a: &sockstats.SockStats{},
b: nil,
wantStats: nil,
},
{
name: "no change",
name: "no-change",
a: &sockstats.SockStats{
Stats: map[sockstats.Label]sockstats.SockStat{
sockstats.LabelDERPHTTPClient: {
@ -69,7 +69,7 @@ func TestDelta(t *testing.T) {
wantStats: nil,
},
{
name: "tx after empty stat",
name: "tx-after-empty-stat",
a: &sockstats.SockStats{},
b: &sockstats.SockStats{
Stats: map[sockstats.Label]sockstats.SockStat{
@ -83,7 +83,7 @@ func TestDelta(t *testing.T) {
},
},
{
name: "rx after non-empty stat",
name: "rx-after-non-empty-stat",
a: &sockstats.SockStats{
Stats: map[sockstats.Label]sockstats.SockStat{
sockstats.LabelDERPHTTPClient: {

@ -42,7 +42,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr bool
}{
{
name: "second last split last empty",
name: "second-last-split-last-empty",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -55,7 +55,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr: false,
},
{
name: "second last no split last empty",
name: "second-last-no-split-last-empty",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -68,7 +68,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr: false,
},
{
name: "second last no split last no split",
name: "second-last-no-split-last-no-split",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -81,7 +81,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr: false,
},
{
name: "second last no split last split",
name: "second-last-no-split-last-split",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -94,7 +94,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr: false,
},
{
name: "second last split last split",
name: "second-last-split-last-split",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -107,7 +107,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
wantErr: false,
},
{
name: "second last no split last split overflow",
name: "second-last-no-split-last-split-overflow",
msgs: []ipv6.Message{
newMsg(0, 0),
newMsg(0, 0),
@ -161,7 +161,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO []int
}{
{
name: "one message no coalesce",
name: "one-message-no-coalesce",
buffs: [][]byte{
withGeneveSpace(1, 1),
},
@ -169,7 +169,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{0},
},
{
name: "one message no coalesce vni.isSet",
name: "one-message-no-coalesce-vni-isSet",
buffs: [][]byte{
withGeneveSpace(1, 1),
},
@ -178,7 +178,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{0},
},
{
name: "two messages equal len coalesce",
name: "two-messages-equal-len-coalesce",
buffs: [][]byte{
withGeneveSpace(1, 2),
withGeneveSpace(1, 1),
@ -187,7 +187,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{1},
},
{
name: "two messages equal len coalesce vni.isSet",
name: "two-messages-equal-len-coalesce-vni-isSet",
buffs: [][]byte{
withGeneveSpace(1, 2+packet.GeneveFixedHeaderLength),
withGeneveSpace(1, 1),
@ -197,7 +197,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{1 + packet.GeneveFixedHeaderLength},
},
{
name: "two messages unequal len coalesce",
name: "two-messages-unequal-len-coalesce",
buffs: [][]byte{
withGeneveSpace(2, 3),
withGeneveSpace(1, 1),
@ -206,7 +206,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{2},
},
{
name: "two messages unequal len coalesce vni.isSet",
name: "two-messages-unequal-len-coalesce-vni-isSet",
buffs: [][]byte{
withGeneveSpace(2, 3+packet.GeneveFixedHeaderLength),
withGeneveSpace(1, 1),
@ -216,7 +216,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{2 + packet.GeneveFixedHeaderLength},
},
{
name: "three messages second unequal len coalesce",
name: "three-messages-second-unequal-len-coalesce",
buffs: [][]byte{
withGeneveSpace(2, 3),
withGeneveSpace(1, 1),
@ -226,7 +226,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{2, 0},
},
{
name: "three messages second unequal len coalesce vni.isSet",
name: "three-messages-second-unequal-len-coalesce-vni-isSet",
buffs: [][]byte{
withGeneveSpace(2, 3+(2*packet.GeneveFixedHeaderLength)),
withGeneveSpace(1, 1),
@ -237,7 +237,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{2 + packet.GeneveFixedHeaderLength, 0},
},
{
name: "three messages limited cap coalesce",
name: "three-messages-limited-cap-coalesce",
buffs: [][]byte{
withGeneveSpace(2, 4),
withGeneveSpace(2, 2),
@ -247,7 +247,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
wantGSO: []int{2},
},
{
name: "three messages limited cap coalesce vni.isSet",
name: "three-messages-limited-cap-coalesce-vni-isSet",
buffs: [][]byte{
withGeneveSpace(2, 4+packet.GeneveFixedHeaderLength),
withGeneveSpace(2, 2),
@ -376,19 +376,19 @@ func Test_getRXQOverflowsFromControl(t *testing.T) {
wantErr: false,
},
{
name: "rxq overflows",
name: "rxq-overflows",
control: rxqOverflowsControl(1),
want: 1,
wantErr: false,
},
{
name: "multiple cmsg rxq overflows at head",
name: "multiple-cmsg-rxq-overflows-at-head",
control: append(rxqOverflowsControl(1), gsoControl(1)...),
want: 1,
wantErr: false,
},
{
name: "multiple cmsg rxq overflows at tail",
name: "multiple-cmsg-rxq-overflows-at-tail",
control: append(gsoControl(1), rxqOverflowsControl(1)...),
want: 1,
wantErr: false,
@ -432,19 +432,19 @@ func Test_getGSOSizeFromControl(t *testing.T) {
wantErr: false,
},
{
name: "rxq overflows",
name: "rxq-overflows",
control: rxqOverflowsControl(1),
want: 0,
wantErr: false,
},
{
name: "multiple cmsg gso at tail",
name: "multiple-cmsg-gso-at-tail",
control: append(rxqOverflowsControl(1), gsoControl(1)...),
want: 1,
wantErr: false,
},
{
name: "multiple cmsg gso at head",
name: "multiple-cmsg-gso-at-head",
control: append(gsoControl(1), rxqOverflowsControl(1)...),
want: 1,
wantErr: false,

@ -22,7 +22,7 @@ func TestLinuxDNSMode(t *testing.T) {
want string
}{
{
name: "no_obvious_resolv.conf_owner",
name: "no_obvious_resolvconf_owner",
env: env(resolvDotConf("nameserver 10.0.0.1")),
wantLog: "dns: [rc=unknown ret=direct]",
want: "direct",
@ -153,7 +153,7 @@ func TestLinuxDNSMode(t *testing.T) {
// alleged that it was managed by systemd-resolved, but it
// was actually a completely static config file pointing
// elsewhere.
name: "allegedly_resolved_but_not_in_resolv.conf",
name: "allegedly_resolved_but_not_in_resolvconf",
env: env(resolvDotConf("# Managed by systemd-resolved", "nameserver 10.0.0.1")),
wantLog: "dns: resolvedIsActuallyResolver error: resolv.conf doesn't point to systemd-resolved; points to [10.0.0.1]\n" +
"dns: [rc=resolved resolved=not-in-use ret=direct]",
@ -163,7 +163,7 @@ func TestLinuxDNSMode(t *testing.T) {
// We used to incorrectly decide that resolved wasn't in
// charge when handed this (admittedly weird and bugged)
// resolv.conf.
name: "resolved_with_duplicates_in_resolv.conf",
name: "resolved_with_duplicates_in_resolvconf",
env: env(
resolvDotConf(
"# Managed by systemd-resolved",

@ -1127,7 +1127,7 @@ func TestForwarderWithManyResolvers(t *testing.T) {
},
},
{
name: "ServFail+Success",
name: "ServFail-and-Success",
responses: [][]byte{ // All upstream servers fail except for one.
makeTestResponse(t, domain, dns.RCodeServerFailure),
makeTestResponse(t, domain, dns.RCodeServerFailure),
@ -1150,7 +1150,7 @@ func TestForwarderWithManyResolvers(t *testing.T) {
},
},
{
name: "NXDomain+Success",
name: "NXDomain-and-Success",
responses: [][]byte{ // All upstream servers returned NXDOMAIN except for one.
makeTestResponse(t, domain, dns.RCodeNameError),
makeTestResponse(t, domain, dns.RCodeNameError),
@ -1173,7 +1173,7 @@ func TestForwarderWithManyResolvers(t *testing.T) {
},
},
{
name: "Refused+Success",
name: "Refused-and-Success",
responses: [][]byte{ // Some upstream servers refuse, but one succeeds.
makeTestResponse(t, domain, dns.RCodeRefused),
makeTestResponse(t, domain, dns.RCodeRefused),
@ -1187,7 +1187,7 @@ func TestForwarderWithManyResolvers(t *testing.T) {
},
},
{
name: "Refused+ServFail",
name: "Refused-and-ServFail",
responses: [][]byte{ // Some servers refuse, at least one fails.
makeTestResponse(t, domain, dns.RCodeRefused),
makeTestResponse(t, domain, dns.RCodeServerFailure),

@ -998,7 +998,7 @@ func TestNodeAddrResolve(t *testing.T) {
}
t.Logf("got IPv6 addr: %v", ap)
})
t.Run("IPv6 Failure", func(t *testing.T) {
t.Run("IPv6-Failure", func(t *testing.T) {
ap, ok := c.nodeAddrPort(ctx, dnV4Only, dn.STUNPort, probeIPv6)
if ok {
t.Fatalf("expected no addr but got: %v", ap)

@ -49,7 +49,7 @@ func TestIgnoreDuplicateNEWADDR(t *testing.T) {
return msg
}
t.Run("suppress duplicate NEWADDRs", func(t *testing.T) {
t.Run("suppress-duplicate-NEWADDRs", func(t *testing.T) {
c := nlConn{
buffered: []netlink.Message{
newAddrMsg(1, "192.168.0.5", unix.RTM_NEWADDR),
@ -69,7 +69,7 @@ func TestIgnoreDuplicateNEWADDR(t *testing.T) {
}
})
t.Run("do not suppress after DELADDR", func(t *testing.T) {
t.Run("no-suppress-after-DELADDR", func(t *testing.T) {
c := nlConn{
buffered: []netlink.Message{
newAddrMsg(1, "192.168.0.5", unix.RTM_NEWADDR),

@ -47,7 +47,7 @@ func TestDownload(t *testing.T) {
// ensure that the test returns an appropriate number of Result structs
expectedLen := int(DefaultDuration.Seconds()) + 1
t.Run("download test", func(t *testing.T) {
t.Run("download-test", func(t *testing.T) {
// conduct a download test
results, err := RunClient(Download, DefaultDuration, serverIP)
@ -65,7 +65,7 @@ func TestDownload(t *testing.T) {
}
})
t.Run("upload test", func(t *testing.T) {
t.Run("upload-test", func(t *testing.T) {
// conduct an upload test
results, err := RunClient(Upload, DefaultDuration, serverIP)

@ -60,7 +60,7 @@ var responseTests = []struct {
wantPort: 59029,
},
{
name: "stun.sipgate.net:10000",
name: "stun-sipgate-net-10000",
data: []byte{
0x01, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42,
0x48, 0x2e, 0xb6, 0x47, 0x15, 0xe8, 0xb2, 0x8e,
@ -82,7 +82,7 @@ var responseTests = []struct {
wantPort: 58539,
},
{
name: "stun.powervoip.com:3478",
name: "stun-powervoip-com-3478",
data: []byte{
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
0x7e, 0x57, 0x96, 0x68, 0x29, 0xf4, 0x44, 0x60,
@ -100,7 +100,7 @@ var responseTests = []struct {
wantPort: 59859,
},
{
name: "in-process pion server",
name: "in-process-pion-server",
data: []byte{
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
0xeb, 0xc2, 0xd3, 0x6e, 0xf4, 0x71, 0x21, 0x7c,
@ -119,7 +119,7 @@ var responseTests = []struct {
wantPort: 61300,
},
{
name: "stuntman-server ipv6",
name: "stuntman-server-ipv6",
data: []byte{
0x01, 0x01, 0x00, 0x48, 0x21, 0x12, 0xa4, 0x42,
0x06, 0xf5, 0x66, 0x85, 0xd2, 0x8a, 0xf3, 0xe6,

@ -28,7 +28,7 @@ func TestSynologyProxyFromConfigCached(t *testing.T) {
tstest.Replace(t, &synologyProxyConfigPath, filepath.Join(t.TempDir(), "proxy.conf"))
t.Run("no config file", func(t *testing.T) {
t.Run("no-config-file", func(t *testing.T) {
if _, err := os.Stat(synologyProxyConfigPath); err == nil {
t.Fatalf("%s must not exist for this test", synologyProxyConfigPath)
}
@ -52,7 +52,7 @@ func TestSynologyProxyFromConfigCached(t *testing.T) {
}
})
t.Run("config file updated", func(t *testing.T) {
t.Run("config-file-updated", func(t *testing.T) {
cache.updated = time.Now()
cache.httpProxy = nil
cache.httpsProxy = nil
@ -84,7 +84,7 @@ https_port=443
}
})
t.Run("config file removed", func(t *testing.T) {
t.Run("config-file-removed", func(t *testing.T) {
cache.updated = time.Now()
cache.httpProxy = urlMustParse("http://127.0.0.1/")
cache.httpsProxy = urlMustParse("http://127.0.0.1/")
@ -108,7 +108,7 @@ https_port=443
}
})
t.Run("picks proxy from request scheme", func(t *testing.T) {
t.Run("picks-proxy-from-request-scheme", func(t *testing.T) {
cache.updated = time.Now()
cache.httpProxy = nil
cache.httpsProxy = nil
@ -164,7 +164,7 @@ func TestSynologyProxiesFromConfig(t *testing.T) {
return openReader, openErr
})
t.Run("with config", func(t *testing.T) {
t.Run("with-config", func(t *testing.T) {
mc := &mustCloser{Reader: strings.NewReader(`
proxy_user=foo
proxy_pwd=bar
@ -200,7 +200,7 @@ http_port=80
})
t.Run("nonexistent config", func(t *testing.T) {
t.Run("nonexistent-config", func(t *testing.T) {
openReader = nil
openErr = os.ErrNotExist
@ -216,7 +216,7 @@ http_port=80
}
})
t.Run("error opening config", func(t *testing.T) {
t.Run("error-opening-config", func(t *testing.T) {
openReader = nil
openErr = errors.New("example error")

@ -97,7 +97,7 @@ func TestSetSelfProxy(t *testing.T) {
wantHTTPS string
}{
{
name: "no self proxy",
name: "no-self-proxy",
env: map[string]string{
"HTTP_PROXY": "127.0.0.1:1234",
"HTTPS_PROXY": "127.0.0.1:1234",
@ -107,7 +107,7 @@ func TestSetSelfProxy(t *testing.T) {
wantHTTPS: "127.0.0.1:1234",
},
{
name: "skip proxies",
name: "skip-proxies",
env: map[string]string{
"HTTP_PROXY": "127.0.0.1:1234",
"HTTPS_PROXY": "127.0.0.1:5678",
@ -117,7 +117,7 @@ func TestSetSelfProxy(t *testing.T) {
wantHTTPS: "", // skipped
},
{
name: "localhost normalization of env var",
name: "localhost-normalization-of-env-var",
env: map[string]string{
"HTTP_PROXY": "localhost:1234",
"HTTPS_PROXY": "[::1]:5678",
@ -127,7 +127,7 @@ func TestSetSelfProxy(t *testing.T) {
wantHTTPS: "", // skipped
},
{
name: "localhost normalization of addr",
name: "localhost-normalization-of-addr",
env: map[string]string{
"HTTP_PROXY": "127.0.0.1:1234",
"HTTPS_PROXY": "127.0.0.1:1234",
@ -137,7 +137,7 @@ func TestSetSelfProxy(t *testing.T) {
wantHTTPS: "", // skipped
},
{
name: "no ports",
name: "no-ports",
env: map[string]string{
"HTTP_PROXY": "myproxy",
"HTTPS_PROXY": "myproxy",

@ -28,32 +28,32 @@ func TestServerEndpointJSONUnmarshal(t *testing.T) {
wantErr: false,
},
{
name: "invalid ServerDisco",
name: "invalid-ServerDisco",
json: []byte(`{"ServerDisco":"1","LamportID":18446744073709551615,"AddrPorts":["127.0.0.1:1","127.0.0.2:2"],"VNI":16777215,"BindLifetime":"30s","SteadyStateLifetime":"5m0s"}`),
wantErr: true,
},
{
name: "invalid LamportID",
name: "invalid-LamportID",
json: []byte(`{"ServerDisco":"discokey:003cd7453e04a653eb0e7a18f206fc353180efadb2facfd05ebd6982a1392c7f","LamportID":1.1,"AddrPorts":["127.0.0.1:1","127.0.0.2:2"],"VNI":16777215,"BindLifetime":"30s","SteadyStateLifetime":"5m0s"}`),
wantErr: true,
},
{
name: "invalid AddrPorts",
name: "invalid-AddrPorts",
json: []byte(`{"ServerDisco":"discokey:003cd7453e04a653eb0e7a18f206fc353180efadb2facfd05ebd6982a1392c7f","LamportID":18446744073709551615,"AddrPorts":["127.0.0.1.1:1","127.0.0.2:2"],"VNI":16777215,"BindLifetime":"30s","SteadyStateLifetime":"5m0s"}`),
wantErr: true,
},
{
name: "invalid VNI",
name: "invalid-VNI",
json: []byte(`{"ServerDisco":"discokey:003cd7453e04a653eb0e7a18f206fc353180efadb2facfd05ebd6982a1392c7f","LamportID":18446744073709551615,"AddrPorts":["127.0.0.1:1","127.0.0.2:2"],"VNI":18446744073709551615,"BindLifetime":"30s","SteadyStateLifetime":"5m0s"}`),
wantErr: true,
},
{
name: "invalid BindLifetime",
name: "invalid-BindLifetime",
json: []byte(`{"ServerDisco":"discokey:003cd7453e04a653eb0e7a18f206fc353180efadb2facfd05ebd6982a1392c7f","LamportID":18446744073709551615,"AddrPorts":["127.0.0.1:1","127.0.0.2:2"],"VNI":16777215,"BindLifetime":"5","SteadyStateLifetime":"5m0s"}`),
wantErr: true,
},
{
name: "invalid SteadyStateLifetime",
name: "invalid-SteadyStateLifetime",
json: []byte(`{"ServerDisco":"discokey:003cd7453e04a653eb0e7a18f206fc353180efadb2facfd05ebd6982a1392c7f","LamportID":18446744073709551615,"AddrPorts":["127.0.0.1:1","127.0.0.2:2"],"VNI":16777215,"BindLifetime":"30s","SteadyStateLifetime":"5"}`),
wantErr: true,
},
@ -79,7 +79,7 @@ func TestServerEndpointJSONMarshal(t *testing.T) {
serverEndpoint ServerEndpoint
}{
{
name: "valid roundtrip",
name: "valid-roundtrip",
serverEndpoint: ServerEndpoint{
ServerDisco: key.NewDisco().Public(),
LamportID: uint64(math.MaxUint64),

@ -196,15 +196,15 @@ func TestServer(t *testing.T) {
forceClientsMixedAF bool
}{
{
name: "over ipv4",
name: "over-ipv4",
staticAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1")},
},
{
name: "over ipv6",
name: "over-ipv6",
staticAddrs: []netip.Addr{netip.MustParseAddr("::1")},
},
{
name: "mixed address families",
name: "mixed-address-families",
staticAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1"), netip.MustParseAddr("::1")},
forceClientsMixedAF: true,
},

@ -41,25 +41,25 @@ func TestPostRequestContentTypeValidation(t *testing.T) {
wantErr bool
}{
{
name: "API routes should accept `application/json` content-type",
name: "API-accept-application-json",
browserRoute: false,
contentType: "application/json",
wantErr: false,
},
{
name: "API routes should reject `application/x-www-form-urlencoded` content-type",
name: "API-reject-form-urlencoded",
browserRoute: false,
contentType: "application/x-www-form-urlencoded",
wantErr: true,
},
{
name: "Browser routes should accept `application/x-www-form-urlencoded` content-type",
name: "browser-accept-form-urlencoded",
browserRoute: true,
contentType: "application/x-www-form-urlencoded",
wantErr: false,
},
{
name: "non Browser routes should accept `application/json` content-type",
name: "browser-accept-application-json",
browserRoute: true,
contentType: "application/json",
wantErr: false,
@ -106,21 +106,21 @@ func TestAPIMuxCrossOriginResourceSharingHeaders(t *testing.T) {
corsMethods []string
}{
{
name: "do not set CORS headers for non-OPTIONS requests",
name: "no-CORS-headers-for-non-OPTIONS",
corsOrigins: []string{"https://foobar.com"},
corsMethods: []string{"GET", "POST", "HEAD"},
httpMethod: "GET",
wantCORSHeaders: false,
},
{
name: "set CORS headers for non-OPTIONS requests",
name: "CORS-headers-for-OPTIONS",
corsOrigins: []string{"https://foobar.com"},
corsMethods: []string{"GET", "POST", "HEAD"},
httpMethod: "OPTIONS",
wantCORSHeaders: true,
},
{
name: "do not serve CORS headers for OPTIONS requests with no configured origins",
name: "no-CORS-headers-for-OPTIONS-without-origins",
httpMethod: "OPTIONS",
wantCORSHeaders: false,
},
@ -162,19 +162,19 @@ func TestCSRFProtection(t *testing.T) {
wantStatus int
}{
{
name: "POST requests to non-API routes require CSRF token and fail if not provided",
name: "non-API-POST-without-CSRF-fails",
apiRoute: false,
passCSRFToken: false,
wantStatus: http.StatusForbidden,
},
{
name: "POST requests to non-API routes require CSRF token and pass if provided",
name: "non-API-POST-with-CSRF-passes",
apiRoute: false,
passCSRFToken: true,
wantStatus: http.StatusOK,
},
{
name: "POST requests to /api/ routes do not require CSRF token",
name: "API-POST-without-CSRF-passes",
apiRoute: true,
passCSRFToken: false,
wantStatus: http.StatusOK,
@ -246,11 +246,11 @@ func TestContentSecurityPolicyHeader(t *testing.T) {
wantCSP string
}{
{
name: "default CSP",
name: "default-CSP",
wantCSP: `base-uri 'self'; block-all-mixed-content; default-src 'self'; form-action 'self'; frame-ancestors 'none';`,
},
{
name: "custom CSP",
name: "custom-CSP",
csp: CSP{
"default-src": {"'self'", "https://tailscale.com"},
"upgrade-insecure-requests": nil,
@ -258,7 +258,7 @@ func TestContentSecurityPolicyHeader(t *testing.T) {
wantCSP: `default-src 'self' https://tailscale.com; upgrade-insecure-requests;`,
},
{
name: "`/api/*` routes do not get CSP headers",
name: "api-routes-no-CSP-headers",
apiRoute: true,
wantCSP: "",
},
@ -301,12 +301,12 @@ func TestCSRFCookieSecureMode(t *testing.T) {
wantSecure bool
}{
{
name: "CSRF cookie should be secure when server is in secure context",
name: "secure-context-cookie-secure",
secureMode: true,
wantSecure: true,
},
{
name: "CSRF cookie should not be secure when server is not in secure context",
name: "non-secure-context-cookie-not-secure",
secureMode: false,
wantSecure: false,
},
@ -343,12 +343,12 @@ func TestRefererPolicy(t *testing.T) {
wantRefererPolicy bool
}{
{
name: "BrowserMux routes get Referer-Policy headers",
name: "BrowserMux-gets-Referer-Policy",
browserRoute: true,
wantRefererPolicy: true,
},
{
name: "APIMux routes do not get Referer-Policy headers",
name: "APIMux-no-Referer-Policy",
browserRoute: false,
wantRefererPolicy: false,
},
@ -420,54 +420,54 @@ func TestRouting(t *testing.T) {
want string
}{
{
desc: "only browser mux",
desc: "only-browser-mux",
browserPatterns: []string{"/"},
requestPath: "/index.html",
want: "browser",
},
{
desc: "only API mux",
desc: "only-API-mux",
apiPatterns: []string{"/api/"},
requestPath: "/api/foo",
want: "api",
},
{
desc: "browser mux match",
desc: "browser-mux-match",
browserPatterns: []string{"/content/"},
apiPatterns: []string{"/api/"},
requestPath: "/content/index.html",
want: "browser",
},
{
desc: "API mux match",
desc: "API-mux-match",
browserPatterns: []string{"/content/"},
apiPatterns: []string{"/api/"},
requestPath: "/api/foo",
want: "api",
},
{
desc: "browser wildcard match",
desc: "browser-wildcard-match",
browserPatterns: []string{"/"},
apiPatterns: []string{"/api/"},
requestPath: "/index.html",
want: "browser",
},
{
desc: "API wildcard match",
desc: "API-wildcard-match",
browserPatterns: []string{"/content/"},
apiPatterns: []string{"/"},
requestPath: "/api/foo",
want: "api",
},
{
desc: "path conflict",
desc: "path-conflict",
browserPatterns: []string{"/foo/"},
apiPatterns: []string{"/foo/bar/"},
requestPath: "/foo/bar/baz",
want: "api",
},
{
desc: "no match",
desc: "no-match",
browserPatterns: []string{"/foo/"},
apiPatterns: []string{"/bar/"},
requestPath: "/baz",
@ -521,43 +521,43 @@ func TestGetMoreSpecificPattern(t *testing.T) {
want: unknownHandler,
},
{
desc: "identical prefix",
desc: "identical-prefix",
a: "/foo/bar/",
b: "/foo/bar/",
want: unknownHandler,
},
{
desc: "trailing slash",
desc: "trailing-slash",
a: "/foo",
b: "/foo/", // path.Clean will strip the trailing slash.
want: unknownHandler,
},
{
desc: "same prefix",
desc: "same-prefix",
a: "/foo/bar/quux",
b: "/foo/bar/", // path.Clean will strip the trailing slash.
want: apiHandler,
},
{
desc: "almost same prefix, but not a path component",
desc: "almost-same-prefix-not-path-component",
a: "/goat/sheep/cheese",
b: "/goat/sheepcheese/", // path.Clean will strip the trailing slash.
want: apiHandler,
},
{
desc: "attempt to make less-specific pattern look more specific",
desc: "traversal-less-specific-pattern",
a: "/goat/cat/buddy",
b: "/goat/../../../../../../../cat", // path.Clean catches this foolishness
want: apiHandler,
},
{
desc: "2 names for / (1)",
desc: "two-names-for-root-1",
a: "/",
b: "/../../../../../../",
want: unknownHandler,
},
{
desc: "2 names for / (2)",
desc: "two-names-for-root-2",
a: "/",
b: "///////",
want: unknownHandler,
@ -586,15 +586,15 @@ func TestStrictTransportSecurityOptions(t *testing.T) {
expect string
}{
{
name: "off by default",
name: "off-by-default",
},
{
name: "default HSTS options in the secure context",
name: "default-HSTS-in-secure-context",
secureContext: true,
expect: DefaultStrictTransportSecurityOptions,
},
{
name: "custom options sent in the secure context",
name: "custom-options-in-secure-context",
options: DefaultStrictTransportSecurityOptions + "; includeSubDomains",
secureContext: true,
expect: DefaultStrictTransportSecurityOptions + "; includeSubDomains",

@ -35,7 +35,7 @@ func TestConnectToRecorder(t *testing.T) {
wantErr bool
}{
{
desc: "v1 recorder",
desc: "v1-recorder",
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
uploadHash := make(chan []byte, 1)
mux := http.NewServeMux()
@ -50,7 +50,7 @@ func TestConnectToRecorder(t *testing.T) {
},
},
{
desc: "v2 recorder",
desc: "v2-recorder",
http2: true,
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
uploadHash := make(chan []byte, 1)
@ -100,7 +100,7 @@ func TestConnectToRecorder(t *testing.T) {
},
},
{
desc: "v2 recorder no acks",
desc: "v2-recorder-no-acks",
http2: true,
wantErr: true,
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {

@ -16,4 +16,4 @@
) {
src = ./.;
}).shellNix
# nix-direnv cache busting line: sha256-39axT5Q0+fNTcMgZCMLMNfJEJN46wMaaKDgfI+Uj+Ps=
# nix-direnv cache busting line: sha256-VsVMvTEblVx/HNbuCVxC9UgKpriRwixswUSKVGLMf3Q=

@ -111,25 +111,25 @@ func TestFilterEnv(t *testing.T) {
wantErrMessage string
}{
{
name: "simple direct matches",
name: "simple-direct-matches",
acceptEnv: []string{"FOO", "FOO2", "FOO_3"},
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
expectedFiltered: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123"},
},
{
name: "bare wildcard",
name: "bare-wildcard",
acceptEnv: []string{"*"},
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
expectedFiltered: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
},
{
name: "complex matches",
name: "complex-matches",
acceptEnv: []string{"FO?", "FOOO*", "FO*5?7"},
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG", "FO1-kmndGamc79567=ABC", "FO57=BAR2"},
expectedFiltered: []string{"FOO=BAR", "FOOOO4-2=AbCdEfG", "FO1-kmndGamc79567=ABC"},
},
{
name: "environ format invalid",
name: "environ-format-invalid",
acceptEnv: []string{"FO?", "FOOO*", "FO*5?7"},
environ: []string{"FOOBAR"},
expectedFiltered: nil,

@ -30,7 +30,7 @@ func BenchmarkShardedInt(b *testing.B) {
})
})
b.Run("sharded int", func(b *testing.B) {
b.Run("sharded-int", func(b *testing.B) {
m := NewShardedInt()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
@ -60,7 +60,7 @@ func TestShardedInt(t *testing.T) {
}
})
t.Run("high concurrency", func(t *testing.T) {
t.Run("high-concurrency", func(t *testing.T) {
m := NewShardedInt()
wg := sync.WaitGroup{}
numWorkers := 1000
@ -83,7 +83,7 @@ func TestShardedInt(t *testing.T) {
}
})
t.Run("encoding.TextAppender", func(t *testing.T) {
t.Run("encoding-TextAppender", func(t *testing.T) {
m := NewShardedInt()
m.Add(1)
b := make([]byte, 0, 10)

@ -18,31 +18,35 @@ func TestProtoPortRangeParsing(t *testing.T) {
return PortRange{First: s, Last: e}
}
tests := []struct {
name string
in string
out ProtoPortRange
err error
}{
{in: "tcp:80", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: pr(80, 80)}},
{in: "80", out: ProtoPortRange{Ports: pr(80, 80)}},
{in: "*", out: ProtoPortRange{Ports: PortRangeAny}},
{in: "*:*", out: ProtoPortRange{Ports: PortRangeAny}},
{in: "tcp:*", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: PortRangeAny}},
{name: "tcp-80", in: "tcp:80", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: pr(80, 80)}},
{name: "80", in: "80", out: ProtoPortRange{Ports: pr(80, 80)}},
{name: "star", in: "*", out: ProtoPortRange{Ports: PortRangeAny}},
{name: "star-star", in: "*:*", out: ProtoPortRange{Ports: PortRangeAny}},
{name: "tcp-star", in: "tcp:*", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: PortRangeAny}},
{
name: "tcp-empty-port",
in: "tcp:",
err: vizerror.Errorf("invalid port list: %#v", ""),
},
{
name: "empty-proto-80",
in: ":80",
err: errEmptyProtocol,
},
{
name: "empty-string",
in: "",
err: errEmptyString,
},
}
for _, tc := range tests {
t.Run(tc.in, func(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
var ppr ProtoPortRange
err := ppr.UnmarshalText([]byte(tc.in))
if tc.err != err {

@ -841,12 +841,12 @@ func TestMarshalToRawMessageAndBack(t *testing.T) {
capType: PeerCapability("foo"),
},
{
name: "some values",
name: "some-values",
val: testRule{Ports: []int{80, 443}, Name: "foo"},
capType: PeerCapability("foo"),
},
{
name: "all values",
name: "all-values",
val: testRule{Ports: []int{80, 443}, Name: "foo", ToggleOn: true, Groups: inner{Groups: []string{"foo", "bar"}}, Addrs: []netip.AddrPort{testip}},
capType: PeerCapability("foo"),
},

@ -185,7 +185,7 @@ func TestMarkActiveChain(t *testing.T) {
expectLastActiveIdx: 0,
},
{
name: "simple truncate",
name: "simple-truncate",
minChain: 2,
chain: []aumTemplate{
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
@ -196,7 +196,7 @@ func TestMarkActiveChain(t *testing.T) {
expectLastActiveIdx: 1,
},
{
name: "long truncate",
name: "long-truncate",
minChain: 5,
chain: []aumTemplate{
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
@ -211,7 +211,7 @@ func TestMarkActiveChain(t *testing.T) {
expectLastActiveIdx: 2,
},
{
name: "truncate finding checkpoint",
name: "truncate-finding-checkpoint",
minChain: 2,
chain: []aumTemplate{
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
@ -342,7 +342,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
wantRetained: []string{"A"},
},
{
name: "no adjustment",
name: "no-adjustment",
chain: newTestchain(t, `
DEAD -> A -> B -> C
A.template = checkpoint
@ -380,7 +380,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
wantDeleted: []string{"A", "B"},
},
{
name: "fork finding earlier checkpoint",
name: "fork-finding-earlier-checkpoint",
chain: newTestchain(t, `
A -> B -> C -> D -> E -> F
| -> FORK
@ -403,7 +403,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
wantDeleted: []string{"A"},
},
{
name: "fork multi",
name: "fork-multi",
chain: newTestchain(t, `
A -> B -> C -> D -> E
| -> DEADFORK
@ -429,7 +429,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
wantDeleted: []string{"A", "B", "DEADFORK"},
},
{
name: "fork multi 2",
name: "fork-multi-2",
chain: newTestchain(t, `
A -> B -> C -> D -> E -> F -> G

@ -68,14 +68,17 @@ func authForPeers(self *ipnstate.PeerStatus, peers []*ipnstate.PeerStatus) *auth
func TestAuthRefreshErrorsNotRunning(t *testing.T) {
tests := []struct {
name string
in *ipnstate.Status
expected string
}{
{
name: "no-status",
in: nil,
expected: "no status",
},
{
name: "ts-server-not-running",
in: &ipnstate.Status{
BackendState: "NeedsMachineAuth",
},
@ -84,7 +87,7 @@ func TestAuthRefreshErrorsNotRunning(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.expected, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ctx := t.Context()
a := authForStatus(tt.in)
err := a.Refresh(ctx)
@ -127,22 +130,22 @@ func TestAuthAllowsHost(t *testing.T) {
expected bool
}{
{
name: "tagged with different tag",
name: "tagged-different-tag",
peerStatus: peers[0],
expected: false,
},
{
name: "not tagged",
name: "not-tagged",
peerStatus: peers[1],
expected: false,
},
{
name: "tags includes testTag",
name: "tags-include-testTag",
peerStatus: peers[2],
expected: true,
},
{
name: "only tag is testTag",
name: "only-testTag",
peerStatus: peers[3],
expected: true,
},
@ -201,12 +204,12 @@ func TestAuthSelfAllowed(t *testing.T) {
expected bool
}{
{
name: "self has different tag",
name: "self-different-tag",
in: []string{"woo"},
expected: false,
},
{
name: "selfs tags include testTag",
name: "self-tags-include-testTag",
in: []string{"woo", testTag},
expected: true,
},

@ -2933,7 +2933,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains string
}{
{
name: "successful resolution via OAuth client secret",
name: "success-oauth-client-secret",
clientSecret: "tskey-client-secret-123",
oauthAvailable: true,
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
@ -2946,7 +2946,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "failing resolution via OAuth client secret",
name: "fail-oauth-client-secret",
clientSecret: "tskey-client-secret-123",
oauthAvailable: true,
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
@ -2955,7 +2955,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "resolution failed",
},
{
name: "successful resolution via federated ID token",
name: "success-federated-id-token",
clientID: "client-id-123",
idToken: "id-token-456",
wifAvailable: true,
@ -2972,7 +2972,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "successful resolution via federated audience",
name: "success-federated-audience",
clientID: "client-id-123",
audience: "api.tailscale.com",
wifAvailable: true,
@ -2989,7 +2989,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "failing resolution via federated ID token",
name: "fail-federated-id-token",
clientID: "client-id-123",
idToken: "id-token-456",
wifAvailable: true,
@ -2999,7 +2999,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "resolution failed",
},
{
name: "empty client ID with ID token",
name: "empty-client-id-with-token",
clientID: "",
idToken: "id-token-456",
wifAvailable: true,
@ -3009,7 +3009,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "empty",
},
{
name: "empty client ID with audience",
name: "empty-client-id-with-audience",
clientID: "",
audience: "api.tailscale.com",
wifAvailable: true,
@ -3019,7 +3019,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "empty",
},
{
name: "empty ID token",
name: "empty-id-token",
clientID: "client-id-123",
idToken: "",
wifAvailable: true,
@ -3029,7 +3029,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "empty",
},
{
name: "audience with ID token",
name: "audience-with-id-token",
clientID: "client-id-123",
idToken: "id-token-456",
audience: "api.tailscale.com",
@ -3040,7 +3040,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "only one of ID token and audience",
},
{
name: "workload identity resolution skipped if resolution via OAuth token succeeds",
name: "wif-skipped-oauth-succeeds",
clientSecret: "tskey-client-secret-123",
oauthAvailable: true,
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
@ -3057,7 +3057,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "workload identity resolution skipped if resolution via OAuth token fails",
name: "wif-skipped-oauth-fails",
clientID: "tskey-client-id-123",
idToken: "",
oauthAvailable: true,
@ -3071,7 +3071,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "failed",
},
{
name: "authkey set and no resolution available",
name: "authkey-set-no-resolution",
authKey: "tskey-auth-123",
oauthAvailable: false,
wifAvailable: false,
@ -3079,14 +3079,14 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "no authkey set and no resolution available",
name: "no-authkey-no-resolution",
oauthAvailable: false,
wifAvailable: false,
wantAuthKey: "",
wantErrContains: "",
},
{
name: "authkey is client secret and resolution via OAuth client secret succeeds",
name: "authkey-client-secret-oauth-succeeds",
authKey: "tskey-client-secret-123",
oauthAvailable: true,
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
@ -3099,7 +3099,7 @@ func TestResolveAuthKey(t *testing.T) {
wantErrContains: "",
},
{
name: "authkey is client secret but resolution via OAuth client secret fails",
name: "authkey-client-secret-oauth-fails",
authKey: "tskey-client-secret-123",
oauthAvailable: true,
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
@ -3282,12 +3282,12 @@ func TestListenUnspecifiedAddr(t *testing.T) {
t.Run("Netstack", func(t *testing.T) {
lt := setupTwoClientTest(t, false)
t.Run("0.0.0.0", func(t *testing.T) { testUnspec(t, lt, "0.0.0.0:8080", "8080") })
t.Run("v4-unspec", func(t *testing.T) { testUnspec(t, lt, "0.0.0.0:8080", "8080") })
t.Run("::", func(t *testing.T) { testUnspec(t, lt, "[::]:8081", "8081") })
})
t.Run("TUN", func(t *testing.T) {
lt := setupTwoClientTest(t, true)
t.Run("0.0.0.0", func(t *testing.T) { testUnspec(t, lt, "0.0.0.0:8080", "8080") })
t.Run("v4-unspec", func(t *testing.T) { testUnspec(t, lt, "0.0.0.0:8080", "8080") })
t.Run("::", func(t *testing.T) { testUnspec(t, lt, "[::]:8081", "8081") })
})
}

@ -22,7 +22,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
wants []time.Time // The return values of sequential calls to Now().
}{
{
name: "increment ms",
name: "increment-ms",
start: time.Unix(12345, 1000),
step: 1000,
wants: []time.Time{
@ -33,7 +33,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
},
},
{
name: "increment second",
name: "increment-second",
start: time.Unix(12345, 1000),
step: time.Second,
wants: []time.Time{
@ -44,7 +44,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
},
},
{
name: "no increment",
name: "no-increment",
start: time.Unix(12345, 1000),
wants: []time.Time{
time.Unix(12345, 1000),
@ -91,7 +91,7 @@ func TestClockWithDefaultStartTime(t *testing.T) {
wants []time.Duration // The return values of sequential calls to Now() after added to Start()
}{
{
name: "increment ms",
name: "increment-ms",
step: 1000,
wants: []time.Duration{
0,
@ -101,7 +101,7 @@ func TestClockWithDefaultStartTime(t *testing.T) {
},
},
{
name: "increment second",
name: "increment-second",
step: time.Second,
wants: []time.Duration{
0 * time.Second,
@ -111,7 +111,7 @@ func TestClockWithDefaultStartTime(t *testing.T) {
},
},
{
name: "no increment",
name: "no-increment",
wants: []time.Duration{0, 0, 0, 0},
},
}
@ -177,7 +177,7 @@ func TestClockSetStep(t *testing.T) {
wants []time.Time // The return values of sequential calls to Now().
}{
{
name: "increment ms then s",
name: "increment-ms-then-s",
start: time.Unix(12345, 1000),
step: 1000,
stepChanges: []stepInfo{
@ -198,7 +198,7 @@ func TestClockSetStep(t *testing.T) {
},
},
{
name: "multiple changes over time",
name: "multiple-changes-over-time",
start: time.Unix(12345, 1000),
step: 1,
stepChanges: []stepInfo{
@ -227,7 +227,7 @@ func TestClockSetStep(t *testing.T) {
},
},
{
name: "multiple changes at once",
name: "multiple-changes-at-once",
start: time.Unix(12345, 1000),
step: 1,
stepChanges: []stepInfo{
@ -252,7 +252,7 @@ func TestClockSetStep(t *testing.T) {
},
},
{
name: "changes at start",
name: "changes-at-start",
start: time.Unix(12345, 1000),
step: 0,
stepChanges: []stepInfo{
@ -325,7 +325,7 @@ func TestClockAdvance(t *testing.T) {
wants []time.Time // The return values of sequential calls to Now().
}{
{
name: "increment ms then advance 1s",
name: "increment-ms-then-advance-1s",
start: time.Unix(12345, 1000),
step: 1000,
advances: []advanceInfo{
@ -346,7 +346,7 @@ func TestClockAdvance(t *testing.T) {
},
},
{
name: "multiple advances over time",
name: "multiple-advances-over-time",
start: time.Unix(12345, 1000),
step: 1,
advances: []advanceInfo{
@ -375,7 +375,7 @@ func TestClockAdvance(t *testing.T) {
},
},
{
name: "multiple advances at once",
name: "multiple-advances-at-once",
start: time.Unix(12345, 1000),
step: 1,
advances: []advanceInfo{
@ -400,7 +400,7 @@ func TestClockAdvance(t *testing.T) {
},
},
{
name: "changes at start",
name: "changes-at-start",
start: time.Unix(12345, 1000),
step: 5,
advances: []advanceInfo{
@ -489,7 +489,7 @@ func TestSingleTicker(t *testing.T) {
steps []testStep
}{
{
name: "no tick advance",
name: "no-tick-advance",
start: time.Unix(12345, 0),
period: time.Second,
steps: []testStep{
@ -500,7 +500,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "no tick step",
name: "no-tick-step",
start: time.Unix(12345, 0),
step: time.Second - 1,
period: time.Second,
@ -514,7 +514,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick advance exact",
name: "single-tick-advance-exact",
start: time.Unix(12345, 0),
period: time.Second,
steps: []testStep{
@ -526,7 +526,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick advance extra",
name: "single-tick-advance-extra",
start: time.Unix(12345, 0),
period: time.Second,
steps: []testStep{
@ -538,7 +538,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick step exact",
name: "single-tick-step-exact",
start: time.Unix(12345, 0),
step: time.Second,
period: time.Second,
@ -553,7 +553,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick step extra",
name: "single-tick-step-extra",
start: time.Unix(12345, 0),
step: time.Second + 1,
period: time.Second,
@ -568,7 +568,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick per advance",
name: "single-tick-per-advance",
start: time.Unix(12345, 0),
period: 3 * time.Second,
steps: []testStep{
@ -597,7 +597,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "single tick per step",
name: "single-tick-per-step",
start: time.Unix(12345, 0),
step: 2 * time.Second,
period: 3 * time.Second,
@ -626,7 +626,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "multiple tick per advance",
name: "multiple-tick-per-advance",
start: time.Unix(12345, 0),
period: time.Second,
channelSize: 3,
@ -655,7 +655,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "multiple tick per step",
name: "multiple-tick-per-step",
start: time.Unix(12345, 0),
step: 3 * time.Second,
period: 2 * time.Second,
@ -723,7 +723,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "reset while running",
name: "reset-while-running",
start: time.Unix(12345, 0),
period: 2 * time.Second,
steps: []testStep{
@ -763,7 +763,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "reset while stopped",
name: "reset-while-stopped",
start: time.Unix(12345, 0),
step: time.Second,
period: 2 * time.Second,
@ -803,7 +803,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "reset absolute",
name: "reset-absolute",
start: time.Unix(12345, 0),
step: time.Second,
period: 2 * time.Second,
@ -841,7 +841,7 @@ func TestSingleTicker(t *testing.T) {
},
},
{
name: "follow real time",
name: "follow-real-time",
realTimeOpts: new(ClockOpts),
start: time.Unix(12345, 0),
period: 2 * time.Second,
@ -965,7 +965,7 @@ func TestSingleTimer(t *testing.T) {
steps []testStep
}{
{
name: "no tick advance",
name: "no-tick-advance",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -976,7 +976,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "no tick step",
name: "no-tick-step",
start: time.Unix(12345, 0),
step: time.Second - 1,
delay: time.Second,
@ -990,7 +990,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "single tick advance exact",
name: "single-tick-advance-exact",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -1006,7 +1006,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "single tick advance extra",
name: "single-tick-advance-extra",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -1022,7 +1022,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "single tick step exact",
name: "single-tick-step-exact",
start: time.Unix(12345, 0),
step: time.Second,
delay: time.Second,
@ -1040,7 +1040,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "single tick step extra",
name: "single-tick-step-extra",
start: time.Unix(12345, 0),
step: time.Second + 1,
delay: time.Second,
@ -1058,7 +1058,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset for single tick per advance",
name: "reset-for-single-tick-per-advance",
start: time.Unix(12345, 0),
delay: 3 * time.Second,
steps: []testStep{
@ -1093,7 +1093,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset for single tick per step",
name: "reset-for-single-tick-per-step",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: 3 * time.Second,
@ -1124,7 +1124,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset while active",
name: "reset-while-active",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: 3 * time.Second,
@ -1155,7 +1155,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "stop after fire",
name: "stop-after-fire",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -1181,7 +1181,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "stop before fire",
name: "stop-before-fire",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -1207,7 +1207,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "stop after reset",
name: "stop-after-reset",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -1235,7 +1235,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset while running",
name: "reset-while-running",
start: time.Unix(12345, 0),
delay: 2 * time.Second,
steps: []testStep{
@ -1275,7 +1275,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset while stopped",
name: "reset-while-stopped",
start: time.Unix(12345, 0),
step: time.Second,
delay: 2 * time.Second,
@ -1310,7 +1310,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "reset absolute",
name: "reset-absolute",
start: time.Unix(12345, 0),
step: time.Second,
delay: 2 * time.Second,
@ -1344,7 +1344,7 @@ func TestSingleTimer(t *testing.T) {
},
},
{
name: "follow real time",
name: "follow-real-time",
realTimeOpts: new(ClockOpts),
start: time.Unix(12345, 0),
delay: 2 * time.Second,
@ -1705,7 +1705,7 @@ func TestClockFollowRealTime(t *testing.T) {
wants []time.Time // The return values of sequential calls to Now().
}{
{
name: "increment ms then advance 1s",
name: "increment-ms-then-advance-1s",
start: time.Unix(12345, 1000),
wantStart: time.Unix(12345, 1000),
advances: []advanceInfo{
@ -1750,7 +1750,7 @@ func TestClockFollowRealTime(t *testing.T) {
},
},
{
name: "multiple advances over time",
name: "multiple-advances-over-time",
start: time.Unix(12345, 1000),
wantStart: time.Unix(12345, 1000),
advances: []advanceInfo{
@ -1795,7 +1795,7 @@ func TestClockFollowRealTime(t *testing.T) {
},
},
{
name: "multiple advances at once",
name: "multiple-advances-at-once",
start: time.Unix(12345, 1000),
wantStart: time.Unix(12345, 1000),
advances: []advanceInfo{
@ -1828,7 +1828,7 @@ func TestClockFollowRealTime(t *testing.T) {
},
},
{
name: "changes at start",
name: "changes-at-start",
start: time.Unix(12345, 1000),
wantStart: time.Unix(12345, 1000),
advances: []advanceInfo{
@ -1861,7 +1861,7 @@ func TestClockFollowRealTime(t *testing.T) {
},
},
{
name: "start from current time",
name: "start-from-current-time",
realTimeClockOpts: ClockOpts{
Start: time.Unix(12345, 0),
},
@ -1966,7 +1966,7 @@ func TestAfterFunc(t *testing.T) {
steps []testStep
}{
{
name: "no tick advance",
name: "no-tick-advance",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -1977,7 +1977,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "no tick step",
name: "no-tick-step",
start: time.Unix(12345, 0),
step: time.Second - 1,
delay: time.Second,
@ -1991,7 +1991,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "single tick advance exact",
name: "single-tick-advance-exact",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -2007,7 +2007,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "single tick advance extra",
name: "single-tick-advance-extra",
start: time.Unix(12345, 0),
delay: time.Second,
steps: []testStep{
@ -2023,7 +2023,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "single tick step exact",
name: "single-tick-step-exact",
start: time.Unix(12345, 0),
step: time.Second,
delay: time.Second,
@ -2041,7 +2041,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "single tick step extra",
name: "single-tick-step-extra",
start: time.Unix(12345, 0),
step: time.Second + 1,
delay: time.Second,
@ -2059,7 +2059,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset for single tick per advance",
name: "reset-for-single-tick-per-advance",
start: time.Unix(12345, 0),
delay: 3 * time.Second,
steps: []testStep{
@ -2094,7 +2094,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset for single tick per step",
name: "reset-for-single-tick-per-step",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: 3 * time.Second,
@ -2125,7 +2125,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset while active",
name: "reset-while-active",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: 3 * time.Second,
@ -2156,7 +2156,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "stop after fire",
name: "stop-after-fire",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -2182,7 +2182,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "stop before fire",
name: "stop-before-fire",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -2208,7 +2208,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "stop after reset",
name: "stop-after-reset",
start: time.Unix(12345, 0),
step: 2 * time.Second,
delay: time.Second,
@ -2236,7 +2236,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset while running",
name: "reset-while-running",
start: time.Unix(12345, 0),
delay: 2 * time.Second,
steps: []testStep{
@ -2270,7 +2270,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset while stopped",
name: "reset-while-stopped",
start: time.Unix(12345, 0),
step: time.Second,
delay: 2 * time.Second,
@ -2303,7 +2303,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "reset absolute",
name: "reset-absolute",
start: time.Unix(12345, 0),
step: time.Second,
delay: 2 * time.Second,
@ -2333,7 +2333,7 @@ func TestAfterFunc(t *testing.T) {
},
},
{
name: "follow real time",
name: "follow-real-time",
realTimeOpts: new(ClockOpts),
start: time.Unix(12345, 0),
delay: 2 * time.Second,

@ -355,7 +355,7 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) {
})
})
t.Run("tailscale status", func(t *testing.T) {
t.Run("tailscale-status", func(t *testing.T) {
dur := 100 * time.Millisecond
var outp []byte
var err error
@ -383,7 +383,7 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) {
t.Fatalf("error: %v", err)
})
t.Run("dump routes", func(t *testing.T) {
t.Run("dump-routes", func(t *testing.T) {
sess, err := cli.NewSession()
if err != nil {
t.Fatal(err)

@ -22,7 +22,7 @@ func TestPrintGoroutines(t *testing.T) {
want: "goroutine profile: total 0",
},
{
name: "single goroutine",
name: "single-goroutine",
in: `goroutine profile: total 1
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -34,7 +34,7 @@ func TestPrintGoroutines(t *testing.T) {
`,
},
{
name: "multiple goroutines sorted",
name: "multiple-goroutines-sorted",
in: `goroutine profile: total 14
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
@ -70,7 +70,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
want string
}{
{
name: "no difference",
name: "no-difference",
x: `goroutine profile: total 1
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261`,
@ -81,7 +81,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
want: "",
},
{
name: "different counts",
name: "different-counts",
x: `goroutine profile: total 1
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -99,7 +99,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
`,
},
{
name: "new goroutine",
name: "new-goroutine",
x: `goroutine profile: total 1
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -119,7 +119,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
`,
},
{
name: "removed goroutine",
name: "removed-goroutine",
x: `goroutine profile: total 2
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -139,7 +139,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
`,
},
{
name: "removed many goroutine",
name: "removed-many-goroutine",
x: `goroutine profile: total 2
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -159,13 +159,13 @@ func TestDiffPprofGoroutines(t *testing.T) {
`,
},
{
name: "invalid input x",
name: "invalid-input-x",
x: "invalid",
y: "goroutine profile: total 0\n",
want: "- invalid\n+ goroutine profile: total 0\n",
},
{
name: "invalid input y",
name: "invalid-input-y",
x: "goroutine profile: total 0\n",
y: "invalid",
want: "- goroutine profile: total 0\n+ invalid\n",
@ -193,13 +193,13 @@ func TestParseGoroutines(t *testing.T) {
wantCount int
}{
{
name: "empty profile",
name: "empty-profile",
in: "goroutine profile: total 0\n",
wantHeader: "goroutine profile: total 0",
wantCount: 0,
},
{
name: "single goroutine",
name: "single-goroutine",
in: `goroutine profile: total 1
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
@ -208,7 +208,7 @@ func TestParseGoroutines(t *testing.T) {
wantCount: 1,
},
{
name: "multiple goroutines",
name: "multiple-goroutines",
in: `goroutine profile: total 14
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
@ -220,7 +220,7 @@ func TestParseGoroutines(t *testing.T) {
wantCount: 2,
},
{
name: "invalid format",
name: "invalid-format",
in: "invalid",
wantHeader: "invalid",
},

@ -85,7 +85,7 @@ func TestStdHandler(t *testing.T) {
wantBody string
}{
{
name: "handler returns 200",
name: "handler-returns-200",
rh: handlerCode(200),
r: req(bgCtx, "http://example.com/"),
wantCode: 200,
@ -102,7 +102,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 200 with request ID",
name: "handler-returns-200-with-request-ID",
rh: handlerCode(200),
r: req(bgCtx, "http://example.com/"),
wantCode: 200,
@ -119,7 +119,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404",
name: "handler-returns-404",
rh: handlerCode(404),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 404,
@ -135,7 +135,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404 with request ID",
name: "handler-returns-404-with-request-ID",
rh: handlerCode(404),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 404,
@ -151,7 +151,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404 via HTTPError",
name: "handler-returns-404-via-HTTPError",
rh: handlerErr(0, Error(404, "not found", testErr)),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 404,
@ -169,7 +169,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404 via HTTPError with request ID",
name: "handler-returns-404-via-HTTPError-with-request-ID",
rh: handlerErr(0, Error(404, "not found", testErr)),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 404,
@ -188,7 +188,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404 with nil child error",
name: "handler-returns-404-nil-child-error",
rh: handlerErr(0, Error(404, "not found", nil)),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 404,
@ -206,7 +206,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns 404 with request ID and nil child error",
name: "handler-returns-404-request-ID-nil-child-error",
rh: handlerErr(0, Error(404, "not found", nil)),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 404,
@ -225,7 +225,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns user-visible error",
name: "handler-returns-user-visible-error",
rh: handlerErr(0, vizerror.New("visible error")),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 500,
@ -243,7 +243,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns user-visible error with request ID",
name: "handler-returns-user-visible-error-with-request-ID",
rh: handlerErr(0, vizerror.New("visible error")),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 500,
@ -262,7 +262,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns user-visible error wrapped by private error",
name: "handler-returns-vizerror-wrapped-by-private-error",
rh: handlerErr(0, fmt.Errorf("private internal error: %w", vizerror.New("visible error"))),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 500,
@ -280,7 +280,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns JSON-formatted HTTPError",
name: "handler-returns-JSON-formatted-HTTPError",
rh: ReturnHandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
h := Error(http.StatusBadRequest, `{"isjson": true}`, errors.New("uh"))
h.Header = http.Header{"Content-Type": {"application/json"}}
@ -303,7 +303,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns user-visible error wrapped by private error with request ID",
name: "handler-returns-vizerror-wrapped-by-private-error-with-request-ID",
rh: handlerErr(0, fmt.Errorf("private internal error: %w", vizerror.New("visible error"))),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 500,
@ -322,7 +322,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns generic error",
name: "handler-returns-generic-error",
rh: handlerErr(0, testErr),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 500,
@ -340,7 +340,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns generic error with request ID",
name: "handler-returns-generic-error-with-request-ID",
rh: handlerErr(0, testErr),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 500,
@ -359,7 +359,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns error after writing response",
name: "handler-returns-error-after-writing-response",
rh: handlerErr(200, testErr),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 200,
@ -376,7 +376,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns error after writing response with request ID",
name: "handler-returns-error-after-writing-response-with-request-ID",
rh: handlerErr(200, testErr),
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
wantCode: 200,
@ -394,7 +394,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler returns HTTPError after writing response",
name: "handler-returns-HTTPError-after-writing-response",
rh: handlerErr(200, Error(404, "not found", testErr)),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 200,
@ -411,7 +411,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler does nothing",
name: "handler-does-nothing",
rh: handlerFunc(func(http.ResponseWriter, *http.Request) error { return nil }),
r: req(bgCtx, "http://example.com/foo"),
wantCode: 200,
@ -427,7 +427,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "handler hijacks conn",
name: "handler-hijacks-conn",
rh: handlerFunc(func(w http.ResponseWriter, r *http.Request) error {
_, _, err := w.(http.Hijacker).Hijack()
if err != nil {
@ -450,7 +450,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "error handler gets run",
name: "error-handler-gets-run",
rh: handlerErr(0, Error(404, "not found", nil)), // status code changed in errHandler
r: req(bgCtx, "http://example.com/"),
wantCode: 200,
@ -472,7 +472,7 @@ func TestStdHandler(t *testing.T) {
},
{
name: "error handler gets run with request ID",
name: "error-handler-gets-run-with-request-ID",
rh: handlerErr(0, Error(404, "not found", nil)), // status code changed in errHandler
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/"),
wantCode: 200,

@ -33,13 +33,13 @@ func TestResolverEqual(t *testing.T) {
want: true,
},
{
name: "nil vs non-nil",
name: "nil-vs-non-nil",
a: nil,
b: &Resolver{},
want: false,
},
{
name: "non-nil vs nil",
name: "non-nil-vs-nil",
a: &Resolver{},
b: nil,
want: false,
@ -51,13 +51,13 @@ func TestResolverEqual(t *testing.T) {
want: true,
},
{
name: "not equal addrs",
name: "not-equal-addrs",
a: &Resolver{Addr: "dns.example.com"},
b: &Resolver{Addr: "dns2.example.com"},
want: false,
},
{
name: "not equal bootstrap",
name: "not-equal-bootstrap",
a: &Resolver{
Addr: "dns.example.com",
BootstrapResolution: []netip.Addr{netip.MustParseAddr("8.8.8.8")},
@ -69,13 +69,13 @@ func TestResolverEqual(t *testing.T) {
want: false,
},
{
name: "equal UseWithExitNode",
name: "equal-UseWithExitNode",
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
want: true,
},
{
name: "not equal UseWithExitNode",
name: "not-equal-UseWithExitNode",
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: false},
want: false,

@ -16,77 +16,77 @@ func TestCompare(t *testing.T) {
want int
}{
{
name: "both empty",
name: "both-empty",
want: 0,
},
{
name: "v1 empty",
name: "v1-empty",
v2: "1.2.3",
want: -1,
},
{
name: "v2 empty",
name: "v2-empty",
v1: "1.2.3",
want: 1,
},
{
name: "semver major",
name: "semver-major",
v1: "2.0.0",
v2: "1.9.9",
want: 1,
},
{
name: "semver major",
name: "semver-major",
v1: "2.0.0",
v2: "1.9.9",
want: 1,
},
{
name: "semver minor",
name: "semver-minor",
v1: "1.9.0",
v2: "1.8.9",
want: 1,
},
{
name: "semver patch",
name: "semver-patch",
v1: "1.9.9",
v2: "1.9.8",
want: 1,
},
{
name: "semver equal",
name: "semver-equal",
v1: "1.9.8",
v2: "1.9.8",
want: 0,
},
{
name: "tailscale major",
name: "tailscale-major",
v1: "1.0-0",
v2: "0.97-105",
want: 1,
},
{
name: "tailscale minor",
name: "tailscale-minor",
v1: "0.98-0",
v2: "0.97-105",
want: 1,
},
{
name: "tailscale patch",
name: "tailscale-patch",
v1: "0.97-120",
v2: "0.97-105",
want: 1,
},
{
name: "tailscale equal",
name: "tailscale-equal",
v1: "0.97-105",
v2: "0.97-105",
want: 0,
},
{
name: "tailscale weird extra field",
name: "tailscale-weird-extra-field",
v1: "0.96.1-0", // more fields == larger
v2: "0.96-105",
want: 1,
@ -96,7 +96,7 @@ func TestCompare(t *testing.T) {
// of strconv.ParseUint with these characters would have lead us to
// panic. We're now only looking at ascii numbers, so test these are
// compared as text.
name: "only ascii numbers",
name: "only-ascii-numbers",
v1: "۱۱", // 2x EXTENDED ARABIC-INDIC DIGIT ONE
v2: "۲", // 1x EXTENDED ARABIC-INDIC DIGIT TWO
want: -1,
@ -104,55 +104,55 @@ func TestCompare(t *testing.T) {
// A few specific OS version tests below.
{
name: "windows version",
name: "windows-version",
v1: "10.0.19045.3324",
v2: "10.0.18362",
want: 1,
},
{
name: "windows 11 is everything above 10.0.22000",
name: "windows-11-above-10_0_22000",
v1: "10.0.22631.2262",
v2: "10.0.22000",
want: 1,
},
{
name: "android short version",
name: "android-short-version",
v1: "10",
v2: "7",
want: 1,
},
{
name: "android longer version",
name: "android-longer-version",
v1: "7.1.2",
v2: "7",
want: 1,
},
{
name: "iOS version",
name: "iOS-version",
v1: "15.6.1",
v2: "15.6",
want: 1,
},
{
name: "Linux short kernel version",
name: "linux-short-kernel-version",
v1: "4.4.302+",
v2: "4.0",
want: 1,
},
{
name: "Linux long kernel version",
name: "linux-long-kernel-version",
v1: "4.14.255-311-248.529.amzn2.x86_64",
v2: "4.0",
want: 1,
},
{
name: "FreeBSD version",
name: "freebsd-version",
v1: "14.0-CURRENT",
v2: "14",
want: 1,
},
{
name: "Synology version",
name: "synology-version",
v1: "Synology 6.2.4; kernel=3.10.105",
v2: "Synology 6",
want: 1,

@ -360,17 +360,17 @@ func TestGetTypeHasher(t *testing.T) {
out32: "\x01\x04\x00\x00\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00*\v\x00\x00\x00\x00\x00\x00\x0010.1.3.4/32\v\x00\x00\x00\x00\x00\x00\x0010.0.0.0/24\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x001.2.3.4/32\x01 \x00\x00\x00\x01\x00\x02\x00\x01\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04!\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00foo\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00",
},
{
name: "netip.Addr",
name: "netip-Addr",
val: netip.MustParseAddr("fe80::123%foo"),
out: u64(16+3) + u64(0x80fe) + u64(0x2301<<48) + "foo",
},
{
name: "ptr-netip.Addr",
name: "ptr-netip-Addr",
val: &someIP,
out: u8(1) + u64(4) + u32(0x04030201),
},
{
name: "ptr-nil-netip.Addr",
name: "ptr-nil-netip-Addr",
val: (*netip.Addr)(nil),
out: "\x00",
},
@ -469,7 +469,7 @@ func TestGetTypeHasher(t *testing.T) {
out: "\x01\x01\x00\x00\x00\x02\x00\x00\x00\x03\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\a\b\x00\x00\x00",
},
{
name: "tailcfg.Node",
name: "tailcfg-Node",
val: &tailcfg.Node{},
out: "ANY", // magic value; just check it doesn't fail to hash
out32: "ANY",

@ -36,17 +36,17 @@ func TestExpectFilter(t *testing.T) {
wantErr string // if non-empty, an error is expected containing this text
}{
{
name: "single event",
name: "single-event",
events: []int{42},
expectFunc: eventbustest.Type[EventFoo](),
},
{
name: "multiple events, single expectation",
name: "multiple-events-single-expectation",
events: []int{42, 1, 2, 3, 4, 5},
expectFunc: eventbustest.Type[EventFoo](),
},
{
name: "filter on event with function",
name: "filter-on-event-with-function",
events: []int{24, 42},
expectFunc: func(event EventFoo) (bool, error) {
if event.Value == 42 {
@ -77,7 +77,7 @@ func TestExpectFilter(t *testing.T) {
wantErr: "value > 10",
},
{
name: "first event has to be func",
name: "first-event-has-to-be-func",
events: []int{24, 42},
expectFunc: func(event EventFoo) (bool, error) {
if event.Value != 42 {
@ -99,7 +99,7 @@ func TestExpectFilter(t *testing.T) {
wantErr: "wrong result (-got, +want)",
},
{
name: "no events",
name: "no-events",
events: []int{},
expectFunc: func(event EventFoo) (bool, error) {
return true, nil
@ -151,37 +151,37 @@ func TestExpectEvents(t *testing.T) {
wantErr bool
}{
{
name: "No expectations",
name: "no-expectations",
events: []any{EventFoo{}},
expectEvents: []any{},
wantErr: true,
},
{
name: "One event",
name: "one-event",
events: []any{EventFoo{}},
expectEvents: []any{eventbustest.Type[EventFoo]()},
wantErr: false,
},
{
name: "Two events",
name: "two-events",
events: []any{EventFoo{}, EventBar{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: false,
},
{
name: "Two expected events with another in the middle",
name: "two-expected-events-with-another-in-middle",
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: false,
},
{
name: "Missing event",
name: "missing-event",
events: []any{EventFoo{}, EventBaz{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: true,
},
{
name: "One event with specific value",
name: "one-event-with-specific-value",
events: []any{EventFoo{42}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -194,7 +194,7 @@ func TestExpectEvents(t *testing.T) {
wantErr: false,
},
{
name: "Two event with one specific value",
name: "two-events-with-one-specific-value",
events: []any{EventFoo{43}, EventFoo{42}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -207,7 +207,7 @@ func TestExpectEvents(t *testing.T) {
wantErr: false,
},
{
name: "One event with wrong value",
name: "one-event-with-wrong-value",
events: []any{EventFoo{43}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -220,7 +220,7 @@ func TestExpectEvents(t *testing.T) {
wantErr: true,
},
{
name: "Two events with specific values",
name: "two-events-with-specific-values",
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -283,37 +283,37 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
wantErr bool
}{
{
name: "No expectations",
name: "no-expectations",
events: []any{EventFoo{}},
expectEvents: []any{},
wantErr: true,
},
{
name: "One event",
name: "one-event",
events: []any{EventFoo{}},
expectEvents: []any{eventbustest.Type[EventFoo]()},
wantErr: false,
},
{
name: "Two events",
name: "two-events",
events: []any{EventFoo{}, EventBar{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: false,
},
{
name: "Two expected events with another in the middle",
name: "two-expected-events-with-another-in-middle",
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: true,
},
{
name: "Missing event",
name: "missing-event",
events: []any{EventFoo{}, EventBaz{}},
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
wantErr: true,
},
{
name: "One event with value",
name: "one-event-with-value",
events: []any{EventFoo{42}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -326,7 +326,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
wantErr: false,
},
{
name: "Two event with one specific value",
name: "two-events-with-one-specific-value",
events: []any{EventFoo{43}, EventFoo{42}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -339,7 +339,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
wantErr: true,
},
{
name: "One event with wrong value",
name: "one-event-with-wrong-value",
events: []any{EventFoo{43}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {
@ -352,7 +352,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
wantErr: true,
},
{
name: "Two events with specific values",
name: "two-events-with-specific-values",
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
expectEvents: []any{
func(ev EventFoo) (bool, error) {

@ -960,32 +960,32 @@ func TestPickFirewallModeFromInstalledRules(t *testing.T) {
want FirewallMode
}{
{
name: "using iptables legacy",
name: "using-iptables-legacy",
det: &testFWDetector{iptRuleCount: 1},
want: FirewallModeIPTables,
},
{
name: "using nftables",
name: "using-nftables",
det: &testFWDetector{nftRuleCount: 1},
want: FirewallModeNfTables,
},
{
name: "using both iptables and nftables",
name: "using-both-iptables-and-nftables",
det: &testFWDetector{iptRuleCount: 2, nftRuleCount: 2},
want: FirewallModeNfTables,
},
{
name: "not using any firewall, both available",
name: "no-firewall-both-available",
det: &testFWDetector{},
want: FirewallModeNfTables,
},
{
name: "not using any firewall, iptables available only",
name: "no-firewall-iptables-only",
det: &testFWDetector{iptRuleCount: 1, nftErr: errors.New("nft error")},
want: FirewallModeIPTables,
},
{
name: "not using any firewall, nftables available only",
name: "no-firewall-nftables-only",
det: &testFWDetector{iptErr: errors.New("iptables error"), nftRuleCount: 1},
want: FirewallModeNfTables,
},

@ -226,42 +226,42 @@ func TestPolicyScopeContains(t *testing.T) {
wantAStrictlyContainsB: false,
},
{
name: "UserScope(1234)/UserScope(1234)",
name: "UserScope-1234/UserScope-1234",
scopeA: UserScopeOf("1234"),
scopeB: UserScopeOf("1234"),
wantAContainsB: true,
wantAStrictlyContainsB: false,
},
{
name: "UserScope(1234)/UserScope(5678)",
name: "UserScope-1234/UserScope-5678",
scopeA: UserScopeOf("1234"),
scopeB: UserScopeOf("5678"),
wantAContainsB: false,
wantAStrictlyContainsB: false,
},
{
name: "ProfileScope(A)/UserScope(A/1234)",
name: "ProfileScope-A/UserScope-A-1234",
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
wantAContainsB: true,
wantAStrictlyContainsB: true,
},
{
name: "ProfileScope(A)/UserScope(B/1234)",
name: "ProfileScope-A/UserScope-B-1234",
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "B"},
wantAContainsB: false,
wantAStrictlyContainsB: false,
},
{
name: "UserScope(1234)/UserScope(A/1234)",
name: "UserScope-1234/UserScope-A-1234",
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
wantAContainsB: true,
wantAStrictlyContainsB: true,
},
{
name: "UserScope(1234)/UserScope(A/5678)",
name: "UserScope-1234/UserScope-A-5678",
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
scopeB: PolicyScope{kind: UserSetting, userID: "5678", profileID: "A"},
wantAContainsB: false,

@ -44,7 +44,7 @@ func TestGetString(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "read existing value",
name: "read-existing-value",
key: pkey.AdminConsoleVisibility,
handlerValue: "hide",
wantValue: "hide",
@ -54,13 +54,13 @@ func TestGetString(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.EnableServerMode,
handlerError: ErrNotConfigured,
wantError: nil,
},
{
name: "read non-existing value, non-blank default",
name: "read-non-existing-value-non-blank-default",
key: pkey.EnableServerMode,
handlerError: ErrNotConfigured,
defaultValue: "test",
@ -68,7 +68,7 @@ func TestGetString(t *testing.T) {
wantError: nil,
},
{
name: "reading value returns other error",
name: "reading-value-returns-other-error",
key: pkey.NetworkDevicesVisibility,
handlerError: someOtherError,
wantError: someOtherError,
@ -124,27 +124,27 @@ func TestGetUint64(t *testing.T) {
wantError error
}{
{
name: "read existing value",
name: "read-existing-value",
key: pkey.LogSCMInteractions,
handlerValue: 1,
wantValue: 1,
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.LogSCMInteractions,
handlerValue: 0,
handlerError: ErrNotConfigured,
wantValue: 0,
},
{
name: "read non-existing value, non-zero default",
name: "read-non-existing-value-non-zero-default",
key: pkey.LogSCMInteractions,
defaultValue: 2,
handlerError: ErrNotConfigured,
wantValue: 2,
},
{
name: "reading value returns other error",
name: "reading-value-returns-other-error",
key: pkey.FlushDNSOnSessionUnlock,
handlerError: someOtherError,
wantError: someOtherError,
@ -191,7 +191,7 @@ func TestGetBoolean(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "read existing value",
name: "read-existing-value",
key: pkey.FlushDNSOnSessionUnlock,
handlerValue: true,
wantValue: true,
@ -201,14 +201,14 @@ func TestGetBoolean(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.LogSCMInteractions,
handlerValue: false,
handlerError: ErrNotConfigured,
wantValue: false,
},
{
name: "reading value returns other error",
name: "reading-value-returns-other-error",
key: pkey.FlushDNSOnSessionUnlock,
handlerError: someOtherError,
wantError: someOtherError, // expect error...
@ -266,7 +266,7 @@ func TestGetPreferenceOption(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "always by policy",
name: "always-by-policy",
key: pkey.EnableIncomingConnections,
handlerValue: "always",
wantValue: ptype.AlwaysByPolicy,
@ -276,7 +276,7 @@ func TestGetPreferenceOption(t *testing.T) {
},
},
{
name: "never by policy",
name: "never-by-policy",
key: pkey.EnableIncomingConnections,
handlerValue: "never",
wantValue: ptype.NeverByPolicy,
@ -286,7 +286,7 @@ func TestGetPreferenceOption(t *testing.T) {
},
},
{
name: "use default",
name: "use-default",
key: pkey.EnableIncomingConnections,
handlerValue: "",
wantValue: ptype.ShowChoiceByPolicy,
@ -296,13 +296,13 @@ func TestGetPreferenceOption(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.EnableIncomingConnections,
handlerError: ErrNotConfigured,
wantValue: ptype.ShowChoiceByPolicy,
},
{
name: "other error is returned",
name: "other-error-is-returned",
key: pkey.EnableIncomingConnections,
handlerError: someOtherError,
wantValue: ptype.ShowChoiceByPolicy,
@ -359,7 +359,7 @@ func TestGetVisibility(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "hidden by policy",
name: "hidden-by-policy",
key: pkey.AdminConsoleVisibility,
handlerValue: "hide",
wantValue: ptype.HiddenByPolicy,
@ -369,7 +369,7 @@ func TestGetVisibility(t *testing.T) {
},
},
{
name: "visibility default",
name: "visibility-default",
key: pkey.AdminConsoleVisibility,
handlerValue: "show",
wantValue: ptype.VisibleByPolicy,
@ -379,14 +379,14 @@ func TestGetVisibility(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.AdminConsoleVisibility,
handlerValue: "show",
handlerError: ErrNotConfigured,
wantValue: ptype.VisibleByPolicy,
},
{
name: "other error is returned",
name: "other-error-is-returned",
key: pkey.AdminConsoleVisibility,
handlerValue: "show",
handlerError: someOtherError,
@ -445,7 +445,7 @@ func TestGetDuration(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "read existing value",
name: "read-existing-value",
key: pkey.KeyExpirationNoticeTime,
handlerValue: "2h",
wantValue: 2 * time.Hour,
@ -456,7 +456,7 @@ func TestGetDuration(t *testing.T) {
},
},
{
name: "invalid duration value",
name: "invalid-duration-value",
key: pkey.KeyExpirationNoticeTime,
handlerValue: "-20",
wantValue: 24 * time.Hour,
@ -468,21 +468,21 @@ func TestGetDuration(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.KeyExpirationNoticeTime,
handlerError: ErrNotConfigured,
wantValue: 24 * time.Hour,
defaultValue: 24 * time.Hour,
},
{
name: "read non-existing value different default",
name: "read-non-existing-value-different-default",
key: pkey.KeyExpirationNoticeTime,
handlerError: ErrNotConfigured,
wantValue: 0 * time.Second,
defaultValue: 0 * time.Second,
},
{
name: "other error is returned",
name: "other-error-is-returned",
key: pkey.KeyExpirationNoticeTime,
handlerError: someOtherError,
wantValue: 24 * time.Hour,
@ -541,7 +541,7 @@ func TestGetStringArray(t *testing.T) {
wantMetrics []metrics.TestState
}{
{
name: "read existing value",
name: "read-existing-value",
key: pkey.AllowedSuggestedExitNodes,
handlerValue: []string{"foo", "bar"},
wantValue: []string{"foo", "bar"},
@ -551,13 +551,13 @@ func TestGetStringArray(t *testing.T) {
},
},
{
name: "read non-existing value",
name: "read-non-existing-value",
key: pkey.AllowedSuggestedExitNodes,
handlerError: ErrNotConfigured,
wantError: nil,
},
{
name: "read non-existing value, non nil default",
name: "read-non-existing-value-non-nil-default",
key: pkey.AllowedSuggestedExitNodes,
handlerError: ErrNotConfigured,
defaultValue: []string{"foo", "bar"},
@ -565,7 +565,7 @@ func TestGetStringArray(t *testing.T) {
wantError: nil,
},
{
name: "reading value returns other error",
name: "reading-value-returns-other-error",
key: pkey.AllowedSuggestedExitNodes,
handlerError: someOtherError,
wantError: someOtherError,

@ -180,7 +180,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
wantMaybe bool
}{
{
name: "nil probeUDPLifetime",
name: "nil-probeUDPLifetime",
localDisco: higher,
remoteDisco: &lower,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -189,28 +189,28 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
bestAddr: addr,
},
{
name: "local higher disco key",
name: "local-higher-disco-key",
localDisco: higher,
remoteDisco: &lower,
probeUDPLifetimeFn: newProbeUDPLifetime,
bestAddr: addr,
},
{
name: "remote no disco key",
name: "remote-no-disco-key",
localDisco: higher,
remoteDisco: nil,
probeUDPLifetimeFn: newProbeUDPLifetime,
bestAddr: addr,
},
{
name: "invalid bestAddr",
name: "invalid-bestAddr",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: newProbeUDPLifetime,
bestAddr: addrQuality{},
},
{
name: "cycle started too recently",
name: "cycle-started-too-recently",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -222,7 +222,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
bestAddr: addr,
},
{
name: "maybe cliff 0 cycle not active",
name: "maybe-cliff-0-cycle-not-active",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -238,7 +238,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
wantMaybe: true,
},
{
name: "maybe cliff 0",
name: "maybe-cliff-0",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -254,7 +254,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
wantMaybe: true,
},
{
name: "maybe cliff 1",
name: "maybe-cliff-1",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -270,7 +270,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
wantMaybe: true,
},
{
name: "maybe cliff 2",
name: "maybe-cliff-2",
localDisco: lower,
remoteDisco: &higher,
probeUDPLifetimeFn: func() *probeUDPLifetime {
@ -341,13 +341,13 @@ func Test_epAddr_isDirectUDP(t *testing.T) {
want: true,
},
{
name: "false derp magic addr",
name: "false-derp-magic-addr",
ap: netip.AddrPortFrom(tailcfg.DerpMagicIPAddr, 0),
vni: packet.VirtualNetworkID{},
want: false,
},
{
name: "false vni set",
name: "false-vni-set",
ap: netip.MustParseAddrPort("192.0.2.1:7"),
vni: vni,
want: false,
@ -397,42 +397,42 @@ func Test_endpoint_udpRelayEndpointReady(t *testing.T) {
wantBestAddr addrQuality
}{
{
name: "bestAddr trusted direct",
name: "bestAddr-trusted-direct",
curBestAddr: directAddrQuality,
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
maybeBest: peerRelayAddrQuality,
wantBestAddr: directAddrQuality,
},
{
name: "bestAddr untrusted direct",
name: "bestAddr-untrusted-direct",
curBestAddr: directAddrQuality,
trustBestAddrUntil: mono.Now().Add(-1 * time.Hour),
maybeBest: peerRelayAddrQuality,
wantBestAddr: peerRelayAddrQuality,
},
{
name: "maybeBest same relay server higher latency bestAddr trusted",
name: "maybeBest-same-relay-higher-latency-trusted",
curBestAddr: peerRelayAddrQuality,
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
maybeBest: peerRelayAddrQualityHigherLatencySameServer,
wantBestAddr: peerRelayAddrQualityHigherLatencySameServer,
},
{
name: "maybeBest diff relay server higher latency bestAddr trusted",
name: "maybeBest-diff-relay-higher-latency-trusted",
curBestAddr: peerRelayAddrQuality,
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
maybeBest: peerRelayAddrQualityHigherLatencyDiffServer,
wantBestAddr: peerRelayAddrQuality,
},
{
name: "maybeBest diff relay server lower latency bestAddr trusted",
name: "maybeBest-diff-relay-lower-latency-trusted",
curBestAddr: peerRelayAddrQuality,
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
maybeBest: peerRelayAddrQualityLowerLatencyDiffServer,
wantBestAddr: peerRelayAddrQualityLowerLatencyDiffServer,
},
{
name: "maybeBest diff relay server equal latency bestAddr trusted",
name: "maybeBest-diff-relay-equal-latency-trusted",
curBestAddr: peerRelayAddrQuality,
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
maybeBest: peerRelayAddrQualityEqualLatencyDiffServer,

@ -184,19 +184,19 @@ func TestBpfDiscardV4(t *testing.T) {
accept bool
}{
{
name: "base accepted datagram",
name: "base-accepted-datagram",
replace: map[int]byte{},
accept: true,
},
{
name: "more fragments",
name: "more-fragments",
replace: map[int]byte{
6: 0x20,
},
accept: false,
},
{
name: "some fragment",
name: "some-fragment",
replace: map[int]byte{
7: 0x01,
},

@ -1217,7 +1217,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
}
outerT := t
t.Run("ping 1.0.0.1", func(t *testing.T) {
t.Run("ping-1_0_0_1", func(t *testing.T) {
setT(t)
defer setT(outerT)
ping1(t)
@ -1225,7 +1225,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
checkStats(t, m2, m2Conns)
})
t.Run("ping 1.0.0.2", func(t *testing.T) {
t.Run("ping-1_0_0_2", func(t *testing.T) {
setT(t)
defer setT(outerT)
ping2(t)
@ -1233,7 +1233,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
checkStats(t, m2, m2Conns)
})
t.Run("ping 1.0.0.2 via SendPacket", func(t *testing.T) {
t.Run("ping-1_0_0_2-via-SendPacket", func(t *testing.T) {
setT(t)
defer setT(outerT)
msg1to2 := tuntest.Ping(netip.MustParseAddr("1.0.0.2"), netip.MustParseAddr("1.0.0.1"))
@ -1251,7 +1251,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
checkStats(t, m2, m2Conns)
})
t.Run("no-op dev1 reconfig", func(t *testing.T) {
t.Run("no-op-dev1-reconfig", func(t *testing.T) {
setT(t)
defer setT(outerT)
if err := m1.Reconfig(m1cfg); err != nil {
@ -2731,7 +2731,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want epAddr
}{
{
name: "no endpoints",
name: "no-endpoints",
sendInitialPing: false,
validAddr: false,
sendFollowUpPing: false,
@ -2740,7 +2740,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want: epAddr{},
},
{
name: "singular endpoint does not request ping",
name: "singular-endpoint-no-ping-request",
sendInitialPing: false,
validAddr: true,
sendFollowUpPing: false,
@ -2754,7 +2754,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
},
{
name: "ping sent within wireguardPingInterval should not request ping",
name: "ping-within-wireguardPingInterval-no-request",
sendInitialPing: true,
validAddr: true,
sendFollowUpPing: false,
@ -2772,7 +2772,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
},
{
name: "ping sent outside of wireguardPingInterval should request ping",
name: "ping-outside-wireguardPingInterval-requests-ping",
sendInitialPing: true,
validAddr: true,
sendFollowUpPing: true,
@ -2790,7 +2790,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
},
{
name: "choose lowest latency for useable IPv4 and IPv6",
name: "choose-lowest-latency-v4-and-v6",
sendInitialPing: true,
validAddr: true,
sendFollowUpPing: false,
@ -2808,7 +2808,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
want: epAddr{ap: netip.MustParseAddrPort("[2345:0425:2CA1:0000:0000:0567:5673:23b5]:222")},
},
{
name: "choose IPv6 address when latency is the same for v4 and v6",
name: "choose-IPv6-when-equal-latency",
sendInitialPing: true,
validAddr: true,
sendFollowUpPing: false,
@ -3378,73 +3378,73 @@ func Test_packetLooksLike(t *testing.T) {
wantIsGeneveEncap bool
}{
{
name: "STUN binding success response",
name: "STUN-binding-success-response",
msg: stun.Response(stun.NewTxID(), netip.MustParseAddrPort("127.0.0.1:1")),
wantPacketLooksLikeType: packetLooksLikeSTUNBinding,
wantIsGeneveEncap: false,
},
{
name: "naked disco",
name: "naked-disco",
msg: nakedDisco,
wantPacketLooksLikeType: packetLooksLikeDisco,
wantIsGeneveEncap: false,
},
{
name: "geneve encap disco",
name: "geneve-encap-disco",
msg: geneveEncapDisco,
wantPacketLooksLikeType: packetLooksLikeDisco,
wantIsGeneveEncap: true,
},
{
name: "geneve encap too short disco",
name: "geneve-encap-too-short-disco",
msg: geneveEncapDisco[:len(geneveEncapDisco)-key.DiscoPublicRawLen],
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "geneve encap disco nonzero geneve version",
name: "geneve-encap-disco-nonzero-geneve-version",
msg: geneveEncapDiscoNonZeroGeneveVersion,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "geneve encap disco nonzero geneve reserved bits",
name: "geneve-encap-disco-nonzero-geneve-reserved-bits",
msg: geneveEncapDiscoNonZeroGeneveReservedBits,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "geneve encap disco nonzero geneve vni lsb",
name: "geneve-encap-disco-nonzero-geneve-vni-lsb",
msg: geneveEncapDiscoNonZeroGeneveVNILSB,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "geneve encap wireguard",
name: "geneve-encap-wireguard",
msg: geneveEncapWireGuard,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: true,
},
{
name: "naked WireGuard Initiation type",
name: "naked-WireGuard-Initiation-type",
msg: nakedWireGuardInitiation,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "naked WireGuard Response type",
name: "naked-WireGuard-Response-type",
msg: nakedWireGuardResponse,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "naked WireGuard Cookie Reply type",
name: "naked-WireGuard-Cookie-Reply-type",
msg: nakedWireGuardCookieReply,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
},
{
name: "naked WireGuard Transport type",
name: "naked-WireGuard-Transport-type",
msg: nakedWireGuardTransport,
wantPacketLooksLikeType: packetLooksLikeWireGuard,
wantIsGeneveEncap: false,
@ -3481,22 +3481,22 @@ func Test_looksLikeInitiationMsg(t *testing.T) {
want bool
}{
{
name: "valid initiation",
name: "valid-initiation",
b: initMsg,
want: true,
},
{
name: "invalid message type field",
name: "invalid-message-type-field",
b: initMsgSizeTransportType,
want: false,
},
{
name: "too small",
name: "too-small",
b: initMsg[:device.MessageInitiationSize-1],
want: false,
},
{
name: "too big",
name: "too-big",
b: append(initMsg, 0),
want: false,
},
@ -3538,7 +3538,7 @@ func Test_nodeHasCap(t *testing.T) {
want bool
}{
{
name: "match v4",
name: "match-v4",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
@ -3556,7 +3556,7 @@ func Test_nodeHasCap(t *testing.T) {
want: true,
},
{
name: "match v6",
name: "match-v6",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
@ -3574,7 +3574,7 @@ func Test_nodeHasCap(t *testing.T) {
want: true,
},
{
name: "no match CapMatch Dst",
name: "no-match-CapMatch-Dst",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
@ -3592,7 +3592,7 @@ func Test_nodeHasCap(t *testing.T) {
want: false,
},
{
name: "no match peer cap",
name: "no-match-peer-cap",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
@ -3610,7 +3610,7 @@ func Test_nodeHasCap(t *testing.T) {
want: false,
},
{
name: "nil src",
name: "nil-src",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
@ -3628,7 +3628,7 @@ func Test_nodeHasCap(t *testing.T) {
want: false,
},
{
name: "nil dst",
name: "nil-dst",
filt: filter.New([]filtertype.Match{
{
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
@ -3706,7 +3706,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
wantRelayClientEnabled bool
}{
{
name: "candidate relay server",
name: "candidate-relay-server",
filt: filter.New([]filtertype.Match{
{
Srcs: peerNodeCandidateRelay.Addresses,
@ -3730,7 +3730,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
wantRelayClientEnabled: true,
},
{
name: "no candidate relay server because self has tailcfg.NodeAttrDisableRelayClient",
name: "no-candidate-self-has-DisableRelayClient", // self has tailcfg.NodeAttrDisableRelayClient
filt: filter.New([]filtertype.Match{
{
Srcs: peerNodeCandidateRelay.Addresses,
@ -3748,7 +3748,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
wantRelayClientEnabled: false,
},
{
name: "no candidate relay server because self has tailcfg.NodeAttrOnlyTCP443",
name: "no-candidate-self-has-OnlyTCP443", // self has tailcfg.NodeAttrOnlyTCP443
filt: filter.New([]filtertype.Match{
{
Srcs: peerNodeCandidateRelay.Addresses,
@ -3766,7 +3766,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
wantRelayClientEnabled: false,
},
{
name: "self candidate relay server",
name: "self-candidate-relay-server",
filt: filter.New([]filtertype.Match{
{
Srcs: selfNode.Addresses,
@ -3790,7 +3790,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
wantRelayClientEnabled: true,
},
{
name: "no candidate relay server",
name: "no-candidate-relay-server",
filt: filter.New([]filtertype.Match{
{
Srcs: peerNodeNotCandidateRelayCapVer.Addresses,
@ -3911,7 +3911,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled bool
}{
{
name: "naked disco",
name: "naked-disco",
b: looksLikeNakedDisco,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3923,7 +3923,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: false,
},
{
name: "geneve encap disco",
name: "geneve-encap-disco",
b: looksLikeGeneveDisco,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3935,7 +3935,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: false,
},
{
name: "STUN binding",
name: "STUN-binding",
b: looksLikeSTUNBinding,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3947,7 +3947,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: false,
},
{
name: "naked WireGuard init lazyEndpoint empty peerMap",
name: "naked-WireGuard-init-lazyEndpoint-empty-peerMap",
b: looksLikeNakedWireGuardInit,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3959,7 +3959,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: false,
},
{
name: "naked WireGuard init endpoint matching peerMap entry",
name: "naked-WireGuard-init-endpoint-matching-peerMap-entry",
b: looksLikeNakedWireGuardInit,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3973,7 +3973,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: true,
},
{
name: "geneve WireGuard init lazyEndpoint empty peerMap",
name: "geneve-WireGuard-init-lazyEndpoint-empty-peerMap",
b: looksLikeGeneveWireGuardInit,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -3985,7 +3985,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: false,
},
{
name: "geneve WireGuard init lazyEndpoint matching peerMap activity noted",
name: "geneve-WireGuard-init-lazyEndpoint-matching-peerMap-activity-noted",
b: looksLikeGeneveWireGuardInit,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -4001,7 +4001,7 @@ func TestConn_receiveIP(t *testing.T) {
wantNoteRecvActivityCalled: true,
},
{
name: "geneve WireGuard init lazyEndpoint matching peerMap no activity noted",
name: "geneve-WireGuard-init-lazyEndpoint-matching-peerMap-no-activity-noted",
b: looksLikeGeneveWireGuardInit,
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
cache: &epAddrEndpointCache{},
@ -4151,25 +4151,25 @@ func Test_lazyEndpoint_InitiationMessagePublicKey(t *testing.T) {
wantNoteRecvActivityCalled bool
}{
{
name: "noteRecvActivity called",
name: "noteRecvActivity-called",
callWithPeerMapKey: true,
maybeEPMatchingKey: false,
wantNoteRecvActivityCalled: true,
},
{
name: "maybeEP early return",
name: "maybeEP-early-return",
callWithPeerMapKey: true,
maybeEPMatchingKey: true,
wantNoteRecvActivityCalled: false,
},
{
name: "not in peerMap early return",
name: "not-in-peerMap-early-return",
callWithPeerMapKey: false,
maybeEPMatchingKey: false,
wantNoteRecvActivityCalled: false,
},
{
name: "not in peerMap maybeEP early return",
name: "not-in-peerMap-maybeEP-early-return",
callWithPeerMapKey: false,
maybeEPMatchingKey: true,
wantNoteRecvActivityCalled: false,
@ -4232,25 +4232,25 @@ func Test_lazyEndpoint_FromPeer(t *testing.T) {
wantEpAddrInPeerMap bool
}{
{
name: "epAddr in peerMap",
name: "epAddr-in-peerMap",
callWithPeerMapKey: true,
maybeEPMatchingKey: false,
wantEpAddrInPeerMap: true,
},
{
name: "maybeEP early return",
name: "maybeEP-early-return",
callWithPeerMapKey: true,
maybeEPMatchingKey: true,
wantEpAddrInPeerMap: false,
},
{
name: "not in peerMap early return",
name: "not-in-peerMap-early-return",
callWithPeerMapKey: false,
maybeEPMatchingKey: false,
wantEpAddrInPeerMap: false,
},
{
name: "not in peerMap maybeEP early return",
name: "not-in-peerMap-maybeEP-early-return",
callWithPeerMapKey: false,
maybeEPMatchingKey: true,
wantEpAddrInPeerMap: false,

@ -141,7 +141,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
}{
{
// Test for http://go/corp/32978
name: "eq server+ep neq VNI higher lamport",
name: "eq-server-ep-neq-VNI-higher-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointALamport1VNI1,
serverAendpointALamport2VNI2,
@ -151,7 +151,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq server+ep neq VNI lower lamport",
name: "eq-server-ep-neq-VNI-lower-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointALamport2VNI2,
serverAendpointALamport1VNI1,
@ -161,7 +161,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq server+vni neq ep lower lamport",
name: "eq-server-vni-neq-ep-lower-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointALamport2VNI2,
serverAendpointBLamport1VNI2,
@ -171,7 +171,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq server+vni neq ep higher lamport",
name: "eq-server-vni-neq-ep-higher-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointBLamport1VNI2,
serverAendpointALamport2VNI2,
@ -181,7 +181,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq server+endpoint+vni higher lamport",
name: "eq-server-endpoint-vni-higher-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointALamport1VNI1,
serverAendpointALamport2VNI1,
@ -191,7 +191,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq server+endpoint+vni lower lamport",
name: "eq-server-endpoint-vni-lower-lamport",
events: []newRelayServerEndpointEvent{
serverAendpointALamport2VNI1,
serverAendpointALamport1VNI1,
@ -201,7 +201,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "eq endpoint+vni+lamport neq server",
name: "eq-endpoint-vni-lamport-neq-server",
events: []newRelayServerEndpointEvent{
serverAendpointALamport1VNI1,
serverBendpointALamport1VNI1,
@ -212,7 +212,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
},
},
{
name: "trusted last best with matching server",
name: "trusted-last-best-with-matching-server",
events: []newRelayServerEndpointEvent{
serverAendpointALamport1VNI1LastBestMatching,
},

@ -54,13 +54,13 @@ ip rule add -6 pref 5270 table 52
want string
}{
{
name: "no config",
name: "no-config",
in: nil,
want: `
up` + basic,
},
{
name: "local addr only",
name: "local-addr-only",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.103/10"),
NetfilterMode: netfilterOff,
@ -71,7 +71,7 @@ ip addr add 100.101.102.103/10 dev tailscale0` + basic,
},
{
name: "addr and routes",
name: "addr-and-routes",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.103/10"),
Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"),
@ -85,7 +85,7 @@ ip route add 192.168.16.0/24 dev tailscale0 table 52` + basic,
},
{
name: "addr and routes and subnet routes",
name: "addr-routes-and-subnet-routes",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.103/10"),
Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"),
@ -100,7 +100,7 @@ ip route add 192.168.16.0/24 dev tailscale0 table 52` + basic,
},
{
name: "addr and routes and subnet routes with netfilter",
name: "addr-routes-subnet-routes-with-netfilter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -141,7 +141,7 @@ v6/nat/ts-postrouting -m mark --mark 0x40000/0xff0000 -j MASQUERADE
`,
},
{
name: "addr and routes and subnet routes with netfilter but no stateful filtering",
name: "addr-routes-subnet-routes-netfilter-no-stateful",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -180,7 +180,7 @@ v6/nat/ts-postrouting -m mark --mark 0x40000/0xff0000 -j MASQUERADE
`,
},
{
name: "addr and routes with netfilter",
name: "addr-and-routes-with-netfilter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -215,7 +215,7 @@ v6/nat/POSTROUTING -j ts-postrouting
},
{
name: "addr and routes and subnet routes with netfilter but no SNAT",
name: "addr-routes-subnet-routes-netfilter-no-SNAT",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -251,7 +251,7 @@ v6/nat/POSTROUTING -j ts-postrouting
`,
},
{
name: "addr and routes with netfilter",
name: "addr-and-routes-with-netfilter-2",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -286,7 +286,7 @@ v6/nat/POSTROUTING -j ts-postrouting
},
{
name: "addr and routes with half netfilter",
name: "addr-and-routes-with-half-netfilter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -310,7 +310,7 @@ v6/filter/ts-forward -o tailscale0 -j ACCEPT
`,
},
{
name: "addr and routes with netfilter2",
name: "addr-and-routes-with-netfilter2",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
@ -344,7 +344,7 @@ v6/nat/POSTROUTING -j ts-postrouting
`,
},
{
name: "addr, routes, and local routes with netfilter",
name: "addr-routes-local-routes-with-netfilter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "0.0.0.0/0"),
@ -380,7 +380,7 @@ v6/nat/POSTROUTING -j ts-postrouting
`,
},
{
name: "addr, routes, and local routes with no netfilter",
name: "addr-routes-local-routes-no-netfilter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32", "0.0.0.0/0"),
@ -396,7 +396,7 @@ ip route add throw 10.0.0.0/8 table 52
ip route add throw 192.168.0.0/24 table 52` + basic,
},
{
name: "subnet routes with connmark for rp_filter",
name: "subnet-routes-connmark-for-rp_filter",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32"),
@ -433,7 +433,7 @@ v6/nat/ts-postrouting -m mark --mark 0x40000/0xff0000 -j MASQUERADE
`,
},
{
name: "subnet routes (connmark always enabled)",
name: "subnet-routes-connmark-always-enabled",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32"),
@ -470,7 +470,7 @@ v6/nat/ts-postrouting -m mark --mark 0x40000/0xff0000 -j MASQUERADE
`,
},
{
name: "connmark with stateful filtering",
name: "connmark-with-stateful-filtering",
in: &Config{
LocalAddrs: mustCIDRs("100.101.102.104/10"),
Routes: mustCIDRs("100.100.100.100/32"),

@ -26,7 +26,7 @@ func TestWatchdog(t *testing.T) {
maxWaitMultiple = 15
}
t.Run("default watchdog does not fire", func(t *testing.T) {
t.Run("default-watchdog-does-not-fire", func(t *testing.T) {
t.Parallel()
bus := eventbustest.NewBus(t)
ht := health.NewTracker(bus)
@ -55,7 +55,7 @@ func TestWatchdogMetrics(t *testing.T) {
wantCounts map[watchdogEvent]int64
}{
{
name: "single event types",
name: "single-event-types",
events: []watchdogEvent{RequestStatus, PeerForIPEvent, Ping},
wantCounts: map[watchdogEvent]int64{
RequestStatus: 1,
@ -64,7 +64,7 @@ func TestWatchdogMetrics(t *testing.T) {
},
},
{
name: "repeated events",
name: "repeated-events",
events: []watchdogEvent{RequestStatus, RequestStatus, Ping, RequestStatus},
wantCounts: map[watchdogEvent]int64{
RequestStatus: 3,

@ -90,14 +90,14 @@ func TestDeviceConfig(t *testing.T) {
}
}
t.Run("device1 config", func(t *testing.T) {
t.Run("device1-config", func(t *testing.T) {
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
cmp(t, device1, cfg1)
})
t.Run("device2 config", func(t *testing.T) {
t.Run("device2-config", func(t *testing.T) {
if err := ReconfigDevice(device2, cfg2, t.Logf); err != nil {
t.Fatal(err)
}
@ -105,7 +105,7 @@ func TestDeviceConfig(t *testing.T) {
})
// This is only to test that Config and Reconfig are properly synchronized.
t.Run("device2 config/reconfig", func(t *testing.T) {
t.Run("device2-config-reconfig", func(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
@ -122,7 +122,7 @@ func TestDeviceConfig(t *testing.T) {
wg.Wait()
})
t.Run("device1 modify peer", func(t *testing.T) {
t.Run("device1-modify-peer", func(t *testing.T) {
cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 1, 31: 0}))
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
@ -130,7 +130,7 @@ func TestDeviceConfig(t *testing.T) {
cmp(t, device1, cfg1)
})
t.Run("device1 replace endpoint", func(t *testing.T) {
t.Run("device1-replace-endpoint", func(t *testing.T) {
cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 2, 31: 0}))
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
@ -138,7 +138,7 @@ func TestDeviceConfig(t *testing.T) {
cmp(t, device1, cfg1)
})
t.Run("device1 add new peer", func(t *testing.T) {
t.Run("device1-add-new-peer", func(t *testing.T) {
cfg1.Peers = append(cfg1.Peers, Peer{
PublicKey: k3,
AllowedIPs: []netip.Prefix{ip3},
@ -178,7 +178,7 @@ func TestDeviceConfig(t *testing.T) {
}
})
t.Run("device1 remove peer", func(t *testing.T) {
t.Run("device1-remove-peer", func(t *testing.T) {
removeKey := cfg1.Peers[len(cfg1.Peers)-1].PublicKey
cfg1.Peers = cfg1.Peers[:len(cfg1.Peers)-1]

Loading…
Cancel
Save