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>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
0f02c20c5e
commit
5ef3713c9f
@@ -36,8 +36,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Run 'go vet'
|
- name: Run 'go vet'
|
||||||
working-directory: src
|
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
|
# Must use ./... instead of tailscale.com/... because the latter will
|
||||||
# include the v2 go client (tailscale.com/client/tailscale/v2) if it's
|
# 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
|
# 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.
|
# 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, input, want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no illegal chars",
|
name: "no-illegal-chars",
|
||||||
input: "/home/user",
|
input: "/home/user",
|
||||||
want: "/home/user",
|
want: "/home/user",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty string",
|
name: "empty-string",
|
||||||
input: "",
|
input: "",
|
||||||
want: "\"\"",
|
want: "\"\"",
|
||||||
},
|
},
|
||||||
@@ -38,12 +38,12 @@ func TestEscape(t *testing.T) {
|
|||||||
want: "\"\n\"",
|
want: "\"\n\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "double quote",
|
name: "double-quote",
|
||||||
input: "\"",
|
input: "\"",
|
||||||
want: "\"\\\"\"",
|
want: "\"\\\"\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single quote",
|
name: "single-quote",
|
||||||
input: "'",
|
input: "'",
|
||||||
want: "\"'\"",
|
want: "\"'\"",
|
||||||
},
|
},
|
||||||
@@ -53,12 +53,12 @@ func TestEscape(t *testing.T) {
|
|||||||
want: "\"\\\\\"",
|
want: "\"\\\\\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "greater than",
|
name: "greater-than",
|
||||||
input: ">",
|
input: ">",
|
||||||
want: "\">\"",
|
want: "\">\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "less than",
|
name: "less-than",
|
||||||
input: "<",
|
input: "<",
|
||||||
want: "\"<\"",
|
want: "\"<\"",
|
||||||
},
|
},
|
||||||
@@ -93,7 +93,7 @@ func TestEscape(t *testing.T) {
|
|||||||
want: "\"*\"",
|
want: "\"*\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "question mark",
|
name: "question-mark",
|
||||||
input: "?",
|
input: "?",
|
||||||
want: "\"?\"",
|
want: "\"?\"",
|
||||||
},
|
},
|
||||||
@@ -103,12 +103,12 @@ func TestEscape(t *testing.T) {
|
|||||||
want: "\"#\"",
|
want: "\"#\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "open paren",
|
name: "open-paren",
|
||||||
input: "(",
|
input: "(",
|
||||||
want: "\"(\"",
|
want: "\"(\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "close paren",
|
name: "close-paren",
|
||||||
input: ")",
|
input: ")",
|
||||||
want: "\")\"",
|
want: "\")\"",
|
||||||
},
|
},
|
||||||
@@ -118,17 +118,17 @@ func TestEscape(t *testing.T) {
|
|||||||
want: "\"\\`\"",
|
want: "\"\\`\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "char without escape",
|
name: "char-without-escape",
|
||||||
input: "/home/user\t",
|
input: "/home/user\t",
|
||||||
want: "\"/home/user\t\"",
|
want: "\"/home/user\t\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "char with escape",
|
name: "char-with-escape",
|
||||||
input: "/home/user\\",
|
input: "/home/user\\",
|
||||||
want: "\"/home/user\\\\\"",
|
want: "\"/home/user\\\\\"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all illegal chars",
|
name: "all-illegal-chars",
|
||||||
input: "/home/user" + needsEscape,
|
input: "/home/user" + needsEscape,
|
||||||
want: "\"/home/user \t\n\\\"'\\\\><~|&;\\$*?#()\\`\"",
|
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`,
|
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"}}},
|
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`,
|
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`,
|
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"}}},
|
elements: []any{"acl", url.Values{"details": {"1"}}},
|
||||||
want: `http://127.0.0.1:1234/api/v2/tailnet/example.com/acl?details=1`,
|
want: `http://127.0.0.1:1234/api/v2/tailnet/example.com/acl?details=1`,
|
||||||
},
|
},
|
||||||
|
|||||||
+15
-15
@@ -41,37 +41,37 @@ func TestQnapAuthnURL(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "localhost http",
|
name: "localhost-http",
|
||||||
in: "http://localhost:8088/",
|
in: "http://localhost:8088/",
|
||||||
want: "http://localhost:8088/cgi-bin/authLogin.cgi?qtoken=token",
|
want: "http://localhost:8088/cgi-bin/authLogin.cgi?qtoken=token",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "localhost https",
|
name: "localhost-https",
|
||||||
in: "https://localhost:5000/",
|
in: "https://localhost:5000/",
|
||||||
want: "https://localhost:5000/cgi-bin/authLogin.cgi?qtoken=token",
|
want: "https://localhost:5000/cgi-bin/authLogin.cgi?qtoken=token",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "IP http",
|
name: "IP-http",
|
||||||
in: "http://10.1.20.4:80/",
|
in: "http://10.1.20.4:80/",
|
||||||
want: "http://10.1.20.4:80/cgi-bin/authLogin.cgi?qtoken=token",
|
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]/",
|
in: "https://[ff7d:0:1:2::1]/",
|
||||||
want: "https://[ff7d:0:1:2::1]/cgi-bin/authLogin.cgi?qtoken=token",
|
want: "https://[ff7d:0:1:2::1]/cgi-bin/authLogin.cgi?qtoken=token",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hostname https",
|
name: "hostname-https",
|
||||||
in: "https://qnap.example.com/",
|
in: "https://qnap.example.com/",
|
||||||
want: "https://qnap.example.com/cgi-bin/authLogin.cgi?qtoken=token",
|
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.",
|
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",
|
want: "http://localhost/cgi-bin/authLogin.cgi?qtoken=token",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "err != nil",
|
name: "err-not-nil",
|
||||||
in: "http://192.168.0.%31/",
|
in: "http://192.168.0.%31/",
|
||||||
want: "http://localhost/cgi-bin/authLogin.cgi?qtoken=token",
|
want: "http://localhost/cgi-bin/authLogin.cgi?qtoken=token",
|
||||||
},
|
},
|
||||||
@@ -1516,47 +1516,47 @@ func TestCSRFProtect(t *testing.T) {
|
|||||||
wantError bool
|
wantError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "GET requests with no header are allowed",
|
name: "GET-no-header-allowed", // GET requests with no header are allowed
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "POST requests with same-origin are allowed",
|
name: "POST-same-origin-allowed",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
secFetchSite: "same-origin",
|
secFetchSite: "same-origin",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "POST requests with cross-site are not allowed",
|
name: "POST-cross-site-rejected",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
secFetchSite: "cross-site",
|
secFetchSite: "cross-site",
|
||||||
wantError: true,
|
wantError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "POST requests with unknown sec-fetch-site values are not allowed",
|
name: "POST-unknown-sec-fetch-site-rejected",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
secFetchSite: "new-unknown-value",
|
secFetchSite: "new-unknown-value",
|
||||||
wantError: true,
|
wantError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "POST requests with none are not allowed",
|
name: "POST-sec-fetch-none-rejected",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
secFetchSite: "none",
|
secFetchSite: "none",
|
||||||
wantError: true,
|
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",
|
method: "POST",
|
||||||
host: "example.com",
|
host: "example.com",
|
||||||
origin: "https://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",
|
method: "POST",
|
||||||
host: "example.com",
|
host: "example.com",
|
||||||
origin: "https://example.net",
|
origin: "https://example.net",
|
||||||
wantError: true,
|
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",
|
method: "POST",
|
||||||
originOverride: "example.net",
|
originOverride: "example.net",
|
||||||
host: "internal.example.foo", // Host can be changed by reverse proxies
|
host: "internal.example.foo", // Host can be changed by reverse proxies
|
||||||
|
|||||||
@@ -148,27 +148,27 @@ func TestUpdateYUMRepoTrack(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "same track",
|
desc: "same-track",
|
||||||
before: YUMRepos[StableTrack],
|
before: YUMRepos[StableTrack],
|
||||||
track: StableTrack,
|
track: StableTrack,
|
||||||
after: YUMRepos[StableTrack],
|
after: YUMRepos[StableTrack],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "change track",
|
desc: "change-track",
|
||||||
before: YUMRepos[StableTrack],
|
before: YUMRepos[StableTrack],
|
||||||
track: UnstableTrack,
|
track: UnstableTrack,
|
||||||
after: YUMRepos[UnstableTrack],
|
after: YUMRepos[UnstableTrack],
|
||||||
rewrote: true,
|
rewrote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "change track RC",
|
desc: "change-track-RC",
|
||||||
before: YUMRepos[StableTrack],
|
before: YUMRepos[StableTrack],
|
||||||
track: ReleaseCandidateTrack,
|
track: ReleaseCandidateTrack,
|
||||||
after: YUMRepos[ReleaseCandidateTrack],
|
after: YUMRepos[ReleaseCandidateTrack],
|
||||||
rewrote: true,
|
rewrote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "non-tailscale repo file",
|
desc: "non-tailscale-repo-file",
|
||||||
before: YUMRepos["FakeRepo"],
|
before: YUMRepos["FakeRepo"],
|
||||||
track: StableTrack,
|
track: StableTrack,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@@ -215,7 +215,7 @@ func TestParseAlpinePackageVersion(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "valid version",
|
desc: "valid-version",
|
||||||
out: `
|
out: `
|
||||||
tailscale-1.44.2-r0 description:
|
tailscale-1.44.2-r0 description:
|
||||||
The easiest, most secure way to use WireGuard and 2FA
|
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",
|
want: "1.44.2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "wrong package output",
|
desc: "wrong-package-output",
|
||||||
out: `
|
out: `
|
||||||
busybox-1.36.1-r0 description:
|
busybox-1.36.1-r0 description:
|
||||||
Size optimized toolbox of many common UNIX utilities
|
Size optimized toolbox of many common UNIX utilities
|
||||||
@@ -243,7 +243,7 @@ busybox-1.36.1-r0 installed size:
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "missing version",
|
desc: "missing-version",
|
||||||
out: `
|
out: `
|
||||||
tailscale description:
|
tailscale description:
|
||||||
The easiest, most secure way to use WireGuard and 2FA
|
The easiest, most secure way to use WireGuard and 2FA
|
||||||
@@ -257,12 +257,12 @@ tailscale installed size:
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty output",
|
desc: "empty-output",
|
||||||
out: "",
|
out: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "multiple versions",
|
desc: "multiple-versions",
|
||||||
out: `
|
out: `
|
||||||
tailscale-1.54.1-r0 description:
|
tailscale-1.54.1-r0 description:
|
||||||
The easiest, most secure way to use WireGuard and 2FA
|
The easiest, most secure way to use WireGuard and 2FA
|
||||||
@@ -322,14 +322,14 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
|
|||||||
track string
|
track string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Up to date",
|
name: "up-to-date",
|
||||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
||||||
latestHTTPVersion: "1.95.3",
|
latestHTTPVersion: "1.95.3",
|
||||||
latestApkVersion: "1.95.3",
|
latestApkVersion: "1.95.3",
|
||||||
track: "unstable",
|
track: "unstable",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Behind unstable",
|
name: "behind-unstable",
|
||||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v3.20/main",
|
||||||
latestHTTPVersion: "1.95.4",
|
latestHTTPVersion: "1.95.4",
|
||||||
latestApkVersion: "1.95.3",
|
latestApkVersion: "1.95.3",
|
||||||
@@ -339,7 +339,7 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
|
|||||||
track: "unstable",
|
track: "unstable",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Behind stable",
|
name: "behind-stable",
|
||||||
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v2.40/main",
|
fileContent: "https://dl-cdn.alpinelinux.org/alpine/v2.40/main",
|
||||||
latestHTTPVersion: "1.94.3",
|
latestHTTPVersion: "1.94.3",
|
||||||
latestApkVersion: "1.92.1",
|
latestApkVersion: "1.92.1",
|
||||||
@@ -349,7 +349,7 @@ func TestCheckOutdatedAlpineRepo(t *testing.T) {
|
|||||||
track: "stable",
|
track: "stable",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Nothing in dist file",
|
name: "nothing-in-dist-file",
|
||||||
fileContent: "",
|
fileContent: "",
|
||||||
latestHTTPVersion: "1.94.3",
|
latestHTTPVersion: "1.94.3",
|
||||||
latestApkVersion: "1.92.1",
|
latestApkVersion: "1.92.1",
|
||||||
@@ -505,14 +505,14 @@ unique=synology_88f6281_213air
|
|||||||
want: "88f6281",
|
want: "88f6281",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "missing unique",
|
desc: "missing-unique",
|
||||||
content: `
|
content: `
|
||||||
company_title="Synology"
|
company_title="Synology"
|
||||||
`,
|
`,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty unique",
|
desc: "empty-unique",
|
||||||
content: `
|
content: `
|
||||||
company_title="Synology"
|
company_title="Synology"
|
||||||
unique=
|
unique=
|
||||||
@@ -520,7 +520,7 @@ unique=
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty unique double-quoted",
|
desc: "empty-unique-double-quoted",
|
||||||
content: `
|
content: `
|
||||||
company_title="Synology"
|
company_title="Synology"
|
||||||
unique=""
|
unique=""
|
||||||
@@ -528,7 +528,7 @@ unique=""
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty unique single-quoted",
|
desc: "empty-unique-single-quoted",
|
||||||
content: `
|
content: `
|
||||||
company_title="Synology"
|
company_title="Synology"
|
||||||
unique=''
|
unique=''
|
||||||
@@ -536,7 +536,7 @@ unique=''
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "malformed unique",
|
desc: "malformed-unique",
|
||||||
content: `
|
content: `
|
||||||
company_title="Synology"
|
company_title="Synology"
|
||||||
unique="synology_88f6281"
|
unique="synology_88f6281"
|
||||||
@@ -544,12 +544,12 @@ unique="synology_88f6281"
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty file",
|
desc: "empty-file",
|
||||||
content: ``,
|
content: ``,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty lines and comments",
|
desc: "empty-lines-and-comments",
|
||||||
content: `
|
content: `
|
||||||
|
|
||||||
# In a file named synoinfo? Shocking!
|
# 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{
|
before: map[string]string{
|
||||||
"tailscale": "v1",
|
"tailscale": "v1",
|
||||||
"tailscaled": "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{
|
before: map[string]string{
|
||||||
"tailscale": "v1",
|
"tailscale": "v1",
|
||||||
"tailscaled": "v1",
|
"tailscaled": "v1",
|
||||||
@@ -661,7 +661,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "tarball missing tailscaled",
|
desc: "tarball-missing-tailscaled",
|
||||||
before: map[string]string{
|
before: map[string]string{
|
||||||
"tailscale": "v1",
|
"tailscale": "v1",
|
||||||
"tailscaled": "v1",
|
"tailscaled": "v1",
|
||||||
@@ -677,7 +677,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "duplicate tailscale binary",
|
desc: "duplicate-tailscale-binary",
|
||||||
before: map[string]string{
|
before: map[string]string{
|
||||||
"tailscale": "v1",
|
"tailscale": "v1",
|
||||||
"tailscaled": "v1",
|
"tailscaled": "v1",
|
||||||
@@ -696,7 +696,7 @@ func TestUnpackLinuxTarball(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "empty archive",
|
desc: "empty-archive",
|
||||||
before: map[string]string{
|
before: map[string]string{
|
||||||
"tailscale": "v1",
|
"tailscale": "v1",
|
||||||
"tailscaled": "v1",
|
"tailscaled": "v1",
|
||||||
@@ -952,17 +952,18 @@ func TestCleanupOldDownloads(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseUnraidPluginVersion(t *testing.T) {
|
func TestParseUnraidPluginVersion(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
plgPath string
|
plgPath string
|
||||||
wantVer string
|
wantVer string
|
||||||
wantErr string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{plgPath: "testdata/tailscale-1.52.0.plg", wantVer: "1.52.0"},
|
{name: "v1_52_0", plgPath: "testdata/tailscale-1.52.0.plg", wantVer: "1.52.0"},
|
||||||
{plgPath: "testdata/tailscale-1.54.0.plg", wantVer: "1.54.0"},
|
{name: "v1_54_0", plgPath: "testdata/tailscale-1.54.0.plg", wantVer: "1.54.0"},
|
||||||
{plgPath: "testdata/tailscale-nover.plg", wantErr: "version not found in plg file"},
|
{name: "nover", 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: "nover-path-mentioned", plgPath: "testdata/tailscale-nover-path-mentioned.plg", wantErr: "version not found in plg file"},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
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)
|
got, err := parseUnraidPluginVersion(tt.plgPath)
|
||||||
if got != tt.wantVer {
|
if got != tt.wantVer {
|
||||||
t.Errorf("got version: %q, want %q", got, tt.wantVer)
|
t.Errorf("got version: %q, want %q", got, tt.wantVer)
|
||||||
@@ -992,7 +993,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "on latest stable",
|
desc: "on-latest-stable",
|
||||||
fromTrack: StableTrack,
|
fromTrack: StableTrack,
|
||||||
toTrack: StableTrack,
|
toTrack: StableTrack,
|
||||||
fromVer: "1.66.0",
|
fromVer: "1.66.0",
|
||||||
@@ -1000,7 +1001,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "stable upgrade",
|
desc: "stable-upgrade",
|
||||||
fromTrack: StableTrack,
|
fromTrack: StableTrack,
|
||||||
toTrack: StableTrack,
|
toTrack: StableTrack,
|
||||||
fromVer: "1.66.0",
|
fromVer: "1.66.0",
|
||||||
@@ -1008,7 +1009,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "unstable upgrade",
|
desc: "unstable-upgrade",
|
||||||
fromTrack: UnstableTrack,
|
fromTrack: UnstableTrack,
|
||||||
toTrack: UnstableTrack,
|
toTrack: UnstableTrack,
|
||||||
fromVer: "1.67.1",
|
fromVer: "1.67.1",
|
||||||
@@ -1016,7 +1017,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "from stable to unstable",
|
desc: "from-stable-to-unstable",
|
||||||
fromTrack: StableTrack,
|
fromTrack: StableTrack,
|
||||||
toTrack: UnstableTrack,
|
toTrack: UnstableTrack,
|
||||||
fromVer: "1.66.0",
|
fromVer: "1.66.0",
|
||||||
@@ -1024,7 +1025,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "from unstable to stable",
|
desc: "from-unstable-to-stable",
|
||||||
fromTrack: UnstableTrack,
|
fromTrack: UnstableTrack,
|
||||||
toTrack: StableTrack,
|
toTrack: StableTrack,
|
||||||
fromVer: "1.67.1",
|
fromVer: "1.67.1",
|
||||||
@@ -1032,7 +1033,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "confirm callback rejects",
|
desc: "confirm-callback-rejects",
|
||||||
fromTrack: StableTrack,
|
fromTrack: StableTrack,
|
||||||
toTrack: StableTrack,
|
toTrack: StableTrack,
|
||||||
fromVer: "1.66.0",
|
fromVer: "1.66.0",
|
||||||
@@ -1043,7 +1044,7 @@ func TestConfirm(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "confirm callback allows",
|
desc: "confirm-callback-allows",
|
||||||
fromTrack: StableTrack,
|
fromTrack: StableTrack,
|
||||||
toTrack: StableTrack,
|
toTrack: StableTrack,
|
||||||
fromVer: "1.66.0",
|
fromVer: "1.66.0",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func TestDownload(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "missing file",
|
desc: "missing-file",
|
||||||
before: func(*testing.T) {},
|
before: func(*testing.T) {},
|
||||||
src: "hello",
|
src: "hello",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@@ -44,7 +44,7 @@ func TestDownload(t *testing.T) {
|
|||||||
want: []byte("world"),
|
want: []byte("world"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "no signature",
|
desc: "no-signature",
|
||||||
before: func(*testing.T) {
|
before: func(*testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
},
|
},
|
||||||
@@ -52,7 +52,7 @@ func TestDownload(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "bad signature",
|
desc: "bad-signature",
|
||||||
before: func(*testing.T) {
|
before: func(*testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", []byte("potato"))
|
srv.add("hello.sig", []byte("potato"))
|
||||||
@@ -61,7 +61,7 @@ func TestDownload(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "signed with untrusted key",
|
desc: "signed-untrusted-key",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
|
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
|
||||||
@@ -70,7 +70,7 @@ func TestDownload(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "signed with root key",
|
desc: "signed-with-root-key",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", ed25519.Sign(srv.roots[0].k, []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,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "bad signing key signature",
|
desc: "bad-signing-key-signature",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("distsign.pub.sig", []byte("potato"))
|
srv.add("distsign.pub.sig", []byte("potato"))
|
||||||
srv.addSigned("hello", []byte("world"))
|
srv.addSigned("hello", []byte("world"))
|
||||||
@@ -130,7 +130,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "missing file",
|
desc: "missing-file",
|
||||||
before: func(*testing.T) {},
|
before: func(*testing.T) {},
|
||||||
src: "hello",
|
src: "hello",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@@ -143,7 +143,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
src: "hello",
|
src: "hello",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "contents changed",
|
desc: "contents-changed",
|
||||||
before: func(*testing.T) {
|
before: func(*testing.T) {
|
||||||
srv.addSigned("hello", []byte("new world"))
|
srv.addSigned("hello", []byte("new world"))
|
||||||
},
|
},
|
||||||
@@ -151,7 +151,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "no signature",
|
desc: "no-signature",
|
||||||
before: func(*testing.T) {
|
before: func(*testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
},
|
},
|
||||||
@@ -159,7 +159,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "bad signature",
|
desc: "bad-signature",
|
||||||
before: func(*testing.T) {
|
before: func(*testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", []byte("potato"))
|
srv.add("hello.sig", []byte("potato"))
|
||||||
@@ -168,7 +168,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "signed with untrusted key",
|
desc: "signed-untrusted-key",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
|
srv.add("hello.sig", newSigningKeyPair(t).sign([]byte("world")))
|
||||||
@@ -177,7 +177,7 @@ func TestValidateLocalBinary(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "signed with root key",
|
desc: "signed-with-root-key",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("hello", []byte("world"))
|
srv.add("hello", []byte("world"))
|
||||||
srv.add("hello.sig", ed25519.Sign(srv.roots[0].k, []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,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "bad signing key signature",
|
desc: "bad-signing-key-signature",
|
||||||
before: func(t *testing.T) {
|
before: func(t *testing.T) {
|
||||||
srv.add("distsign.pub.sig", []byte("potato"))
|
srv.add("distsign.pub.sig", []byte("potato"))
|
||||||
srv.addSigned("hello", []byte("world"))
|
srv.addSigned("hello", []byte("world"))
|
||||||
@@ -341,7 +341,7 @@ func TestParseRootKey(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "invalid PEM tag",
|
desc: "invalid-PEM-tag",
|
||||||
generate: func() ([]byte, []byte, error) {
|
generate: func() ([]byte, []byte, error) {
|
||||||
priv, pub, err := GenerateRootKey()
|
priv, pub, err := GenerateRootKey()
|
||||||
priv = bytes.Replace(priv, []byte("ROOT "), nil, -1)
|
priv = bytes.Replace(priv, []byte("ROOT "), nil, -1)
|
||||||
@@ -350,7 +350,7 @@ func TestParseRootKey(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "not PEM",
|
desc: "not-PEM",
|
||||||
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
|
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@@ -399,7 +399,7 @@ func TestParseSigningKey(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "invalid PEM tag",
|
desc: "invalid-PEM-tag",
|
||||||
generate: func() ([]byte, []byte, error) {
|
generate: func() ([]byte, []byte, error) {
|
||||||
priv, pub, err := GenerateSigningKey()
|
priv, pub, err := GenerateSigningKey()
|
||||||
priv = bytes.Replace(priv, []byte("SIGNING "), nil, -1)
|
priv = bytes.Replace(priv, []byte("SIGNING "), nil, -1)
|
||||||
@@ -408,7 +408,7 @@ func TestParseSigningKey(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "not PEM",
|
desc: "not-PEM",
|
||||||
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
|
generate: func() ([]byte, []byte, error) { return []byte("s3cr3t"), nil, nil },
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
kc *kubeClient
|
kc *kubeClient
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "TS_AUTHKEY set, state Secret exists",
|
name: "authkey-set-secret-exists",
|
||||||
cfg: &settings{
|
cfg: &settings{
|
||||||
AuthKey: "foo",
|
AuthKey: "foo",
|
||||||
KubeSecret: "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{
|
cfg: &settings{
|
||||||
AuthKey: "foo",
|
AuthKey: "foo",
|
||||||
KubeSecret: "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{
|
cfg: &settings{
|
||||||
AuthKey: "foo",
|
AuthKey: "foo",
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
@@ -89,7 +89,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
wantErr: true,
|
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{
|
cfg: &settings{
|
||||||
AuthKey: "foo",
|
AuthKey: "foo",
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
@@ -109,7 +109,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
wantErr: true,
|
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{
|
cfg: &settings{
|
||||||
AuthKey: "foo",
|
AuthKey: "foo",
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
@@ -127,7 +127,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Interactive login using URL in Pod logs
|
// 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{
|
cfg: &settings{
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
},
|
},
|
||||||
@@ -145,7 +145,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Interactive login using URL in Pod logs
|
// 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{
|
cfg: &settings{
|
||||||
KubeSecret: "foo",
|
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{
|
cfg: &settings{
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
},
|
},
|
||||||
@@ -180,7 +180,7 @@ func TestSetupKube(t *testing.T) {
|
|||||||
wantErr: true,
|
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{
|
cfg: &settings{
|
||||||
KubeSecret: "foo",
|
KubeSecret: "foo",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -89,24 +89,24 @@ type settings struct {
|
|||||||
|
|
||||||
func configFromEnv() (*settings, error) {
|
func configFromEnv() (*settings, error) {
|
||||||
cfg := &settings{
|
cfg := &settings{
|
||||||
AuthKey: defaultEnvs([]string{"TS_AUTHKEY", "TS_AUTH_KEY"}, ""),
|
AuthKey: defaultEnvs([]string{"TS_AUTHKEY", "TS_AUTH_KEY"}, ""),
|
||||||
ClientID: defaultEnv("TS_CLIENT_ID", ""),
|
ClientID: defaultEnv("TS_CLIENT_ID", ""),
|
||||||
ClientSecret: defaultEnv("TS_CLIENT_SECRET", ""),
|
ClientSecret: defaultEnv("TS_CLIENT_SECRET", ""),
|
||||||
IDToken: defaultEnv("TS_ID_TOKEN", ""),
|
IDToken: defaultEnv("TS_ID_TOKEN", ""),
|
||||||
Audience: defaultEnv("TS_AUDIENCE", ""),
|
Audience: defaultEnv("TS_AUDIENCE", ""),
|
||||||
Hostname: defaultEnv("TS_HOSTNAME", ""),
|
Hostname: defaultEnv("TS_HOSTNAME", ""),
|
||||||
Routes: defaultEnvStringPointer("TS_ROUTES"),
|
Routes: defaultEnvStringPointer("TS_ROUTES"),
|
||||||
ServeConfigPath: defaultEnv("TS_SERVE_CONFIG", ""),
|
ServeConfigPath: defaultEnv("TS_SERVE_CONFIG", ""),
|
||||||
ProxyTargetIP: defaultEnv("TS_DEST_IP", ""),
|
ProxyTargetIP: defaultEnv("TS_DEST_IP", ""),
|
||||||
ProxyTargetDNSName: defaultEnv("TS_EXPERIMENTAL_DEST_DNS_NAME", ""),
|
ProxyTargetDNSName: defaultEnv("TS_EXPERIMENTAL_DEST_DNS_NAME", ""),
|
||||||
TailnetTargetIP: defaultEnv("TS_TAILNET_TARGET_IP", ""),
|
TailnetTargetIP: defaultEnv("TS_TAILNET_TARGET_IP", ""),
|
||||||
TailnetTargetFQDN: defaultEnv("TS_TAILNET_TARGET_FQDN", ""),
|
TailnetTargetFQDN: defaultEnv("TS_TAILNET_TARGET_FQDN", ""),
|
||||||
DaemonExtraArgs: defaultEnv("TS_TAILSCALED_EXTRA_ARGS", ""),
|
DaemonExtraArgs: defaultEnv("TS_TAILSCALED_EXTRA_ARGS", ""),
|
||||||
ExtraArgs: defaultEnv("TS_EXTRA_ARGS", ""),
|
ExtraArgs: defaultEnv("TS_EXTRA_ARGS", ""),
|
||||||
InKubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "",
|
InKubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "",
|
||||||
UserspaceMode: defaultBool("TS_USERSPACE", true),
|
UserspaceMode: defaultBool("TS_USERSPACE", true),
|
||||||
StateDir: defaultEnv("TS_STATE_DIR", ""),
|
StateDir: defaultEnv("TS_STATE_DIR", ""),
|
||||||
AcceptDNS: defaultEnvBoolPointer("TS_ACCEPT_DNS"),
|
AcceptDNS: defaultEnvBoolPointer("TS_ACCEPT_DNS"),
|
||||||
KubeSecret: func() string {
|
KubeSecret: func() string {
|
||||||
if os.Getenv("KUBERNETES_SERVICE_HOST") != "" {
|
if os.Getenv("KUBERNETES_SERVICE_HOST") != "" {
|
||||||
return defaultEnv("TS_KUBE_SECRET", "tailscale")
|
return defaultEnv("TS_KUBE_SECRET", "tailscale")
|
||||||
|
|||||||
@@ -46,30 +46,30 @@ func TestNoContent(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no challenge",
|
name: "no-challenge",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "valid challenge",
|
name: "valid-challenge",
|
||||||
input: "input",
|
input: "input",
|
||||||
want: "response input",
|
want: "response input",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "valid challenge hostname",
|
name: "valid-challenge-hostname",
|
||||||
input: "ts_derp99b.tailscale.com",
|
input: "ts_derp99b.tailscale.com",
|
||||||
want: "response ts_derp99b.tailscale.com",
|
want: "response ts_derp99b.tailscale.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid challenge",
|
name: "invalid-challenge",
|
||||||
input: "foo\x00bar",
|
input: "foo\x00bar",
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "whitespace invalid challenge",
|
name: "whitespace-invalid-challenge",
|
||||||
input: "foo bar",
|
input: "foo bar",
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "long challenge",
|
name: "long-challenge",
|
||||||
input: strings.Repeat("x", 65),
|
input: strings.Repeat("x", 65),
|
||||||
want: "",
|
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)
|
b, _ := json.Marshal(aclTestErr)
|
||||||
var e ACLGitopsTestError
|
var e ACLGitopsTestError
|
||||||
err := json.Unmarshal(b, &e)
|
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.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)
|
b, _ := json.Marshal(gitopsErr)
|
||||||
var e tailscale.ACLTestError
|
var e tailscale.ACLTestError
|
||||||
err := json.Unmarshal(b, &e)
|
err := json.Unmarshal(b, &e)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func TestNameserver(t *testing.T) {
|
|||||||
wantResp *dns.Msg
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeA}},
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "baz.bar.com", Qtype: dns.TypeA}},
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "foo..bar.com", Qtype: dns.TypeA}},
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeAAAA}},
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "baz.bar.com", Qtype: dns.TypeAAAA}},
|
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")}},
|
ip6: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {net.ParseIP("2001:db8::1")}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeAAAA}},
|
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}}},
|
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")}},
|
ip6: map[dnsname.FQDN][]net.IP{dnsname.FQDN("dual.bar.com."): {net.ParseIP("2001:db8::1")}},
|
||||||
query: &dns.Msg{
|
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}}},
|
ip4: map[dnsname.FQDN][]net.IP{dnsname.FQDN("foo.bar.com."): {{1, 2, 3, 4}}},
|
||||||
query: &dns.Msg{
|
query: &dns.Msg{
|
||||||
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeCNAME}},
|
Question: []dns.Question{{Name: "foo.bar.com", Qtype: dns.TypeCNAME}},
|
||||||
@@ -200,20 +200,20 @@ func TestResetRecords(t *testing.T) {
|
|||||||
wantsErr bool
|
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"]}}`),
|
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}}},
|
wantsIp4: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {{1, 2, 3, 4}}},
|
||||||
wantsIp6: make(map[dnsname.FQDN][]net.IP),
|
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}}},
|
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"]}}`),
|
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}}},
|
wantsIp4: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {{1, 2, 3, 4}}},
|
||||||
wantsIp6: make(map[dnsname.FQDN][]net.IP),
|
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}}},
|
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"]}}`),
|
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}}},
|
wantsIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
|
||||||
@@ -221,26 +221,26 @@ func TestResetRecords(t *testing.T) {
|
|||||||
wantsErr: true,
|
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}}},
|
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
|
||||||
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
||||||
wantsIp6: 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}}},
|
hasIp4: map[dnsname.FQDN][]net.IP{"baz.bar.com.": {{1, 1, 3, 3}}},
|
||||||
config: []byte(`{"version": "v1alpha1", "ip4": {}}`),
|
config: []byte(`{"version": "v1alpha1", "ip4": {}}`),
|
||||||
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
||||||
wantsIp6: 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"]}}`),
|
config: []byte(`{"version": "v1alpha1", "ip6": {"foo.bar.com": ["2001:db8::1"]}}`),
|
||||||
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
wantsIp4: make(map[dnsname.FQDN][]net.IP),
|
||||||
wantsIp6: map[dnsname.FQDN][]net.IP{"foo.bar.com.": {net.ParseIP("2001:db8::1")}},
|
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"]}}`),
|
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}}},
|
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")}},
|
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)
|
nameserverLabels := nameserverResourceLabels(dnsConfig.Name, tsNamespace)
|
||||||
|
|
||||||
wantsDeploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "nameserver", Namespace: tsNamespace}, TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.Identifier()}}
|
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 {
|
if err = yaml.Unmarshal(deployYaml, wantsDeploy); err != nil {
|
||||||
t.Fatalf("unmarshalling yaml: %v", err)
|
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()}}
|
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 {
|
if err = yaml.Unmarshal(svcYaml, wantsSvc); err != nil {
|
||||||
t.Fatalf("unmarshalling yaml: %v", err)
|
t.Fatalf("unmarshalling yaml: %v", err)
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ func TestNameserverReconciler(t *testing.T) {
|
|||||||
expectEqual(t, fc, wantsSvc)
|
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,
|
// Verify that DNSConfig advertizes the nameserver's Service IP address,
|
||||||
// has the ready status condition and tailscale finalizer.
|
// has the ready status condition and tailscale finalizer.
|
||||||
mustUpdate(t, fc, "tailscale", "nameserver", func(svc *corev1.Service) {
|
mustUpdate(t, fc, "tailscale", "nameserver", func(svc *corev1.Service) {
|
||||||
@@ -136,7 +136,7 @@ func TestNameserverReconciler(t *testing.T) {
|
|||||||
expectEqual(t, fc, dnsConfig)
|
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.
|
// Verify that nameserver image gets updated to match DNSConfig spec.
|
||||||
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {
|
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {
|
||||||
dnsCfg.Spec.Nameserver.Image.Tag = "v0.0.2"
|
dnsCfg.Spec.Nameserver.Image.Tag = "v0.0.2"
|
||||||
@@ -146,7 +146,7 @@ func TestNameserverReconciler(t *testing.T) {
|
|||||||
expectEqual(t, fc, wantsDeploy)
|
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
|
// Verify that when another actor sets ConfigMap data, it does not get
|
||||||
// overwritten by nameserver reconciler.
|
// overwritten by nameserver reconciler.
|
||||||
dnsRecords := &operatorutils.Records{Version: "v1alpha1", IP4: map[string][]string{"foo.ts.net": {"1.2.3.4"}}}
|
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)
|
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,
|
// Verify that if dnsconfig.spec.nameserver.image.{repo,tag} are unset,
|
||||||
// the nameserver image defaults to tailscale/k8s-nameserver:unstable.
|
// the nameserver image defaults to tailscale/k8s-nameserver:unstable.
|
||||||
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {
|
mustUpdate(t, fc, "", "test", func(dnsCfg *tsapi.DNSConfig) {
|
||||||
|
|||||||
@@ -1498,24 +1498,28 @@ func TestProxyFirewallMode(t *testing.T) {
|
|||||||
|
|
||||||
func Test_isMagicDNSName(t *testing.T) {
|
func Test_isMagicDNSName(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
in string
|
in string
|
||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "foo-tail4567-ts-net",
|
||||||
in: "foo.tail4567.ts.net",
|
in: "foo.tail4567.ts.net",
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "foo-tail4567-ts-net-trailing-dot",
|
||||||
in: "foo.tail4567.ts.net.",
|
in: "foo.tail4567.ts.net.",
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "foo-tail4567",
|
||||||
in: "foo.tail4567",
|
in: "foo.tail4567",
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
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 {
|
if got := isMagicDNSName(tt.in); got != tt.want {
|
||||||
t.Errorf("isMagicDNSName(%q) = %v, want %v", 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
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "success- custom domain",
|
name: "success-custom-domain",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "department.org.io")},
|
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",
|
want: "department.org.io",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "success- default domain",
|
name: "success-default-domain",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.cluster.local."), toFQDN(t, "svc.cluster.local."), toFQDN(t, "cluster.local.")},
|
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",
|
want: "cluster.local",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only two search domains found",
|
name: "only-two-search-domains",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "svc.department.org.io"), toFQDN(t, "department.org.io")},
|
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",
|
want: "cluster.local",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "first search domain does not match the expected structure",
|
name: "first-search-domain-mismatch",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.bar.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "some.other.fqdn")},
|
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",
|
want: "cluster.local",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second search domain does not match the expected structure",
|
name: "second-search-domain-mismatch",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "foo.department.org.io"), toFQDN(t, "some.other.fqdn")},
|
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",
|
want: "cluster.local",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "third search domain does not match the expected structure",
|
name: "third-search-domain-mismatch",
|
||||||
conf: &resolvconffile.Config{
|
conf: &resolvconffile.Config{
|
||||||
SearchDomains: []dnsname.FQDN{toFQDN(t, "foo.svc.department.org.io"), toFQDN(t, "svc.department.org.io"), toFQDN(t, "some.other.fqdn")},
|
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
|
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"},
|
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"},
|
want: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
|
||||||
managed: tailscaleManagedLabels,
|
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"},
|
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"},
|
want: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
|
||||||
managed: tailscaleManagedLabels,
|
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"},
|
current: map[string]string{kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
|
||||||
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
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"},
|
want: map[string]string{"foo": "bar", "something.io/foo": "bar", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
|
||||||
managed: tailscaleManagedLabels,
|
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"},
|
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"},
|
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"},
|
want: map[string]string{"foo": "bar", "something.io/foo": "bar", "app": "1234", kubetypes.LabelManaged: "true", LabelParentName: "foo", LabelParentType: "svc", LabelParentNamespace: "foo"},
|
||||||
managed: tailscaleManagedLabels,
|
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"},
|
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
||||||
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
||||||
managed: tailscaleManagedLabels,
|
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{},
|
want: map[string]string{},
|
||||||
managed: tailscaleManagedLabels,
|
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"},
|
current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
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"},
|
current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
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"},
|
current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
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"},
|
want: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
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"},
|
current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
custom: map[string]string{"something.io/foo": "bar"},
|
custom: map[string]string{"something.io/foo": "bar"},
|
||||||
want: map[string]string{"something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
|
want: map[string]string{"something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
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"},
|
custom: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
||||||
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
want: map[string]string{"foo": "bar", "something.io/foo": "bar"},
|
||||||
managed: tailscaleManagedAnnotations,
|
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{},
|
want: map[string]string{},
|
||||||
managed: tailscaleManagedAnnotations,
|
managed: tailscaleManagedAnnotations,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRecorderSpecs(t *testing.T) {
|
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{
|
tsr := &tsapi.Recorder{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
|
|||||||
@@ -1533,13 +1533,13 @@ func TestParseNLArgs(t *testing.T) {
|
|||||||
parseDisablements: true,
|
parseDisablements: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "key no votes",
|
name: "key-no-votes",
|
||||||
input: []string{"nlpub:" + strings.Repeat("00", 32)},
|
input: []string{"nlpub:" + strings.Repeat("00", 32)},
|
||||||
parseKeys: true,
|
parseKeys: true,
|
||||||
wantKeys: []tka.Key{{Kind: tka.Key25519, Votes: 1, Public: bytes.Repeat([]byte{0}, 32)}},
|
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"},
|
input: []string{"nlpub:" + strings.Repeat("01", 32) + "?5"},
|
||||||
parseKeys: true,
|
parseKeys: true,
|
||||||
wantKeys: []tka.Key{{Kind: tka.Key25519, Votes: 5, Public: bytes.Repeat([]byte{1}, 32)}},
|
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)},
|
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)},
|
input: []string{"disablement:" + strings.Repeat("02", 32)},
|
||||||
parseKeys: true,
|
parseKeys: true,
|
||||||
wantErr: fmt.Errorf("parsing key 1: key hex string doesn't have expected type prefix tlpub:"),
|
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)},
|
input: []string{"nlpub:" + strings.Repeat("02", 32)},
|
||||||
parseDisablements: true,
|
parseDisablements: true,
|
||||||
wantErr: fmt.Errorf("parsing argument 1: expected value with \"disablement:\" or \"disablement-secret:\" prefix, got %q", "nlpub:0202020202020202020202020202020202020202020202020202020202020202"),
|
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`,
|
token: unused`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all configs, clusters, users have been deleted",
|
name: "all-configs-clusters-users-deleted",
|
||||||
in: `apiVersion: v1
|
in: `apiVersion: v1
|
||||||
clusters: null
|
clusters: null
|
||||||
contexts: null
|
contexts: null
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func Test_listCerts(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "normal response",
|
name: "normal-response",
|
||||||
caller: fakeAPICaller{
|
caller: fakeAPICaller{
|
||||||
Data: json.RawMessage(`{
|
Data: json.RawMessage(`{
|
||||||
"certificates" : [
|
"certificates" : [
|
||||||
@@ -117,12 +117,12 @@ func Test_listCerts(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "call error",
|
name: "call-error",
|
||||||
caller: fakeAPICaller{nil, fmt.Errorf("caller failed")},
|
caller: fakeAPICaller{nil, fmt.Errorf("caller failed")},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "payload decode error",
|
name: "payload-decode-error",
|
||||||
caller: fakeAPICaller{json.RawMessage("This isn't JSON!"), nil},
|
caller: fakeAPICaller{json.RawMessage("This isn't JSON!"), nil},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestFilterFormatAndSortExitNodes(t *testing.T) {
|
func TestFilterFormatAndSortExitNodes(t *testing.T) {
|
||||||
t.Run("without filter", func(t *testing.T) {
|
t.Run("without-filter", func(t *testing.T) {
|
||||||
ps := []*ipnstate.PeerStatus{
|
ps := []*ipnstate.PeerStatus{
|
||||||
{
|
{
|
||||||
HostName: "everest-1",
|
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{
|
ps := []*ipnstate.PeerStatus{
|
||||||
{
|
{
|
||||||
HostName: "baker-1",
|
HostName: "baker-1",
|
||||||
|
|||||||
@@ -1056,49 +1056,49 @@ func TestSrcTypeFromFlags(t *testing.T) {
|
|||||||
expectedErr bool
|
expectedErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "only http set",
|
name: "only-http-set",
|
||||||
env: &serveEnv{http: 80},
|
env: &serveEnv{http: 80},
|
||||||
expectedType: serveTypeHTTP,
|
expectedType: serveTypeHTTP,
|
||||||
expectedPort: 80,
|
expectedPort: 80,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only https set",
|
name: "only-https-set",
|
||||||
env: &serveEnv{https: 10000},
|
env: &serveEnv{https: 10000},
|
||||||
expectedType: serveTypeHTTPS,
|
expectedType: serveTypeHTTPS,
|
||||||
expectedPort: 10000,
|
expectedPort: 10000,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only tcp set",
|
name: "only-tcp-set",
|
||||||
env: &serveEnv{tcp: 8000},
|
env: &serveEnv{tcp: 8000},
|
||||||
expectedType: serveTypeTCP,
|
expectedType: serveTypeTCP,
|
||||||
expectedPort: 8000,
|
expectedPort: 8000,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only tls-terminated-tcp set",
|
name: "only-tls-terminated-tcp-set",
|
||||||
env: &serveEnv{tlsTerminatedTCP: 8080},
|
env: &serveEnv{tlsTerminatedTCP: 8080},
|
||||||
expectedType: serveTypeTLSTerminatedTCP,
|
expectedType: serveTypeTLSTerminatedTCP,
|
||||||
expectedPort: 8080,
|
expectedPort: 8080,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "defaults to https, port 443",
|
name: "defaults-to-https-443",
|
||||||
env: &serveEnv{},
|
env: &serveEnv{},
|
||||||
expectedType: serveTypeHTTPS,
|
expectedType: serveTypeHTTPS,
|
||||||
expectedPort: 443,
|
expectedPort: 443,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "defaults to https, port 443 for service",
|
name: "defaults-to-https-443-for-service",
|
||||||
env: &serveEnv{service: "svc:foo"},
|
env: &serveEnv{service: "svc:foo"},
|
||||||
expectedType: serveTypeHTTPS,
|
expectedType: serveTypeHTTPS,
|
||||||
expectedPort: 443,
|
expectedPort: 443,
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple types set",
|
name: "multiple-types-set",
|
||||||
env: &serveEnv{http: 80, https: 443},
|
env: &serveEnv{http: 80, https: 443},
|
||||||
expectedPort: 0,
|
expectedPort: 0,
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
@@ -1235,19 +1235,20 @@ func TestAcceptSetAppCapsFlag(t *testing.T) {
|
|||||||
|
|
||||||
func TestCleanURLPath(t *testing.T) {
|
func TestCleanURLPath(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
input string
|
input string
|
||||||
expected string
|
expected string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{input: "", expected: "/"},
|
{name: "empty", input: "", expected: "/"},
|
||||||
{input: "/", expected: "/"},
|
{name: "slash", input: "/", expected: "/"},
|
||||||
{input: "/foo", expected: "/foo"},
|
{name: "foo", input: "/foo", expected: "/foo"},
|
||||||
{input: "/foo/", expected: "/foo/"},
|
{name: "foo-trailing-slash", input: "/foo/", expected: "/foo/"},
|
||||||
{input: "/../bar", wantErr: true},
|
{name: "dotdot-bar", input: "/../bar", wantErr: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
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)
|
actual, err := cleanURLPath(tt.input)
|
||||||
|
|
||||||
if tt.wantErr == true && err == nil {
|
if tt.wantErr == true && err == nil {
|
||||||
@@ -1275,18 +1276,18 @@ func TestAddServiceToPrefs(t *testing.T) {
|
|||||||
expected []string
|
expected []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "add service to empty prefs",
|
name: "add-service-to-empty-prefs",
|
||||||
svcName: "svc:foo",
|
svcName: "svc:foo",
|
||||||
expected: []string{"svc:foo"},
|
expected: []string{"svc:foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "add service to existing prefs",
|
name: "add-service-to-existing-prefs",
|
||||||
svcName: "svc:bar",
|
svcName: "svc:bar",
|
||||||
startServices: []string{"svc:foo"},
|
startServices: []string{"svc:foo"},
|
||||||
expected: []string{"svc:foo", "svc:bar"},
|
expected: []string{"svc:foo", "svc:bar"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "add existing service to prefs",
|
name: "add-existing-service-to-prefs",
|
||||||
svcName: "svc:foo",
|
svcName: "svc:foo",
|
||||||
startServices: []string{"svc:foo"},
|
startServices: []string{"svc:foo"},
|
||||||
expected: []string{"svc:foo"},
|
expected: []string{"svc:foo"},
|
||||||
@@ -1323,18 +1324,18 @@ func TestRemoveServiceFromPrefs(t *testing.T) {
|
|||||||
expected []string
|
expected []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "remove service from empty prefs",
|
name: "remove-service-from-empty-prefs",
|
||||||
svcName: "svc:foo",
|
svcName: "svc:foo",
|
||||||
expected: []string{},
|
expected: []string{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "remove existing service from prefs",
|
name: "remove-existing-service-from-prefs",
|
||||||
svcName: "svc:foo",
|
svcName: "svc:foo",
|
||||||
startServices: []string{"svc:foo"},
|
startServices: []string{"svc:foo"},
|
||||||
expected: []string{},
|
expected: []string{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "remove service not in prefs",
|
name: "remove-service-not-in-prefs",
|
||||||
svcName: "svc:bar",
|
svcName: "svc:bar",
|
||||||
startServices: []string{"svc:foo"},
|
startServices: []string{"svc:foo"},
|
||||||
expected: []string{"svc:foo"},
|
expected: []string{"svc:foo"},
|
||||||
@@ -1446,7 +1447,7 @@ func TestMessageForPort(t *testing.T) {
|
|||||||
}, "\n"),
|
}, "\n"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve service http",
|
name: "serve-service-http",
|
||||||
subcmd: serve,
|
subcmd: serve,
|
||||||
serveConfig: &ipn.ServeConfig{
|
serveConfig: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1490,7 +1491,7 @@ func TestMessageForPort(t *testing.T) {
|
|||||||
}, "\n"),
|
}, "\n"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve service no capmap",
|
name: "serve-service-no-capmap",
|
||||||
subcmd: serve,
|
subcmd: serve,
|
||||||
serveConfig: &ipn.ServeConfig{
|
serveConfig: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1534,7 +1535,7 @@ func TestMessageForPort(t *testing.T) {
|
|||||||
}, "\n"),
|
}, "\n"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve service https non-default port",
|
name: "serve-service-https-non-default-port",
|
||||||
subcmd: serve,
|
subcmd: serve,
|
||||||
serveConfig: &ipn.ServeConfig{
|
serveConfig: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1576,7 +1577,7 @@ func TestMessageForPort(t *testing.T) {
|
|||||||
}, "\n"),
|
}, "\n"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve service TCPForward",
|
name: "serve-service-TCPForward",
|
||||||
subcmd: serve,
|
subcmd: serve,
|
||||||
serveConfig: &ipn.ServeConfig{
|
serveConfig: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1613,7 +1614,7 @@ func TestMessageForPort(t *testing.T) {
|
|||||||
}, "\n"),
|
}, "\n"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve service Tun",
|
name: "serve-service-Tun",
|
||||||
subcmd: serve,
|
subcmd: serve,
|
||||||
serveConfig: &ipn.ServeConfig{
|
serveConfig: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1790,7 +1791,7 @@ func TestSetServe(t *testing.T) {
|
|||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "add new handler",
|
name: "add-new-handler",
|
||||||
desc: "add a new http handler to empty config",
|
desc: "add a new http handler to empty config",
|
||||||
cfg: &ipn.ServeConfig{},
|
cfg: &ipn.ServeConfig{},
|
||||||
dnsName: "foo.test.ts.net",
|
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",
|
desc: "update an existing http handler on the same port to same type",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}},
|
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",
|
desc: "update an existing TCP handler on the same port to a http handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{80: {TCPForward: "http://localhost:3000"}},
|
TCP: map[uint16]*ipn.TCPPortHandler{80: {TCPForward: "http://localhost:3000"}},
|
||||||
@@ -1852,7 +1853,7 @@ func TestSetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "add new service handler",
|
name: "add-new-service-handler",
|
||||||
desc: "add a new service TCP handler to empty config",
|
desc: "add a new service TCP handler to empty config",
|
||||||
cfg: &ipn.ServeConfig{},
|
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",
|
desc: "update an existing service TCP handler on the same port to same type",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
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",
|
desc: "update an existing service TCP handler on the same port to a http handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1908,7 +1909,7 @@ func TestSetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "add new service handler",
|
name: "add-new-service-handler",
|
||||||
desc: "add a new service HTTP handler to empty config",
|
desc: "add a new service HTTP handler to empty config",
|
||||||
cfg: &ipn.ServeConfig{},
|
cfg: &ipn.ServeConfig{},
|
||||||
dnsName: "svc:bar",
|
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",
|
desc: "update an existing service HTTP handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
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",
|
desc: "add a new service HTTP handler to existing service config",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
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",
|
desc: "add a new service mount to existing service config",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
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",
|
desc: "add a new service handler in tun mode to empty config",
|
||||||
cfg: &ipn.ServeConfig{},
|
cfg: &ipn.ServeConfig{},
|
||||||
dnsName: "svc:bar",
|
dnsName: "svc:bar",
|
||||||
@@ -2103,7 +2104,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "unset http handler",
|
name: "unset-http-handler",
|
||||||
desc: "remove an existing http handler",
|
desc: "remove an existing http handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -2128,7 +2129,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset service handler",
|
name: "unset-service-handler",
|
||||||
desc: "remove an existing service TCP handler",
|
desc: "remove an existing service TCP handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -2157,7 +2158,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset service handler tun",
|
name: "unset-service-handler-tun",
|
||||||
desc: "remove an existing service handler in tun mode",
|
desc: "remove an existing service handler in tun mode",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -2175,7 +2176,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset service handler tcp",
|
name: "unset-service-handler-tcp",
|
||||||
desc: "remove an existing service TCP handler",
|
desc: "remove an existing service TCP handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -2196,7 +2197,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset http handler not found",
|
name: "unset-http-handler-not-found",
|
||||||
desc: "try to remove a non-existing http handler",
|
desc: "try to remove a non-existing http handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -2221,7 +2222,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset service handler not found",
|
name: "unset-service-handler-not-found",
|
||||||
desc: "try to remove a non-existing service TCP handler",
|
desc: "try to remove a non-existing service TCP handler",
|
||||||
|
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
@@ -2253,7 +2254,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset service doesn't exist",
|
name: "unset-service-doesnt-exist",
|
||||||
desc: "try to remove a non-existing service's handler",
|
desc: "try to remove a non-existing service's handler",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -2273,7 +2274,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
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",
|
desc: "try to remove a TCP handler while the port is used for web",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -2297,7 +2298,7 @@ func TestUnsetServe(t *testing.T) {
|
|||||||
expectErr: true,
|
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",
|
desc: "try to remove a service TCP handler while the port is used for web",
|
||||||
cfg: &ipn.ServeConfig{
|
cfg: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func TestStateStoreError(t *testing.T) {
|
|||||||
args.statedir = t.TempDir()
|
args.statedir = t.TempDir()
|
||||||
args.tunname = "userspace-networking"
|
args.tunname = "userspace-networking"
|
||||||
|
|
||||||
t.Run("new state", func(t *testing.T) {
|
t.Run("new-state", func(t *testing.T) {
|
||||||
sys := tsd.NewSystem()
|
sys := tsd.NewSystem()
|
||||||
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
|
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
|
||||||
lb, err := getLocalBackend(t.Context(), t.Logf, logID.Public(), sys)
|
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.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 := tsd.NewSystem()
|
||||||
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
|
sys.NetMon.Set(must.Get(netmon.New(sys.Bus.Get(), t.Logf)))
|
||||||
// Populate the state file with something that will fail to parse to
|
// Populate the state file with something that will fail to parse to
|
||||||
|
|||||||
+65
-58
@@ -137,14 +137,14 @@ func TestFlattenExtraClaims(t *testing.T) {
|
|||||||
expected map[string]any
|
expected map[string]any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty extra claims",
|
name: "empty-extra-claims",
|
||||||
input: []capRule{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{}},
|
{ExtraClaims: map[string]any{}},
|
||||||
},
|
},
|
||||||
expected: map[string]any{},
|
expected: map[string]any{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "string and number values",
|
name: "string-and-number-values",
|
||||||
input: []capRule{
|
input: []capRule{
|
||||||
{
|
{
|
||||||
ExtraClaims: map[string]any{
|
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{
|
input: []capRule{
|
||||||
{
|
{
|
||||||
ExtraClaims: map[string]any{
|
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{
|
input: []capRule{
|
||||||
{
|
{
|
||||||
ExtraClaims: map[string]any{
|
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{
|
input: []capRule{
|
||||||
{
|
{
|
||||||
ExtraClaims: map[string]any{
|
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{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{"foo": "bar"}},
|
{ExtraClaims: map[string]any{"foo": "bar"}},
|
||||||
{ExtraClaims: map[string]any{"foo": []any{"baz"}}},
|
{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{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{"foo": "bar"}},
|
{ExtraClaims: map[string]any{"foo": "bar"}},
|
||||||
{ExtraClaims: map[string]any{"foo": map[string]any{"bad": "entry"}}},
|
{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{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{"roles": []any{"admin", "user"}}},
|
{ExtraClaims: map[string]any{"roles": []any{"admin", "user"}}},
|
||||||
{ExtraClaims: map[string]any{"roles": []any{"admin", "guest"}}},
|
{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{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{
|
{ExtraClaims: map[string]any{
|
||||||
"mixed": []any{"ok", 42, map[string]string{"oops": "fail"}},
|
"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{
|
input: []capRule{
|
||||||
{ExtraClaims: map[string]any{"env": "prod"}},
|
{ExtraClaims: map[string]any{"env": "prod"}},
|
||||||
{ExtraClaims: map[string]any{"env": "prod"}},
|
{ExtraClaims: map[string]any{"env": "prod"}},
|
||||||
@@ -279,7 +281,7 @@ func TestExtraClaims(t *testing.T) {
|
|||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "extra claim",
|
name: "extra-claim",
|
||||||
claim: tailscaleClaims{
|
claim: tailscaleClaims{
|
||||||
Claims: jwt.Claims{},
|
Claims: jwt.Claims{},
|
||||||
Nonce: "foobar",
|
Nonce: "foobar",
|
||||||
@@ -312,7 +314,7 @@ func TestExtraClaims(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "duplicate claim distinct values",
|
name: "duplicate-claim-distinct-values",
|
||||||
claim: tailscaleClaims{
|
claim: tailscaleClaims{
|
||||||
Claims: jwt.Claims{},
|
Claims: jwt.Claims{},
|
||||||
Nonce: "foobar",
|
Nonce: "foobar",
|
||||||
@@ -350,7 +352,7 @@ func TestExtraClaims(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple extra claims",
|
name: "multiple-extra-claims",
|
||||||
claim: tailscaleClaims{
|
claim: tailscaleClaims{
|
||||||
Claims: jwt.Claims{},
|
Claims: jwt.Claims{},
|
||||||
Nonce: "foobar",
|
Nonce: "foobar",
|
||||||
@@ -389,7 +391,7 @@ func TestExtraClaims(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "overwrite claim",
|
name: "overwrite-claim",
|
||||||
claim: tailscaleClaims{
|
claim: tailscaleClaims{
|
||||||
Claims: jwt.Claims{},
|
Claims: jwt.Claims{},
|
||||||
Nonce: "foobar",
|
Nonce: "foobar",
|
||||||
@@ -422,7 +424,7 @@ func TestExtraClaims(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty extra claims",
|
name: "empty-extra-claims",
|
||||||
claim: tailscaleClaims{
|
claim: tailscaleClaims{
|
||||||
Claims: jwt.Claims{},
|
Claims: jwt.Claims{},
|
||||||
Nonce: "foobar",
|
Nonce: "foobar",
|
||||||
@@ -496,21 +498,21 @@ func TestServeToken(t *testing.T) {
|
|||||||
expected map[string]any
|
expected map[string]any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "GET not allowed",
|
name: "GET-not-allowed",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unsupported grant type",
|
name: "unsupported-grant-type",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "pkcs",
|
grantType: "pkcs",
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid code",
|
name: "invalid-code",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
code: "invalid-code",
|
code: "invalid-code",
|
||||||
@@ -518,7 +520,7 @@ func TestServeToken(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "omit code from form",
|
name: "omit-code-from-form",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
omitCode: true,
|
omitCode: true,
|
||||||
@@ -526,7 +528,7 @@ func TestServeToken(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid redirect uri",
|
name: "invalid-redirect-uri",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
code: "valid-code",
|
code: "valid-code",
|
||||||
@@ -536,7 +538,7 @@ func TestServeToken(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid remoteAddr",
|
name: "invalid-remoteAddr",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
redirectURI: "https://rp.example.com/callback",
|
||||||
@@ -546,7 +548,7 @@ func TestServeToken(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "extra claim included (non-strict)",
|
name: "extra-claim-included-non-strict",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
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",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
redirectURI: "https://rp.example.com/callback",
|
||||||
@@ -708,7 +711,7 @@ func TestExtraUserInfo(t *testing.T) {
|
|||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "extra claim",
|
name: "extra-claim",
|
||||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
caps: tailcfg.PeerCapMap{
|
caps: tailcfg.PeerCapMap{
|
||||||
tailcfg.PeerCapabilityTsIDP: {
|
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),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
caps: tailcfg.PeerCapMap{
|
caps: tailcfg.PeerCapMap{
|
||||||
tailcfg.PeerCapabilityTsIDP: {
|
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),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
caps: tailcfg.PeerCapMap{
|
caps: tailcfg.PeerCapMap{
|
||||||
tailcfg.PeerCapabilityTsIDP: {
|
tailcfg.PeerCapabilityTsIDP: {
|
||||||
@@ -761,13 +764,13 @@ func TestExtraUserInfo(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty extra claims",
|
name: "empty-extra-claims",
|
||||||
caps: tailcfg.PeerCapMap{},
|
caps: tailcfg.PeerCapMap{},
|
||||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
expected: map[string]any{},
|
expected: map[string]any{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "attempt to overwrite protected claim",
|
name: "overwrite-protected-claim",
|
||||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
caps: tailcfg.PeerCapMap{
|
caps: tailcfg.PeerCapMap{
|
||||||
tailcfg.PeerCapabilityTsIDP: {
|
tailcfg.PeerCapabilityTsIDP: {
|
||||||
@@ -783,7 +786,7 @@ func TestExtraUserInfo(t *testing.T) {
|
|||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "extra claim omitted",
|
name: "extra-claim-omitted",
|
||||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||||
caps: tailcfg.PeerCapMap{
|
caps: tailcfg.PeerCapMap{
|
||||||
tailcfg.PeerCapabilityTsIDP: {
|
tailcfg.PeerCapabilityTsIDP: {
|
||||||
@@ -798,7 +801,7 @@ func TestExtraUserInfo(t *testing.T) {
|
|||||||
expected: map[string]any{},
|
expected: map[string]any{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expired token",
|
name: "expired-token",
|
||||||
caps: tailcfg.PeerCapMap{},
|
caps: tailcfg.PeerCapMap{},
|
||||||
tokenValidTill: time.Now().Add(-1 * time.Minute),
|
tokenValidTill: time.Now().Add(-1 * time.Minute),
|
||||||
expected: map[string]any{},
|
expected: map[string]any{},
|
||||||
@@ -1131,19 +1134,22 @@ func TestGetAllowInsecureRegistration(t *testing.T) {
|
|||||||
expectAllowInsecureRegistration bool
|
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,
|
flagSet: true,
|
||||||
flagValue: false,
|
flagValue: false,
|
||||||
expectAllowInsecureRegistration: 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,
|
flagSet: true,
|
||||||
flagValue: true,
|
flagValue: true,
|
||||||
expectAllowInsecureRegistration: 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,
|
flagSet: false,
|
||||||
flagValue: false, // not used when unset
|
flagValue: false, // not used when unset
|
||||||
expectAllowInsecureRegistration: true,
|
expectAllowInsecureRegistration: true,
|
||||||
@@ -1192,7 +1198,7 @@ func TestMigrateOAuthClients(t *testing.T) {
|
|||||||
expectOldRenamed bool
|
expectOldRenamed bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "migrate from old file to new file",
|
name: "migrate-old-to-new",
|
||||||
setupOldFile: true,
|
setupOldFile: true,
|
||||||
oldFileContent: map[string]*funnelClient{
|
oldFileContent: map[string]*funnelClient{
|
||||||
"old-client": {
|
"old-client": {
|
||||||
@@ -1206,7 +1212,7 @@ func TestMigrateOAuthClients(t *testing.T) {
|
|||||||
expectOldRenamed: true,
|
expectOldRenamed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new file already exists - no migration",
|
name: "new-file-exists-no-migration",
|
||||||
setupNewFile: true,
|
setupNewFile: true,
|
||||||
newFileContent: map[string]*funnelClient{
|
newFileContent: map[string]*funnelClient{
|
||||||
"existing-client": {
|
"existing-client": {
|
||||||
@@ -1220,12 +1226,12 @@ func TestMigrateOAuthClients(t *testing.T) {
|
|||||||
expectOldRenamed: false,
|
expectOldRenamed: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "neither file exists - create empty new file",
|
name: "neither-exists-create-empty",
|
||||||
expectNewFileExists: true,
|
expectNewFileExists: true,
|
||||||
expectOldRenamed: false,
|
expectOldRenamed: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "both files exist - prefer new file",
|
name: "both-exist-prefer-new",
|
||||||
setupOldFile: true,
|
setupOldFile: true,
|
||||||
setupNewFile: true,
|
setupNewFile: true,
|
||||||
oldFileContent: map[string]*funnelClient{
|
oldFileContent: map[string]*funnelClient{
|
||||||
@@ -1373,19 +1379,19 @@ func TestGetConfigFilePath(t *testing.T) {
|
|||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "file exists in current directory - use current directory",
|
name: "file-in-cwd-use-cwd",
|
||||||
fileName: "test-config.json",
|
fileName: "test-config.json",
|
||||||
createInCwd: true,
|
createInCwd: true,
|
||||||
expectInCwd: true,
|
expectInCwd: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "file does not exist - use root path",
|
name: "file-missing-use-root",
|
||||||
fileName: "test-config.json",
|
fileName: "test-config.json",
|
||||||
createInCwd: false,
|
createInCwd: false,
|
||||||
expectInCwd: false,
|
expectInCwd: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "file exists in both - prefer current directory",
|
name: "file-in-both-prefer-cwd",
|
||||||
fileName: "test-config.json",
|
fileName: "test-config.json",
|
||||||
createInCwd: true,
|
createInCwd: true,
|
||||||
createInRoot: true,
|
createInRoot: true,
|
||||||
@@ -1472,7 +1478,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
// Security boundary test: funnel rejection
|
// Security boundary test: funnel rejection
|
||||||
{
|
{
|
||||||
name: "funnel requests are always rejected for security",
|
name: "funnel-rejected",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
clientID: "test-client",
|
clientID: "test-client",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
redirectURI: "https://rp.example.com/callback",
|
||||||
@@ -1487,7 +1493,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
|||||||
|
|
||||||
// Strict mode parameter validation tests (non-funnel)
|
// Strict mode parameter validation tests (non-funnel)
|
||||||
{
|
{
|
||||||
name: "strict mode - missing client_id",
|
name: "strict-missing-client_id",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
clientID: "",
|
clientID: "",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
redirectURI: "https://rp.example.com/callback",
|
||||||
@@ -1496,7 +1502,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - missing redirect_uri",
|
name: "strict-missing-redirect_uri",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
clientID: "test-client",
|
clientID: "test-client",
|
||||||
redirectURI: "",
|
redirectURI: "",
|
||||||
@@ -1507,7 +1513,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
|||||||
|
|
||||||
// Strict mode client validation tests (non-funnel)
|
// Strict mode client validation tests (non-funnel)
|
||||||
{
|
{
|
||||||
name: "strict mode - invalid client_id",
|
name: "strict-invalid-client_id",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
clientID: "invalid-client",
|
clientID: "invalid-client",
|
||||||
redirectURI: "https://rp.example.com/callback",
|
redirectURI: "https://rp.example.com/callback",
|
||||||
@@ -1517,7 +1523,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - redirect_uri mismatch",
|
name: "strict-redirect_uri-mismatch",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
clientID: "test-client",
|
clientID: "test-client",
|
||||||
redirectURI: "https://wrong.example.com/callback",
|
redirectURI: "https://wrong.example.com/callback",
|
||||||
@@ -1666,7 +1672,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectIDToken bool
|
expectIDToken bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "strict mode - valid token exchange with form credentials",
|
name: "strict-token-exchange-form-creds",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1680,7 +1686,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectIDToken: true,
|
expectIDToken: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - valid token exchange with basic auth",
|
name: "strict-token-exchange-basic-auth",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1695,7 +1701,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectIDToken: true,
|
expectIDToken: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - missing client credentials",
|
name: "strict-missing-client-creds",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1708,7 +1714,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusUnauthorized,
|
expectCode: http.StatusUnauthorized,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - client_id mismatch",
|
name: "strict-client_id-mismatch",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1722,7 +1728,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - invalid client secret",
|
name: "strict-invalid-client-secret",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1737,7 +1743,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusUnauthorized,
|
expectCode: http.StatusUnauthorized,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - redirect_uri mismatch",
|
name: "strict-redirect_uri-mismatch",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1752,7 +1758,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-strict mode - no client validation required",
|
name: "non-strict-no-client-validation",
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
grantType: "authorization_code",
|
grantType: "authorization_code",
|
||||||
@@ -1913,7 +1919,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectUserInfo bool
|
expectUserInfo bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "strict mode - valid token with existing client",
|
name: "strict-valid-token-existing-client",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
setupToken: true,
|
setupToken: true,
|
||||||
setupClient: true,
|
setupClient: true,
|
||||||
@@ -1923,7 +1929,8 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectUserInfo: true,
|
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,
|
strictMode: true,
|
||||||
setupToken: true,
|
setupToken: true,
|
||||||
setupClient: false,
|
setupClient: false,
|
||||||
@@ -1934,7 +1941,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusUnauthorized,
|
expectCode: http.StatusUnauthorized,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - expired token",
|
name: "strict-expired-token",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
setupToken: true,
|
setupToken: true,
|
||||||
setupClient: true,
|
setupClient: true,
|
||||||
@@ -1945,7 +1952,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - invalid token",
|
name: "strict-invalid-token",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
setupToken: false,
|
setupToken: false,
|
||||||
token: "invalid-token",
|
token: "invalid-token",
|
||||||
@@ -1953,7 +1960,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strict mode - token without client association",
|
name: "strict-token-no-client-assoc",
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
setupToken: true,
|
setupToken: true,
|
||||||
setupClient: false,
|
setupClient: false,
|
||||||
@@ -1964,7 +1971,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
|||||||
expectCode: http.StatusBadRequest,
|
expectCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-strict mode - no client validation required",
|
name: "non-strict-no-client-validation",
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
setupToken: true,
|
setupToken: true,
|
||||||
setupClient: false,
|
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) {})
|
||||||
|
}
|
||||||
+2
-1
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/tools/go/analysis/unitchecker"
|
"golang.org/x/tools/go/analysis/unitchecker"
|
||||||
"tailscale.com/cmd/vet/jsontags"
|
"tailscale.com/cmd/vet/jsontags"
|
||||||
|
"tailscale.com/cmd/vet/subtestnames"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed jsontags_allowlist
|
//go:embed jsontags_allowlist
|
||||||
@@ -20,5 +21,5 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
unitchecker.Main(jsontags.Analyzer)
|
unitchecker.Main(jsontags.Analyzer, subtestnames.Analyzer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -801,7 +801,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
|
|||||||
expectNewDisco bool
|
expectNewDisco bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "disco key wired through when newer lastSeen",
|
name: "disco-key-newer-lastSeen",
|
||||||
initialOnline: false,
|
initialOnline: false,
|
||||||
initialLastSeen: oldTime,
|
initialLastSeen: oldTime,
|
||||||
updateOnline: false,
|
updateOnline: false,
|
||||||
@@ -809,7 +809,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
|
|||||||
expectNewDisco: true,
|
expectNewDisco: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "disco key NOT wired through when older lastSeen",
|
name: "disco-key-older-lastSeen",
|
||||||
initialOnline: false,
|
initialOnline: false,
|
||||||
initialLastSeen: now,
|
initialLastSeen: now,
|
||||||
updateOnline: false,
|
updateOnline: false,
|
||||||
@@ -817,7 +817,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
|
|||||||
expectNewDisco: false,
|
expectNewDisco: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "disco key wired through when newer lastSeen, going offline",
|
name: "disco-key-newer-lastSeen-going-offline",
|
||||||
initialOnline: true,
|
initialOnline: true,
|
||||||
initialLastSeen: oldTime,
|
initialLastSeen: oldTime,
|
||||||
updateOnline: false,
|
updateOnline: false,
|
||||||
@@ -825,7 +825,7 @@ func TestUpdateDiscoForNodeCallbackWithFullNetmap(t *testing.T) {
|
|||||||
expectNewDisco: true,
|
expectNewDisco: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "online flip with newer lastSeen",
|
name: "online-flip-newer-lastSeen",
|
||||||
initialOnline: false,
|
initialOnline: false,
|
||||||
initialLastSeen: oldTime,
|
initialLastSeen: oldTime,
|
||||||
updateOnline: true,
|
updateOnline: true,
|
||||||
|
|||||||
+2
-2
@@ -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, "bob")
|
||||||
drain(t, "cathy")
|
drain(t, "cathy")
|
||||||
isEmpty(t, "alice")
|
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,
|
// Block cathy. Now the cathyConn buffer will fill up quickly,
|
||||||
// and the derp server will back up.
|
// and the derp server will back up.
|
||||||
cathyConn.SetReadBlock(true)
|
cathyConn.SetReadBlock(true)
|
||||||
|
|||||||
+28
-28
@@ -447,7 +447,7 @@ func TestXDP(t *testing.T) {
|
|||||||
wantMetrics map[bpfCountersKey]uint64
|
wantMetrics map[bpfCountersKey]uint64
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ipv4 STUN Binding Request Drop STUN",
|
name: "ipv4-STUN-Binding-Request-Drop-STUN",
|
||||||
dropSTUN: true,
|
dropSTUN: true,
|
||||||
packetIn: ipv4STUNBindingReqTX,
|
packetIn: ipv4STUNBindingReqTX,
|
||||||
wantCode: xdpActionDrop,
|
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,
|
dropSTUN: true,
|
||||||
packetIn: ipv6STUNBindingReqTX,
|
packetIn: ipv6STUNBindingReqTX,
|
||||||
wantCode: xdpActionDrop,
|
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,
|
packetIn: ipv4STUNBindingReqTX,
|
||||||
wantCode: xdpActionTX,
|
wantCode: xdpActionTX,
|
||||||
wantPacketOut: getIPv4STUNBindingResp(),
|
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,
|
packetIn: ipv6STUNBindingReqTX,
|
||||||
wantCode: xdpActionTX,
|
wantCode: xdpActionTX,
|
||||||
wantPacketOut: getIPv6STUNBindingResp(),
|
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,
|
packetIn: ipv4STUNBindingReqIPCsumPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqIPCsumPass,
|
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,
|
packetIn: ipv4STUNBindingReqIHLPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqIHLPass,
|
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,
|
packetIn: ipv4STUNBindingReqIPVerPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqIPVerPass,
|
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,
|
packetIn: ipv4STUNBindingReqIPProtoPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqIPProtoPass,
|
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,
|
packetIn: ipv4STUNBindingReqFragOffsetPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqFragOffsetPass,
|
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,
|
packetIn: ipv4STUNBindingReqFlagsMFPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqFlagsMFPass,
|
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,
|
packetIn: ipv4STUNBindingReqTotLenPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqTotLenPass,
|
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,
|
packetIn: ipv6STUNBindingReqIPVerPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqIPVerPass,
|
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,
|
packetIn: ipv6STUNBindingReqNextHdrPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqNextHdrPass,
|
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,
|
packetIn: ipv6STUNBindingReqPayloadLenPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqPayloadLenPass,
|
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,
|
packetIn: ipv4STUNBindingReqUDPCsumPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqUDPCsumPass,
|
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,
|
packetIn: ipv6STUNBindingReqUDPCsumPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqUDPCsumPass,
|
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,
|
packetIn: ipv4STUNBindingReqSTUNTypePass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqSTUNTypePass,
|
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,
|
packetIn: ipv6STUNBindingReqSTUNTypePass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqSTUNTypePass,
|
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,
|
packetIn: ipv4STUNBindingReqSTUNMagicPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqSTUNMagicPass,
|
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,
|
packetIn: ipv6STUNBindingReqSTUNMagicPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqSTUNMagicPass,
|
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,
|
packetIn: ipv4STUNBindingReqSTUNAttrsLenPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqSTUNAttrsLenPass,
|
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,
|
packetIn: ipv6STUNBindingReqSTUNAttrsLenPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqSTUNAttrsLenPass,
|
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,
|
packetIn: ipv4STUNBindingReqSTUNSWValPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqSTUNSWValPass,
|
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,
|
packetIn: ipv6STUNBindingReqSTUNSWValPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqSTUNSWValPass,
|
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,
|
packetIn: ipv4STUNBindingReqSTUNFirstAttrPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv4STUNBindingReqSTUNFirstAttrPass,
|
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,
|
packetIn: ipv6STUNBindingReqSTUNFirstAttrPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqSTUNFirstAttrPass,
|
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,
|
packetIn: ipv4STUNBindingReqUDPZeroCsumTx,
|
||||||
wantCode: xdpActionTX,
|
wantCode: xdpActionTX,
|
||||||
wantPacketOut: getIPv4STUNBindingResp(),
|
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,
|
packetIn: ipv6STUNBindingReqUDPZeroCsumPass,
|
||||||
wantCode: xdpActionPass,
|
wantCode: xdpActionPass,
|
||||||
wantPacketOut: ipv6STUNBindingReqUDPZeroCsumPass,
|
wantPacketOut: ipv6STUNBindingReqUDPZeroCsumPass,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func TestStat(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
label: "root folder",
|
label: "root-folder",
|
||||||
name: "",
|
name: "",
|
||||||
expected: &shared.StaticFileInfo{
|
expected: &shared.StaticFileInfo{
|
||||||
Named: "",
|
Named: "",
|
||||||
@@ -40,7 +40,7 @@ func TestStat(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "static root folder",
|
label: "static-root-folder",
|
||||||
name: "/domain",
|
name: "/domain",
|
||||||
expected: &shared.StaticFileInfo{
|
expected: &shared.StaticFileInfo{
|
||||||
Named: "domain",
|
Named: "domain",
|
||||||
@@ -73,7 +73,7 @@ func TestStat(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "non-existent remote",
|
label: "non-existent-remote",
|
||||||
name: "remote3",
|
name: "remote3",
|
||||||
err: os.ErrNotExist,
|
err: os.ErrNotExist,
|
||||||
},
|
},
|
||||||
@@ -108,7 +108,7 @@ func TestListDir(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
label: "root folder",
|
label: "root-folder",
|
||||||
name: "",
|
name: "",
|
||||||
expected: []fs.FileInfo{
|
expected: []fs.FileInfo{
|
||||||
&shared.StaticFileInfo{
|
&shared.StaticFileInfo{
|
||||||
@@ -121,7 +121,7 @@ func TestListDir(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "static root folder",
|
label: "static-root-folder",
|
||||||
name: "/domain",
|
name: "/domain",
|
||||||
expected: []fs.FileInfo{
|
expected: []fs.FileInfo{
|
||||||
&shared.StaticFileInfo{
|
&shared.StaticFileInfo{
|
||||||
@@ -189,19 +189,19 @@ func TestMkdir(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
label: "attempt to create root folder",
|
label: "create-root-folder",
|
||||||
name: "/",
|
name: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "attempt to create static root folder",
|
label: "create-static-root-folder",
|
||||||
name: "/domain",
|
name: "/domain",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "attempt to create remote",
|
label: "create-remote",
|
||||||
name: "/domain/remote1",
|
name: "/domain/remote1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "attempt to create non-existent remote",
|
label: "create-non-existent-remote",
|
||||||
name: "/domain/remote3",
|
name: "/domain/remote3",
|
||||||
err: os.ErrPermission,
|
err: os.ErrPermission,
|
||||||
},
|
},
|
||||||
@@ -231,7 +231,7 @@ func TestRemoveAll(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
label: "attempt to remove root folder",
|
label: "remove-root-folder",
|
||||||
name: "/",
|
name: "/",
|
||||||
err: os.ErrPermission,
|
err: os.ErrPermission,
|
||||||
},
|
},
|
||||||
@@ -258,7 +258,7 @@ func TestRename(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
label: "attempt to move root folder",
|
label: "move-root-folder",
|
||||||
oldName: "/",
|
oldName: "/",
|
||||||
newName: "/domain/remote2/copy.txt",
|
newName: "/domain/remote2/copy.txt",
|
||||||
err: os.ErrPermission,
|
err: os.ErrPermission,
|
||||||
|
|||||||
@@ -156,27 +156,27 @@ func TestMissingPaths(t *testing.T) {
|
|||||||
wantStatus int
|
wantStatus int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty path",
|
name: "empty-path",
|
||||||
path: "",
|
path: "",
|
||||||
wantStatus: http.StatusForbidden,
|
wantStatus: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single slash",
|
name: "single-slash",
|
||||||
path: "/",
|
path: "/",
|
||||||
wantStatus: http.StatusForbidden,
|
wantStatus: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only token",
|
name: "only-token",
|
||||||
path: "/" + secretToken,
|
path: "/" + secretToken,
|
||||||
wantStatus: http.StatusBadRequest,
|
wantStatus: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "token with trailing slash",
|
name: "token-trailing-slash",
|
||||||
path: "/" + secretToken + "/",
|
path: "/" + secretToken + "/",
|
||||||
wantStatus: http.StatusBadRequest,
|
wantStatus: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "token and invalid share",
|
name: "token-invalid-share",
|
||||||
path: "/" + secretToken + "/nonexistentshare",
|
path: "/" + secretToken + "/nonexistentshare",
|
||||||
wantStatus: http.StatusNotFound,
|
wantStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErr: "",
|
wantErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing client id short-circuits without error",
|
name: "missing-client-id-noop",
|
||||||
clientID: "",
|
clientID: "",
|
||||||
idToken: "token",
|
idToken: "token",
|
||||||
audience: "api://tailscale-wif",
|
audience: "api://tailscale-wif",
|
||||||
@@ -40,7 +40,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErr: "",
|
wantErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing id token and audience",
|
name: "missing-id-token-and-audience",
|
||||||
clientID: "client-123",
|
clientID: "client-123",
|
||||||
idToken: "",
|
idToken: "",
|
||||||
audience: "",
|
audience: "",
|
||||||
@@ -48,7 +48,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErr: "federated identity requires either an ID token or an audience",
|
wantErr: "federated identity requires either an ID token or an audience",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing tags",
|
name: "missing-tags",
|
||||||
clientID: "client-123",
|
clientID: "client-123",
|
||||||
idToken: "token",
|
idToken: "token",
|
||||||
audience: "api://tailscale-wif",
|
audience: "api://tailscale-wif",
|
||||||
@@ -56,7 +56,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErr: "federated identity authkeys require --advertise-tags",
|
wantErr: "federated identity authkeys require --advertise-tags",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid client id attributes",
|
name: "invalid-client-id-attrs",
|
||||||
clientID: "client-123?invalid=value",
|
clientID: "client-123?invalid=value",
|
||||||
idToken: "token",
|
idToken: "token",
|
||||||
audience: "api://tailscale-wif",
|
audience: "api://tailscale-wif",
|
||||||
@@ -99,7 +99,7 @@ func TestParseOptionalAttributes(t *testing.T) {
|
|||||||
wantErr string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "default values",
|
name: "default-values",
|
||||||
clientID: "client-123",
|
clientID: "client-123",
|
||||||
wantClientID: "client-123",
|
wantClientID: "client-123",
|
||||||
wantEphemeral: true,
|
wantEphemeral: true,
|
||||||
@@ -107,7 +107,7 @@ func TestParseOptionalAttributes(t *testing.T) {
|
|||||||
wantErr: "",
|
wantErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "custom values",
|
name: "custom-values",
|
||||||
clientID: "client-123?ephemeral=false&preauthorized=true",
|
clientID: "client-123?ephemeral=false&preauthorized=true",
|
||||||
wantClientID: "client-123",
|
wantClientID: "client-123",
|
||||||
wantEphemeral: false,
|
wantEphemeral: false,
|
||||||
@@ -115,7 +115,7 @@ func TestParseOptionalAttributes(t *testing.T) {
|
|||||||
wantErr: "",
|
wantErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unknown attribute",
|
name: "unknown-attribute",
|
||||||
clientID: "client-123?unknown=value",
|
clientID: "client-123?unknown=value",
|
||||||
wantClientID: "",
|
wantClientID: "",
|
||||||
wantEphemeral: false,
|
wantEphemeral: false,
|
||||||
@@ -123,7 +123,7 @@ func TestParseOptionalAttributes(t *testing.T) {
|
|||||||
wantErr: `unknown optional config attribute "unknown"`,
|
wantErr: `unknown optional config attribute "unknown"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid value",
|
name: "invalid-value",
|
||||||
clientID: "client-123?ephemeral=invalid",
|
clientID: "client-123?ephemeral=invalid",
|
||||||
wantClientID: "",
|
wantClientID: "",
|
||||||
wantEphemeral: false,
|
wantEphemeral: false,
|
||||||
|
|||||||
@@ -20,42 +20,42 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "keys without client secret prefix pass through unchanged",
|
name: "non-client-secret-passthrough",
|
||||||
clientID: "tskey-auth-regular",
|
clientID: "tskey-auth-regular",
|
||||||
tags: []string{"tag:test"},
|
tags: []string{"tag:test"},
|
||||||
wantAuthKey: "tskey-auth-regular",
|
wantAuthKey: "tskey-auth-regular",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client secret without advertised tags",
|
name: "client-secret-no-tags",
|
||||||
clientID: "tskey-client-abc",
|
clientID: "tskey-client-abc",
|
||||||
tags: nil,
|
tags: nil,
|
||||||
wantAuthKey: "",
|
wantAuthKey: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client secret with default attributes",
|
name: "client-secret-default-attrs",
|
||||||
clientID: "tskey-client-abc",
|
clientID: "tskey-client-abc",
|
||||||
tags: []string{"tag:test"},
|
tags: []string{"tag:test"},
|
||||||
wantAuthKey: "tskey-auth-xyz",
|
wantAuthKey: "tskey-auth-xyz",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client secret with custom attributes",
|
name: "client-secret-custom-attrs",
|
||||||
clientID: "tskey-client-abc?ephemeral=false&preauthorized=true",
|
clientID: "tskey-client-abc?ephemeral=false&preauthorized=true",
|
||||||
tags: []string{"tag:test"},
|
tags: []string{"tag:test"},
|
||||||
wantAuthKey: "tskey-auth-xyz",
|
wantAuthKey: "tskey-auth-xyz",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "client secret with unknown attribute",
|
name: "client-secret-unknown-attr",
|
||||||
clientID: "tskey-client-abc?unknown=value",
|
clientID: "tskey-client-abc?unknown=value",
|
||||||
tags: []string{"tag:test"},
|
tags: []string{"tag:test"},
|
||||||
wantAuthKey: "",
|
wantAuthKey: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "oauth client secret with invalid attribute value",
|
name: "client-secret-invalid-attr-value",
|
||||||
clientID: "tskey-client-abc?ephemeral=invalid",
|
clientID: "tskey-client-abc?ephemeral=invalid",
|
||||||
tags: []string{"tag:test"},
|
tags: []string{"tag:test"},
|
||||||
wantAuthKey: "",
|
wantAuthKey: "",
|
||||||
@@ -111,7 +111,7 @@ func TestResolveAuthKeyAttributes(t *testing.T) {
|
|||||||
wantBaseURL string
|
wantBaseURL string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "default values",
|
name: "default-values",
|
||||||
clientSecret: "tskey-client-abc",
|
clientSecret: "tskey-client-abc",
|
||||||
wantEphemeral: true,
|
wantEphemeral: true,
|
||||||
wantPreauth: false,
|
wantPreauth: false,
|
||||||
@@ -132,14 +132,14 @@ func TestResolveAuthKeyAttributes(t *testing.T) {
|
|||||||
wantBaseURL: "https://api.tailscale.com",
|
wantBaseURL: "https://api.tailscale.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "baseURL=https://api.example.com",
|
name: "baseURL-custom",
|
||||||
clientSecret: "tskey-client-abc?baseURL=https://api.example.com",
|
clientSecret: "tskey-client-abc?baseURL=https://api.example.com",
|
||||||
wantEphemeral: true,
|
wantEphemeral: true,
|
||||||
wantPreauth: false,
|
wantPreauth: false,
|
||||||
wantBaseURL: "https://api.example.com",
|
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",
|
clientSecret: "tskey-client-abc?ephemeral=false&preauthorized=true&baseURL=https://api.example.com",
|
||||||
wantEphemeral: false,
|
wantEphemeral: false,
|
||||||
wantPreauth: true,
|
wantPreauth: true,
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantEndpoints []netip.AddrPort
|
wantEndpoints []netip.AddrPort
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no changes non-nil port previously running",
|
name: "no-changes-non-nil-port-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -62,7 +62,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set addr ports unchanged port previously running",
|
name: "set-addr-ports-unchanged-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -77,7 +77,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
|
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set addr ports not previously running",
|
name: "set-addr-ports-not-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: nil,
|
port: nil,
|
||||||
rs: nil,
|
rs: nil,
|
||||||
@@ -92,7 +92,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
|
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "clear addr ports unchanged port previously running",
|
name: "clear-addr-ports-unchanged-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
staticEndpoints: views.SliceOf(prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints),
|
staticEndpoints: views.SliceOf(prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints),
|
||||||
@@ -108,7 +108,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantEndpoints: nil,
|
wantEndpoints: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefs port nil",
|
name: "prefs-port-nil",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
},
|
},
|
||||||
@@ -121,7 +121,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefs port nil previously running",
|
name: "prefs-port-nil-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -135,7 +135,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefs port changed",
|
name: "prefs-port-changed",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(2)),
|
port: new(uint16(2)),
|
||||||
},
|
},
|
||||||
@@ -148,7 +148,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefs port changed previously running",
|
name: "prefs-port-changed-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(2)),
|
port: new(uint16(2)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -162,7 +162,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "sameNode false",
|
name: "sameNode-false",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
},
|
},
|
||||||
@@ -175,7 +175,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "sameNode false previously running",
|
name: "sameNode-false-running",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -189,7 +189,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefs port non-nil extension port nil",
|
name: "prefs-port-non-nil-ext-nil",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
port: nil,
|
port: nil,
|
||||||
},
|
},
|
||||||
@@ -277,7 +277,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated bool
|
wantRelayServerFieldMutated bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "want running",
|
name: "want-running",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
hasNodeAttrDisableRelayServer: false,
|
hasNodeAttrDisableRelayServer: false,
|
||||||
@@ -285,7 +285,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "want running previously running",
|
name: "want-running-previously-running",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -294,7 +294,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "shutdown true",
|
name: "shutdown-true",
|
||||||
shutdown: true,
|
shutdown: true,
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
hasNodeAttrDisableRelayServer: false,
|
hasNodeAttrDisableRelayServer: false,
|
||||||
@@ -302,7 +302,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "shutdown true previously running",
|
name: "shutdown-true-previously-running",
|
||||||
shutdown: true,
|
shutdown: true,
|
||||||
port: new(uint16(1)),
|
port: new(uint16(1)),
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -311,7 +311,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "port nil",
|
name: "port-nil",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: nil,
|
port: nil,
|
||||||
hasNodeAttrDisableRelayServer: false,
|
hasNodeAttrDisableRelayServer: false,
|
||||||
@@ -319,7 +319,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "port nil previously running",
|
name: "port-nil-previously-running",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: nil,
|
port: nil,
|
||||||
rs: mockRelayServerNotZeroVal(),
|
rs: mockRelayServerNotZeroVal(),
|
||||||
@@ -328,7 +328,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: true,
|
wantRelayServerFieldMutated: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hasNodeAttrDisableRelayServer true",
|
name: "hasNodeAttrDisableRelayServer-true",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: nil,
|
port: nil,
|
||||||
hasNodeAttrDisableRelayServer: true,
|
hasNodeAttrDisableRelayServer: true,
|
||||||
@@ -336,7 +336,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
|
|||||||
wantRelayServerFieldMutated: false,
|
wantRelayServerFieldMutated: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hasNodeAttrDisableRelayServer true previously running",
|
name: "hasNodeAttrDisableRelayServer-true-running",
|
||||||
shutdown: false,
|
shutdown: false,
|
||||||
port: nil,
|
port: nil,
|
||||||
rs: mockRelayServerNotZeroVal(),
|
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
@@ -1 +1 @@
|
|||||||
sha256-39axT5Q0+fNTcMgZCMLMNfJEJN46wMaaKDgfI+Uj+Ps=
|
sha256-VsVMvTEblVx/HNbuCVxC9UgKpriRwixswUSKVGLMf3Q=
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ func TestShowUpdateWarnable(t *testing.T) {
|
|||||||
wantShow bool
|
wantShow bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "nil ClientVersion",
|
desc: "nil-ClientVersion",
|
||||||
check: true,
|
check: true,
|
||||||
cv: nil,
|
cv: nil,
|
||||||
wantWarnable: nil,
|
wantWarnable: nil,
|
||||||
@@ -402,35 +402,35 @@ func TestShowUpdateWarnable(t *testing.T) {
|
|||||||
wantShow: false,
|
wantShow: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "no LatestVersion",
|
desc: "no-LatestVersion",
|
||||||
check: true,
|
check: true,
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: ""},
|
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: ""},
|
||||||
wantWarnable: nil,
|
wantWarnable: nil,
|
||||||
wantShow: false,
|
wantShow: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "show regular update",
|
desc: "show-regular-update",
|
||||||
check: true,
|
check: true,
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
||||||
wantWarnable: updateAvailableWarnable,
|
wantWarnable: updateAvailableWarnable,
|
||||||
wantShow: true,
|
wantShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "show security update",
|
desc: "show-security-update",
|
||||||
check: true,
|
check: true,
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3", UrgentSecurityUpdate: true},
|
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3", UrgentSecurityUpdate: true},
|
||||||
wantWarnable: securityUpdateAvailableWarnable,
|
wantWarnable: securityUpdateAvailableWarnable,
|
||||||
wantShow: true,
|
wantShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "update check disabled",
|
desc: "update-check-disabled",
|
||||||
check: false,
|
check: false,
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
||||||
wantWarnable: nil,
|
wantWarnable: nil,
|
||||||
wantShow: false,
|
wantShow: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "hide update with auto-updates",
|
desc: "hide-update-with-auto-updates",
|
||||||
check: true,
|
check: true,
|
||||||
apply: opt.NewBool(true),
|
apply: opt.NewBool(true),
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3"},
|
||||||
@@ -438,7 +438,7 @@ func TestShowUpdateWarnable(t *testing.T) {
|
|||||||
wantShow: false,
|
wantShow: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "show security update with auto-updates",
|
desc: "show-security-update-with-auto-updates",
|
||||||
check: true,
|
check: true,
|
||||||
apply: opt.NewBool(true),
|
apply: opt.NewBool(true),
|
||||||
cv: &tailcfg.ClientVersion{RunningLatest: false, LatestVersion: "1.2.3", UrgentSecurityUpdate: 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{
|
wantStrs := []string{
|
||||||
"Control health message: Extra help.",
|
"Control health message: Extra help.",
|
||||||
"Control health message: Extra help. Learn more: http://www.example.com",
|
"Control health message: Extra help. Learn more: http://www.example.com",
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func TestHandleC2NTLSCertStatus(t *testing.T) {
|
|||||||
want *tailcfg.C2NTLSCertInfo
|
want *tailcfg.C2NTLSCertInfo
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no domain",
|
name: "no-domain",
|
||||||
wantStatus: 400,
|
wantStatus: 400,
|
||||||
wantError: "no 'domain'\n",
|
wantError: "no 'domain'\n",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -39,25 +39,29 @@ func TestCertRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
domain string
|
domain string
|
||||||
wantSANs []string
|
wantSANs []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "example-com",
|
||||||
domain: "example.com",
|
domain: "example.com",
|
||||||
wantSANs: []string{"example.com"},
|
wantSANs: []string{"example.com"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "wildcard-example-com",
|
||||||
domain: "*.example.com",
|
domain: "*.example.com",
|
||||||
wantSANs: []string{"*.example.com", "example.com"},
|
wantSANs: []string{"*.example.com", "example.com"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "wildcard-foo-bar-com",
|
||||||
domain: "*.foo.bar.com",
|
domain: "*.foo.bar.com",
|
||||||
wantSANs: []string{"*.foo.bar.com", "foo.bar.com"},
|
wantSANs: []string{"*.foo.bar.com", "foo.bar.com"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
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)
|
csrDER, err := certRequest(key, tt.domain, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("certRequest: %v", err)
|
t.Fatalf("certRequest: %v", err)
|
||||||
@@ -365,19 +369,19 @@ func TestShouldStartDomainRenewal(t *testing.T) {
|
|||||||
wantErr string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "should renew",
|
name: "should-renew",
|
||||||
notBefore: now.AddDate(0, 0, -89),
|
notBefore: now.AddDate(0, 0, -89),
|
||||||
lifetime: 90 * 24 * time.Hour,
|
lifetime: 90 * 24 * time.Hour,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "short-lived renewal",
|
name: "short-lived-renewal",
|
||||||
notBefore: now.AddDate(0, 0, -7),
|
notBefore: now.AddDate(0, 0, -7),
|
||||||
lifetime: 10 * 24 * time.Hour,
|
lifetime: 10 * 24 * time.Hour,
|
||||||
want: true,
|
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
|
notBefore: now.AddDate(0, 0, -59), // 59 days ago == not 2/3rds of the way through 90 days yet
|
||||||
lifetime: 90 * 24 * time.Hour,
|
lifetime: 90 * 24 * time.Hour,
|
||||||
want: false,
|
want: false,
|
||||||
|
|||||||
+130
-92
@@ -3035,20 +3035,20 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
lastSuggestedExitNode tailcfg.StableNodeID
|
lastSuggestedExitNode tailcfg.StableNodeID
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ExitNodeID key is set",
|
name: "exitNodeID-set",
|
||||||
exitNodeIDKey: true,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "123",
|
exitNodeID: "123",
|
||||||
exitNodeIDWant: "123",
|
exitNodeIDWant: "123",
|
||||||
prefsChanged: true,
|
prefsChanged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExitNodeID key not set",
|
name: "exitNodeID-not-set",
|
||||||
exitNodeIDKey: true,
|
exitNodeIDKey: true,
|
||||||
exitNodeIDWant: "",
|
exitNodeIDWant: "",
|
||||||
prefsChanged: false,
|
prefsChanged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExitNodeID key set, ExitNodeIP preference set",
|
name: "exitNodeID-set-exitNodeIP-pref-set",
|
||||||
exitNodeIDKey: true,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "123",
|
exitNodeID: "123",
|
||||||
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
||||||
@@ -3056,7 +3056,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
prefsChanged: true,
|
prefsChanged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExitNodeID key not set, ExitNodeIP key set",
|
name: "exitNodeID-not-set-exitNodeIP-set",
|
||||||
exitNodeIPKey: true,
|
exitNodeIPKey: true,
|
||||||
exitNodeIP: "127.0.0.1",
|
exitNodeIP: "127.0.0.1",
|
||||||
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("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,
|
prefsChanged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ExitNodeIP key set, existing ExitNodeIP pref",
|
name: "exitNodeIP-set-existing-pref",
|
||||||
exitNodeIPKey: true,
|
exitNodeIPKey: true,
|
||||||
exitNodeIP: "127.0.0.1",
|
exitNodeIP: "127.0.0.1",
|
||||||
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("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,
|
prefsChanged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "existing preferences match policy",
|
name: "existing-prefs-match-policy",
|
||||||
exitNodeIDKey: true,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "123",
|
exitNodeID: "123",
|
||||||
prefs: &ipn.Prefs{ExitNodeID: tailcfg.StableNodeID("123")},
|
prefs: &ipn.Prefs{ExitNodeID: tailcfg.StableNodeID("123")},
|
||||||
@@ -3080,7 +3080,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
prefsChanged: false,
|
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,
|
exitNodeIPKey: true,
|
||||||
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
||||||
exitNodeIP: "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")},
|
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
||||||
exitNodeIPKey: true,
|
exitNodeIPKey: true,
|
||||||
exitNodeIP: "127.0.0.1",
|
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")},
|
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
||||||
exitNodeIPWant: "",
|
exitNodeIPWant: "",
|
||||||
exitNodeIDWant: "123",
|
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,
|
exitNodeIPKey: true,
|
||||||
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
prefs: &ipn.Prefs{ExitNodeIP: netip.MustParseAddr("127.0.0.1")},
|
||||||
exitNodeIP: "100.64.5.6",
|
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,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "auto:any",
|
exitNodeID: "auto:any",
|
||||||
lastSuggestedExitNode: "123",
|
lastSuggestedExitNode: "123",
|
||||||
@@ -3243,7 +3247,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
prefsChanged: true,
|
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,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "auto:any",
|
exitNodeID: "auto:any",
|
||||||
exitNodeIDWant: "auto:any",
|
exitNodeIDWant: "auto:any",
|
||||||
@@ -3251,7 +3255,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
prefsChanged: true,
|
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,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "auto:foo",
|
exitNodeID: "auto:foo",
|
||||||
lastSuggestedExitNode: "123",
|
lastSuggestedExitNode: "123",
|
||||||
@@ -3260,7 +3264,7 @@ func TestSetExitNodeIDPolicy(t *testing.T) {
|
|||||||
prefsChanged: true,
|
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,
|
exitNodeIDKey: true,
|
||||||
exitNodeID: "auto:foo",
|
exitNodeID: "auto:foo",
|
||||||
exitNodeIDWant: "auto:any", // should be "auto:any" for compatibility with existing clients
|
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
|
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{
|
prefs: ipn.Prefs{
|
||||||
ControlURL: "1",
|
ControlURL: "1",
|
||||||
ShieldsUp: true,
|
ShieldsUp: true,
|
||||||
@@ -3667,7 +3671,7 @@ func TestApplySysPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty prefs with policies",
|
name: "empty-prefs-with-policies",
|
||||||
wantPrefs: ipn.Prefs{
|
wantPrefs: ipn.Prefs{
|
||||||
ControlURL: "1",
|
ControlURL: "1",
|
||||||
ShieldsUp: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
ControlURL: "1",
|
ControlURL: "1",
|
||||||
ShieldsUp: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
ControlURL: "1",
|
ControlURL: "1",
|
||||||
ShieldsUp: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
ControlURL: "1",
|
ControlURL: "1",
|
||||||
ShieldsUp: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||||
Check: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||||
Check: true,
|
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{
|
prefs: ipn.Prefs{
|
||||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||||
Check: false,
|
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{
|
prefs: ipn.Prefs{
|
||||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||||
Check: true,
|
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
|
// Profile manager fills in blank ControlURL but it's not set
|
||||||
// in most test cases to avoid cluttering them, so adjust for
|
// in most test cases to avoid cluttering them, so adjust for
|
||||||
// that.
|
// that.
|
||||||
@@ -3919,75 +3923,75 @@ func TestPreferencePolicyInfo(t *testing.T) {
|
|||||||
policyError error
|
policyError error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "force enable modify",
|
name: "force-enable-modify",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
wantChange: true,
|
wantChange: true,
|
||||||
policyValue: "always",
|
policyValue: "always",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "force enable unchanged",
|
name: "force-enable-unchanged",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
policyValue: "always",
|
policyValue: "always",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "force disable modify",
|
name: "force-disable-modify",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
wantChange: true,
|
wantChange: true,
|
||||||
policyValue: "never",
|
policyValue: "never",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "force disable unchanged",
|
name: "force-disable-unchanged",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
policyValue: "never",
|
policyValue: "never",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unforced enabled",
|
name: "unforced-enabled",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
policyValue: "user-decides",
|
policyValue: "user-decides",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unforced disabled",
|
name: "unforced-disabled",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
policyValue: "user-decides",
|
policyValue: "user-decides",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "blank enabled",
|
name: "blank-enabled",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
policyValue: "",
|
policyValue: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "blank disabled",
|
name: "blank-disabled",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
policyValue: "",
|
policyValue: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset enabled",
|
name: "unset-enabled",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
policyError: syspolicy.ErrNoSuchKey,
|
policyError: syspolicy.ErrNoSuchKey,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unset disabled",
|
name: "unset-disabled",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
policyError: syspolicy.ErrNoSuchKey,
|
policyError: syspolicy.ErrNoSuchKey,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "error enabled",
|
name: "error-enabled",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
wantValue: true,
|
wantValue: true,
|
||||||
policyError: errors.New("test error"),
|
policyError: errors.New("test error"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "error disabled",
|
name: "error-disabled",
|
||||||
initialValue: false,
|
initialValue: false,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
policyError: errors.New("test error"),
|
policyError: errors.New("test error"),
|
||||||
@@ -4113,53 +4117,62 @@ func TestOnTailnetDefaultAutoUpdate(t *testing.T) {
|
|||||||
func TestTCPHandlerForDst(t *testing.T) {
|
func TestTCPHandlerForDst(t *testing.T) {
|
||||||
b := newTestBackend(t)
|
b := newTestBackend(t)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
desc string
|
desc string
|
||||||
dst string
|
dst string
|
||||||
intercept bool
|
intercept bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "100_100_100_100-port80",
|
||||||
desc: "intercept port 80 (Web UI) on quad100 IPv4",
|
desc: "intercept port 80 (Web UI) on quad100 IPv4",
|
||||||
dst: "100.100.100.100:80",
|
dst: "100.100.100.100:80",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port80",
|
||||||
desc: "intercept port 80 (Web UI) on quad100 IPv6",
|
desc: "intercept port 80 (Web UI) on quad100 IPv6",
|
||||||
dst: "[fd7a:115c:a1e0::53]:80",
|
dst: "[fd7a:115c:a1e0::53]:80",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port80",
|
||||||
desc: "don't intercept port 80 on local ip",
|
desc: "don't intercept port 80 on local ip",
|
||||||
dst: "100.100.103.100:80",
|
dst: "100.100.103.100:80",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port8080",
|
||||||
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
|
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
|
||||||
dst: "[fd7a:115c:a1e0::53]:8080",
|
dst: "[fd7a:115c:a1e0::53]:8080",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port8080",
|
||||||
desc: "don't intercept port 8080 on local ip",
|
desc: "don't intercept port 8080 on local ip",
|
||||||
dst: "100.100.103.100:8080",
|
dst: "100.100.103.100:8080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_100_100-port9080",
|
||||||
desc: "don't intercept port 9080 on quad100 IPv4",
|
desc: "don't intercept port 9080 on quad100 IPv4",
|
||||||
dst: "100.100.100.100:9080",
|
dst: "100.100.100.100:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port9080",
|
||||||
desc: "don't intercept port 9080 on quad100 IPv6",
|
desc: "don't intercept port 9080 on quad100 IPv6",
|
||||||
dst: "[fd7a:115c:a1e0::53]:9080",
|
dst: "[fd7a:115c:a1e0::53]:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port9080",
|
||||||
desc: "don't intercept port 9080 on local ip",
|
desc: "don't intercept port 9080 on local ip",
|
||||||
dst: "100.100.103.100:9080",
|
dst: "100.100.103.100:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.dst, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Log(tt.desc)
|
t.Log(tt.desc)
|
||||||
src := netip.MustParseAddrPort("100.100.102.100:51234")
|
src := netip.MustParseAddrPort("100.100.102.100:51234")
|
||||||
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
|
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
|
||||||
@@ -4258,122 +4271,146 @@ func TestTCPHandlerForDstWithVIPService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
desc string
|
desc string
|
||||||
dst string
|
dst string
|
||||||
intercept bool
|
intercept bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "100_100_100_100-port80",
|
||||||
desc: "intercept port 80 (Web UI) on quad100 IPv4",
|
desc: "intercept port 80 (Web UI) on quad100 IPv4",
|
||||||
dst: "100.100.100.100:80",
|
dst: "100.100.100.100:80",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port80",
|
||||||
desc: "intercept port 80 (Web UI) on quad100 IPv6",
|
desc: "intercept port 80 (Web UI) on quad100 IPv6",
|
||||||
dst: "[fd7a:115c:a1e0::53]:80",
|
dst: "[fd7a:115c:a1e0::53]:80",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port80",
|
||||||
desc: "don't intercept port 80 on local ip",
|
desc: "don't intercept port 80 on local ip",
|
||||||
dst: "100.100.103.100:80",
|
dst: "100.100.103.100:80",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_100_100-port8080",
|
||||||
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
|
desc: "intercept port 8080 (Taildrive) on quad100 IPv4",
|
||||||
dst: "100.100.100.100:8080",
|
dst: "100.100.100.100:8080",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port8080",
|
||||||
desc: "intercept port 8080 (Taildrive) on quad100 IPv6",
|
desc: "intercept port 8080 (Taildrive) on quad100 IPv6",
|
||||||
dst: "[fd7a:115c:a1e0::53]:8080",
|
dst: "[fd7a:115c:a1e0::53]:8080",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port8080",
|
||||||
desc: "don't intercept port 8080 on local ip",
|
desc: "don't intercept port 8080 on local ip",
|
||||||
dst: "100.100.103.100:8080",
|
dst: "100.100.103.100:8080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_100_100-port9080",
|
||||||
desc: "don't intercept port 9080 on quad100 IPv4",
|
desc: "don't intercept port 9080 on quad100 IPv4",
|
||||||
dst: "100.100.100.100:9080",
|
dst: "100.100.100.100:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0--53-port9080",
|
||||||
desc: "don't intercept port 9080 on quad100 IPv6",
|
desc: "don't intercept port 9080 on quad100 IPv6",
|
||||||
dst: "[fd7a:115c:a1e0::53]:9080",
|
dst: "[fd7a:115c:a1e0::53]:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_100_103_100-port9080",
|
||||||
desc: "don't intercept port 9080 on local ip",
|
desc: "don't intercept port 9080 on local ip",
|
||||||
dst: "100.100.103.100:9080",
|
dst: "100.100.103.100:9080",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
// VIP service destinations
|
// VIP service destinations
|
||||||
{
|
{
|
||||||
|
name: "100_101_101_101-port882",
|
||||||
desc: "intercept port 882 (HTTP) on service foo IPv4",
|
desc: "intercept port 882 (HTTP) on service foo IPv4",
|
||||||
dst: "100.101.101.101:882",
|
dst: "100.101.101.101:882",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port882",
|
||||||
desc: "intercept port 882 (HTTP) on service foo IPv6",
|
desc: "intercept port 882 (HTTP) on service foo IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:882",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:882",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_101_101_101-port883",
|
||||||
desc: "intercept port 883 (HTTPS) on service foo IPv4",
|
desc: "intercept port 883 (HTTPS) on service foo IPv4",
|
||||||
dst: "100.101.101.101:883",
|
dst: "100.101.101.101:883",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port883",
|
||||||
desc: "intercept port 883 (HTTPS) on service foo IPv6",
|
desc: "intercept port 883 (HTTPS) on service foo IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:883",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:883",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_99_99_99-port990",
|
||||||
desc: "intercept port 990 (TCPForward) on service bar IPv4",
|
desc: "intercept port 990 (TCPForward) on service bar IPv4",
|
||||||
dst: "100.99.99.99:990",
|
dst: "100.99.99.99:990",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port990",
|
||||||
desc: "intercept port 990 (TCPForward) on service bar IPv6",
|
desc: "intercept port 990 (TCPForward) on service bar IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_99_99_99-port990-terminateTLS",
|
||||||
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv4",
|
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv4",
|
||||||
dst: "100.99.99.99:990",
|
dst: "100.99.99.99:990",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port990-terminateTLS",
|
||||||
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv6",
|
desc: "intercept port 991 (TCPForward with TerminateTLS) on service bar IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:990",
|
||||||
intercept: true,
|
intercept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_101_101_101-port4444",
|
||||||
desc: "don't intercept port 4444 on service foo IPv4",
|
desc: "don't intercept port 4444 on service foo IPv4",
|
||||||
dst: "100.101.101.101:4444",
|
dst: "100.101.101.101:4444",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-6565-6565-port4444",
|
||||||
desc: "don't intercept port 4444 on service foo IPv6",
|
desc: "don't intercept port 4444 on service foo IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:4444",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:6565:6565]:4444",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_22_22_22-port883",
|
||||||
desc: "don't intercept port 600 on unknown service IPv4",
|
desc: "don't intercept port 600 on unknown service IPv4",
|
||||||
dst: "100.22.22.22:883",
|
dst: "100.22.22.22:883",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-626b-628b-port883",
|
||||||
desc: "don't intercept port 600 on unknown service IPv6",
|
desc: "don't intercept port 600 on unknown service IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:883",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:626b:628b]:883",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "100_133_133_133-port600",
|
||||||
desc: "don't intercept port 600 (HTTPS) on service baz IPv4",
|
desc: "don't intercept port 600 (HTTPS) on service baz IPv4",
|
||||||
dst: "100.133.133.133:600",
|
dst: "100.133.133.133:600",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "fd7a-115c-a1e0-ab12-4843-cd96-8585-8585-port600",
|
||||||
desc: "don't intercept port 600 (HTTPS) on service baz IPv6",
|
desc: "don't intercept port 600 (HTTPS) on service baz IPv6",
|
||||||
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:8585:8585]:600",
|
dst: "[fd7a:115c:a1e0:ab12:4843:cd96:8585:8585]:600",
|
||||||
intercept: false,
|
intercept: false,
|
||||||
@@ -4381,7 +4418,7 @@ func TestTCPHandlerForDstWithVIPService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.dst, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Log(tt.desc)
|
t.Log(tt.desc)
|
||||||
src := netip.MustParseAddrPort("100.100.102.100:51234")
|
src := netip.MustParseAddrPort("100.100.102.100:51234")
|
||||||
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
|
h, _ := b.TCPHandlerForDst(src, netip.MustParseAddrPort(tt.dst))
|
||||||
@@ -4664,14 +4701,14 @@ func TestRoundTraffic(t *testing.T) {
|
|||||||
bytes int64
|
bytes int64
|
||||||
want float64
|
want float64
|
||||||
}{
|
}{
|
||||||
{name: "under 5 bytes", bytes: 4, want: 4},
|
{name: "under-5B", bytes: 4, want: 4},
|
||||||
{name: "under 1000 bytes", bytes: 987, want: 990},
|
{name: "under-1000B", bytes: 987, want: 990},
|
||||||
{name: "under 10_000 bytes", bytes: 8875, want: 8900},
|
{name: "under-10000B", bytes: 8875, want: 8900},
|
||||||
{name: "under 100_000 bytes", bytes: 77777, want: 78000},
|
{name: "under-100000B", bytes: 77777, want: 78000},
|
||||||
{name: "under 1_000_000 bytes", bytes: 666523, want: 670000},
|
{name: "under-1000000B", bytes: 666523, want: 670000},
|
||||||
{name: "under 10_000_000 bytes", bytes: 22556677, want: 23000000},
|
{name: "under-10000000B", bytes: 22556677, want: 23000000},
|
||||||
{name: "under 1_000_000_000 bytes", bytes: 1234234234, want: 1200000000},
|
{name: "under-1000000000B", bytes: 1234234234, want: 1200000000},
|
||||||
{name: "under 1_000_000_000 bytes", bytes: 123423423499, want: 123400000000},
|
{name: "over-1000000000B", bytes: 123423423499, want: 123400000000},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -5033,7 +5070,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantError error
|
wantError error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "2 exit nodes in same region",
|
name: "2-exits-same-region",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5051,7 +5088,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantID: "stable1",
|
wantID: "stable1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "2 exit nodes different regions unknown latency",
|
name: "2-exits-different-regions-unknown-latency",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: defaultNetmap,
|
netMap: defaultNetmap,
|
||||||
wantRegions: []int{1, 3}, // the only regions with peers
|
wantRegions: []int{1, 3}, // the only regions with peers
|
||||||
@@ -5060,7 +5097,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantID: "stable2",
|
wantID: "stable2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "2 derp based exit nodes, different regions, equal latency",
|
name: "2-derp-exits-different-regions-equal-latency",
|
||||||
lastReport: &netcheck.Report{
|
lastReport: &netcheck.Report{
|
||||||
RegionLatency: map[int]time.Duration{
|
RegionLatency: map[int]time.Duration{
|
||||||
1: 10,
|
1: 10,
|
||||||
@@ -5083,7 +5120,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantID: "stable1",
|
wantID: "stable1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mullvad nodes, no derp based exit nodes",
|
name: "mullvad-no-derp-exits",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: locationNetmap,
|
netMap: locationNetmap,
|
||||||
wantID: "stable5",
|
wantID: "stable5",
|
||||||
@@ -5091,7 +5128,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "Dallas",
|
wantName: "Dallas",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nearby mullvad nodes with different priorities",
|
name: "nearby-mullvad-different-priorities",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5107,7 +5144,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "Fort Worth",
|
wantName: "Fort Worth",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nearby mullvad nodes with same priorities",
|
name: "nearby-mullvad-same-priorities",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5124,7 +5161,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "Dallas",
|
wantName: "Dallas",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mullvad nodes, remaining node is not in preferred derp",
|
name: "mullvad-remaining-not-in-preferred-derp",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5140,7 +5177,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "peer4",
|
wantName: "peer4",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no peers",
|
name: "no-peers",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5148,13 +5185,13 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil report",
|
name: "nil-report",
|
||||||
lastReport: nil,
|
lastReport: nil,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
wantError: ErrNoPreferredDERP,
|
wantError: ErrNoPreferredDERP,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no preferred derp region",
|
name: "no-preferred-derp-region",
|
||||||
lastReport: preferredNoneReport,
|
lastReport: preferredNoneReport,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5163,13 +5200,13 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantError: ErrNoPreferredDERP,
|
wantError: ErrNoPreferredDERP,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil netmap",
|
name: "nil-netmap",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: nil,
|
netMap: nil,
|
||||||
wantError: ErrNoPreferredDERP,
|
wantError: ErrNoPreferredDERP,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil derpmap",
|
name: "nil-derpmap",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5181,7 +5218,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantError: ErrNoPreferredDERP,
|
wantError: ErrNoPreferredDERP,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing suggestion capability",
|
name: "missing-suggestion-capability",
|
||||||
lastReport: noLatency1Report,
|
lastReport: noLatency1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5193,7 +5230,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefer last node",
|
name: "prefer-last-node",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
SelfNode: selfNode.View(),
|
SelfNode: selfNode.View(),
|
||||||
@@ -5212,7 +5249,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantID: "stable2",
|
wantID: "stable2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "found better derp node",
|
name: "found-better-derp-node",
|
||||||
lastSuggestion: "stable3",
|
lastSuggestion: "stable3",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: defaultNetmap,
|
netMap: defaultNetmap,
|
||||||
@@ -5220,7 +5257,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "peer2",
|
wantName: "peer2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefer last mullvad node",
|
name: "prefer-last-mullvad-node",
|
||||||
lastSuggestion: "stable2",
|
lastSuggestion: "stable2",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
@@ -5238,7 +5275,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantLocation: dallas.View(),
|
wantLocation: dallas.View(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prefer better mullvad node",
|
name: "prefer-better-mullvad-node",
|
||||||
lastSuggestion: "stable2",
|
lastSuggestion: "stable2",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: &netmap.NetworkMap{
|
netMap: &netmap.NetworkMap{
|
||||||
@@ -5256,7 +5293,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantLocation: fortWorth.View(),
|
wantLocation: fortWorth.View(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "large netmap",
|
name: "large-netmap",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
wantNodes: []tailcfg.StableNodeID{"stable1", "stable2"},
|
wantNodes: []tailcfg.StableNodeID{"stable1", "stable2"},
|
||||||
@@ -5264,13 +5301,13 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "peer2",
|
wantName: "peer2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no allowed suggestions",
|
name: "no-allowed-suggestions",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
allowPolicy: []tailcfg.StableNodeID{},
|
allowPolicy: []tailcfg.StableNodeID{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only derp suggestions",
|
name: "only-derp-suggestions",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
allowPolicy: []tailcfg.StableNodeID{"stable1", "stable2", "stable3"},
|
allowPolicy: []tailcfg.StableNodeID{"stable1", "stable2", "stable3"},
|
||||||
@@ -5279,7 +5316,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "peer2",
|
wantName: "peer2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only mullvad suggestions",
|
name: "only-mullvad-suggestions",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
allowPolicy: []tailcfg.StableNodeID{"stable5", "stable6", "stable7"},
|
allowPolicy: []tailcfg.StableNodeID{"stable5", "stable6", "stable7"},
|
||||||
@@ -5288,7 +5325,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantLocation: fortWorth.View(),
|
wantLocation: fortWorth.View(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only worst derp",
|
name: "only-worst-derp",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
allowPolicy: []tailcfg.StableNodeID{"stable3"},
|
allowPolicy: []tailcfg.StableNodeID{"stable3"},
|
||||||
@@ -5296,7 +5333,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
wantName: "peer3",
|
wantName: "peer3",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only worst mullvad",
|
name: "only-worst-mullvad",
|
||||||
lastReport: preferred1Report,
|
lastReport: preferred1Report,
|
||||||
netMap: largeNetmap,
|
netMap: largeNetmap,
|
||||||
allowPolicy: []tailcfg.StableNodeID{"stable6"},
|
allowPolicy: []tailcfg.StableNodeID{"stable6"},
|
||||||
@@ -5306,7 +5343,7 @@ func TestSuggestExitNode(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Regression test for https://github.com/tailscale/tailscale/issues/17661
|
// 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{
|
lastReport: &netcheck.Report{
|
||||||
RegionLatency: map[int]time.Duration{
|
RegionLatency: map[int]time.Duration{
|
||||||
1: 10,
|
1: 10,
|
||||||
@@ -5388,7 +5425,7 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
|
|||||||
wantIDs []tailcfg.StableNodeID
|
wantIDs []tailcfg.StableNodeID
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "different priorities",
|
name: "different-priorities",
|
||||||
candidates: []tailcfg.NodeView{
|
candidates: []tailcfg.NodeView{
|
||||||
makePeer(2, withExitRoutes(), withLocation(location20.View())),
|
makePeer(2, withExitRoutes(), withLocation(location20.View())),
|
||||||
makePeer(3, withExitRoutes(), withLocation(location10.View())),
|
makePeer(3, withExitRoutes(), withLocation(location10.View())),
|
||||||
@@ -5396,7 +5433,7 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
|
|||||||
wantIDs: []tailcfg.StableNodeID{"stable2"},
|
wantIDs: []tailcfg.StableNodeID{"stable2"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "same priorities",
|
name: "same-priorities",
|
||||||
candidates: []tailcfg.NodeView{
|
candidates: []tailcfg.NodeView{
|
||||||
makePeer(2, withExitRoutes(), withLocation(location10.View())),
|
makePeer(2, withExitRoutes(), withLocation(location10.View())),
|
||||||
makePeer(3, withExitRoutes(), withLocation(location10.View())),
|
makePeer(3, withExitRoutes(), withLocation(location10.View())),
|
||||||
@@ -5404,11 +5441,11 @@ func TestSuggestExitNodePickWeighted(t *testing.T) {
|
|||||||
wantIDs: []tailcfg.StableNodeID{"stable2", "stable3"},
|
wantIDs: []tailcfg.StableNodeID{"stable2", "stable3"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<1 candidates",
|
name: "lt1-candidates",
|
||||||
candidates: []tailcfg.NodeView{},
|
candidates: []tailcfg.NodeView{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "1 candidate",
|
name: "1-candidate",
|
||||||
candidates: []tailcfg.NodeView{
|
candidates: []tailcfg.NodeView{
|
||||||
makePeer(2, withExitRoutes(), withLocation(location20.View())),
|
makePeer(2, withExitRoutes(), withLocation(location20.View())),
|
||||||
},
|
},
|
||||||
@@ -5444,7 +5481,7 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
|
|||||||
want float64
|
want float64
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zero values",
|
name: "zero-values",
|
||||||
fromLat: 0,
|
fromLat: 0,
|
||||||
fromLong: 0,
|
fromLong: 0,
|
||||||
toLat: 0,
|
toLat: 0,
|
||||||
@@ -5452,7 +5489,7 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
|
|||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "valid values",
|
name: "valid-values",
|
||||||
fromLat: 40.73061,
|
fromLat: 40.73061,
|
||||||
fromLong: -73.935242,
|
fromLong: -73.935242,
|
||||||
toLat: 37.3382082,
|
toLat: 37.3382082,
|
||||||
@@ -5460,7 +5497,8 @@ func TestSuggestExitNodeLongLatDistance(t *testing.T) {
|
|||||||
want: 4117266.873301274,
|
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,
|
fromLat: 40.73061,
|
||||||
fromLong: -73.935242,
|
fromLong: -73.935242,
|
||||||
toLat: -33.861481,
|
toLat: -33.861481,
|
||||||
@@ -5865,13 +5903,13 @@ func TestMinLatencyDERPregion(t *testing.T) {
|
|||||||
wantRegion int
|
wantRegion int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "regions, no latency values",
|
name: "regions-no-latency",
|
||||||
regions: []int{1, 2, 3},
|
regions: []int{1, 2, 3},
|
||||||
wantRegion: 0,
|
wantRegion: 0,
|
||||||
report: &netcheck.Report{},
|
report: &netcheck.Report{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "regions, different latency values",
|
name: "regions-different-latency",
|
||||||
regions: []int{1, 2, 3},
|
regions: []int{1, 2, 3},
|
||||||
wantRegion: 2,
|
wantRegion: 2,
|
||||||
report: &netcheck.Report{
|
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},
|
regions: []int{1, 2, 3},
|
||||||
wantRegion: 1,
|
wantRegion: 1,
|
||||||
report: &netcheck.Report{
|
report: &netcheck.Report{
|
||||||
@@ -6030,7 +6068,7 @@ func TestFillAllowedSuggestions(t *testing.T) {
|
|||||||
want: []tailcfg.StableNodeID{"one", "three", "four", "two"}, // order should not matter
|
want: []tailcfg.StableNodeID{"one", "three", "four", "two"}, // order should not matter
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "preserve case",
|
name: "preserve-case",
|
||||||
allowPolicy: []string{"ABC", "def", "gHiJ"},
|
allowPolicy: []string{"ABC", "def", "gHiJ"},
|
||||||
want: []tailcfg.StableNodeID{"ABC", "def", "gHiJ"},
|
want: []tailcfg.StableNodeID{"ABC", "def", "gHiJ"},
|
||||||
},
|
},
|
||||||
@@ -6184,61 +6222,61 @@ func TestNotificationTargetMatch(t *testing.T) {
|
|||||||
wantMatch: false,
|
wantMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FilterByUID+CID/Nil",
|
name: "FilterByUID-CID/Nil",
|
||||||
target: notificationTarget{userID: "S-1-5-21-1-2-3-4"},
|
target: notificationTarget{userID: "S-1-5-21-1-2-3-4"},
|
||||||
actor: nil,
|
actor: nil,
|
||||||
wantMatch: false,
|
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")},
|
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
|
||||||
actor: &ipnauth.TestActor{},
|
actor: &ipnauth.TestActor{},
|
||||||
wantMatch: false,
|
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")},
|
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
|
||||||
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("A")},
|
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("A")},
|
||||||
wantMatch: false,
|
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")},
|
target: notificationTarget{userID: "S-1-5-21-1-2-3-4", clientID: ipnauth.ClientIDFrom("A")},
|
||||||
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("B")},
|
actor: &ipnauth.TestActor{CID: ipnauth.ClientIDFrom("B")},
|
||||||
wantMatch: false,
|
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")},
|
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"},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4"},
|
||||||
wantMatch: false,
|
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")},
|
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")},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4", CID: ipnauth.ClientIDFrom("A")},
|
||||||
wantMatch: true,
|
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")},
|
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")},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-1-2-3-4", CID: ipnauth.ClientIDFrom("B")},
|
||||||
wantMatch: false,
|
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")},
|
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"},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8"},
|
||||||
wantMatch: false,
|
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")},
|
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")},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8", CID: ipnauth.ClientIDFrom("A")},
|
||||||
wantMatch: false,
|
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")},
|
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")},
|
actor: &ipnauth.TestActor{UID: "S-1-5-21-5-6-7-8", CID: ipnauth.ClientIDFrom("B")},
|
||||||
wantMatch: false,
|
wantMatch: false,
|
||||||
|
|||||||
@@ -300,9 +300,9 @@ func TestTKASync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcs := []tkaSyncScenario{
|
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 {
|
controlAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
|
||||||
b := a.NewUpdater(signer)
|
b := a.NewUpdater(signer)
|
||||||
if err := b.RemoveKey(someKey.MustID()); err != nil {
|
if err := b.RemoveKey(someKey.MustID()); err != nil {
|
||||||
@@ -317,7 +317,7 @@ func TestTKASync(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// AKA 'control data loss' scenario
|
// 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 {
|
nodeAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
|
||||||
b := a.NewUpdater(signer)
|
b := a.NewUpdater(signer)
|
||||||
if err := b.RemoveKey(someKey.MustID()); err != nil {
|
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
|
// 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 {
|
controlAUMs: func(t *testing.T, a *tka.Authority, storage tka.Chonk, signer tka.Signer) []tka.AUM {
|
||||||
b := a.NewUpdater(signer)
|
b := a.NewUpdater(signer)
|
||||||
if err := b.SetKeyMeta(someKey.MustID(), map[string]string{"ye": "swiggity"}); err != nil {
|
if err := b.SetKeyMeta(someKey.MustID(), map[string]string{"ye": "swiggity"}); err != nil {
|
||||||
@@ -1020,7 +1020,7 @@ func TestTKAAffectedSigs(t *testing.T) {
|
|||||||
wantErr string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"no error",
|
"no-error",
|
||||||
func() *tka.NodeKeySignature {
|
func() *tka.NodeKeySignature {
|
||||||
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
|
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
|
||||||
return sig
|
return sig
|
||||||
@@ -1028,7 +1028,7 @@ func TestTKAAffectedSigs(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"signature for different keyID",
|
"signature-for-different-keyID",
|
||||||
func() *tka.NodeKeySignature {
|
func() *tka.NodeKeySignature {
|
||||||
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, untrustedKey)
|
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, untrustedKey)
|
||||||
return sig
|
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()),
|
fmt.Sprintf("got signature with keyID %X from request for %X", untrustedKey.KeyID(), nlPriv.KeyID()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid signature",
|
"invalid-signature",
|
||||||
func() *tka.NodeKeySignature {
|
func() *tka.NodeKeySignature {
|
||||||
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
|
sig, _ := signNodeKey(tailcfg.TKASignInfo{NodePublic: nodePriv.Public()}, nlPriv)
|
||||||
copy(sig.Signature, []byte{1, 2, 3, 4, 5, 6}) // overwrite with trash to invalid signature
|
copy(sig.Signature, []byte{1, 2, 3, 4, 5, 6}) // overwrite with trash to invalid signature
|
||||||
|
|||||||
+22
-22
@@ -619,49 +619,49 @@ func TestServeHTTPProxyPath(t *testing.T) {
|
|||||||
wantRequestPath string
|
wantRequestPath string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "/foo -> /foo, with mount point and path /foo",
|
name: "foo-to-foo-mount-foo",
|
||||||
mountPoint: "/foo",
|
mountPoint: "/foo",
|
||||||
proxyPath: "/foo",
|
proxyPath: "/foo",
|
||||||
requestPath: "/foo",
|
requestPath: "/foo",
|
||||||
wantRequestPath: "/foo",
|
wantRequestPath: "/foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "/foo/ -> /foo/, with mount point and path /foo",
|
name: "foo-slash-to-foo-slash-mount-foo",
|
||||||
mountPoint: "/foo",
|
mountPoint: "/foo",
|
||||||
proxyPath: "/foo",
|
proxyPath: "/foo",
|
||||||
requestPath: "/foo/",
|
requestPath: "/foo/",
|
||||||
wantRequestPath: "/foo/",
|
wantRequestPath: "/foo/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "/foo -> /foo/, with mount point and path /foo/",
|
name: "foo-to-foo-slash-mount-foo-slash",
|
||||||
mountPoint: "/foo/",
|
mountPoint: "/foo/",
|
||||||
proxyPath: "/foo/",
|
proxyPath: "/foo/",
|
||||||
requestPath: "/foo",
|
requestPath: "/foo",
|
||||||
wantRequestPath: "/foo/",
|
wantRequestPath: "/foo/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "/-> /, with mount point and path /",
|
name: "root-to-root-mount-root",
|
||||||
mountPoint: "/",
|
mountPoint: "/",
|
||||||
proxyPath: "/",
|
proxyPath: "/",
|
||||||
requestPath: "/",
|
requestPath: "/",
|
||||||
wantRequestPath: "/",
|
wantRequestPath: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "/foo -> /foo, with mount point and path /",
|
name: "foo-to-foo-mount-root",
|
||||||
mountPoint: "/",
|
mountPoint: "/",
|
||||||
proxyPath: "/",
|
proxyPath: "/",
|
||||||
requestPath: "/foo",
|
requestPath: "/foo",
|
||||||
wantRequestPath: "/foo",
|
wantRequestPath: "/foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "/foo/bar -> /foo/bar, with mount point and path /foo",
|
name: "foo-bar-to-foo-bar-mount-foo",
|
||||||
mountPoint: "/foo",
|
mountPoint: "/foo",
|
||||||
proxyPath: "/foo",
|
proxyPath: "/foo",
|
||||||
requestPath: "/foo/bar",
|
requestPath: "/foo/bar",
|
||||||
wantRequestPath: "/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",
|
mountPoint: "/foo",
|
||||||
proxyPath: "/foo",
|
proxyPath: "/foo",
|
||||||
requestPath: "/foo/bar/baz",
|
requestPath: "/foo/bar/baz",
|
||||||
@@ -1457,7 +1457,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError bool
|
wantError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty existing config",
|
name: "empty-existing-config",
|
||||||
description: "should be able to update with empty existing config",
|
description: "should be able to update with empty existing config",
|
||||||
existing: &ipn.ServeConfig{},
|
existing: &ipn.ServeConfig{},
|
||||||
incoming: &ipn.ServeConfig{
|
incoming: &ipn.ServeConfig{
|
||||||
@@ -1468,7 +1468,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no existing config",
|
name: "no-existing-config",
|
||||||
description: "should be able to update with no existing config",
|
description: "should be able to update with no existing config",
|
||||||
existing: nil,
|
existing: nil,
|
||||||
incoming: &ipn.ServeConfig{
|
incoming: &ipn.ServeConfig{
|
||||||
@@ -1479,7 +1479,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty incoming config",
|
name: "empty-incoming-config",
|
||||||
description: "wiping config should work",
|
description: "wiping config should work",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1490,7 +1490,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no incoming config",
|
name: "no-incoming-config",
|
||||||
description: "missing incoming config should not result in an error",
|
description: "missing incoming config should not result in an error",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1501,7 +1501,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-overlapping update",
|
name: "non-overlapping-update",
|
||||||
description: "non-overlapping update should work",
|
description: "non-overlapping update should work",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1516,7 +1516,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "overwriting background port",
|
name: "overwriting-background-port",
|
||||||
description: "should be able to overwrite a background port",
|
description: "should be able to overwrite a background port",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1535,7 +1535,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
wantError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "broken existing config",
|
name: "broken-existing-config",
|
||||||
description: "broken existing config should not prevent new config updates",
|
description: "broken existing config should not prevent new config updates",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1573,7 +1573,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
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",
|
description: "services should be able to use the same port as background listeners",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1592,7 +1592,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: false,
|
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",
|
description: "TUN mode should be mutually exclusive with TCP or web handlers for new Services",
|
||||||
existing: &ipn.ServeConfig{},
|
existing: &ipn.ServeConfig{},
|
||||||
incoming: &ipn.ServeConfig{
|
incoming: &ipn.ServeConfig{
|
||||||
@@ -1608,7 +1608,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
wantError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new foreground listener",
|
name: "new-foreground-listener",
|
||||||
description: "new foreground listeners must be on open ports",
|
description: "new foreground listeners must be on open ports",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1627,7 +1627,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
wantError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new background listener",
|
name: "new-background-listener",
|
||||||
description: "new background listers cannot overwrite foreground listeners",
|
description: "new background listers cannot overwrite foreground listeners",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
Foreground: map[string]*ipn.ServeConfig{
|
Foreground: map[string]*ipn.ServeConfig{
|
||||||
@@ -1646,7 +1646,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
wantError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "serve type overwrite",
|
name: "serve-type-overwrite",
|
||||||
description: "incoming configuration cannot change the serve type in use by a port",
|
description: "incoming configuration cannot change the serve type in use by a port",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
TCP: map[uint16]*ipn.TCPPortHandler{
|
TCP: map[uint16]*ipn.TCPPortHandler{
|
||||||
@@ -1665,7 +1665,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
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",
|
description: "incoming Services configuration cannot change the serve type in use by a port",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1692,7 +1692,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
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",
|
description: "Services cannot enable TUN mode if L4 or L7 handlers already exist",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
@@ -1720,7 +1720,7 @@ func TestValidateServeConfigUpdate(t *testing.T) {
|
|||||||
wantError: true,
|
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",
|
description: "Services cannot add L4 or L7 handlers if TUN mode is already enabled",
|
||||||
existing: &ipn.ServeConfig{
|
existing: &ipn.ServeConfig{
|
||||||
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
Services: map[tailcfg.ServiceName]*ipn.ServiceConfig{
|
||||||
|
|||||||
@@ -23,26 +23,30 @@ import (
|
|||||||
|
|
||||||
func TestExpandProxyArgUnix(t *testing.T) {
|
func TestExpandProxyArgUnix(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
input string
|
input string
|
||||||
wantURL string
|
wantURL string
|
||||||
wantInsecure bool
|
wantInsecure bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "unix-tmp-sock",
|
||||||
input: "unix:/tmp/test.sock",
|
input: "unix:/tmp/test.sock",
|
||||||
wantURL: "unix:/tmp/test.sock",
|
wantURL: "unix:/tmp/test.sock",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "unix-var-run-docker-sock",
|
||||||
input: "unix:/var/run/docker.sock",
|
input: "unix:/var/run/docker.sock",
|
||||||
wantURL: "unix:/var/run/docker.sock",
|
wantURL: "unix:/var/run/docker.sock",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "unix-relative-sock",
|
||||||
input: "unix:./relative.sock",
|
input: "unix:./relative.sock",
|
||||||
wantURL: "unix:./relative.sock",
|
wantURL: "unix:./relative.sock",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
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)
|
gotURL, gotInsecure := expandProxyArg(tt.input)
|
||||||
if gotURL != tt.wantURL {
|
if gotURL != tt.wantURL {
|
||||||
t.Errorf("expandProxyArg(%q) url = %q, want %q", tt.input, gotURL, tt.wantURL)
|
t.Errorf("expandProxyArg(%q) url = %q, want %q", tt.input, gotURL, tt.wantURL)
|
||||||
|
|||||||
+5
-5
@@ -458,7 +458,7 @@ func TestPrefsFromBytesPreservesOldValues(t *testing.T) {
|
|||||||
want: Prefs{ControlURL: "https://foo", RouteAll: true},
|
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"},
|
old: Prefs{Sync: "unset"},
|
||||||
json: []byte(`{}`),
|
json: []byte(`{}`),
|
||||||
want: Prefs{Sync: "unset"},
|
want: Prefs{Sync: "unset"},
|
||||||
@@ -1236,13 +1236,13 @@ func TestParseAutoExitNodeString(t *testing.T) {
|
|||||||
wantExpr ExitNodeExpression
|
wantExpr ExitNodeExpression
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty expr",
|
name: "empty-expr",
|
||||||
exitNodeID: "",
|
exitNodeID: "",
|
||||||
wantOk: false,
|
wantOk: false,
|
||||||
wantExpr: "",
|
wantExpr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no auto prefix",
|
name: "no-auto-prefix",
|
||||||
exitNodeID: "foo",
|
exitNodeID: "foo",
|
||||||
wantOk: false,
|
wantOk: false,
|
||||||
wantExpr: "",
|
wantExpr: "",
|
||||||
@@ -1260,13 +1260,13 @@ func TestParseAutoExitNodeString(t *testing.T) {
|
|||||||
wantExpr: "foo",
|
wantExpr: "foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "auto prefix but empty suffix",
|
name: "auto-prefix-empty-suffix",
|
||||||
exitNodeID: "auto:",
|
exitNodeID: "auto:",
|
||||||
wantOk: false,
|
wantOk: false,
|
||||||
wantExpr: "",
|
wantExpr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "auto prefix no colon",
|
name: "auto-prefix-no-colon",
|
||||||
exitNodeID: "auto",
|
exitNodeID: "auto",
|
||||||
wantOk: false,
|
wantOk: false,
|
||||||
wantExpr: "",
|
wantExpr: "",
|
||||||
|
|||||||
+2
-2
@@ -283,11 +283,11 @@ func TestExpandProxyTargetDev(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{name: "port-only", input: "8080", expected: "http://127.0.0.1:8080"},
|
{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: "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: "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-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-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: "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"},
|
{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
|
ExpectsError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "single policy, denies all",
|
Name: "single-policy-denies-all",
|
||||||
ExpectedPolicyCount: 2,
|
ExpectedPolicyCount: 2,
|
||||||
Request: reconcile.Request{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
@@ -53,7 +53,7 @@ func TestReconciler_Reconcile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "multiple policies merged",
|
Name: "multiple-policies-merged",
|
||||||
ExpectedPolicyCount: 2,
|
ExpectedPolicyCount: 2,
|
||||||
Request: reconcile.Request{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
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,
|
ExpectedPolicyCount: 0,
|
||||||
Request: reconcile.Request{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func TestReconciler_Reconcile(t *testing.T) {
|
|||||||
ClientFunc func(*tsapi.Tailnet, *corev1.Secret) tailnet.TailscaleClient
|
ClientFunc func(*tsapi.Tailnet, *corev1.Secret) tailnet.TailscaleClient
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "ignores unknown tailnet requests",
|
Name: "ignores-unknown-tailnet-requests",
|
||||||
Request: reconcile.Request{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "test",
|
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{
|
Request: reconcile.Request{
|
||||||
NamespacedName: types.NamespacedName{
|
NamespacedName: types.NamespacedName{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
|||||||
@@ -39,19 +39,19 @@ func TestDelta(t *testing.T) {
|
|||||||
wantStats map[sockstats.Label]deltaStat
|
wantStats map[sockstats.Label]deltaStat
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "nil a stat",
|
name: "nil-a-stat",
|
||||||
a: nil,
|
a: nil,
|
||||||
b: &sockstats.SockStats{},
|
b: &sockstats.SockStats{},
|
||||||
wantStats: nil,
|
wantStats: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil b stat",
|
name: "nil-b-stat",
|
||||||
a: &sockstats.SockStats{},
|
a: &sockstats.SockStats{},
|
||||||
b: nil,
|
b: nil,
|
||||||
wantStats: nil,
|
wantStats: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no change",
|
name: "no-change",
|
||||||
a: &sockstats.SockStats{
|
a: &sockstats.SockStats{
|
||||||
Stats: map[sockstats.Label]sockstats.SockStat{
|
Stats: map[sockstats.Label]sockstats.SockStat{
|
||||||
sockstats.LabelDERPHTTPClient: {
|
sockstats.LabelDERPHTTPClient: {
|
||||||
@@ -69,7 +69,7 @@ func TestDelta(t *testing.T) {
|
|||||||
wantStats: nil,
|
wantStats: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tx after empty stat",
|
name: "tx-after-empty-stat",
|
||||||
a: &sockstats.SockStats{},
|
a: &sockstats.SockStats{},
|
||||||
b: &sockstats.SockStats{
|
b: &sockstats.SockStats{
|
||||||
Stats: map[sockstats.Label]sockstats.SockStat{
|
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{
|
a: &sockstats.SockStats{
|
||||||
Stats: map[sockstats.Label]sockstats.SockStat{
|
Stats: map[sockstats.Label]sockstats.SockStat{
|
||||||
sockstats.LabelDERPHTTPClient: {
|
sockstats.LabelDERPHTTPClient: {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "second last split last empty",
|
name: "second-last-split-last-empty",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -55,7 +55,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second last no split last empty",
|
name: "second-last-no-split-last-empty",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -68,7 +68,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second last no split last no split",
|
name: "second-last-no-split-last-no-split",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -81,7 +81,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second last no split last split",
|
name: "second-last-no-split-last-split",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -94,7 +94,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second last split last split",
|
name: "second-last-split-last-split",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -107,7 +107,7 @@ func Test_linuxBatchingConn_splitCoalescedMessages(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "second last no split last split overflow",
|
name: "second-last-no-split-last-split-overflow",
|
||||||
msgs: []ipv6.Message{
|
msgs: []ipv6.Message{
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
newMsg(0, 0),
|
newMsg(0, 0),
|
||||||
@@ -161,7 +161,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO []int
|
wantGSO []int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "one message no coalesce",
|
name: "one-message-no-coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
},
|
},
|
||||||
@@ -169,7 +169,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{0},
|
wantGSO: []int{0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "one message no coalesce vni.isSet",
|
name: "one-message-no-coalesce-vni-isSet",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
},
|
},
|
||||||
@@ -178,7 +178,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{0},
|
wantGSO: []int{0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two messages equal len coalesce",
|
name: "two-messages-equal-len-coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(1, 2),
|
withGeneveSpace(1, 2),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -187,7 +187,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{1},
|
wantGSO: []int{1},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two messages equal len coalesce vni.isSet",
|
name: "two-messages-equal-len-coalesce-vni-isSet",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(1, 2+packet.GeneveFixedHeaderLength),
|
withGeneveSpace(1, 2+packet.GeneveFixedHeaderLength),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -197,7 +197,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{1 + packet.GeneveFixedHeaderLength},
|
wantGSO: []int{1 + packet.GeneveFixedHeaderLength},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two messages unequal len coalesce",
|
name: "two-messages-unequal-len-coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 3),
|
withGeneveSpace(2, 3),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -206,7 +206,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{2},
|
wantGSO: []int{2},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two messages unequal len coalesce vni.isSet",
|
name: "two-messages-unequal-len-coalesce-vni-isSet",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 3+packet.GeneveFixedHeaderLength),
|
withGeneveSpace(2, 3+packet.GeneveFixedHeaderLength),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -216,7 +216,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{2 + packet.GeneveFixedHeaderLength},
|
wantGSO: []int{2 + packet.GeneveFixedHeaderLength},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "three messages second unequal len coalesce",
|
name: "three-messages-second-unequal-len-coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 3),
|
withGeneveSpace(2, 3),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -226,7 +226,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{2, 0},
|
wantGSO: []int{2, 0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "three messages second unequal len coalesce vni.isSet",
|
name: "three-messages-second-unequal-len-coalesce-vni-isSet",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 3+(2*packet.GeneveFixedHeaderLength)),
|
withGeneveSpace(2, 3+(2*packet.GeneveFixedHeaderLength)),
|
||||||
withGeneveSpace(1, 1),
|
withGeneveSpace(1, 1),
|
||||||
@@ -237,7 +237,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{2 + packet.GeneveFixedHeaderLength, 0},
|
wantGSO: []int{2 + packet.GeneveFixedHeaderLength, 0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "three messages limited cap coalesce",
|
name: "three-messages-limited-cap-coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 4),
|
withGeneveSpace(2, 4),
|
||||||
withGeneveSpace(2, 2),
|
withGeneveSpace(2, 2),
|
||||||
@@ -247,7 +247,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
wantGSO: []int{2},
|
wantGSO: []int{2},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "three messages limited cap coalesce vni.isSet",
|
name: "three-messages-limited-cap-coalesce-vni-isSet",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
withGeneveSpace(2, 4+packet.GeneveFixedHeaderLength),
|
withGeneveSpace(2, 4+packet.GeneveFixedHeaderLength),
|
||||||
withGeneveSpace(2, 2),
|
withGeneveSpace(2, 2),
|
||||||
@@ -376,19 +376,19 @@ func Test_getRXQOverflowsFromControl(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rxq overflows",
|
name: "rxq-overflows",
|
||||||
control: rxqOverflowsControl(1),
|
control: rxqOverflowsControl(1),
|
||||||
want: 1,
|
want: 1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple cmsg rxq overflows at head",
|
name: "multiple-cmsg-rxq-overflows-at-head",
|
||||||
control: append(rxqOverflowsControl(1), gsoControl(1)...),
|
control: append(rxqOverflowsControl(1), gsoControl(1)...),
|
||||||
want: 1,
|
want: 1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple cmsg rxq overflows at tail",
|
name: "multiple-cmsg-rxq-overflows-at-tail",
|
||||||
control: append(gsoControl(1), rxqOverflowsControl(1)...),
|
control: append(gsoControl(1), rxqOverflowsControl(1)...),
|
||||||
want: 1,
|
want: 1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@@ -432,19 +432,19 @@ func Test_getGSOSizeFromControl(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rxq overflows",
|
name: "rxq-overflows",
|
||||||
control: rxqOverflowsControl(1),
|
control: rxqOverflowsControl(1),
|
||||||
want: 0,
|
want: 0,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple cmsg gso at tail",
|
name: "multiple-cmsg-gso-at-tail",
|
||||||
control: append(rxqOverflowsControl(1), gsoControl(1)...),
|
control: append(rxqOverflowsControl(1), gsoControl(1)...),
|
||||||
want: 1,
|
want: 1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple cmsg gso at head",
|
name: "multiple-cmsg-gso-at-head",
|
||||||
control: append(gsoControl(1), rxqOverflowsControl(1)...),
|
control: append(gsoControl(1), rxqOverflowsControl(1)...),
|
||||||
want: 1,
|
want: 1,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func TestLinuxDNSMode(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no_obvious_resolv.conf_owner",
|
name: "no_obvious_resolvconf_owner",
|
||||||
env: env(resolvDotConf("nameserver 10.0.0.1")),
|
env: env(resolvDotConf("nameserver 10.0.0.1")),
|
||||||
wantLog: "dns: [rc=unknown ret=direct]",
|
wantLog: "dns: [rc=unknown ret=direct]",
|
||||||
want: "direct",
|
want: "direct",
|
||||||
@@ -153,7 +153,7 @@ func TestLinuxDNSMode(t *testing.T) {
|
|||||||
// alleged that it was managed by systemd-resolved, but it
|
// alleged that it was managed by systemd-resolved, but it
|
||||||
// was actually a completely static config file pointing
|
// was actually a completely static config file pointing
|
||||||
// elsewhere.
|
// 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")),
|
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" +
|
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]",
|
"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
|
// We used to incorrectly decide that resolved wasn't in
|
||||||
// charge when handed this (admittedly weird and bugged)
|
// charge when handed this (admittedly weird and bugged)
|
||||||
// resolv.conf.
|
// resolv.conf.
|
||||||
name: "resolved_with_duplicates_in_resolv.conf",
|
name: "resolved_with_duplicates_in_resolvconf",
|
||||||
env: env(
|
env: env(
|
||||||
resolvDotConf(
|
resolvDotConf(
|
||||||
"# Managed by systemd-resolved",
|
"# 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.
|
responses: [][]byte{ // All upstream servers fail except for one.
|
||||||
makeTestResponse(t, domain, dns.RCodeServerFailure),
|
makeTestResponse(t, domain, dns.RCodeServerFailure),
|
||||||
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.
|
responses: [][]byte{ // All upstream servers returned NXDOMAIN except for one.
|
||||||
makeTestResponse(t, domain, dns.RCodeNameError),
|
makeTestResponse(t, domain, dns.RCodeNameError),
|
||||||
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.
|
responses: [][]byte{ // Some upstream servers refuse, but one succeeds.
|
||||||
makeTestResponse(t, domain, dns.RCodeRefused),
|
makeTestResponse(t, domain, dns.RCodeRefused),
|
||||||
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.
|
responses: [][]byte{ // Some servers refuse, at least one fails.
|
||||||
makeTestResponse(t, domain, dns.RCodeRefused),
|
makeTestResponse(t, domain, dns.RCodeRefused),
|
||||||
makeTestResponse(t, domain, dns.RCodeServerFailure),
|
makeTestResponse(t, domain, dns.RCodeServerFailure),
|
||||||
|
|||||||
@@ -998,7 +998,7 @@ func TestNodeAddrResolve(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Logf("got IPv6 addr: %v", ap)
|
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)
|
ap, ok := c.nodeAddrPort(ctx, dnV4Only, dn.STUNPort, probeIPv6)
|
||||||
if ok {
|
if ok {
|
||||||
t.Fatalf("expected no addr but got: %v", ap)
|
t.Fatalf("expected no addr but got: %v", ap)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func TestIgnoreDuplicateNEWADDR(t *testing.T) {
|
|||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("suppress duplicate NEWADDRs", func(t *testing.T) {
|
t.Run("suppress-duplicate-NEWADDRs", func(t *testing.T) {
|
||||||
c := nlConn{
|
c := nlConn{
|
||||||
buffered: []netlink.Message{
|
buffered: []netlink.Message{
|
||||||
newAddrMsg(1, "192.168.0.5", unix.RTM_NEWADDR),
|
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{
|
c := nlConn{
|
||||||
buffered: []netlink.Message{
|
buffered: []netlink.Message{
|
||||||
newAddrMsg(1, "192.168.0.5", unix.RTM_NEWADDR),
|
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
|
// ensure that the test returns an appropriate number of Result structs
|
||||||
expectedLen := int(DefaultDuration.Seconds()) + 1
|
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
|
// conduct a download test
|
||||||
results, err := RunClient(Download, DefaultDuration, serverIP)
|
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
|
// conduct an upload test
|
||||||
results, err := RunClient(Upload, DefaultDuration, serverIP)
|
results, err := RunClient(Upload, DefaultDuration, serverIP)
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ var responseTests = []struct {
|
|||||||
wantPort: 59029,
|
wantPort: 59029,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "stun.sipgate.net:10000",
|
name: "stun-sipgate-net-10000",
|
||||||
data: []byte{
|
data: []byte{
|
||||||
0x01, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42,
|
0x01, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42,
|
||||||
0x48, 0x2e, 0xb6, 0x47, 0x15, 0xe8, 0xb2, 0x8e,
|
0x48, 0x2e, 0xb6, 0x47, 0x15, 0xe8, 0xb2, 0x8e,
|
||||||
@@ -82,7 +82,7 @@ var responseTests = []struct {
|
|||||||
wantPort: 58539,
|
wantPort: 58539,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "stun.powervoip.com:3478",
|
name: "stun-powervoip-com-3478",
|
||||||
data: []byte{
|
data: []byte{
|
||||||
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
|
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
|
||||||
0x7e, 0x57, 0x96, 0x68, 0x29, 0xf4, 0x44, 0x60,
|
0x7e, 0x57, 0x96, 0x68, 0x29, 0xf4, 0x44, 0x60,
|
||||||
@@ -100,7 +100,7 @@ var responseTests = []struct {
|
|||||||
wantPort: 59859,
|
wantPort: 59859,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "in-process pion server",
|
name: "in-process-pion-server",
|
||||||
data: []byte{
|
data: []byte{
|
||||||
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
|
0x01, 0x01, 0x00, 0x24, 0x21, 0x12, 0xa4, 0x42,
|
||||||
0xeb, 0xc2, 0xd3, 0x6e, 0xf4, 0x71, 0x21, 0x7c,
|
0xeb, 0xc2, 0xd3, 0x6e, 0xf4, 0x71, 0x21, 0x7c,
|
||||||
@@ -119,7 +119,7 @@ var responseTests = []struct {
|
|||||||
wantPort: 61300,
|
wantPort: 61300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "stuntman-server ipv6",
|
name: "stuntman-server-ipv6",
|
||||||
data: []byte{
|
data: []byte{
|
||||||
0x01, 0x01, 0x00, 0x48, 0x21, 0x12, 0xa4, 0x42,
|
0x01, 0x01, 0x00, 0x48, 0x21, 0x12, 0xa4, 0x42,
|
||||||
0x06, 0xf5, 0x66, 0x85, 0xd2, 0x8a, 0xf3, 0xe6,
|
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"))
|
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 {
|
if _, err := os.Stat(synologyProxyConfigPath); err == nil {
|
||||||
t.Fatalf("%s must not exist for this test", synologyProxyConfigPath)
|
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.updated = time.Now()
|
||||||
cache.httpProxy = nil
|
cache.httpProxy = nil
|
||||||
cache.httpsProxy = 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.updated = time.Now()
|
||||||
cache.httpProxy = urlMustParse("http://127.0.0.1/")
|
cache.httpProxy = urlMustParse("http://127.0.0.1/")
|
||||||
cache.httpsProxy = 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.updated = time.Now()
|
||||||
cache.httpProxy = nil
|
cache.httpProxy = nil
|
||||||
cache.httpsProxy = nil
|
cache.httpsProxy = nil
|
||||||
@@ -164,7 +164,7 @@ func TestSynologyProxiesFromConfig(t *testing.T) {
|
|||||||
return openReader, openErr
|
return openReader, openErr
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("with config", func(t *testing.T) {
|
t.Run("with-config", func(t *testing.T) {
|
||||||
mc := &mustCloser{Reader: strings.NewReader(`
|
mc := &mustCloser{Reader: strings.NewReader(`
|
||||||
proxy_user=foo
|
proxy_user=foo
|
||||||
proxy_pwd=bar
|
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
|
openReader = nil
|
||||||
openErr = os.ErrNotExist
|
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
|
openReader = nil
|
||||||
openErr = errors.New("example error")
|
openErr = errors.New("example error")
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func TestSetSelfProxy(t *testing.T) {
|
|||||||
wantHTTPS string
|
wantHTTPS string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no self proxy",
|
name: "no-self-proxy",
|
||||||
env: map[string]string{
|
env: map[string]string{
|
||||||
"HTTP_PROXY": "127.0.0.1:1234",
|
"HTTP_PROXY": "127.0.0.1:1234",
|
||||||
"HTTPS_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",
|
wantHTTPS: "127.0.0.1:1234",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "skip proxies",
|
name: "skip-proxies",
|
||||||
env: map[string]string{
|
env: map[string]string{
|
||||||
"HTTP_PROXY": "127.0.0.1:1234",
|
"HTTP_PROXY": "127.0.0.1:1234",
|
||||||
"HTTPS_PROXY": "127.0.0.1:5678",
|
"HTTPS_PROXY": "127.0.0.1:5678",
|
||||||
@@ -117,7 +117,7 @@ func TestSetSelfProxy(t *testing.T) {
|
|||||||
wantHTTPS: "", // skipped
|
wantHTTPS: "", // skipped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "localhost normalization of env var",
|
name: "localhost-normalization-of-env-var",
|
||||||
env: map[string]string{
|
env: map[string]string{
|
||||||
"HTTP_PROXY": "localhost:1234",
|
"HTTP_PROXY": "localhost:1234",
|
||||||
"HTTPS_PROXY": "[::1]:5678",
|
"HTTPS_PROXY": "[::1]:5678",
|
||||||
@@ -127,7 +127,7 @@ func TestSetSelfProxy(t *testing.T) {
|
|||||||
wantHTTPS: "", // skipped
|
wantHTTPS: "", // skipped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "localhost normalization of addr",
|
name: "localhost-normalization-of-addr",
|
||||||
env: map[string]string{
|
env: map[string]string{
|
||||||
"HTTP_PROXY": "127.0.0.1:1234",
|
"HTTP_PROXY": "127.0.0.1:1234",
|
||||||
"HTTPS_PROXY": "127.0.0.1:1234",
|
"HTTPS_PROXY": "127.0.0.1:1234",
|
||||||
@@ -137,7 +137,7 @@ func TestSetSelfProxy(t *testing.T) {
|
|||||||
wantHTTPS: "", // skipped
|
wantHTTPS: "", // skipped
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no ports",
|
name: "no-ports",
|
||||||
env: map[string]string{
|
env: map[string]string{
|
||||||
"HTTP_PROXY": "myproxy",
|
"HTTP_PROXY": "myproxy",
|
||||||
"HTTPS_PROXY": "myproxy",
|
"HTTPS_PROXY": "myproxy",
|
||||||
|
|||||||
@@ -28,32 +28,32 @@ func TestServerEndpointJSONUnmarshal(t *testing.T) {
|
|||||||
wantErr: false,
|
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"}`),
|
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,
|
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"}`),
|
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,
|
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"}`),
|
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,
|
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"}`),
|
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,
|
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"}`),
|
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,
|
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"}`),
|
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,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@@ -79,7 +79,7 @@ func TestServerEndpointJSONMarshal(t *testing.T) {
|
|||||||
serverEndpoint ServerEndpoint
|
serverEndpoint ServerEndpoint
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "valid roundtrip",
|
name: "valid-roundtrip",
|
||||||
serverEndpoint: ServerEndpoint{
|
serverEndpoint: ServerEndpoint{
|
||||||
ServerDisco: key.NewDisco().Public(),
|
ServerDisco: key.NewDisco().Public(),
|
||||||
LamportID: uint64(math.MaxUint64),
|
LamportID: uint64(math.MaxUint64),
|
||||||
|
|||||||
@@ -196,15 +196,15 @@ func TestServer(t *testing.T) {
|
|||||||
forceClientsMixedAF bool
|
forceClientsMixedAF bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "over ipv4",
|
name: "over-ipv4",
|
||||||
staticAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1")},
|
staticAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1")},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "over ipv6",
|
name: "over-ipv6",
|
||||||
staticAddrs: []netip.Addr{netip.MustParseAddr("::1")},
|
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")},
|
staticAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1"), netip.MustParseAddr("::1")},
|
||||||
forceClientsMixedAF: true,
|
forceClientsMixedAF: true,
|
||||||
},
|
},
|
||||||
|
|||||||
+35
-35
@@ -41,25 +41,25 @@ func TestPostRequestContentTypeValidation(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "API routes should accept `application/json` content-type",
|
name: "API-accept-application-json",
|
||||||
browserRoute: false,
|
browserRoute: false,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "API routes should reject `application/x-www-form-urlencoded` content-type",
|
name: "API-reject-form-urlencoded",
|
||||||
browserRoute: false,
|
browserRoute: false,
|
||||||
contentType: "application/x-www-form-urlencoded",
|
contentType: "application/x-www-form-urlencoded",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Browser routes should accept `application/x-www-form-urlencoded` content-type",
|
name: "browser-accept-form-urlencoded",
|
||||||
browserRoute: true,
|
browserRoute: true,
|
||||||
contentType: "application/x-www-form-urlencoded",
|
contentType: "application/x-www-form-urlencoded",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non Browser routes should accept `application/json` content-type",
|
name: "browser-accept-application-json",
|
||||||
browserRoute: true,
|
browserRoute: true,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@@ -106,21 +106,21 @@ func TestAPIMuxCrossOriginResourceSharingHeaders(t *testing.T) {
|
|||||||
corsMethods []string
|
corsMethods []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "do not set CORS headers for non-OPTIONS requests",
|
name: "no-CORS-headers-for-non-OPTIONS",
|
||||||
corsOrigins: []string{"https://foobar.com"},
|
corsOrigins: []string{"https://foobar.com"},
|
||||||
corsMethods: []string{"GET", "POST", "HEAD"},
|
corsMethods: []string{"GET", "POST", "HEAD"},
|
||||||
httpMethod: "GET",
|
httpMethod: "GET",
|
||||||
wantCORSHeaders: false,
|
wantCORSHeaders: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set CORS headers for non-OPTIONS requests",
|
name: "CORS-headers-for-OPTIONS",
|
||||||
corsOrigins: []string{"https://foobar.com"},
|
corsOrigins: []string{"https://foobar.com"},
|
||||||
corsMethods: []string{"GET", "POST", "HEAD"},
|
corsMethods: []string{"GET", "POST", "HEAD"},
|
||||||
httpMethod: "OPTIONS",
|
httpMethod: "OPTIONS",
|
||||||
wantCORSHeaders: true,
|
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",
|
httpMethod: "OPTIONS",
|
||||||
wantCORSHeaders: false,
|
wantCORSHeaders: false,
|
||||||
},
|
},
|
||||||
@@ -162,19 +162,19 @@ func TestCSRFProtection(t *testing.T) {
|
|||||||
wantStatus int
|
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,
|
apiRoute: false,
|
||||||
passCSRFToken: false,
|
passCSRFToken: false,
|
||||||
wantStatus: http.StatusForbidden,
|
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,
|
apiRoute: false,
|
||||||
passCSRFToken: true,
|
passCSRFToken: true,
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "POST requests to /api/ routes do not require CSRF token",
|
name: "API-POST-without-CSRF-passes",
|
||||||
apiRoute: true,
|
apiRoute: true,
|
||||||
passCSRFToken: false,
|
passCSRFToken: false,
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
@@ -246,11 +246,11 @@ func TestContentSecurityPolicyHeader(t *testing.T) {
|
|||||||
wantCSP string
|
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';`,
|
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{
|
csp: CSP{
|
||||||
"default-src": {"'self'", "https://tailscale.com"},
|
"default-src": {"'self'", "https://tailscale.com"},
|
||||||
"upgrade-insecure-requests": nil,
|
"upgrade-insecure-requests": nil,
|
||||||
@@ -258,7 +258,7 @@ func TestContentSecurityPolicyHeader(t *testing.T) {
|
|||||||
wantCSP: `default-src 'self' https://tailscale.com; upgrade-insecure-requests;`,
|
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,
|
apiRoute: true,
|
||||||
wantCSP: "",
|
wantCSP: "",
|
||||||
},
|
},
|
||||||
@@ -301,12 +301,12 @@ func TestCSRFCookieSecureMode(t *testing.T) {
|
|||||||
wantSecure bool
|
wantSecure bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "CSRF cookie should be secure when server is in secure context",
|
name: "secure-context-cookie-secure",
|
||||||
secureMode: true,
|
secureMode: true,
|
||||||
wantSecure: 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,
|
secureMode: false,
|
||||||
wantSecure: false,
|
wantSecure: false,
|
||||||
},
|
},
|
||||||
@@ -343,12 +343,12 @@ func TestRefererPolicy(t *testing.T) {
|
|||||||
wantRefererPolicy bool
|
wantRefererPolicy bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "BrowserMux routes get Referer-Policy headers",
|
name: "BrowserMux-gets-Referer-Policy",
|
||||||
browserRoute: true,
|
browserRoute: true,
|
||||||
wantRefererPolicy: true,
|
wantRefererPolicy: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "APIMux routes do not get Referer-Policy headers",
|
name: "APIMux-no-Referer-Policy",
|
||||||
browserRoute: false,
|
browserRoute: false,
|
||||||
wantRefererPolicy: false,
|
wantRefererPolicy: false,
|
||||||
},
|
},
|
||||||
@@ -420,54 +420,54 @@ func TestRouting(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "only browser mux",
|
desc: "only-browser-mux",
|
||||||
browserPatterns: []string{"/"},
|
browserPatterns: []string{"/"},
|
||||||
requestPath: "/index.html",
|
requestPath: "/index.html",
|
||||||
want: "browser",
|
want: "browser",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "only API mux",
|
desc: "only-API-mux",
|
||||||
apiPatterns: []string{"/api/"},
|
apiPatterns: []string{"/api/"},
|
||||||
requestPath: "/api/foo",
|
requestPath: "/api/foo",
|
||||||
want: "api",
|
want: "api",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "browser mux match",
|
desc: "browser-mux-match",
|
||||||
browserPatterns: []string{"/content/"},
|
browserPatterns: []string{"/content/"},
|
||||||
apiPatterns: []string{"/api/"},
|
apiPatterns: []string{"/api/"},
|
||||||
requestPath: "/content/index.html",
|
requestPath: "/content/index.html",
|
||||||
want: "browser",
|
want: "browser",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "API mux match",
|
desc: "API-mux-match",
|
||||||
browserPatterns: []string{"/content/"},
|
browserPatterns: []string{"/content/"},
|
||||||
apiPatterns: []string{"/api/"},
|
apiPatterns: []string{"/api/"},
|
||||||
requestPath: "/api/foo",
|
requestPath: "/api/foo",
|
||||||
want: "api",
|
want: "api",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "browser wildcard match",
|
desc: "browser-wildcard-match",
|
||||||
browserPatterns: []string{"/"},
|
browserPatterns: []string{"/"},
|
||||||
apiPatterns: []string{"/api/"},
|
apiPatterns: []string{"/api/"},
|
||||||
requestPath: "/index.html",
|
requestPath: "/index.html",
|
||||||
want: "browser",
|
want: "browser",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "API wildcard match",
|
desc: "API-wildcard-match",
|
||||||
browserPatterns: []string{"/content/"},
|
browserPatterns: []string{"/content/"},
|
||||||
apiPatterns: []string{"/"},
|
apiPatterns: []string{"/"},
|
||||||
requestPath: "/api/foo",
|
requestPath: "/api/foo",
|
||||||
want: "api",
|
want: "api",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "path conflict",
|
desc: "path-conflict",
|
||||||
browserPatterns: []string{"/foo/"},
|
browserPatterns: []string{"/foo/"},
|
||||||
apiPatterns: []string{"/foo/bar/"},
|
apiPatterns: []string{"/foo/bar/"},
|
||||||
requestPath: "/foo/bar/baz",
|
requestPath: "/foo/bar/baz",
|
||||||
want: "api",
|
want: "api",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "no match",
|
desc: "no-match",
|
||||||
browserPatterns: []string{"/foo/"},
|
browserPatterns: []string{"/foo/"},
|
||||||
apiPatterns: []string{"/bar/"},
|
apiPatterns: []string{"/bar/"},
|
||||||
requestPath: "/baz",
|
requestPath: "/baz",
|
||||||
@@ -521,43 +521,43 @@ func TestGetMoreSpecificPattern(t *testing.T) {
|
|||||||
want: unknownHandler,
|
want: unknownHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "identical prefix",
|
desc: "identical-prefix",
|
||||||
a: "/foo/bar/",
|
a: "/foo/bar/",
|
||||||
b: "/foo/bar/",
|
b: "/foo/bar/",
|
||||||
want: unknownHandler,
|
want: unknownHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "trailing slash",
|
desc: "trailing-slash",
|
||||||
a: "/foo",
|
a: "/foo",
|
||||||
b: "/foo/", // path.Clean will strip the trailing slash.
|
b: "/foo/", // path.Clean will strip the trailing slash.
|
||||||
want: unknownHandler,
|
want: unknownHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "same prefix",
|
desc: "same-prefix",
|
||||||
a: "/foo/bar/quux",
|
a: "/foo/bar/quux",
|
||||||
b: "/foo/bar/", // path.Clean will strip the trailing slash.
|
b: "/foo/bar/", // path.Clean will strip the trailing slash.
|
||||||
want: apiHandler,
|
want: apiHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "almost same prefix, but not a path component",
|
desc: "almost-same-prefix-not-path-component",
|
||||||
a: "/goat/sheep/cheese",
|
a: "/goat/sheep/cheese",
|
||||||
b: "/goat/sheepcheese/", // path.Clean will strip the trailing slash.
|
b: "/goat/sheepcheese/", // path.Clean will strip the trailing slash.
|
||||||
want: apiHandler,
|
want: apiHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "attempt to make less-specific pattern look more specific",
|
desc: "traversal-less-specific-pattern",
|
||||||
a: "/goat/cat/buddy",
|
a: "/goat/cat/buddy",
|
||||||
b: "/goat/../../../../../../../cat", // path.Clean catches this foolishness
|
b: "/goat/../../../../../../../cat", // path.Clean catches this foolishness
|
||||||
want: apiHandler,
|
want: apiHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "2 names for / (1)",
|
desc: "two-names-for-root-1",
|
||||||
a: "/",
|
a: "/",
|
||||||
b: "/../../../../../../",
|
b: "/../../../../../../",
|
||||||
want: unknownHandler,
|
want: unknownHandler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "2 names for / (2)",
|
desc: "two-names-for-root-2",
|
||||||
a: "/",
|
a: "/",
|
||||||
b: "///////",
|
b: "///////",
|
||||||
want: unknownHandler,
|
want: unknownHandler,
|
||||||
@@ -586,15 +586,15 @@ func TestStrictTransportSecurityOptions(t *testing.T) {
|
|||||||
expect string
|
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,
|
secureContext: true,
|
||||||
expect: DefaultStrictTransportSecurityOptions,
|
expect: DefaultStrictTransportSecurityOptions,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "custom options sent in the secure context",
|
name: "custom-options-in-secure-context",
|
||||||
options: DefaultStrictTransportSecurityOptions + "; includeSubDomains",
|
options: DefaultStrictTransportSecurityOptions + "; includeSubDomains",
|
||||||
secureContext: true,
|
secureContext: true,
|
||||||
expect: DefaultStrictTransportSecurityOptions + "; includeSubDomains",
|
expect: DefaultStrictTransportSecurityOptions + "; includeSubDomains",
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func TestConnectToRecorder(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "v1 recorder",
|
desc: "v1-recorder",
|
||||||
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
||||||
uploadHash := make(chan []byte, 1)
|
uploadHash := make(chan []byte, 1)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
@@ -50,7 +50,7 @@ func TestConnectToRecorder(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "v2 recorder",
|
desc: "v2-recorder",
|
||||||
http2: true,
|
http2: true,
|
||||||
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
||||||
uploadHash := make(chan []byte, 1)
|
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,
|
http2: true,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
setup: func(t *testing.T) (*http.ServeMux, <-chan []byte) {
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
) {
|
) {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
}).shellNix
|
}).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
|
wantErrMessage string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "simple direct matches",
|
name: "simple-direct-matches",
|
||||||
acceptEnv: []string{"FOO", "FOO2", "FOO_3"},
|
acceptEnv: []string{"FOO", "FOO2", "FOO_3"},
|
||||||
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
|
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
|
||||||
expectedFiltered: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123"},
|
expectedFiltered: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bare wildcard",
|
name: "bare-wildcard",
|
||||||
acceptEnv: []string{"*"},
|
acceptEnv: []string{"*"},
|
||||||
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
|
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG"},
|
||||||
expectedFiltered: []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"},
|
acceptEnv: []string{"FO?", "FOOO*", "FO*5?7"},
|
||||||
environ: []string{"FOO=BAR", "FOO2=BAZ", "FOO_3=123", "FOOOO4-2=AbCdEfG", "FO1-kmndGamc79567=ABC", "FO57=BAR2"},
|
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"},
|
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"},
|
acceptEnv: []string{"FO?", "FOOO*", "FO*5?7"},
|
||||||
environ: []string{"FOOBAR"},
|
environ: []string{"FOOBAR"},
|
||||||
expectedFiltered: nil,
|
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()
|
m := NewShardedInt()
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
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()
|
m := NewShardedInt()
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
numWorkers := 1000
|
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 := NewShardedInt()
|
||||||
m.Add(1)
|
m.Add(1)
|
||||||
b := make([]byte, 0, 10)
|
b := make([]byte, 0, 10)
|
||||||
|
|||||||
@@ -18,31 +18,35 @@ func TestProtoPortRangeParsing(t *testing.T) {
|
|||||||
return PortRange{First: s, Last: e}
|
return PortRange{First: s, Last: e}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
in string
|
name string
|
||||||
out ProtoPortRange
|
in string
|
||||||
err error
|
out ProtoPortRange
|
||||||
|
err error
|
||||||
}{
|
}{
|
||||||
{in: "tcp:80", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: pr(80, 80)}},
|
{name: "tcp-80", in: "tcp:80", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: pr(80, 80)}},
|
||||||
{in: "80", out: ProtoPortRange{Ports: pr(80, 80)}},
|
{name: "80", in: "80", out: ProtoPortRange{Ports: pr(80, 80)}},
|
||||||
{in: "*", out: ProtoPortRange{Ports: PortRangeAny}},
|
{name: "star", in: "*", out: ProtoPortRange{Ports: PortRangeAny}},
|
||||||
{in: "*:*", out: ProtoPortRange{Ports: PortRangeAny}},
|
{name: "star-star", in: "*:*", out: ProtoPortRange{Ports: PortRangeAny}},
|
||||||
{in: "tcp:*", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: PortRangeAny}},
|
{name: "tcp-star", in: "tcp:*", out: ProtoPortRange{Proto: int(ipproto.TCP), Ports: PortRangeAny}},
|
||||||
{
|
{
|
||||||
in: "tcp:",
|
name: "tcp-empty-port",
|
||||||
err: vizerror.Errorf("invalid port list: %#v", ""),
|
in: "tcp:",
|
||||||
|
err: vizerror.Errorf("invalid port list: %#v", ""),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
in: ":80",
|
name: "empty-proto-80",
|
||||||
err: errEmptyProtocol,
|
in: ":80",
|
||||||
|
err: errEmptyProtocol,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
in: "",
|
name: "empty-string",
|
||||||
err: errEmptyString,
|
in: "",
|
||||||
|
err: errEmptyString,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.in, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var ppr ProtoPortRange
|
var ppr ProtoPortRange
|
||||||
err := ppr.UnmarshalText([]byte(tc.in))
|
err := ppr.UnmarshalText([]byte(tc.in))
|
||||||
if tc.err != err {
|
if tc.err != err {
|
||||||
|
|||||||
@@ -841,12 +841,12 @@ func TestMarshalToRawMessageAndBack(t *testing.T) {
|
|||||||
capType: PeerCapability("foo"),
|
capType: PeerCapability("foo"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "some values",
|
name: "some-values",
|
||||||
val: testRule{Ports: []int{80, 443}, Name: "foo"},
|
val: testRule{Ports: []int{80, 443}, Name: "foo"},
|
||||||
capType: PeerCapability("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}},
|
val: testRule{Ports: []int{80, 443}, Name: "foo", ToggleOn: true, Groups: inner{Groups: []string{"foo", "bar"}}, Addrs: []netip.AddrPort{testip}},
|
||||||
capType: PeerCapability("foo"),
|
capType: PeerCapability("foo"),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ func TestMarkActiveChain(t *testing.T) {
|
|||||||
expectLastActiveIdx: 0,
|
expectLastActiveIdx: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "simple truncate",
|
name: "simple-truncate",
|
||||||
minChain: 2,
|
minChain: 2,
|
||||||
chain: []aumTemplate{
|
chain: []aumTemplate{
|
||||||
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
||||||
@@ -196,7 +196,7 @@ func TestMarkActiveChain(t *testing.T) {
|
|||||||
expectLastActiveIdx: 1,
|
expectLastActiveIdx: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "long truncate",
|
name: "long-truncate",
|
||||||
minChain: 5,
|
minChain: 5,
|
||||||
chain: []aumTemplate{
|
chain: []aumTemplate{
|
||||||
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
||||||
@@ -211,7 +211,7 @@ func TestMarkActiveChain(t *testing.T) {
|
|||||||
expectLastActiveIdx: 2,
|
expectLastActiveIdx: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "truncate finding checkpoint",
|
name: "truncate-finding-checkpoint",
|
||||||
minChain: 2,
|
minChain: 2,
|
||||||
chain: []aumTemplate{
|
chain: []aumTemplate{
|
||||||
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
{AUM: AUM{MessageKind: AUMCheckpoint, State: &State{}}},
|
||||||
@@ -342,7 +342,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
|
|||||||
wantRetained: []string{"A"},
|
wantRetained: []string{"A"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no adjustment",
|
name: "no-adjustment",
|
||||||
chain: newTestchain(t, `
|
chain: newTestchain(t, `
|
||||||
DEAD -> A -> B -> C
|
DEAD -> A -> B -> C
|
||||||
A.template = checkpoint
|
A.template = checkpoint
|
||||||
@@ -380,7 +380,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
|
|||||||
wantDeleted: []string{"A", "B"},
|
wantDeleted: []string{"A", "B"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fork finding earlier checkpoint",
|
name: "fork-finding-earlier-checkpoint",
|
||||||
chain: newTestchain(t, `
|
chain: newTestchain(t, `
|
||||||
A -> B -> C -> D -> E -> F
|
A -> B -> C -> D -> E -> F
|
||||||
| -> FORK
|
| -> FORK
|
||||||
@@ -403,7 +403,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
|
|||||||
wantDeleted: []string{"A"},
|
wantDeleted: []string{"A"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fork multi",
|
name: "fork-multi",
|
||||||
chain: newTestchain(t, `
|
chain: newTestchain(t, `
|
||||||
A -> B -> C -> D -> E
|
A -> B -> C -> D -> E
|
||||||
| -> DEADFORK
|
| -> DEADFORK
|
||||||
@@ -429,7 +429,7 @@ func TestMarkAncestorIntersectionAUMs(t *testing.T) {
|
|||||||
wantDeleted: []string{"A", "B", "DEADFORK"},
|
wantDeleted: []string{"A", "B", "DEADFORK"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fork multi 2",
|
name: "fork-multi-2",
|
||||||
chain: newTestchain(t, `
|
chain: newTestchain(t, `
|
||||||
A -> B -> C -> D -> E -> F -> G
|
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) {
|
func TestAuthRefreshErrorsNotRunning(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
name string
|
||||||
in *ipnstate.Status
|
in *ipnstate.Status
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "no-status",
|
||||||
in: nil,
|
in: nil,
|
||||||
expected: "no status",
|
expected: "no status",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "ts-server-not-running",
|
||||||
in: &ipnstate.Status{
|
in: &ipnstate.Status{
|
||||||
BackendState: "NeedsMachineAuth",
|
BackendState: "NeedsMachineAuth",
|
||||||
},
|
},
|
||||||
@@ -84,7 +87,7 @@ func TestAuthRefreshErrorsNotRunning(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.expected, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ctx := t.Context()
|
ctx := t.Context()
|
||||||
a := authForStatus(tt.in)
|
a := authForStatus(tt.in)
|
||||||
err := a.Refresh(ctx)
|
err := a.Refresh(ctx)
|
||||||
@@ -127,22 +130,22 @@ func TestAuthAllowsHost(t *testing.T) {
|
|||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "tagged with different tag",
|
name: "tagged-different-tag",
|
||||||
peerStatus: peers[0],
|
peerStatus: peers[0],
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not tagged",
|
name: "not-tagged",
|
||||||
peerStatus: peers[1],
|
peerStatus: peers[1],
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tags includes testTag",
|
name: "tags-include-testTag",
|
||||||
peerStatus: peers[2],
|
peerStatus: peers[2],
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "only tag is testTag",
|
name: "only-testTag",
|
||||||
peerStatus: peers[3],
|
peerStatus: peers[3],
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
@@ -201,12 +204,12 @@ func TestAuthSelfAllowed(t *testing.T) {
|
|||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "self has different tag",
|
name: "self-different-tag",
|
||||||
in: []string{"woo"},
|
in: []string{"woo"},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "selfs tags include testTag",
|
name: "self-tags-include-testTag",
|
||||||
in: []string{"woo", testTag},
|
in: []string{"woo", testTag},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
|||||||
+17
-17
@@ -2933,7 +2933,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains string
|
wantErrContains string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "successful resolution via OAuth client secret",
|
name: "success-oauth-client-secret",
|
||||||
clientSecret: "tskey-client-secret-123",
|
clientSecret: "tskey-client-secret-123",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
||||||
@@ -2946,7 +2946,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failing resolution via OAuth client secret",
|
name: "fail-oauth-client-secret",
|
||||||
clientSecret: "tskey-client-secret-123",
|
clientSecret: "tskey-client-secret-123",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
||||||
@@ -2955,7 +2955,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "resolution failed",
|
wantErrContains: "resolution failed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "successful resolution via federated ID token",
|
name: "success-federated-id-token",
|
||||||
clientID: "client-id-123",
|
clientID: "client-id-123",
|
||||||
idToken: "id-token-456",
|
idToken: "id-token-456",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -2972,7 +2972,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "successful resolution via federated audience",
|
name: "success-federated-audience",
|
||||||
clientID: "client-id-123",
|
clientID: "client-id-123",
|
||||||
audience: "api.tailscale.com",
|
audience: "api.tailscale.com",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -2989,7 +2989,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failing resolution via federated ID token",
|
name: "fail-federated-id-token",
|
||||||
clientID: "client-id-123",
|
clientID: "client-id-123",
|
||||||
idToken: "id-token-456",
|
idToken: "id-token-456",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -2999,7 +2999,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "resolution failed",
|
wantErrContains: "resolution failed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty client ID with ID token",
|
name: "empty-client-id-with-token",
|
||||||
clientID: "",
|
clientID: "",
|
||||||
idToken: "id-token-456",
|
idToken: "id-token-456",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -3009,7 +3009,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "empty",
|
wantErrContains: "empty",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty client ID with audience",
|
name: "empty-client-id-with-audience",
|
||||||
clientID: "",
|
clientID: "",
|
||||||
audience: "api.tailscale.com",
|
audience: "api.tailscale.com",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -3019,7 +3019,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "empty",
|
wantErrContains: "empty",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty ID token",
|
name: "empty-id-token",
|
||||||
clientID: "client-id-123",
|
clientID: "client-id-123",
|
||||||
idToken: "",
|
idToken: "",
|
||||||
wifAvailable: true,
|
wifAvailable: true,
|
||||||
@@ -3029,7 +3029,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "empty",
|
wantErrContains: "empty",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "audience with ID token",
|
name: "audience-with-id-token",
|
||||||
clientID: "client-id-123",
|
clientID: "client-id-123",
|
||||||
idToken: "id-token-456",
|
idToken: "id-token-456",
|
||||||
audience: "api.tailscale.com",
|
audience: "api.tailscale.com",
|
||||||
@@ -3040,7 +3040,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "only one of ID token and audience",
|
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",
|
clientSecret: "tskey-client-secret-123",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
||||||
@@ -3057,7 +3057,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "workload identity resolution skipped if resolution via OAuth token fails",
|
name: "wif-skipped-oauth-fails",
|
||||||
clientID: "tskey-client-id-123",
|
clientID: "tskey-client-id-123",
|
||||||
idToken: "",
|
idToken: "",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
@@ -3071,7 +3071,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "failed",
|
wantErrContains: "failed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "authkey set and no resolution available",
|
name: "authkey-set-no-resolution",
|
||||||
authKey: "tskey-auth-123",
|
authKey: "tskey-auth-123",
|
||||||
oauthAvailable: false,
|
oauthAvailable: false,
|
||||||
wifAvailable: false,
|
wifAvailable: false,
|
||||||
@@ -3079,14 +3079,14 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no authkey set and no resolution available",
|
name: "no-authkey-no-resolution",
|
||||||
oauthAvailable: false,
|
oauthAvailable: false,
|
||||||
wifAvailable: false,
|
wifAvailable: false,
|
||||||
wantAuthKey: "",
|
wantAuthKey: "",
|
||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "authkey is client secret and resolution via OAuth client secret succeeds",
|
name: "authkey-client-secret-oauth-succeeds",
|
||||||
authKey: "tskey-client-secret-123",
|
authKey: "tskey-client-secret-123",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
||||||
@@ -3099,7 +3099,7 @@ func TestResolveAuthKey(t *testing.T) {
|
|||||||
wantErrContains: "",
|
wantErrContains: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "authkey is client secret but resolution via OAuth client secret fails",
|
name: "authkey-client-secret-oauth-fails",
|
||||||
authKey: "tskey-client-secret-123",
|
authKey: "tskey-client-secret-123",
|
||||||
oauthAvailable: true,
|
oauthAvailable: true,
|
||||||
resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
|
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) {
|
t.Run("Netstack", func(t *testing.T) {
|
||||||
lt := setupTwoClientTest(t, false)
|
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("::", func(t *testing.T) { testUnspec(t, lt, "[::]:8081", "8081") })
|
||||||
})
|
})
|
||||||
t.Run("TUN", func(t *testing.T) {
|
t.Run("TUN", func(t *testing.T) {
|
||||||
lt := setupTwoClientTest(t, true)
|
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") })
|
t.Run("::", func(t *testing.T) { testUnspec(t, lt, "[::]:8081", "8081") })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-65
@@ -22,7 +22,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
|
|||||||
wants []time.Time // The return values of sequential calls to Now().
|
wants []time.Time // The return values of sequential calls to Now().
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "increment ms",
|
name: "increment-ms",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1000,
|
step: 1000,
|
||||||
wants: []time.Time{
|
wants: []time.Time{
|
||||||
@@ -33,7 +33,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "increment second",
|
name: "increment-second",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
wants: []time.Time{
|
wants: []time.Time{
|
||||||
@@ -44,7 +44,7 @@ func TestClockWithDefinedStartTime(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no increment",
|
name: "no-increment",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
wants: []time.Time{
|
wants: []time.Time{
|
||||||
time.Unix(12345, 1000),
|
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()
|
wants []time.Duration // The return values of sequential calls to Now() after added to Start()
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "increment ms",
|
name: "increment-ms",
|
||||||
step: 1000,
|
step: 1000,
|
||||||
wants: []time.Duration{
|
wants: []time.Duration{
|
||||||
0,
|
0,
|
||||||
@@ -101,7 +101,7 @@ func TestClockWithDefaultStartTime(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "increment second",
|
name: "increment-second",
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
wants: []time.Duration{
|
wants: []time.Duration{
|
||||||
0 * time.Second,
|
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},
|
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().
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1000,
|
step: 1000,
|
||||||
stepChanges: []stepInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1,
|
step: 1,
|
||||||
stepChanges: []stepInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1,
|
step: 1,
|
||||||
stepChanges: []stepInfo{
|
stepChanges: []stepInfo{
|
||||||
@@ -252,7 +252,7 @@ func TestClockSetStep(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "changes at start",
|
name: "changes-at-start",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
step: 0,
|
step: 0,
|
||||||
stepChanges: []stepInfo{
|
stepChanges: []stepInfo{
|
||||||
@@ -325,7 +325,7 @@ func TestClockAdvance(t *testing.T) {
|
|||||||
wants []time.Time // The return values of sequential calls to Now().
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1000,
|
step: 1000,
|
||||||
advances: []advanceInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1,
|
step: 1,
|
||||||
advances: []advanceInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
step: 1,
|
step: 1,
|
||||||
advances: []advanceInfo{
|
advances: []advanceInfo{
|
||||||
@@ -400,7 +400,7 @@ func TestClockAdvance(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "changes at start",
|
name: "changes-at-start",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
step: 5,
|
step: 5,
|
||||||
advances: []advanceInfo{
|
advances: []advanceInfo{
|
||||||
@@ -489,7 +489,7 @@ func TestSingleTicker(t *testing.T) {
|
|||||||
steps []testStep
|
steps []testStep
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no tick advance",
|
name: "no-tick-advance",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
period: time.Second,
|
period: time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -500,7 +500,7 @@ func TestSingleTicker(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no tick step",
|
name: "no-tick-step",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second - 1,
|
step: time.Second - 1,
|
||||||
period: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
period: time.Second,
|
period: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
period: time.Second,
|
period: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
period: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second + 1,
|
step: time.Second + 1,
|
||||||
period: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
period: 3 * time.Second,
|
period: 3 * time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
period: 3 * 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),
|
start: time.Unix(12345, 0),
|
||||||
period: time.Second,
|
period: time.Second,
|
||||||
channelSize: 3,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: 3 * time.Second,
|
step: 3 * time.Second,
|
||||||
period: 2 * 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),
|
start: time.Unix(12345, 0),
|
||||||
period: 2 * time.Second,
|
period: 2 * time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -763,7 +763,7 @@ func TestSingleTicker(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reset while stopped",
|
name: "reset-while-stopped",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
period: 2 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
period: 2 * 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),
|
realTimeOpts: new(ClockOpts),
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
period: 2 * time.Second,
|
period: 2 * time.Second,
|
||||||
@@ -965,7 +965,7 @@ func TestSingleTimer(t *testing.T) {
|
|||||||
steps []testStep
|
steps []testStep
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no tick advance",
|
name: "no-tick-advance",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -976,7 +976,7 @@ func TestSingleTimer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no tick step",
|
name: "no-tick-step",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second - 1,
|
step: time.Second - 1,
|
||||||
delay: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second + 1,
|
step: time.Second + 1,
|
||||||
delay: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: 3 * time.Second,
|
delay: 3 * time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 3 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 3 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
delay: 2 * time.Second,
|
delay: 2 * time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -1275,7 +1275,7 @@ func TestSingleTimer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reset while stopped",
|
name: "reset-while-stopped",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 2 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 2 * 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),
|
realTimeOpts: new(ClockOpts),
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
delay: 2 * time.Second,
|
delay: 2 * time.Second,
|
||||||
@@ -1705,7 +1705,7 @@ func TestClockFollowRealTime(t *testing.T) {
|
|||||||
wants []time.Time // The return values of sequential calls to Now().
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
wantStart: time.Unix(12345, 1000),
|
wantStart: time.Unix(12345, 1000),
|
||||||
advances: []advanceInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
wantStart: time.Unix(12345, 1000),
|
wantStart: time.Unix(12345, 1000),
|
||||||
advances: []advanceInfo{
|
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),
|
start: time.Unix(12345, 1000),
|
||||||
wantStart: time.Unix(12345, 1000),
|
wantStart: time.Unix(12345, 1000),
|
||||||
advances: []advanceInfo{
|
advances: []advanceInfo{
|
||||||
@@ -1828,7 +1828,7 @@ func TestClockFollowRealTime(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "changes at start",
|
name: "changes-at-start",
|
||||||
start: time.Unix(12345, 1000),
|
start: time.Unix(12345, 1000),
|
||||||
wantStart: time.Unix(12345, 1000),
|
wantStart: time.Unix(12345, 1000),
|
||||||
advances: []advanceInfo{
|
advances: []advanceInfo{
|
||||||
@@ -1861,7 +1861,7 @@ func TestClockFollowRealTime(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "start from current time",
|
name: "start-from-current-time",
|
||||||
realTimeClockOpts: ClockOpts{
|
realTimeClockOpts: ClockOpts{
|
||||||
Start: time.Unix(12345, 0),
|
Start: time.Unix(12345, 0),
|
||||||
},
|
},
|
||||||
@@ -1966,7 +1966,7 @@ func TestAfterFunc(t *testing.T) {
|
|||||||
steps []testStep
|
steps []testStep
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no tick advance",
|
name: "no-tick-advance",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -1977,7 +1977,7 @@ func TestAfterFunc(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no tick step",
|
name: "no-tick-step",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second - 1,
|
step: time.Second - 1,
|
||||||
delay: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: time.Second,
|
delay: time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second + 1,
|
step: time.Second + 1,
|
||||||
delay: time.Second,
|
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),
|
start: time.Unix(12345, 0),
|
||||||
delay: 3 * time.Second,
|
delay: 3 * time.Second,
|
||||||
steps: []testStep{
|
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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 3 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 3 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
step: 2 * time.Second,
|
step: 2 * time.Second,
|
||||||
delay: 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),
|
start: time.Unix(12345, 0),
|
||||||
delay: 2 * time.Second,
|
delay: 2 * time.Second,
|
||||||
steps: []testStep{
|
steps: []testStep{
|
||||||
@@ -2270,7 +2270,7 @@ func TestAfterFunc(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reset while stopped",
|
name: "reset-while-stopped",
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 2 * 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),
|
start: time.Unix(12345, 0),
|
||||||
step: time.Second,
|
step: time.Second,
|
||||||
delay: 2 * 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),
|
realTimeOpts: new(ClockOpts),
|
||||||
start: time.Unix(12345, 0),
|
start: time.Unix(12345, 0),
|
||||||
delay: 2 * time.Second,
|
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
|
dur := 100 * time.Millisecond
|
||||||
var outp []byte
|
var outp []byte
|
||||||
var err error
|
var err error
|
||||||
@@ -383,7 +383,7 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) {
|
|||||||
t.Fatalf("error: %v", err)
|
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()
|
sess, err := cli.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
+13
-13
@@ -22,7 +22,7 @@ func TestPrintGoroutines(t *testing.T) {
|
|||||||
want: "goroutine profile: total 0",
|
want: "goroutine profile: total 0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single goroutine",
|
name: "single-goroutine",
|
||||||
in: `goroutine profile: total 1
|
in: `goroutine profile: total 1
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 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
|
in: `goroutine profile: total 14
|
||||||
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
|
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
|
||||||
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
|
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
|
||||||
@@ -70,7 +70,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no difference",
|
name: "no-difference",
|
||||||
x: `goroutine profile: total 1
|
x: `goroutine profile: total 1
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261`,
|
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261`,
|
||||||
@@ -81,7 +81,7 @@ func TestDiffPprofGoroutines(t *testing.T) {
|
|||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "different counts",
|
name: "different-counts",
|
||||||
x: `goroutine profile: total 1
|
x: `goroutine profile: total 1
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 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
|
x: `goroutine profile: total 1
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 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
|
x: `goroutine profile: total 2
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 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
|
x: `goroutine profile: total 2
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 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",
|
x: "invalid",
|
||||||
y: "goroutine profile: total 0\n",
|
y: "goroutine profile: total 0\n",
|
||||||
want: "- invalid\n+ 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",
|
x: "goroutine profile: total 0\n",
|
||||||
y: "invalid",
|
y: "invalid",
|
||||||
want: "- goroutine profile: total 0\n+ invalid\n",
|
want: "- goroutine profile: total 0\n+ invalid\n",
|
||||||
@@ -193,13 +193,13 @@ func TestParseGoroutines(t *testing.T) {
|
|||||||
wantCount int
|
wantCount int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty profile",
|
name: "empty-profile",
|
||||||
in: "goroutine profile: total 0\n",
|
in: "goroutine profile: total 0\n",
|
||||||
wantHeader: "goroutine profile: total 0",
|
wantHeader: "goroutine profile: total 0",
|
||||||
wantCount: 0,
|
wantCount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single goroutine",
|
name: "single-goroutine",
|
||||||
in: `goroutine profile: total 1
|
in: `goroutine profile: total 1
|
||||||
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
1 @ 0x47bc0e 0x458e57 0x847587 0x483da1
|
||||||
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
# 0x847586 database/sql.(*DB).connectionOpener+0x86 database/sql/sql.go:1261
|
||||||
@@ -208,7 +208,7 @@ func TestParseGoroutines(t *testing.T) {
|
|||||||
wantCount: 1,
|
wantCount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple goroutines",
|
name: "multiple-goroutines",
|
||||||
in: `goroutine profile: total 14
|
in: `goroutine profile: total 14
|
||||||
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
|
7 @ 0x47bc0e 0x413705 0x4132b2 0x10fda4d 0x483da1
|
||||||
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
|
# 0x10fda4c github.com/user/pkg.RoutineA+0x16c pkg/a.go:443
|
||||||
@@ -220,7 +220,7 @@ func TestParseGoroutines(t *testing.T) {
|
|||||||
wantCount: 2,
|
wantCount: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid format",
|
name: "invalid-format",
|
||||||
in: "invalid",
|
in: "invalid",
|
||||||
wantHeader: "invalid",
|
wantHeader: "invalid",
|
||||||
},
|
},
|
||||||
|
|||||||
+22
-22
@@ -85,7 +85,7 @@ func TestStdHandler(t *testing.T) {
|
|||||||
wantBody string
|
wantBody string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "handler returns 200",
|
name: "handler-returns-200",
|
||||||
rh: handlerCode(200),
|
rh: handlerCode(200),
|
||||||
r: req(bgCtx, "http://example.com/"),
|
r: req(bgCtx, "http://example.com/"),
|
||||||
wantCode: 200,
|
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),
|
rh: handlerCode(200),
|
||||||
r: req(bgCtx, "http://example.com/"),
|
r: req(bgCtx, "http://example.com/"),
|
||||||
wantCode: 200,
|
wantCode: 200,
|
||||||
@@ -119,7 +119,7 @@ func TestStdHandler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "handler returns 404",
|
name: "handler-returns-404",
|
||||||
rh: handlerCode(404),
|
rh: handlerCode(404),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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),
|
rh: handlerCode(404),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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)),
|
rh: handlerErr(0, Error(404, "not found", testErr)),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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)),
|
rh: handlerErr(0, Error(404, "not found", testErr)),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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)),
|
rh: handlerErr(0, Error(404, "not found", nil)),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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)),
|
rh: handlerErr(0, Error(404, "not found", nil)),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 404,
|
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")),
|
rh: handlerErr(0, vizerror.New("visible error")),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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")),
|
rh: handlerErr(0, vizerror.New("visible error")),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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"))),
|
rh: handlerErr(0, fmt.Errorf("private internal error: %w", vizerror.New("visible error"))),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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 {
|
rh: ReturnHandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||||
h := Error(http.StatusBadRequest, `{"isjson": true}`, errors.New("uh"))
|
h := Error(http.StatusBadRequest, `{"isjson": true}`, errors.New("uh"))
|
||||||
h.Header = http.Header{"Content-Type": {"application/json"}}
|
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"))),
|
rh: handlerErr(0, fmt.Errorf("private internal error: %w", vizerror.New("visible error"))),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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),
|
rh: handlerErr(0, testErr),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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),
|
rh: handlerErr(0, testErr),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 500,
|
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),
|
rh: handlerErr(200, testErr),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 200,
|
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),
|
rh: handlerErr(200, testErr),
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/foo"),
|
||||||
wantCode: 200,
|
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)),
|
rh: handlerErr(200, Error(404, "not found", testErr)),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 200,
|
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 }),
|
rh: handlerFunc(func(http.ResponseWriter, *http.Request) error { return nil }),
|
||||||
r: req(bgCtx, "http://example.com/foo"),
|
r: req(bgCtx, "http://example.com/foo"),
|
||||||
wantCode: 200,
|
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 {
|
rh: handlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||||
_, _, err := w.(http.Hijacker).Hijack()
|
_, _, err := w.(http.Hijacker).Hijack()
|
||||||
if err != nil {
|
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
|
rh: handlerErr(0, Error(404, "not found", nil)), // status code changed in errHandler
|
||||||
r: req(bgCtx, "http://example.com/"),
|
r: req(bgCtx, "http://example.com/"),
|
||||||
wantCode: 200,
|
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
|
rh: handlerErr(0, Error(404, "not found", nil)), // status code changed in errHandler
|
||||||
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/"),
|
r: req(RequestIDKey.WithValue(bgCtx, exampleRequestID), "http://example.com/"),
|
||||||
wantCode: 200,
|
wantCode: 200,
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ func TestResolverEqual(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil vs non-nil",
|
name: "nil-vs-non-nil",
|
||||||
a: nil,
|
a: nil,
|
||||||
b: &Resolver{},
|
b: &Resolver{},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "non-nil vs nil",
|
name: "non-nil-vs-nil",
|
||||||
a: &Resolver{},
|
a: &Resolver{},
|
||||||
b: nil,
|
b: nil,
|
||||||
want: false,
|
want: false,
|
||||||
@@ -51,13 +51,13 @@ func TestResolverEqual(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not equal addrs",
|
name: "not-equal-addrs",
|
||||||
a: &Resolver{Addr: "dns.example.com"},
|
a: &Resolver{Addr: "dns.example.com"},
|
||||||
b: &Resolver{Addr: "dns2.example.com"},
|
b: &Resolver{Addr: "dns2.example.com"},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not equal bootstrap",
|
name: "not-equal-bootstrap",
|
||||||
a: &Resolver{
|
a: &Resolver{
|
||||||
Addr: "dns.example.com",
|
Addr: "dns.example.com",
|
||||||
BootstrapResolution: []netip.Addr{netip.MustParseAddr("8.8.8.8")},
|
BootstrapResolution: []netip.Addr{netip.MustParseAddr("8.8.8.8")},
|
||||||
@@ -69,13 +69,13 @@ func TestResolverEqual(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "equal UseWithExitNode",
|
name: "equal-UseWithExitNode",
|
||||||
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||||
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not equal UseWithExitNode",
|
name: "not-equal-UseWithExitNode",
|
||||||
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
a: &Resolver{Addr: "dns.example.com", UseWithExitNode: true},
|
||||||
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: false},
|
b: &Resolver{Addr: "dns.example.com", UseWithExitNode: false},
|
||||||
want: false,
|
want: false,
|
||||||
|
|||||||
+23
-23
@@ -16,77 +16,77 @@ func TestCompare(t *testing.T) {
|
|||||||
want int
|
want int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "both empty",
|
name: "both-empty",
|
||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "v1 empty",
|
name: "v1-empty",
|
||||||
v2: "1.2.3",
|
v2: "1.2.3",
|
||||||
want: -1,
|
want: -1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "v2 empty",
|
name: "v2-empty",
|
||||||
v1: "1.2.3",
|
v1: "1.2.3",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "semver major",
|
name: "semver-major",
|
||||||
v1: "2.0.0",
|
v1: "2.0.0",
|
||||||
v2: "1.9.9",
|
v2: "1.9.9",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "semver major",
|
name: "semver-major",
|
||||||
v1: "2.0.0",
|
v1: "2.0.0",
|
||||||
v2: "1.9.9",
|
v2: "1.9.9",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "semver minor",
|
name: "semver-minor",
|
||||||
v1: "1.9.0",
|
v1: "1.9.0",
|
||||||
v2: "1.8.9",
|
v2: "1.8.9",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "semver patch",
|
name: "semver-patch",
|
||||||
v1: "1.9.9",
|
v1: "1.9.9",
|
||||||
v2: "1.9.8",
|
v2: "1.9.8",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "semver equal",
|
name: "semver-equal",
|
||||||
v1: "1.9.8",
|
v1: "1.9.8",
|
||||||
v2: "1.9.8",
|
v2: "1.9.8",
|
||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "tailscale major",
|
name: "tailscale-major",
|
||||||
v1: "1.0-0",
|
v1: "1.0-0",
|
||||||
v2: "0.97-105",
|
v2: "0.97-105",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tailscale minor",
|
name: "tailscale-minor",
|
||||||
v1: "0.98-0",
|
v1: "0.98-0",
|
||||||
v2: "0.97-105",
|
v2: "0.97-105",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tailscale patch",
|
name: "tailscale-patch",
|
||||||
v1: "0.97-120",
|
v1: "0.97-120",
|
||||||
v2: "0.97-105",
|
v2: "0.97-105",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tailscale equal",
|
name: "tailscale-equal",
|
||||||
v1: "0.97-105",
|
v1: "0.97-105",
|
||||||
v2: "0.97-105",
|
v2: "0.97-105",
|
||||||
want: 0,
|
want: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tailscale weird extra field",
|
name: "tailscale-weird-extra-field",
|
||||||
v1: "0.96.1-0", // more fields == larger
|
v1: "0.96.1-0", // more fields == larger
|
||||||
v2: "0.96-105",
|
v2: "0.96-105",
|
||||||
want: 1,
|
want: 1,
|
||||||
@@ -96,7 +96,7 @@ func TestCompare(t *testing.T) {
|
|||||||
// of strconv.ParseUint with these characters would have lead us to
|
// of strconv.ParseUint with these characters would have lead us to
|
||||||
// panic. We're now only looking at ascii numbers, so test these are
|
// panic. We're now only looking at ascii numbers, so test these are
|
||||||
// compared as text.
|
// compared as text.
|
||||||
name: "only ascii numbers",
|
name: "only-ascii-numbers",
|
||||||
v1: "۱۱", // 2x EXTENDED ARABIC-INDIC DIGIT ONE
|
v1: "۱۱", // 2x EXTENDED ARABIC-INDIC DIGIT ONE
|
||||||
v2: "۲", // 1x EXTENDED ARABIC-INDIC DIGIT TWO
|
v2: "۲", // 1x EXTENDED ARABIC-INDIC DIGIT TWO
|
||||||
want: -1,
|
want: -1,
|
||||||
@@ -104,55 +104,55 @@ func TestCompare(t *testing.T) {
|
|||||||
|
|
||||||
// A few specific OS version tests below.
|
// A few specific OS version tests below.
|
||||||
{
|
{
|
||||||
name: "windows version",
|
name: "windows-version",
|
||||||
v1: "10.0.19045.3324",
|
v1: "10.0.19045.3324",
|
||||||
v2: "10.0.18362",
|
v2: "10.0.18362",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "windows 11 is everything above 10.0.22000",
|
name: "windows-11-above-10_0_22000",
|
||||||
v1: "10.0.22631.2262",
|
v1: "10.0.22631.2262",
|
||||||
v2: "10.0.22000",
|
v2: "10.0.22000",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "android short version",
|
name: "android-short-version",
|
||||||
v1: "10",
|
v1: "10",
|
||||||
v2: "7",
|
v2: "7",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "android longer version",
|
name: "android-longer-version",
|
||||||
v1: "7.1.2",
|
v1: "7.1.2",
|
||||||
v2: "7",
|
v2: "7",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "iOS version",
|
name: "iOS-version",
|
||||||
v1: "15.6.1",
|
v1: "15.6.1",
|
||||||
v2: "15.6",
|
v2: "15.6",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Linux short kernel version",
|
name: "linux-short-kernel-version",
|
||||||
v1: "4.4.302+",
|
v1: "4.4.302+",
|
||||||
v2: "4.0",
|
v2: "4.0",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Linux long kernel version",
|
name: "linux-long-kernel-version",
|
||||||
v1: "4.14.255-311-248.529.amzn2.x86_64",
|
v1: "4.14.255-311-248.529.amzn2.x86_64",
|
||||||
v2: "4.0",
|
v2: "4.0",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FreeBSD version",
|
name: "freebsd-version",
|
||||||
v1: "14.0-CURRENT",
|
v1: "14.0-CURRENT",
|
||||||
v2: "14",
|
v2: "14",
|
||||||
want: 1,
|
want: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Synology version",
|
name: "synology-version",
|
||||||
v1: "Synology 6.2.4; kernel=3.10.105",
|
v1: "Synology 6.2.4; kernel=3.10.105",
|
||||||
v2: "Synology 6",
|
v2: "Synology 6",
|
||||||
want: 1,
|
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",
|
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"),
|
val: netip.MustParseAddr("fe80::123%foo"),
|
||||||
out: u64(16+3) + u64(0x80fe) + u64(0x2301<<48) + "foo",
|
out: u64(16+3) + u64(0x80fe) + u64(0x2301<<48) + "foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ptr-netip.Addr",
|
name: "ptr-netip-Addr",
|
||||||
val: &someIP,
|
val: &someIP,
|
||||||
out: u8(1) + u64(4) + u32(0x04030201),
|
out: u8(1) + u64(4) + u32(0x04030201),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ptr-nil-netip.Addr",
|
name: "ptr-nil-netip-Addr",
|
||||||
val: (*netip.Addr)(nil),
|
val: (*netip.Addr)(nil),
|
||||||
out: "\x00",
|
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",
|
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{},
|
val: &tailcfg.Node{},
|
||||||
out: "ANY", // magic value; just check it doesn't fail to hash
|
out: "ANY", // magic value; just check it doesn't fail to hash
|
||||||
out32: "ANY",
|
out32: "ANY",
|
||||||
|
|||||||
@@ -36,17 +36,17 @@ func TestExpectFilter(t *testing.T) {
|
|||||||
wantErr string // if non-empty, an error is expected containing this text
|
wantErr string // if non-empty, an error is expected containing this text
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "single event",
|
name: "single-event",
|
||||||
events: []int{42},
|
events: []int{42},
|
||||||
expectFunc: eventbustest.Type[EventFoo](),
|
expectFunc: eventbustest.Type[EventFoo](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple events, single expectation",
|
name: "multiple-events-single-expectation",
|
||||||
events: []int{42, 1, 2, 3, 4, 5},
|
events: []int{42, 1, 2, 3, 4, 5},
|
||||||
expectFunc: eventbustest.Type[EventFoo](),
|
expectFunc: eventbustest.Type[EventFoo](),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "filter on event with function",
|
name: "filter-on-event-with-function",
|
||||||
events: []int{24, 42},
|
events: []int{24, 42},
|
||||||
expectFunc: func(event EventFoo) (bool, error) {
|
expectFunc: func(event EventFoo) (bool, error) {
|
||||||
if event.Value == 42 {
|
if event.Value == 42 {
|
||||||
@@ -77,7 +77,7 @@ func TestExpectFilter(t *testing.T) {
|
|||||||
wantErr: "value > 10",
|
wantErr: "value > 10",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "first event has to be func",
|
name: "first-event-has-to-be-func",
|
||||||
events: []int{24, 42},
|
events: []int{24, 42},
|
||||||
expectFunc: func(event EventFoo) (bool, error) {
|
expectFunc: func(event EventFoo) (bool, error) {
|
||||||
if event.Value != 42 {
|
if event.Value != 42 {
|
||||||
@@ -99,7 +99,7 @@ func TestExpectFilter(t *testing.T) {
|
|||||||
wantErr: "wrong result (-got, +want)",
|
wantErr: "wrong result (-got, +want)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no events",
|
name: "no-events",
|
||||||
events: []int{},
|
events: []int{},
|
||||||
expectFunc: func(event EventFoo) (bool, error) {
|
expectFunc: func(event EventFoo) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
@@ -151,37 +151,37 @@ func TestExpectEvents(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "No expectations",
|
name: "no-expectations",
|
||||||
events: []any{EventFoo{}},
|
events: []any{EventFoo{}},
|
||||||
expectEvents: []any{},
|
expectEvents: []any{},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event",
|
name: "one-event",
|
||||||
events: []any{EventFoo{}},
|
events: []any{EventFoo{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo]()},
|
expectEvents: []any{eventbustest.Type[EventFoo]()},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two events",
|
name: "two-events",
|
||||||
events: []any{EventFoo{}, EventBar{}},
|
events: []any{EventFoo{}, EventBar{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two expected events with another in the middle",
|
name: "two-expected-events-with-another-in-middle",
|
||||||
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
|
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Missing event",
|
name: "missing-event",
|
||||||
events: []any{EventFoo{}, EventBaz{}},
|
events: []any{EventFoo{}, EventBaz{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event with specific value",
|
name: "one-event-with-specific-value",
|
||||||
events: []any{EventFoo{42}},
|
events: []any{EventFoo{42}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -194,7 +194,7 @@ func TestExpectEvents(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two event with one specific value",
|
name: "two-events-with-one-specific-value",
|
||||||
events: []any{EventFoo{43}, EventFoo{42}},
|
events: []any{EventFoo{43}, EventFoo{42}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -207,7 +207,7 @@ func TestExpectEvents(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event with wrong value",
|
name: "one-event-with-wrong-value",
|
||||||
events: []any{EventFoo{43}},
|
events: []any{EventFoo{43}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -220,7 +220,7 @@ func TestExpectEvents(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two events with specific values",
|
name: "two-events-with-specific-values",
|
||||||
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
|
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -283,37 +283,37 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "No expectations",
|
name: "no-expectations",
|
||||||
events: []any{EventFoo{}},
|
events: []any{EventFoo{}},
|
||||||
expectEvents: []any{},
|
expectEvents: []any{},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event",
|
name: "one-event",
|
||||||
events: []any{EventFoo{}},
|
events: []any{EventFoo{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo]()},
|
expectEvents: []any{eventbustest.Type[EventFoo]()},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two events",
|
name: "two-events",
|
||||||
events: []any{EventFoo{}, EventBar{}},
|
events: []any{EventFoo{}, EventBar{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two expected events with another in the middle",
|
name: "two-expected-events-with-another-in-middle",
|
||||||
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
|
events: []any{EventFoo{}, EventBaz{}, EventBar{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Missing event",
|
name: "missing-event",
|
||||||
events: []any{EventFoo{}, EventBaz{}},
|
events: []any{EventFoo{}, EventBaz{}},
|
||||||
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
expectEvents: []any{eventbustest.Type[EventFoo](), eventbustest.Type[EventBar]()},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event with value",
|
name: "one-event-with-value",
|
||||||
events: []any{EventFoo{42}},
|
events: []any{EventFoo{42}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -326,7 +326,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two event with one specific value",
|
name: "two-events-with-one-specific-value",
|
||||||
events: []any{EventFoo{43}, EventFoo{42}},
|
events: []any{EventFoo{43}, EventFoo{42}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -339,7 +339,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "One event with wrong value",
|
name: "one-event-with-wrong-value",
|
||||||
events: []any{EventFoo{43}},
|
events: []any{EventFoo{43}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
@@ -352,7 +352,7 @@ func TestExpectExactlyEventsFilter(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Two events with specific values",
|
name: "two-events-with-specific-values",
|
||||||
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
|
events: []any{EventFoo{42}, EventFoo{42}, EventBar{"42"}},
|
||||||
expectEvents: []any{
|
expectEvents: []any{
|
||||||
func(ev EventFoo) (bool, error) {
|
func(ev EventFoo) (bool, error) {
|
||||||
|
|||||||
@@ -960,32 +960,32 @@ func TestPickFirewallModeFromInstalledRules(t *testing.T) {
|
|||||||
want FirewallMode
|
want FirewallMode
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "using iptables legacy",
|
name: "using-iptables-legacy",
|
||||||
det: &testFWDetector{iptRuleCount: 1},
|
det: &testFWDetector{iptRuleCount: 1},
|
||||||
want: FirewallModeIPTables,
|
want: FirewallModeIPTables,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "using nftables",
|
name: "using-nftables",
|
||||||
det: &testFWDetector{nftRuleCount: 1},
|
det: &testFWDetector{nftRuleCount: 1},
|
||||||
want: FirewallModeNfTables,
|
want: FirewallModeNfTables,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "using both iptables and nftables",
|
name: "using-both-iptables-and-nftables",
|
||||||
det: &testFWDetector{iptRuleCount: 2, nftRuleCount: 2},
|
det: &testFWDetector{iptRuleCount: 2, nftRuleCount: 2},
|
||||||
want: FirewallModeNfTables,
|
want: FirewallModeNfTables,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not using any firewall, both available",
|
name: "no-firewall-both-available",
|
||||||
det: &testFWDetector{},
|
det: &testFWDetector{},
|
||||||
want: FirewallModeNfTables,
|
want: FirewallModeNfTables,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not using any firewall, iptables available only",
|
name: "no-firewall-iptables-only",
|
||||||
det: &testFWDetector{iptRuleCount: 1, nftErr: errors.New("nft error")},
|
det: &testFWDetector{iptRuleCount: 1, nftErr: errors.New("nft error")},
|
||||||
want: FirewallModeIPTables,
|
want: FirewallModeIPTables,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not using any firewall, nftables available only",
|
name: "no-firewall-nftables-only",
|
||||||
det: &testFWDetector{iptErr: errors.New("iptables error"), nftRuleCount: 1},
|
det: &testFWDetector{iptErr: errors.New("iptables error"), nftRuleCount: 1},
|
||||||
want: FirewallModeNfTables,
|
want: FirewallModeNfTables,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -226,42 +226,42 @@ func TestPolicyScopeContains(t *testing.T) {
|
|||||||
wantAStrictlyContainsB: false,
|
wantAStrictlyContainsB: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UserScope(1234)/UserScope(1234)",
|
name: "UserScope-1234/UserScope-1234",
|
||||||
scopeA: UserScopeOf("1234"),
|
scopeA: UserScopeOf("1234"),
|
||||||
scopeB: UserScopeOf("1234"),
|
scopeB: UserScopeOf("1234"),
|
||||||
wantAContainsB: true,
|
wantAContainsB: true,
|
||||||
wantAStrictlyContainsB: false,
|
wantAStrictlyContainsB: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UserScope(1234)/UserScope(5678)",
|
name: "UserScope-1234/UserScope-5678",
|
||||||
scopeA: UserScopeOf("1234"),
|
scopeA: UserScopeOf("1234"),
|
||||||
scopeB: UserScopeOf("5678"),
|
scopeB: UserScopeOf("5678"),
|
||||||
wantAContainsB: false,
|
wantAContainsB: false,
|
||||||
wantAStrictlyContainsB: false,
|
wantAStrictlyContainsB: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ProfileScope(A)/UserScope(A/1234)",
|
name: "ProfileScope-A/UserScope-A-1234",
|
||||||
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
|
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
|
||||||
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
|
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
|
||||||
wantAContainsB: true,
|
wantAContainsB: true,
|
||||||
wantAStrictlyContainsB: true,
|
wantAStrictlyContainsB: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ProfileScope(A)/UserScope(B/1234)",
|
name: "ProfileScope-A/UserScope-B-1234",
|
||||||
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
|
scopeA: PolicyScope{kind: ProfileSetting, profileID: "A"},
|
||||||
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "B"},
|
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "B"},
|
||||||
wantAContainsB: false,
|
wantAContainsB: false,
|
||||||
wantAStrictlyContainsB: false,
|
wantAStrictlyContainsB: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UserScope(1234)/UserScope(A/1234)",
|
name: "UserScope-1234/UserScope-A-1234",
|
||||||
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
|
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
|
||||||
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
|
scopeB: PolicyScope{kind: UserSetting, userID: "1234", profileID: "A"},
|
||||||
wantAContainsB: true,
|
wantAContainsB: true,
|
||||||
wantAStrictlyContainsB: true,
|
wantAStrictlyContainsB: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UserScope(1234)/UserScope(A/5678)",
|
name: "UserScope-1234/UserScope-A-5678",
|
||||||
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
|
scopeA: PolicyScope{kind: UserSetting, userID: "1234"},
|
||||||
scopeB: PolicyScope{kind: UserSetting, userID: "5678", profileID: "A"},
|
scopeB: PolicyScope{kind: UserSetting, userID: "5678", profileID: "A"},
|
||||||
wantAContainsB: false,
|
wantAContainsB: false,
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func TestGetString(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "read existing value",
|
name: "read-existing-value",
|
||||||
key: pkey.AdminConsoleVisibility,
|
key: pkey.AdminConsoleVisibility,
|
||||||
handlerValue: "hide",
|
handlerValue: "hide",
|
||||||
wantValue: "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,
|
key: pkey.EnableServerMode,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantError: nil,
|
wantError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "read non-existing value, non-blank default",
|
name: "read-non-existing-value-non-blank-default",
|
||||||
key: pkey.EnableServerMode,
|
key: pkey.EnableServerMode,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
defaultValue: "test",
|
defaultValue: "test",
|
||||||
@@ -68,7 +68,7 @@ func TestGetString(t *testing.T) {
|
|||||||
wantError: nil,
|
wantError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reading value returns other error",
|
name: "reading-value-returns-other-error",
|
||||||
key: pkey.NetworkDevicesVisibility,
|
key: pkey.NetworkDevicesVisibility,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantError: someOtherError,
|
wantError: someOtherError,
|
||||||
@@ -124,27 +124,27 @@ func TestGetUint64(t *testing.T) {
|
|||||||
wantError error
|
wantError error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "read existing value",
|
name: "read-existing-value",
|
||||||
key: pkey.LogSCMInteractions,
|
key: pkey.LogSCMInteractions,
|
||||||
handlerValue: 1,
|
handlerValue: 1,
|
||||||
wantValue: 1,
|
wantValue: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "read non-existing value",
|
name: "read-non-existing-value",
|
||||||
key: pkey.LogSCMInteractions,
|
key: pkey.LogSCMInteractions,
|
||||||
handlerValue: 0,
|
handlerValue: 0,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: 0,
|
wantValue: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "read non-existing value, non-zero default",
|
name: "read-non-existing-value-non-zero-default",
|
||||||
key: pkey.LogSCMInteractions,
|
key: pkey.LogSCMInteractions,
|
||||||
defaultValue: 2,
|
defaultValue: 2,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: 2,
|
wantValue: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reading value returns other error",
|
name: "reading-value-returns-other-error",
|
||||||
key: pkey.FlushDNSOnSessionUnlock,
|
key: pkey.FlushDNSOnSessionUnlock,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantError: someOtherError,
|
wantError: someOtherError,
|
||||||
@@ -191,7 +191,7 @@ func TestGetBoolean(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "read existing value",
|
name: "read-existing-value",
|
||||||
key: pkey.FlushDNSOnSessionUnlock,
|
key: pkey.FlushDNSOnSessionUnlock,
|
||||||
handlerValue: true,
|
handlerValue: true,
|
||||||
wantValue: 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,
|
key: pkey.LogSCMInteractions,
|
||||||
handlerValue: false,
|
handlerValue: false,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: false,
|
wantValue: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reading value returns other error",
|
name: "reading-value-returns-other-error",
|
||||||
key: pkey.FlushDNSOnSessionUnlock,
|
key: pkey.FlushDNSOnSessionUnlock,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantError: someOtherError, // expect error...
|
wantError: someOtherError, // expect error...
|
||||||
@@ -266,7 +266,7 @@ func TestGetPreferenceOption(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "always by policy",
|
name: "always-by-policy",
|
||||||
key: pkey.EnableIncomingConnections,
|
key: pkey.EnableIncomingConnections,
|
||||||
handlerValue: "always",
|
handlerValue: "always",
|
||||||
wantValue: ptype.AlwaysByPolicy,
|
wantValue: ptype.AlwaysByPolicy,
|
||||||
@@ -276,7 +276,7 @@ func TestGetPreferenceOption(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "never by policy",
|
name: "never-by-policy",
|
||||||
key: pkey.EnableIncomingConnections,
|
key: pkey.EnableIncomingConnections,
|
||||||
handlerValue: "never",
|
handlerValue: "never",
|
||||||
wantValue: ptype.NeverByPolicy,
|
wantValue: ptype.NeverByPolicy,
|
||||||
@@ -286,7 +286,7 @@ func TestGetPreferenceOption(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "use default",
|
name: "use-default",
|
||||||
key: pkey.EnableIncomingConnections,
|
key: pkey.EnableIncomingConnections,
|
||||||
handlerValue: "",
|
handlerValue: "",
|
||||||
wantValue: ptype.ShowChoiceByPolicy,
|
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,
|
key: pkey.EnableIncomingConnections,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: ptype.ShowChoiceByPolicy,
|
wantValue: ptype.ShowChoiceByPolicy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "other error is returned",
|
name: "other-error-is-returned",
|
||||||
key: pkey.EnableIncomingConnections,
|
key: pkey.EnableIncomingConnections,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantValue: ptype.ShowChoiceByPolicy,
|
wantValue: ptype.ShowChoiceByPolicy,
|
||||||
@@ -359,7 +359,7 @@ func TestGetVisibility(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hidden by policy",
|
name: "hidden-by-policy",
|
||||||
key: pkey.AdminConsoleVisibility,
|
key: pkey.AdminConsoleVisibility,
|
||||||
handlerValue: "hide",
|
handlerValue: "hide",
|
||||||
wantValue: ptype.HiddenByPolicy,
|
wantValue: ptype.HiddenByPolicy,
|
||||||
@@ -369,7 +369,7 @@ func TestGetVisibility(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "visibility default",
|
name: "visibility-default",
|
||||||
key: pkey.AdminConsoleVisibility,
|
key: pkey.AdminConsoleVisibility,
|
||||||
handlerValue: "show",
|
handlerValue: "show",
|
||||||
wantValue: ptype.VisibleByPolicy,
|
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,
|
key: pkey.AdminConsoleVisibility,
|
||||||
handlerValue: "show",
|
handlerValue: "show",
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: ptype.VisibleByPolicy,
|
wantValue: ptype.VisibleByPolicy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "other error is returned",
|
name: "other-error-is-returned",
|
||||||
key: pkey.AdminConsoleVisibility,
|
key: pkey.AdminConsoleVisibility,
|
||||||
handlerValue: "show",
|
handlerValue: "show",
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
@@ -445,7 +445,7 @@ func TestGetDuration(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "read existing value",
|
name: "read-existing-value",
|
||||||
key: pkey.KeyExpirationNoticeTime,
|
key: pkey.KeyExpirationNoticeTime,
|
||||||
handlerValue: "2h",
|
handlerValue: "2h",
|
||||||
wantValue: 2 * time.Hour,
|
wantValue: 2 * time.Hour,
|
||||||
@@ -456,7 +456,7 @@ func TestGetDuration(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid duration value",
|
name: "invalid-duration-value",
|
||||||
key: pkey.KeyExpirationNoticeTime,
|
key: pkey.KeyExpirationNoticeTime,
|
||||||
handlerValue: "-20",
|
handlerValue: "-20",
|
||||||
wantValue: 24 * time.Hour,
|
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,
|
key: pkey.KeyExpirationNoticeTime,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: 24 * time.Hour,
|
wantValue: 24 * time.Hour,
|
||||||
defaultValue: 24 * time.Hour,
|
defaultValue: 24 * time.Hour,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "read non-existing value different default",
|
name: "read-non-existing-value-different-default",
|
||||||
key: pkey.KeyExpirationNoticeTime,
|
key: pkey.KeyExpirationNoticeTime,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantValue: 0 * time.Second,
|
wantValue: 0 * time.Second,
|
||||||
defaultValue: 0 * time.Second,
|
defaultValue: 0 * time.Second,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "other error is returned",
|
name: "other-error-is-returned",
|
||||||
key: pkey.KeyExpirationNoticeTime,
|
key: pkey.KeyExpirationNoticeTime,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantValue: 24 * time.Hour,
|
wantValue: 24 * time.Hour,
|
||||||
@@ -541,7 +541,7 @@ func TestGetStringArray(t *testing.T) {
|
|||||||
wantMetrics []metrics.TestState
|
wantMetrics []metrics.TestState
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "read existing value",
|
name: "read-existing-value",
|
||||||
key: pkey.AllowedSuggestedExitNodes,
|
key: pkey.AllowedSuggestedExitNodes,
|
||||||
handlerValue: []string{"foo", "bar"},
|
handlerValue: []string{"foo", "bar"},
|
||||||
wantValue: []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,
|
key: pkey.AllowedSuggestedExitNodes,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
wantError: nil,
|
wantError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "read non-existing value, non nil default",
|
name: "read-non-existing-value-non-nil-default",
|
||||||
key: pkey.AllowedSuggestedExitNodes,
|
key: pkey.AllowedSuggestedExitNodes,
|
||||||
handlerError: ErrNotConfigured,
|
handlerError: ErrNotConfigured,
|
||||||
defaultValue: []string{"foo", "bar"},
|
defaultValue: []string{"foo", "bar"},
|
||||||
@@ -565,7 +565,7 @@ func TestGetStringArray(t *testing.T) {
|
|||||||
wantError: nil,
|
wantError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reading value returns other error",
|
name: "reading-value-returns-other-error",
|
||||||
key: pkey.AllowedSuggestedExitNodes,
|
key: pkey.AllowedSuggestedExitNodes,
|
||||||
handlerError: someOtherError,
|
handlerError: someOtherError,
|
||||||
wantError: someOtherError,
|
wantError: someOtherError,
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
wantMaybe bool
|
wantMaybe bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "nil probeUDPLifetime",
|
name: "nil-probeUDPLifetime",
|
||||||
localDisco: higher,
|
localDisco: higher,
|
||||||
remoteDisco: &lower,
|
remoteDisco: &lower,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -189,28 +189,28 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
bestAddr: addr,
|
bestAddr: addr,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "local higher disco key",
|
name: "local-higher-disco-key",
|
||||||
localDisco: higher,
|
localDisco: higher,
|
||||||
remoteDisco: &lower,
|
remoteDisco: &lower,
|
||||||
probeUDPLifetimeFn: newProbeUDPLifetime,
|
probeUDPLifetimeFn: newProbeUDPLifetime,
|
||||||
bestAddr: addr,
|
bestAddr: addr,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "remote no disco key",
|
name: "remote-no-disco-key",
|
||||||
localDisco: higher,
|
localDisco: higher,
|
||||||
remoteDisco: nil,
|
remoteDisco: nil,
|
||||||
probeUDPLifetimeFn: newProbeUDPLifetime,
|
probeUDPLifetimeFn: newProbeUDPLifetime,
|
||||||
bestAddr: addr,
|
bestAddr: addr,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid bestAddr",
|
name: "invalid-bestAddr",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: newProbeUDPLifetime,
|
probeUDPLifetimeFn: newProbeUDPLifetime,
|
||||||
bestAddr: addrQuality{},
|
bestAddr: addrQuality{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "cycle started too recently",
|
name: "cycle-started-too-recently",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -222,7 +222,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
bestAddr: addr,
|
bestAddr: addr,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybe cliff 0 cycle not active",
|
name: "maybe-cliff-0-cycle-not-active",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -238,7 +238,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
wantMaybe: true,
|
wantMaybe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybe cliff 0",
|
name: "maybe-cliff-0",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -254,7 +254,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
wantMaybe: true,
|
wantMaybe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybe cliff 1",
|
name: "maybe-cliff-1",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -270,7 +270,7 @@ func Test_endpoint_maybeProbeUDPLifetimeLocked(t *testing.T) {
|
|||||||
wantMaybe: true,
|
wantMaybe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybe cliff 2",
|
name: "maybe-cliff-2",
|
||||||
localDisco: lower,
|
localDisco: lower,
|
||||||
remoteDisco: &higher,
|
remoteDisco: &higher,
|
||||||
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
probeUDPLifetimeFn: func() *probeUDPLifetime {
|
||||||
@@ -341,13 +341,13 @@ func Test_epAddr_isDirectUDP(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "false derp magic addr",
|
name: "false-derp-magic-addr",
|
||||||
ap: netip.AddrPortFrom(tailcfg.DerpMagicIPAddr, 0),
|
ap: netip.AddrPortFrom(tailcfg.DerpMagicIPAddr, 0),
|
||||||
vni: packet.VirtualNetworkID{},
|
vni: packet.VirtualNetworkID{},
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "false vni set",
|
name: "false-vni-set",
|
||||||
ap: netip.MustParseAddrPort("192.0.2.1:7"),
|
ap: netip.MustParseAddrPort("192.0.2.1:7"),
|
||||||
vni: vni,
|
vni: vni,
|
||||||
want: false,
|
want: false,
|
||||||
@@ -397,42 +397,42 @@ func Test_endpoint_udpRelayEndpointReady(t *testing.T) {
|
|||||||
wantBestAddr addrQuality
|
wantBestAddr addrQuality
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "bestAddr trusted direct",
|
name: "bestAddr-trusted-direct",
|
||||||
curBestAddr: directAddrQuality,
|
curBestAddr: directAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQuality,
|
maybeBest: peerRelayAddrQuality,
|
||||||
wantBestAddr: directAddrQuality,
|
wantBestAddr: directAddrQuality,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bestAddr untrusted direct",
|
name: "bestAddr-untrusted-direct",
|
||||||
curBestAddr: directAddrQuality,
|
curBestAddr: directAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(-1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(-1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQuality,
|
maybeBest: peerRelayAddrQuality,
|
||||||
wantBestAddr: peerRelayAddrQuality,
|
wantBestAddr: peerRelayAddrQuality,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeBest same relay server higher latency bestAddr trusted",
|
name: "maybeBest-same-relay-higher-latency-trusted",
|
||||||
curBestAddr: peerRelayAddrQuality,
|
curBestAddr: peerRelayAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQualityHigherLatencySameServer,
|
maybeBest: peerRelayAddrQualityHigherLatencySameServer,
|
||||||
wantBestAddr: peerRelayAddrQualityHigherLatencySameServer,
|
wantBestAddr: peerRelayAddrQualityHigherLatencySameServer,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeBest diff relay server higher latency bestAddr trusted",
|
name: "maybeBest-diff-relay-higher-latency-trusted",
|
||||||
curBestAddr: peerRelayAddrQuality,
|
curBestAddr: peerRelayAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQualityHigherLatencyDiffServer,
|
maybeBest: peerRelayAddrQualityHigherLatencyDiffServer,
|
||||||
wantBestAddr: peerRelayAddrQuality,
|
wantBestAddr: peerRelayAddrQuality,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeBest diff relay server lower latency bestAddr trusted",
|
name: "maybeBest-diff-relay-lower-latency-trusted",
|
||||||
curBestAddr: peerRelayAddrQuality,
|
curBestAddr: peerRelayAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQualityLowerLatencyDiffServer,
|
maybeBest: peerRelayAddrQualityLowerLatencyDiffServer,
|
||||||
wantBestAddr: peerRelayAddrQualityLowerLatencyDiffServer,
|
wantBestAddr: peerRelayAddrQualityLowerLatencyDiffServer,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeBest diff relay server equal latency bestAddr trusted",
|
name: "maybeBest-diff-relay-equal-latency-trusted",
|
||||||
curBestAddr: peerRelayAddrQuality,
|
curBestAddr: peerRelayAddrQuality,
|
||||||
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
trustBestAddrUntil: mono.Now().Add(1 * time.Hour),
|
||||||
maybeBest: peerRelayAddrQualityEqualLatencyDiffServer,
|
maybeBest: peerRelayAddrQualityEqualLatencyDiffServer,
|
||||||
|
|||||||
@@ -184,19 +184,19 @@ func TestBpfDiscardV4(t *testing.T) {
|
|||||||
accept bool
|
accept bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "base accepted datagram",
|
name: "base-accepted-datagram",
|
||||||
replace: map[int]byte{},
|
replace: map[int]byte{},
|
||||||
accept: true,
|
accept: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "more fragments",
|
name: "more-fragments",
|
||||||
replace: map[int]byte{
|
replace: map[int]byte{
|
||||||
6: 0x20,
|
6: 0x20,
|
||||||
},
|
},
|
||||||
accept: false,
|
accept: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "some fragment",
|
name: "some-fragment",
|
||||||
replace: map[int]byte{
|
replace: map[int]byte{
|
||||||
7: 0x01,
|
7: 0x01,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1217,7 +1217,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outerT := t
|
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)
|
setT(t)
|
||||||
defer setT(outerT)
|
defer setT(outerT)
|
||||||
ping1(t)
|
ping1(t)
|
||||||
@@ -1225,7 +1225,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
|||||||
checkStats(t, m2, m2Conns)
|
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)
|
setT(t)
|
||||||
defer setT(outerT)
|
defer setT(outerT)
|
||||||
ping2(t)
|
ping2(t)
|
||||||
@@ -1233,7 +1233,7 @@ func testTwoDevicePing(t *testing.T, d *devices) {
|
|||||||
checkStats(t, m2, m2Conns)
|
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)
|
setT(t)
|
||||||
defer setT(outerT)
|
defer setT(outerT)
|
||||||
msg1to2 := tuntest.Ping(netip.MustParseAddr("1.0.0.2"), netip.MustParseAddr("1.0.0.1"))
|
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)
|
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)
|
setT(t)
|
||||||
defer setT(outerT)
|
defer setT(outerT)
|
||||||
if err := m1.Reconfig(m1cfg); err != nil {
|
if err := m1.Reconfig(m1cfg); err != nil {
|
||||||
@@ -2731,7 +2731,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
|
|||||||
want epAddr
|
want epAddr
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no endpoints",
|
name: "no-endpoints",
|
||||||
sendInitialPing: false,
|
sendInitialPing: false,
|
||||||
validAddr: false,
|
validAddr: false,
|
||||||
sendFollowUpPing: false,
|
sendFollowUpPing: false,
|
||||||
@@ -2740,7 +2740,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
|
|||||||
want: epAddr{},
|
want: epAddr{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "singular endpoint does not request ping",
|
name: "singular-endpoint-no-ping-request",
|
||||||
sendInitialPing: false,
|
sendInitialPing: false,
|
||||||
validAddr: true,
|
validAddr: true,
|
||||||
sendFollowUpPing: false,
|
sendFollowUpPing: false,
|
||||||
@@ -2754,7 +2754,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
|
|||||||
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
|
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,
|
sendInitialPing: true,
|
||||||
validAddr: true,
|
validAddr: true,
|
||||||
sendFollowUpPing: false,
|
sendFollowUpPing: false,
|
||||||
@@ -2772,7 +2772,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
|
|||||||
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
|
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,
|
sendInitialPing: true,
|
||||||
validAddr: true,
|
validAddr: true,
|
||||||
sendFollowUpPing: true,
|
sendFollowUpPing: true,
|
||||||
@@ -2790,7 +2790,7 @@ func TestAddrForSendLockedForWireGuardOnly(t *testing.T) {
|
|||||||
want: epAddr{ap: netip.MustParseAddrPort("1.1.1.1:111")},
|
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,
|
sendInitialPing: true,
|
||||||
validAddr: true,
|
validAddr: true,
|
||||||
sendFollowUpPing: false,
|
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")},
|
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,
|
sendInitialPing: true,
|
||||||
validAddr: true,
|
validAddr: true,
|
||||||
sendFollowUpPing: false,
|
sendFollowUpPing: false,
|
||||||
@@ -3378,73 +3378,73 @@ func Test_packetLooksLike(t *testing.T) {
|
|||||||
wantIsGeneveEncap bool
|
wantIsGeneveEncap bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "STUN binding success response",
|
name: "STUN-binding-success-response",
|
||||||
msg: stun.Response(stun.NewTxID(), netip.MustParseAddrPort("127.0.0.1:1")),
|
msg: stun.Response(stun.NewTxID(), netip.MustParseAddrPort("127.0.0.1:1")),
|
||||||
wantPacketLooksLikeType: packetLooksLikeSTUNBinding,
|
wantPacketLooksLikeType: packetLooksLikeSTUNBinding,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked disco",
|
name: "naked-disco",
|
||||||
msg: nakedDisco,
|
msg: nakedDisco,
|
||||||
wantPacketLooksLikeType: packetLooksLikeDisco,
|
wantPacketLooksLikeType: packetLooksLikeDisco,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap disco",
|
name: "geneve-encap-disco",
|
||||||
msg: geneveEncapDisco,
|
msg: geneveEncapDisco,
|
||||||
wantPacketLooksLikeType: packetLooksLikeDisco,
|
wantPacketLooksLikeType: packetLooksLikeDisco,
|
||||||
wantIsGeneveEncap: true,
|
wantIsGeneveEncap: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap too short disco",
|
name: "geneve-encap-too-short-disco",
|
||||||
msg: geneveEncapDisco[:len(geneveEncapDisco)-key.DiscoPublicRawLen],
|
msg: geneveEncapDisco[:len(geneveEncapDisco)-key.DiscoPublicRawLen],
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap disco nonzero geneve version",
|
name: "geneve-encap-disco-nonzero-geneve-version",
|
||||||
msg: geneveEncapDiscoNonZeroGeneveVersion,
|
msg: geneveEncapDiscoNonZeroGeneveVersion,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap disco nonzero geneve reserved bits",
|
name: "geneve-encap-disco-nonzero-geneve-reserved-bits",
|
||||||
msg: geneveEncapDiscoNonZeroGeneveReservedBits,
|
msg: geneveEncapDiscoNonZeroGeneveReservedBits,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap disco nonzero geneve vni lsb",
|
name: "geneve-encap-disco-nonzero-geneve-vni-lsb",
|
||||||
msg: geneveEncapDiscoNonZeroGeneveVNILSB,
|
msg: geneveEncapDiscoNonZeroGeneveVNILSB,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap wireguard",
|
name: "geneve-encap-wireguard",
|
||||||
msg: geneveEncapWireGuard,
|
msg: geneveEncapWireGuard,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: true,
|
wantIsGeneveEncap: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard Initiation type",
|
name: "naked-WireGuard-Initiation-type",
|
||||||
msg: nakedWireGuardInitiation,
|
msg: nakedWireGuardInitiation,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard Response type",
|
name: "naked-WireGuard-Response-type",
|
||||||
msg: nakedWireGuardResponse,
|
msg: nakedWireGuardResponse,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard Cookie Reply type",
|
name: "naked-WireGuard-Cookie-Reply-type",
|
||||||
msg: nakedWireGuardCookieReply,
|
msg: nakedWireGuardCookieReply,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard Transport type",
|
name: "naked-WireGuard-Transport-type",
|
||||||
msg: nakedWireGuardTransport,
|
msg: nakedWireGuardTransport,
|
||||||
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
wantPacketLooksLikeType: packetLooksLikeWireGuard,
|
||||||
wantIsGeneveEncap: false,
|
wantIsGeneveEncap: false,
|
||||||
@@ -3481,22 +3481,22 @@ func Test_looksLikeInitiationMsg(t *testing.T) {
|
|||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "valid initiation",
|
name: "valid-initiation",
|
||||||
b: initMsg,
|
b: initMsg,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid message type field",
|
name: "invalid-message-type-field",
|
||||||
b: initMsgSizeTransportType,
|
b: initMsgSizeTransportType,
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "too small",
|
name: "too-small",
|
||||||
b: initMsg[:device.MessageInitiationSize-1],
|
b: initMsg[:device.MessageInitiationSize-1],
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "too big",
|
name: "too-big",
|
||||||
b: append(initMsg, 0),
|
b: append(initMsg, 0),
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
@@ -3538,7 +3538,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "match v4",
|
name: "match-v4",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
||||||
@@ -3556,7 +3556,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match v6",
|
name: "match-v6",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
||||||
@@ -3574,7 +3574,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no match CapMatch Dst",
|
name: "no-match-CapMatch-Dst",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
||||||
@@ -3592,7 +3592,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no match peer cap",
|
name: "no-match-peer-cap",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("::2/128")},
|
||||||
@@ -3610,7 +3610,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil src",
|
name: "nil-src",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
||||||
@@ -3628,7 +3628,7 @@ func Test_nodeHasCap(t *testing.T) {
|
|||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nil dst",
|
name: "nil-dst",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
Srcs: []netip.Prefix{netip.MustParsePrefix("2.2.2.2/32")},
|
||||||
@@ -3706,7 +3706,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
|
|||||||
wantRelayClientEnabled bool
|
wantRelayClientEnabled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "candidate relay server",
|
name: "candidate-relay-server",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: peerNodeCandidateRelay.Addresses,
|
Srcs: peerNodeCandidateRelay.Addresses,
|
||||||
@@ -3730,7 +3730,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
|
|||||||
wantRelayClientEnabled: true,
|
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{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: peerNodeCandidateRelay.Addresses,
|
Srcs: peerNodeCandidateRelay.Addresses,
|
||||||
@@ -3748,7 +3748,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
|
|||||||
wantRelayClientEnabled: false,
|
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{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: peerNodeCandidateRelay.Addresses,
|
Srcs: peerNodeCandidateRelay.Addresses,
|
||||||
@@ -3766,7 +3766,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
|
|||||||
wantRelayClientEnabled: false,
|
wantRelayClientEnabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "self candidate relay server",
|
name: "self-candidate-relay-server",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: selfNode.Addresses,
|
Srcs: selfNode.Addresses,
|
||||||
@@ -3790,7 +3790,7 @@ func TestConn_SetNetworkMap_updateRelayServersSet(t *testing.T) {
|
|||||||
wantRelayClientEnabled: true,
|
wantRelayClientEnabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no candidate relay server",
|
name: "no-candidate-relay-server",
|
||||||
filt: filter.New([]filtertype.Match{
|
filt: filter.New([]filtertype.Match{
|
||||||
{
|
{
|
||||||
Srcs: peerNodeNotCandidateRelayCapVer.Addresses,
|
Srcs: peerNodeNotCandidateRelayCapVer.Addresses,
|
||||||
@@ -3911,7 +3911,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled bool
|
wantNoteRecvActivityCalled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "naked disco",
|
name: "naked-disco",
|
||||||
b: looksLikeNakedDisco,
|
b: looksLikeNakedDisco,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3923,7 +3923,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve encap disco",
|
name: "geneve-encap-disco",
|
||||||
b: looksLikeGeneveDisco,
|
b: looksLikeGeneveDisco,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3935,7 +3935,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "STUN binding",
|
name: "STUN-binding",
|
||||||
b: looksLikeSTUNBinding,
|
b: looksLikeSTUNBinding,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3947,7 +3947,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard init lazyEndpoint empty peerMap",
|
name: "naked-WireGuard-init-lazyEndpoint-empty-peerMap",
|
||||||
b: looksLikeNakedWireGuardInit,
|
b: looksLikeNakedWireGuardInit,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3959,7 +3959,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "naked WireGuard init endpoint matching peerMap entry",
|
name: "naked-WireGuard-init-endpoint-matching-peerMap-entry",
|
||||||
b: looksLikeNakedWireGuardInit,
|
b: looksLikeNakedWireGuardInit,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3973,7 +3973,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: true,
|
wantNoteRecvActivityCalled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve WireGuard init lazyEndpoint empty peerMap",
|
name: "geneve-WireGuard-init-lazyEndpoint-empty-peerMap",
|
||||||
b: looksLikeGeneveWireGuardInit,
|
b: looksLikeGeneveWireGuardInit,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -3985,7 +3985,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve WireGuard init lazyEndpoint matching peerMap activity noted",
|
name: "geneve-WireGuard-init-lazyEndpoint-matching-peerMap-activity-noted",
|
||||||
b: looksLikeGeneveWireGuardInit,
|
b: looksLikeGeneveWireGuardInit,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -4001,7 +4001,7 @@ func TestConn_receiveIP(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled: true,
|
wantNoteRecvActivityCalled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geneve WireGuard init lazyEndpoint matching peerMap no activity noted",
|
name: "geneve-WireGuard-init-lazyEndpoint-matching-peerMap-no-activity-noted",
|
||||||
b: looksLikeGeneveWireGuardInit,
|
b: looksLikeGeneveWireGuardInit,
|
||||||
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
ipp: netip.MustParseAddrPort("127.0.0.1:7777"),
|
||||||
cache: &epAddrEndpointCache{},
|
cache: &epAddrEndpointCache{},
|
||||||
@@ -4151,25 +4151,25 @@ func Test_lazyEndpoint_InitiationMessagePublicKey(t *testing.T) {
|
|||||||
wantNoteRecvActivityCalled bool
|
wantNoteRecvActivityCalled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "noteRecvActivity called",
|
name: "noteRecvActivity-called",
|
||||||
callWithPeerMapKey: true,
|
callWithPeerMapKey: true,
|
||||||
maybeEPMatchingKey: false,
|
maybeEPMatchingKey: false,
|
||||||
wantNoteRecvActivityCalled: true,
|
wantNoteRecvActivityCalled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeEP early return",
|
name: "maybeEP-early-return",
|
||||||
callWithPeerMapKey: true,
|
callWithPeerMapKey: true,
|
||||||
maybeEPMatchingKey: true,
|
maybeEPMatchingKey: true,
|
||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not in peerMap early return",
|
name: "not-in-peerMap-early-return",
|
||||||
callWithPeerMapKey: false,
|
callWithPeerMapKey: false,
|
||||||
maybeEPMatchingKey: false,
|
maybeEPMatchingKey: false,
|
||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not in peerMap maybeEP early return",
|
name: "not-in-peerMap-maybeEP-early-return",
|
||||||
callWithPeerMapKey: false,
|
callWithPeerMapKey: false,
|
||||||
maybeEPMatchingKey: true,
|
maybeEPMatchingKey: true,
|
||||||
wantNoteRecvActivityCalled: false,
|
wantNoteRecvActivityCalled: false,
|
||||||
@@ -4232,25 +4232,25 @@ func Test_lazyEndpoint_FromPeer(t *testing.T) {
|
|||||||
wantEpAddrInPeerMap bool
|
wantEpAddrInPeerMap bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "epAddr in peerMap",
|
name: "epAddr-in-peerMap",
|
||||||
callWithPeerMapKey: true,
|
callWithPeerMapKey: true,
|
||||||
maybeEPMatchingKey: false,
|
maybeEPMatchingKey: false,
|
||||||
wantEpAddrInPeerMap: true,
|
wantEpAddrInPeerMap: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "maybeEP early return",
|
name: "maybeEP-early-return",
|
||||||
callWithPeerMapKey: true,
|
callWithPeerMapKey: true,
|
||||||
maybeEPMatchingKey: true,
|
maybeEPMatchingKey: true,
|
||||||
wantEpAddrInPeerMap: false,
|
wantEpAddrInPeerMap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not in peerMap early return",
|
name: "not-in-peerMap-early-return",
|
||||||
callWithPeerMapKey: false,
|
callWithPeerMapKey: false,
|
||||||
maybeEPMatchingKey: false,
|
maybeEPMatchingKey: false,
|
||||||
wantEpAddrInPeerMap: false,
|
wantEpAddrInPeerMap: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not in peerMap maybeEP early return",
|
name: "not-in-peerMap-maybeEP-early-return",
|
||||||
callWithPeerMapKey: false,
|
callWithPeerMapKey: false,
|
||||||
maybeEPMatchingKey: true,
|
maybeEPMatchingKey: true,
|
||||||
wantEpAddrInPeerMap: false,
|
wantEpAddrInPeerMap: false,
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// Test for http://go/corp/32978
|
// Test for http://go/corp/32978
|
||||||
name: "eq server+ep neq VNI higher lamport",
|
name: "eq-server-ep-neq-VNI-higher-lamport",
|
||||||
events: []newRelayServerEndpointEvent{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport1VNI1,
|
serverAendpointALamport1VNI1,
|
||||||
serverAendpointALamport2VNI2,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport2VNI2,
|
serverAendpointALamport2VNI2,
|
||||||
serverAendpointALamport1VNI1,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport2VNI2,
|
serverAendpointALamport2VNI2,
|
||||||
serverAendpointBLamport1VNI2,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointBLamport1VNI2,
|
serverAendpointBLamport1VNI2,
|
||||||
serverAendpointALamport2VNI2,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport1VNI1,
|
serverAendpointALamport1VNI1,
|
||||||
serverAendpointALamport2VNI1,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport2VNI1,
|
serverAendpointALamport2VNI1,
|
||||||
serverAendpointALamport1VNI1,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport1VNI1,
|
serverAendpointALamport1VNI1,
|
||||||
serverBendpointALamport1VNI1,
|
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{
|
events: []newRelayServerEndpointEvent{
|
||||||
serverAendpointALamport1VNI1LastBestMatching,
|
serverAendpointALamport1VNI1LastBestMatching,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,13 +54,13 @@ ip rule add -6 pref 5270 table 52
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no config",
|
name: "no-config",
|
||||||
in: nil,
|
in: nil,
|
||||||
want: `
|
want: `
|
||||||
up` + basic,
|
up` + basic,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "local addr only",
|
name: "local-addr-only",
|
||||||
in: &Config{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
||||||
NetfilterMode: netfilterOff,
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
LocalAddrs: mustCIDRs("100.101.102.103/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "0.0.0.0/0"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32", "0.0.0.0/0"),
|
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,
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32"),
|
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{
|
in: &Config{
|
||||||
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
LocalAddrs: mustCIDRs("100.101.102.104/10"),
|
||||||
Routes: mustCIDRs("100.100.100.100/32"),
|
Routes: mustCIDRs("100.100.100.100/32"),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func TestWatchdog(t *testing.T) {
|
|||||||
maxWaitMultiple = 15
|
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()
|
t.Parallel()
|
||||||
bus := eventbustest.NewBus(t)
|
bus := eventbustest.NewBus(t)
|
||||||
ht := health.NewTracker(bus)
|
ht := health.NewTracker(bus)
|
||||||
@@ -55,7 +55,7 @@ func TestWatchdogMetrics(t *testing.T) {
|
|||||||
wantCounts map[watchdogEvent]int64
|
wantCounts map[watchdogEvent]int64
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "single event types",
|
name: "single-event-types",
|
||||||
events: []watchdogEvent{RequestStatus, PeerForIPEvent, Ping},
|
events: []watchdogEvent{RequestStatus, PeerForIPEvent, Ping},
|
||||||
wantCounts: map[watchdogEvent]int64{
|
wantCounts: map[watchdogEvent]int64{
|
||||||
RequestStatus: 1,
|
RequestStatus: 1,
|
||||||
@@ -64,7 +64,7 @@ func TestWatchdogMetrics(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "repeated events",
|
name: "repeated-events",
|
||||||
events: []watchdogEvent{RequestStatus, RequestStatus, Ping, RequestStatus},
|
events: []watchdogEvent{RequestStatus, RequestStatus, Ping, RequestStatus},
|
||||||
wantCounts: map[watchdogEvent]int64{
|
wantCounts: map[watchdogEvent]int64{
|
||||||
RequestStatus: 3,
|
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 {
|
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
cmp(t, device1, cfg1)
|
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 {
|
if err := ReconfigDevice(device2, cfg2, t.Logf); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func TestDeviceConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// This is only to test that Config and Reconfig are properly synchronized.
|
// 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
|
var wg sync.WaitGroup
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ func TestDeviceConfig(t *testing.T) {
|
|||||||
wg.Wait()
|
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}))
|
cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 1, 31: 0}))
|
||||||
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
|
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -130,7 +130,7 @@ func TestDeviceConfig(t *testing.T) {
|
|||||||
cmp(t, device1, cfg1)
|
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}))
|
cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 2, 31: 0}))
|
||||||
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
|
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -138,7 +138,7 @@ func TestDeviceConfig(t *testing.T) {
|
|||||||
cmp(t, device1, cfg1)
|
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{
|
cfg1.Peers = append(cfg1.Peers, Peer{
|
||||||
PublicKey: k3,
|
PublicKey: k3,
|
||||||
AllowedIPs: []netip.Prefix{ip3},
|
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
|
removeKey := cfg1.Peers[len(cfg1.Peers)-1].PublicKey
|
||||||
cfg1.Peers = cfg1.Peers[:len(cfg1.Peers)-1]
|
cfg1.Peers = cfg1.Peers[:len(cfg1.Peers)-1]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user