滑动续期、网络错误归类、API Key 激活乐观锁与生效提示

This commit is contained in:
2026-08-11 11:45:03 +08:00
parent 23b2820101
commit e63af49831
21 changed files with 679 additions and 15 deletions
+110
View File
@@ -1,8 +1,10 @@
package oci
import (
"context"
"errors"
"fmt"
"net/url"
"testing"
)
@@ -95,6 +97,11 @@ func TestErrorHint(t *testing.T) {
err: fmt.Errorf("launch: %w", fakeServiceError{500, "InternalError", "Out of host capacity."}),
want: ociErrorHints["OutOfHostCapacity"],
},
{
name: "NotAuthenticated 提示密钥无效或传播中",
err: fmt.Errorf("get instance: %w", fakeServiceError{401, "NotAuthenticated", "The required information ..."}),
want: ociErrorHints["NotAuthenticated"],
},
{
name: "未知错误码返回空串",
err: fmt.Errorf("x: %w", fakeServiceError{400, "SomethingNew", "boom"}),
@@ -158,3 +165,106 @@ func TestIsModelUnavailable(t *testing.T) {
})
}
}
// fakeTimeoutErr 模拟实现 net.Error 的超时错误(如响应体读取超时)。
type fakeTimeoutErr struct{}
func (fakeTimeoutErr) Error() string { return "read tcp 10.0.0.1:443: i/o timeout" }
func (fakeTimeoutErr) Timeout() bool { return true }
func (fakeTimeoutErr) Temporary() bool { return false }
type upstreamNetworkErrorCase struct {
name string
err error
want string
wantOK bool
}
var upstreamNetworkErrorCases = []upstreamNetworkErrorCase{
{
name: "OCI 服务错误不归网络",
err: fmt.Errorf("get instance: %w", fakeServiceError{status: 401, code: "NotAuthenticated", message: "x"}),
wantOK: false,
},
{
name: "普通业务错误不归网络",
err: errors.New("parse payload: bad json"),
wantOK: false,
},
{
name: "代理 CONNECT 失败带中文分类且 URL 缩为主机",
err: fmt.Errorf("list instances: %w", &url.Error{
Op: "Get",
URL: "https://iaas.uk-london-1.oraclecloud.com/20160918/instances?limit=100",
Err: errors.New("proxyconnect tcp: dial tcp 1.2.3.4:8080: connect: connection refused"),
}),
want: "代理连接失败: Get iaas.uk-london-1.oraclecloud.com: proxyconnect tcp: dial tcp 1.2.3.4:8080: connect: connection refused",
wantOK: true,
},
{
name: "SOCKS 握手失败归代理类",
err: &url.Error{
Op: "Post",
URL: "https://identity.us-sanjose-1.oci.oraclecloud.com/20160918/users",
Err: errors.New("socks connect tcp 5.6.7.8:1080->identity: dial refused"),
},
want: "代理连接失败: Post identity.us-sanjose-1.oci.oraclecloud.com: socks connect tcp 5.6.7.8:1080->identity: dial refused",
wantOK: true,
},
{
name: "URL 内嵌 userinfo 不回显",
err: &url.Error{
Op: "Get",
URL: "https://user:pass@example.com/path",
Err: errors.New("EOF"),
},
want: "上游连接失败: Get example.com: EOF",
wantOK: true,
},
{
name: "嵌套 URL 的代理 userinfo 不回显",
err: &url.Error{
Op: "Get",
URL: "https://identity.us-ashburn-1.oraclecloud.com/20160918/tenancies/x",
Err: fmt.Errorf("proxyconnect tcp: %w", &url.Error{
Op: "Dial", URL: "http://proxy-user:proxy-pass@proxy.example.com:8080",
Err: errors.New("connect: connection refused"),
}),
},
want: "代理连接失败: Get identity.us-ashburn-1.oraclecloud.com: proxyconnect tcp: Dial proxy.example.com:8080: connect: connection refused",
wantOK: true,
},
{
name: "普通内层错误中的存量代理 userinfo 不回显",
err: &url.Error{
Op: "Get",
URL: "https://identity.us-phoenix-1.oraclecloud.com/20160918/tenancies/x",
Err: errors.New("proxyconnect tcp: dial tcp alice:secret@proxy.example.com:8080: connect: connection refused"),
},
want: "代理连接失败: Get identity.us-phoenix-1.oraclecloud.com: proxyconnect tcp: dial tcp proxy.example.com:8080: connect: connection refused",
wantOK: true,
},
{
name: "context 超时归网络",
err: fmt.Errorf("summarize costs: %w", context.DeadlineExceeded),
want: "上游连接失败: 请求超时",
wantOK: true,
},
{
name: "net.Error 超时归网络",
err: fmt.Errorf("read body: %w", fakeTimeoutErr{}),
want: "上游连接失败: 连接超时",
wantOK: true,
},
}
func TestUpstreamNetworkError(t *testing.T) {
for _, tt := range upstreamNetworkErrorCases {
t.Run(tt.name, func(t *testing.T) {
got, ok := UpstreamNetworkError(tt.err)
if ok != tt.wantOK || got != tt.want {
t.Errorf("UpstreamNetworkError() = (%q, %v), want (%q, %v)", got, ok, tt.want, tt.wantOK)
}
})
}
}