134 lines
5.2 KiB
Go
134 lines
5.2 KiB
Go
package tencentrtc
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestRESTClientRemoveUserByStrRoomIDBuildsTencentCloudRequest 锁定 TRTC 字符串房间踢人的 API 3.0 请求形态。
|
|
func TestRESTClientRemoveUserByStrRoomIDBuildsTencentCloudRequest(t *testing.T) {
|
|
var capturedBody map[string]any
|
|
var capturedHeader http.Header
|
|
client, err := NewRESTClient(RESTConfig{
|
|
SDKAppID: 1400000001,
|
|
SecretID: "AKIDEXAMPLE",
|
|
SecretKey: "secret",
|
|
Region: "ap-guangzhou",
|
|
HTTPClient: &http.Client{Transport: roundTripFunc(func(request *http.Request) (*http.Response, error) {
|
|
capturedHeader = request.Header.Clone()
|
|
if err := json.NewDecoder(request.Body).Decode(&capturedBody); err != nil {
|
|
t.Fatalf("decode request body failed: %v", err)
|
|
}
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"Response":{"RequestId":"req-1"}}`))),
|
|
Header: make(http.Header),
|
|
}, nil
|
|
})},
|
|
Now: func() time.Time { return time.Unix(1_700_000_000, 0).UTC() },
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("NewRESTClient failed: %v", err)
|
|
}
|
|
|
|
if err := client.RemoveUserByStrRoomID(context.Background(), "room_1001", 10002); err != nil {
|
|
t.Fatalf("RemoveUserByStrRoomID failed: %v", err)
|
|
}
|
|
|
|
if capturedBody["SdkAppId"].(float64) != 1400000001 || capturedBody["RoomId"] != "room_1001" {
|
|
t.Fatalf("unexpected remove user body: %+v", capturedBody)
|
|
}
|
|
users, ok := capturedBody["UserIds"].([]any)
|
|
if !ok || len(users) != 1 || users[0] != "10002" {
|
|
t.Fatalf("unexpected user ids: %+v", capturedBody)
|
|
}
|
|
if capturedHeader.Get("X-TC-Action") != removeUserByStrRoomAction || capturedHeader.Get("X-TC-Version") != trtcAPIVersion {
|
|
t.Fatalf("unexpected tencent cloud headers: %+v", capturedHeader)
|
|
}
|
|
if !strings.HasPrefix(capturedHeader.Get("Authorization"), tencentCloudTC3Algorithm+" Credential=AKIDEXAMPLE/") {
|
|
t.Fatalf("authorization header missing TC3 credential: %s", capturedHeader.Get("Authorization"))
|
|
}
|
|
}
|
|
|
|
// TestRESTClientSetUserAudioBlockedByStrRoomIDBuildsAudioOnlyRequest 锁定服务端禁言只关闭上行音频,
|
|
// 解除时恢复音视频能力,避免误用 IsMute=1 把未来的视频房能力一并关闭。
|
|
func TestRESTClientSetUserAudioBlockedByStrRoomIDBuildsAudioOnlyRequest(t *testing.T) {
|
|
var bodies []map[string]any
|
|
var actions []string
|
|
client, err := NewRESTClient(RESTConfig{
|
|
SDKAppID: 1400000001,
|
|
SecretID: "AKIDEXAMPLE",
|
|
SecretKey: "secret",
|
|
Region: "ap-singapore",
|
|
HTTPClient: &http.Client{Transport: roundTripFunc(func(request *http.Request) (*http.Response, error) {
|
|
var body map[string]any
|
|
if err := json.NewDecoder(request.Body).Decode(&body); err != nil {
|
|
t.Fatalf("decode request body failed: %v", err)
|
|
}
|
|
bodies = append(bodies, body)
|
|
actions = append(actions, request.Header.Get("X-TC-Action"))
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"Response":{"RequestId":"req-block"}}`))),
|
|
Header: make(http.Header),
|
|
}, nil
|
|
})},
|
|
Now: func() time.Time { return time.Unix(1_700_000_000, 0).UTC() },
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("NewRESTClient failed: %v", err)
|
|
}
|
|
|
|
if err := client.SetUserAudioBlockedByStrRoomID(context.Background(), "room_1001", 10002, true); err != nil {
|
|
t.Fatalf("block user audio failed: %v", err)
|
|
}
|
|
if err := client.SetUserAudioBlockedByStrRoomID(context.Background(), "room_1001", 10002, false); err != nil {
|
|
t.Fatalf("unblock user audio failed: %v", err)
|
|
}
|
|
|
|
if len(bodies) != 2 || len(actions) != 2 {
|
|
t.Fatalf("unexpected request count: bodies=%d actions=%d", len(bodies), len(actions))
|
|
}
|
|
for index, expectedMute := range []float64{trtcUserAudioDisabled, trtcUserMediaEnabled} {
|
|
if actions[index] != setUserBlockedByStrAction || bodies[index]["SdkAppId"] != float64(1400000001) || bodies[index]["StrRoomId"] != "room_1001" || bodies[index]["UserId"] != "10002" || bodies[index]["IsMute"] != expectedMute {
|
|
t.Fatalf("unexpected set user blocked request %d: action=%s body=%+v", index, actions[index], bodies[index])
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestRESTClientSetUserAudioBlockedTreatsAbsentRTCUserAsConverged 防止用户先退 RTC 后的历史
|
|
// RoomUserMuted 事件把 durable outbox 永久卡在无意义重试上。
|
|
func TestRESTClientSetUserAudioBlockedTreatsAbsentRTCUserAsConverged(t *testing.T) {
|
|
client, err := NewRESTClient(RESTConfig{
|
|
SDKAppID: 1400000001,
|
|
SecretID: "AKIDEXAMPLE",
|
|
SecretKey: "secret",
|
|
Region: "ap-singapore",
|
|
HTTPClient: &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) {
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"Response":{"Error":{"Code":"FailedOperation.UserNotExist","Message":"user absent"},"RequestId":"req-absent"}}`))),
|
|
Header: make(http.Header),
|
|
}, nil
|
|
})},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("NewRESTClient failed: %v", err)
|
|
}
|
|
if err := client.SetUserAudioBlockedByStrRoomID(context.Background(), "room_1001", 10002, true); err != nil {
|
|
t.Fatalf("absent RTC user must be treated as converged: %v", err)
|
|
}
|
|
}
|
|
|
|
type roundTripFunc func(*http.Request) (*http.Response, error)
|
|
|
|
func (f roundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) {
|
|
return f(request)
|
|
}
|