feat(all): configure proxies, reuse native HTTP and stabilize recovery
Persist direct/manual proxy settings in Client Studio and apply them to resource, Unity and native requests, with loopback bypass and no automatic system proxy. Pool WinHTTP/curl connections, bound workers and deadlines, cancel safely, and log queue and transport timings without exposing sensitive paths. Return explicit relay failures, probe through native HTTP, retry interrupted requests and recognize completed home, field and pack scenes during recovery.
This commit is contained in:
@@ -6,39 +6,66 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGameProxyEnvironmentPreservesExplicitAndIsIdempotent(t *testing.T) {
|
||||
input := []string{"PATH=kept", "UNITY_PROXYSERVER=http://explicit:8080", "UNITY_NOPROXY=example.org;localhost"}
|
||||
got := gameProxyEnvironment(input, "http://system:8888")
|
||||
if !reflect.DeepEqual(got, gameProxyEnvironment(got, "http://other:9999")) {
|
||||
t.Fatal("environment is not idempotent")
|
||||
}
|
||||
if got[1] != input[1] || input[2] != "UNITY_NOPROXY=example.org;localhost" {
|
||||
t.Fatal("explicit environment changed or input mutated")
|
||||
}
|
||||
if !strings.Contains(got[2], "127.0.0.1") || !strings.Contains(got[2], "::1") {
|
||||
t.Fatal("loopback bypass missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharedWindowsProxy(t *testing.T) {
|
||||
for _, test := range []struct{ input, want string }{
|
||||
{"127.0.0.1:12451", "http://127.0.0.1:12451"},
|
||||
{"http=proxy:8080;https=proxy:8080", "http://proxy:8080"},
|
||||
{"http=proxy:8080;https=other:8080", ""},
|
||||
{"https=proxy:8080", ""}, {"user:password@proxy:8080", ""}, {"proxy:99999", ""},
|
||||
} {
|
||||
if got := sharedWindowsProxy(test.input); got != test.want {
|
||||
t.Errorf("proxy configuration result mismatch")
|
||||
func TestGameProxyEnvironmentAuthoritative(t *testing.T) {
|
||||
input := []string{"PATH=kept", "UNITY_PROXYSERVER=http://stale:8080", "uNiTy_NoPrOxY=*", "http_proxy=http://stale:8080", "HTTPS_PROXY=http://stale:8080", "All_Proxy=http://stale:8080", "NO_PROXY=*", "bd2_client_proxy_url=http://stale:8080"}
|
||||
original := append([]string(nil), input...)
|
||||
for _, proxy := range []string{"", "http://127.0.0.1:12451"} {
|
||||
got := gameProxyEnvironment(input, proxy)
|
||||
if !reflect.DeepEqual(got, gameProxyEnvironment(got, proxy)) {
|
||||
t.Fatal("environment is not idempotent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGameProxyEnvironmentIgnoresInvalidSystemProxy(t *testing.T) {
|
||||
for _, proxy := range []string{"", "https://proxy:443", "http://user:password@proxy:8080", "http://proxy:8080/path"} {
|
||||
for _, entry := range gameProxyEnvironment(nil, proxy) {
|
||||
if strings.HasPrefix(entry, "UNITY_PROXYSERVER=") {
|
||||
t.Fatal("invalid system proxy accepted")
|
||||
if got[0] != "PATH=kept" || !reflect.DeepEqual(input, original) {
|
||||
t.Fatal("unrelated environment or input changed")
|
||||
}
|
||||
seen := map[string]string{}
|
||||
for _, entry := range got[1:] {
|
||||
key, value, _ := strings.Cut(entry, "=")
|
||||
if !isGameProxyEnvironmentKey(key) || strings.Contains(value, "stale") {
|
||||
t.Fatal("stale proxy survived")
|
||||
}
|
||||
seen[key] = value
|
||||
}
|
||||
for _, key := range []string{"UNITY_PROXYSERVER", "HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy", "BD2_CLIENT_PROXY_URL"} {
|
||||
if value, ok := seen[key]; !ok || value != proxy {
|
||||
t.Errorf("missing authoritative %s override", key)
|
||||
}
|
||||
}
|
||||
for _, key := range []string{"UNITY_NOPROXY", "NO_PROXY", "no_proxy"} {
|
||||
if seen[key] != "localhost,127.0.0.1,::1" {
|
||||
t.Errorf("loopback bypass missing for %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGameProxyEnvironmentKeys(t *testing.T) {
|
||||
for _, key := range []string{"UNITY_PROXYSERVER", "unity_noproxy", "http_proxy", "HTTPS_PROXY", "All_Proxy", "NO_PROXY", "bd2_client_proxy_url"} {
|
||||
if !isGameProxyEnvironmentKey(key) {
|
||||
t.Errorf("proxy key %q not recognized", key)
|
||||
}
|
||||
}
|
||||
for _, key := range []string{"PATH", "SECRET", "HTTP_PROXY_PASSWORD", "NO_PROXY_EXTRA"} {
|
||||
if isGameProxyEnvironmentKey(key) {
|
||||
t.Errorf("unrelated key %q recognized", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGameOpenArgumentsOverridesLaunchServicesProxy(t *testing.T) {
|
||||
args := gameOpenArguments("/Applications/BrownDust II.app", []string{"HTTP_PROXY=http://stale:80", "PATH=private"}, "")
|
||||
overrides := map[string]bool{}
|
||||
for index := 1; index < len(args) && args[index] != "--args"; index += 2 {
|
||||
if args[index] != "--env" {
|
||||
t.Fatal("missing explicit LaunchServices environment flag")
|
||||
}
|
||||
overrides[args[index+1]] = true
|
||||
}
|
||||
for _, entry := range []string{"HTTP_PROXY=", "http_proxy=", "HTTPS_PROXY=", "ALL_PROXY=", "UNITY_PROXYSERVER=", "BD2_CLIENT_PROXY_URL=", "UNITY_NOPROXY=localhost,127.0.0.1,::1"} {
|
||||
if !overrides[entry] {
|
||||
t.Errorf("LaunchServices override missing: %s", entry)
|
||||
}
|
||||
}
|
||||
if overrides["PATH=private"] || overrides["HTTP_PROXY=http://stale:80"] {
|
||||
t.Fatal("unrelated or stale environment forwarded")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user