package oci import ( "errors" "fmt" "testing" ) // fakeServiceError 模拟 oci-go-sdk 的 common.ServiceError, // Error() 按 SDK 真实格式输出长文以验证截断。 type fakeServiceError struct { status int code string message string } func (e fakeServiceError) Error() string { return fmt.Sprintf( "Error returned by Compute Service. Http Status Code: %d. Error Code: %s. Message: %s. Troubleshooting Tips: See https://docs.oracle.com/ ...", e.status, e.code, e.message) } func (e fakeServiceError) GetHTTPStatusCode() int { return e.status } func (e fakeServiceError) GetMessage() string { return e.message } func (e fakeServiceError) GetCode() string { return e.code } func (e fakeServiceError) GetOpcRequestID() string { return "req-1" } func TestCompactError(t *testing.T) { capacity := fakeServiceError{status: 500, code: "InternalError", message: "Out of host capacity."} tests := []struct { name string err error want string }{ { name: "非 OCI 错误原样返回", err: errors.New("parse payload: unexpected end of JSON input"), want: "parse payload: unexpected end of JSON input", }, { name: "带操作前缀的 OCI 错误保留前缀并剥掉长文", err: fmt.Errorf("launch instance: %w", capacity), want: "launch instance: Out of host capacity.", }, { name: "多层包装保留完整前缀链", err: fmt.Errorf("snatch-1: %w", fmt.Errorf("launch instance: %w", capacity)), want: "snatch-1: launch instance: Out of host capacity.", }, { name: "无前缀时只输出服务端消息", err: error(capacity), want: "Out of host capacity.", }, { name: "消息中的长 OCID 压缩为类型加尾位", err: fmt.Errorf("update instance: %w", fakeServiceError{ status: 500, code: "InternalError", message: "instance ocid1.instance.oc1.phx.anyhqljtp537sbqcr2f5ed2jwkglwyd3g6dfbmgtwdp4xdarxum5q7tdcyla: Out of host capacity.", }), want: "update instance: instance ocid1.instance…tdcyla: Out of host capacity.", }, { name: "非 OCI 错误里的 OCID 同样压缩", err: errors.New("get instance ocid1.instance.oc1..aaaaaaaabbbbbbbbccccccccdddddddd failed"), want: "get instance ocid1.instance…dddddd failed", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := CompactError(tt.err); got != tt.want { t.Errorf("CompactError() = %q, want %q", got, tt.want) } }) } } func TestErrorHint(t *testing.T) { tests := []struct { name string err error want string }{ { name: "非 OCI 错误无提示", err: errors.New("db locked"), want: "", }, { name: "已知错误码给出中文提示", err: fmt.Errorf("delete vcn: %w", fakeServiceError{409, "IncorrectState", "vcn in use"}), want: ociErrorHints["IncorrectState"], }, { name: "InternalError 但消息为容量不足时归到容量提示", err: fmt.Errorf("launch: %w", fakeServiceError{500, "InternalError", "Out of host capacity."}), want: ociErrorHints["OutOfHostCapacity"], }, { name: "未知错误码返回空串", err: fmt.Errorf("x: %w", fakeServiceError{400, "SomethingNew", "boom"}), want: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := ErrorHint(tt.err); got != tt.want { t.Errorf("ErrorHint() = %q, want %q", got, tt.want) } }) } }