118 lines
4.4 KiB
Go
118 lines
4.4 KiB
Go
package sms
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
|
aliyun "github.com/alibabacloud-go/dysmsapi-20170525/v4/client"
|
|
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
|
"github.com/alibabacloud-go/tea/tea"
|
|
tencent "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111"
|
|
biz "kra/internal/biz/integration"
|
|
"kra/internal/integration/runtimeconfig"
|
|
)
|
|
|
|
type aliFake struct {
|
|
calls int
|
|
request *aliyun.SendSmsRequest
|
|
code string
|
|
}
|
|
|
|
func (f *aliFake) SendSmsWithOptions(req *aliyun.SendSmsRequest, opts *util.RuntimeOptions) (*aliyun.SendSmsResponse, error) {
|
|
f.calls++
|
|
f.request = req
|
|
if tea.BoolValue(opts.Autoretry) {
|
|
panic("SMS must not retry automatically")
|
|
}
|
|
return &aliyun.SendSmsResponse{Body: &aliyun.SendSmsResponseBody{Code: tea.String(f.code), BizId: tea.String("ali-message"), RequestId: tea.String("ali-request")}}, nil
|
|
}
|
|
|
|
type tcFake struct {
|
|
calls int
|
|
request *tencent.SendSmsRequest
|
|
code string
|
|
}
|
|
|
|
func (f *tcFake) SendSmsWithContext(_ context.Context, req *tencent.SendSmsRequest) (*tencent.SendSmsResponse, error) {
|
|
f.calls++
|
|
f.request = req
|
|
return &tencent.SendSmsResponse{Response: &tencent.SendSmsResponseParams{RequestId: tea.String("tc-request"), SendStatusSet: []*tencent.SendStatus{{Code: tea.String(f.code), SerialNo: tea.String("tc-message")}}}}, nil
|
|
}
|
|
|
|
func testSender(t *testing.T, provider string) *Sender {
|
|
t.Helper()
|
|
store := runtimeconfig.NewStore()
|
|
values := biz.DefaultIntegrationConfig("sms", provider)
|
|
for k, v := range values {
|
|
if v == "" {
|
|
values[k] = "test-" + k
|
|
}
|
|
}
|
|
raw, _ := json.Marshal(values)
|
|
store.Set(runtimeconfig.Config{Kind: "sms", Provider: provider, Enabled: true, Values: raw})
|
|
return NewSender(store).(*Sender)
|
|
}
|
|
|
|
func TestAliyunSendAndRejection(t *testing.T) {
|
|
s := testSender(t, "aliyun")
|
|
f := &aliFake{code: "OK"}
|
|
s.newAliyun = func(c *openapi.Config) (aliyunClient, error) {
|
|
if tea.StringValue(c.Endpoint) != "dysmsapi.aliyuncs.com" || tea.StringValue(c.AccessKeySecret) != "test-access_key_secret" {
|
|
t.Fatal("incorrect client configuration")
|
|
}
|
|
return f, nil
|
|
}
|
|
m := &biz.SMSMessage{Provider: "aliyun", Phone: "+8613800138000", NamedParams: map[string]string{"code": "123456"}}
|
|
result, err := s.Send(context.Background(), m)
|
|
if err != nil || result.MessageID != "ali-message" {
|
|
t.Fatalf("result=%v error=%v", result, err)
|
|
}
|
|
if tea.StringValue(f.request.PhoneNumbers) != "13800138000" || tea.StringValue(f.request.TemplateParam) != `{"code":"123456"}` || tea.StringValue(f.request.TemplateCode) != "test-template_id" {
|
|
t.Fatal("incorrect Aliyun request")
|
|
}
|
|
f.code = "isv.BUSINESS_LIMIT_CONTROL"
|
|
if _, err = s.Send(context.Background(), m); err == nil || !strings.Contains(err.Error(), f.code) {
|
|
t.Fatalf("provider rejection not surfaced: %v", err)
|
|
}
|
|
if f.calls != 2 {
|
|
t.Fatal("unexpected retry")
|
|
}
|
|
}
|
|
|
|
func TestTencentSendAndRejection(t *testing.T) {
|
|
s := testSender(t, "tencent")
|
|
f := &tcFake{code: "Ok"}
|
|
s.newTencent = func(id, key, region string) (tencentClient, error) { return f, nil }
|
|
m := &biz.SMSMessage{Provider: "tencent", Phone: "+8613800138000", Params: []string{"123456", "5"}}
|
|
result, err := s.Send(context.Background(), m)
|
|
if err != nil || result.MessageID != "tc-message" {
|
|
t.Fatalf("result=%v error=%v", result, err)
|
|
}
|
|
if len(f.request.PhoneNumberSet) != 1 || *f.request.PhoneNumberSet[0] != m.Phone || len(f.request.TemplateParamSet) != 2 || *f.request.TemplateParamSet[1] != "5" || *f.request.SmsSdkAppId != "test-sdk_app_id" {
|
|
t.Fatal("incorrect Tencent request")
|
|
}
|
|
f.code = "FailedOperation.SignatureIncorrectOrUnapproved"
|
|
if _, err = s.Send(context.Background(), m); err == nil || !strings.Contains(err.Error(), f.code) {
|
|
t.Fatalf("provider rejection not surfaced: %v", err)
|
|
}
|
|
c, _ := s.store.Get("sms", "tencent")
|
|
c.Enabled = false
|
|
s.store.Set(c)
|
|
if _, err = s.Send(context.Background(), m); err == nil {
|
|
t.Fatal("disabled channel sent SMS")
|
|
}
|
|
if f.calls != 2 {
|
|
t.Fatal("disabled channel reached SDK")
|
|
}
|
|
}
|
|
|
|
func TestSDKErrorDoesNotExposeRawMessage(t *testing.T) {
|
|
err := sdkError(&tea.SDKError{Code: tea.String("InvalidAccessKeyId.NotFound"), Message: tea.String("secret +8613800138000 signed request")})
|
|
if strings.Contains(err.Error(), "secret") || strings.Contains(err.Error(), "13800138000") || !strings.Contains(err.Error(), "InvalidAccessKeyId.NotFound") {
|
|
t.Fatalf("unsafe error: %v", err)
|
|
}
|
|
}
|