Skip to content

Commit dbc63f8

Browse files
committed
test: allow mocking web socket server message
1 parent be1eb9d commit dbc63f8

File tree

9 files changed

+151
-42
lines changed

9 files changed

+151
-42
lines changed

sample/Cnblogs.DashScope.Sample/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
{
6969
using var tts = await dashScopeClient.CreateSpeechSynthesizerSocketSessionAsync("cosyvoice-v2");
7070
var taskId = await tts.RunTaskAsync(
71-
new SpeechSynthesizerParameters() { Voice = "longxiaochun_v2", Format = "mp3" });
71+
new SpeechSynthesizerParameters { Voice = "longxiaochun_v2", Format = "mp3" });
7272
await tts.ContinueTaskAsync(taskId, "博客园");
7373
await tts.ContinueTaskAsync(taskId, "代码改变世界");
7474
await tts.FinishTaskAsync(taskId);

src/Cnblogs.DashScope.Core/DashScopeClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private static DashScopeClientWebSocketPool GetConfiguredSocketPool(
4949
if (pool is null)
5050
{
5151
pool = new DashScopeClientWebSocketPool(
52-
new DashScopeOptions()
52+
new DashScopeOptions
5353
{
5454
ApiKey = apiKey,
5555
BaseWebsocketAddress = baseAddress,

src/Cnblogs.DashScope.Core/DashScopeClientWebSocket.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,13 @@ public async Task ReceiveMessagesAsync<TOutput>(CancellationToken cancellationTo
198198
throw new DashScopeException(
199199
null,
200200
400,
201-
new DashScopeError()
201+
new DashScopeError
202202
{
203203
Code = json.Header.ErrorCode ?? string.Empty,
204204
Message = json.Header.ErrorMessage ?? string.Empty,
205205
RequestId = json.Header.Attributes.RequestUuid ?? string.Empty
206206
},
207207
json.Header.ErrorMessage ?? "The task was failed");
208-
default:
209-
break;
210208
}
211209
}
212210

src/Cnblogs.DashScope.Core/DashScopeWebSocketRequestHeader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ public class DashScopeWebSocketRequestHeader
1818
/// <summary>
1919
/// Streaming type.
2020
/// </summary>
21-
public string Streaming { get; set; } = "duplex";
21+
public string? Streaming { get; set; } = "duplex";
2222
}

src/Cnblogs.DashScope.Core/SpeechSynthesizerSocketSession.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ public async Task<string> RunTaskAsync(
4949
string? text = null,
5050
CancellationToken cancellationToken = default)
5151
{
52-
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
52+
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
5353
{
54-
Header = new DashScopeWebSocketRequestHeader()
54+
Header = new DashScopeWebSocketRequestHeader
5555
{
5656
Action = "run-task", TaskId = taskId,
5757
},
58-
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
58+
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>
5959
{
60-
Input = new SpeechSynthesizerInput() { Text = text, },
60+
Input = new SpeechSynthesizerInput { Text = text, },
6161
TaskGroup = "audio",
6262
Task = "tts",
6363
Function = "SpeechSynthesizer",
@@ -79,15 +79,15 @@ public async Task<string> RunTaskAsync(
7979
/// <param name="cancellationToken">Cancellation token to use.</param>
8080
public async Task ContinueTaskAsync(string taskId, string input, CancellationToken cancellationToken = default)
8181
{
82-
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
82+
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
8383
{
84-
Header = new DashScopeWebSocketRequestHeader()
84+
Header = new DashScopeWebSocketRequestHeader
8585
{
8686
Action = "continue-task", TaskId = taskId,
8787
},
88-
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
88+
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>
8989
{
90-
Input = new SpeechSynthesizerInput() { Text = input }
90+
Input = new SpeechSynthesizerInput { Text = input }
9191
}
9292
};
9393
await _socket.SendMessageAsync(command, cancellationToken);
@@ -100,10 +100,10 @@ public async Task ContinueTaskAsync(string taskId, string input, CancellationTok
100100
/// <param name="cancellationToken">The cancellation token to use.</param>
101101
public async Task FinishTaskAsync(string taskId, CancellationToken cancellationToken = default)
102102
{
103-
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
103+
var command = new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
104104
{
105-
Header = new DashScopeWebSocketRequestHeader() { TaskId = taskId, Action = "finish-task" },
106-
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
105+
Header = new DashScopeWebSocketRequestHeader { TaskId = taskId, Action = "finish-task" },
106+
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>
107107
{
108108
Input = new SpeechSynthesizerInput()
109109
}

test/Cnblogs.DashScope.Sdk.UnitTests/DashScopeClientWebSocketTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public async Task SendMessageAsync_Connected_SendAsync()
133133

134134
// Assert
135135
await socket.Received().SendAsync(
136-
Arg.Is<ArraySegment<byte>>(s => Checkers.IsJsonEquivalent(s, snapshot.GetRequestJson())),
136+
Arg.Is<ArraySegment<byte>>(s => Checkers.IsJsonEquivalent(s, snapshot.GetMessageJson())),
137137
WebSocketMessageType.Text,
138138
true,
139139
Arg.Any<CancellationToken>());
@@ -153,6 +153,24 @@ public async Task ReceiveMessageAsync_ServerClosed_CloseAsync()
153153
Assert.Equal(WebSocketCloseStatus.NormalClosure, server.CloseStatus);
154154
}
155155

156+
[Fact]
157+
public async Task ReceiveMessageAsync_TaskStarted_UpdateStateToRunningAsync()
158+
{
159+
// Arrange
160+
var (_, clientWebSocket, server) = await Sut.GetSocketTestClientAsync<SpeechSynthesizerOutput>();
161+
var snapshot = Snapshots.SpeechSynthesizer.TaskStarted;
162+
var taskStarted = clientWebSocket.TaskStarted;
163+
164+
// Act
165+
await server.WriteServerMessageAsync(snapshot.GetMessageJson());
166+
var timeout = Task.Delay(2000); // socket handles message in other thread, wait for it.
167+
var any = await Task.WhenAny(timeout, taskStarted);
168+
169+
// Assert
170+
Assert.Equal(any, taskStarted);
171+
Assert.Equal(DashScopeWebSocketState.RunningTask, clientWebSocket.State);
172+
}
173+
156174
private static WebHeaderCollection ExtractHeaders(DashScopeClientWebSocket socket)
157175
{
158176
var obj = InnerSocketInfo.GetValue(socket);

test/Cnblogs.DashScope.Tests.Shared/Utils/FakeClientWebSocket.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Net.WebSockets;
2+
using System.Text;
23
using System.Threading.Channels;
34
using Cnblogs.DashScope.Core.Internals;
45

@@ -11,11 +12,24 @@ public sealed class FakeClientWebSocket : IClientWebSocket
1112
public Channel<WebSocketReceiveResult> Server { get; } =
1213
Channel.CreateUnbounded<WebSocketReceiveResult>();
1314

15+
public Channel<byte[]> ServerBuffer { get; } = Channel.CreateUnbounded<byte[]>();
16+
1417
public async Task WriteServerCloseAsync()
1518
{
1619
var close = new WebSocketReceiveResult(1, WebSocketMessageType.Close, true);
1720
await Server.Writer.WriteAsync(close);
1821
Server.Writer.Complete();
22+
ServerBuffer.Writer.Complete();
23+
}
24+
25+
public async Task WriteServerMessageAsync(string json)
26+
{
27+
var binary = Encoding.UTF8.GetBytes(json);
28+
await Server.Writer.WriteAsync(new WebSocketReceiveResult(binary.Length, WebSocketMessageType.Text, true));
29+
30+
await ServerBuffer.Writer.WriteAsync(binary);
31+
await Server.Reader.WaitToReadAsync();
32+
await ServerBuffer.Reader.WaitToReadAsync();
1933
}
2034

2135
private void Dispose(bool disposing)
@@ -63,6 +77,13 @@ public async Task<WebSocketReceiveResult> ReceiveAsync(
6377
CancellationToken cancellationToken)
6478
{
6579
await Server.Reader.WaitToReadAsync(cancellationToken);
80+
await ServerBuffer.Reader.WaitToReadAsync(cancellationToken);
81+
var binary = await ServerBuffer.Reader.ReadAsync(cancellationToken);
82+
for (var i = 0; i < binary.Length; i++)
83+
{
84+
buffer[i] = binary[i];
85+
}
86+
6687
return await Server.Reader.ReadAsync(cancellationToken);
6788
}
6889

test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.SocketRequests.cs

Lines changed: 95 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,103 @@ public static class SpeechSynthesizer
1010

1111
public static readonly
1212
SocketMessageSnapshot<DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>>
13-
RunTask = new(GroupName, "run-task", new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
14-
{
15-
Header = new DashScopeWebSocketRequestHeader()
13+
RunTask = new(
14+
GroupName,
15+
"run-task",
16+
new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
1617
{
17-
Action = "run-task",
18-
Streaming = "duplex",
19-
TaskId = "439e0616-2f5b-44e0-8872-0002a066a49c"
20-
},
21-
Payload = new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>()
18+
Header = new DashScopeWebSocketRequestHeader
19+
{
20+
Action = "run-task",
21+
Streaming = "duplex",
22+
TaskId = "439e0616-2f5b-44e0-8872-0002a066a49c"
23+
},
24+
Payload =
25+
new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>
26+
{
27+
Task = "tts",
28+
TaskGroup = "audio",
29+
Function = "SpeechSynthesizer",
30+
Model = "cosyvoice-v1",
31+
Parameters = new SpeechSynthesizerParameters
32+
{
33+
EnableSsml = true,
34+
Format = "mp3",
35+
Pitch = 1.2f,
36+
Voice = "longxiaochun",
37+
Volume = 50,
38+
SampleRate = 0,
39+
Rate = 1.1f,
40+
}
41+
}
42+
});
43+
44+
public static readonly
45+
SocketMessageSnapshot<DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>>
46+
ContinueTask = new(
47+
GroupName,
48+
"continue-task",
49+
new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
2250
{
23-
Task = "tts",
24-
TaskGroup = "audio",
25-
Function = "SpeechSynthesizer",
26-
Model = "cosyvoice-v1",
27-
Parameters = new SpeechSynthesizerParameters()
51+
Header = new DashScopeWebSocketRequestHeader
2852
{
29-
EnableSsml = true,
30-
Format = "mp3",
31-
Pitch = 1.2f,
32-
Voice = "longxiaochun",
33-
Volume = 50,
34-
SampleRate = 0,
35-
Rate = 1.1f,
36-
}
37-
}
38-
});
53+
Action = "continue-task",
54+
TaskId = "439e0616-2f5b-44e0-8872-0002a066a49c",
55+
Streaming = null
56+
},
57+
Payload =
58+
new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput, SpeechSynthesizerParameters>
59+
{
60+
Input = new SpeechSynthesizerInput { Text = "代码改变世界" }
61+
}
62+
});
63+
64+
public static readonly
65+
SocketMessageSnapshot<DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>>
66+
FinishTask =
67+
new(
68+
GroupName,
69+
"finish-task",
70+
new DashScopeWebSocketRequest<SpeechSynthesizerInput, SpeechSynthesizerParameters>
71+
{
72+
Header = new DashScopeWebSocketRequestHeader
73+
{
74+
Action = "finish-task",
75+
TaskId = "439e0616-2f5b-44e0-8872-0002a066a49c",
76+
Streaming = null
77+
},
78+
Payload =
79+
new DashScopeWebSocketRequestPayload<SpeechSynthesizerInput,
80+
SpeechSynthesizerParameters> { Input = new SpeechSynthesizerInput() }
81+
});
82+
83+
public static readonly SocketMessageSnapshot<DashScopeWebSocketResponse<SpeechSynthesizerOutput>> TaskStarted =
84+
new(
85+
GroupName,
86+
"task-started",
87+
new DashScopeWebSocketResponse<SpeechSynthesizerOutput>(
88+
new DashScopeWebSocketResponseHeader(
89+
"439e0616-2f5b-44e0-8872-0002a066a49c",
90+
"task-started",
91+
null,
92+
null,
93+
new DashScopeWebSocketResponseHeaderAttributes(null)),
94+
new DashScopeWebSocketResponsePayload<SpeechSynthesizerOutput>(null, null)));
95+
96+
public static readonly SocketMessageSnapshot<DashScopeWebSocketResponse<SpeechSynthesizerOutput>> TaskFinished =
97+
new(
98+
GroupName,
99+
"task-finished",
100+
new DashScopeWebSocketResponse<SpeechSynthesizerOutput>(
101+
new DashScopeWebSocketResponseHeader(
102+
"439e0616-2f5b-44e0-8872-0002a066a49c",
103+
"finished-task",
104+
null,
105+
null,
106+
new DashScopeWebSocketResponseHeaderAttributes(null)),
107+
new DashScopeWebSocketResponsePayload<SpeechSynthesizerOutput>(null, null)));
108+
109+
public static readonly SocketMessageSnapshot TaskFailed = new(GroupName, "task-failed");
110+
public static readonly SocketMessageSnapshot ResultGenerated = new(GroupName, "result-generated");
39111
}
40112
}

test/Cnblogs.DashScope.Tests.Shared/Utils/SocketMessageSnapshot.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
public record SocketMessageSnapshot(string GroupName, string MessageName)
44
{
5-
public string GetRequestJson()
5+
public string GetMessageJson()
66
{
77
return File.ReadAllText(Path.Combine("RawHttpData", $"socket-{GroupName}.{MessageName}.json"));
88
}

0 commit comments

Comments
 (0)