Skip to content

Commit 3b3c683

Browse files
committed
- Addressed review comments.
1 parent 7fdc13e commit 3b3c683

File tree

4 files changed

+142
-48
lines changed

4 files changed

+142
-48
lines changed

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9174,13 +9174,13 @@ internal int WriteVectorSupportFeatureRequest(bool write)
91749174
/// <summary>
91759175
/// Writes the User Agent feature request to the physical state
91769176
/// object. The request includes the feature ID, feature data length,
9177-
/// version number and encoded JSON payload.
9177+
/// and UCS-2 little-endian encoded payload.
91789178
/// </summary>
91799179
/// <remarks>
91809180
/// The feature request consists of:
91819181
/// - 1 byte for the feature ID.
91829182
/// - 4 bytes for the feature data length.
9183-
/// - N bytes for the JSON payload
9183+
/// - N bytes for the UCS-2 payload
91849184
/// </remarks>
91859185
/// <param name="userAgent">
91869186
/// UCS-2 little-endian encoded UserAgent payload.
@@ -9194,7 +9194,7 @@ internal int WriteUserAgentFeatureRequest(ReadOnlyMemory<byte> userAgent,
91949194
bool write)
91959195
{
91969196
// 1 byte (Feature ID) + 4 bytes (Feature Data Length) + N bytes
9197-
// (JSON payload size)
9197+
// (UCS-2 payload size)
91989198
int totalLen = 1 + 4 + userAgent.Length;
91999199

92009200
if (write)
@@ -9205,7 +9205,7 @@ internal int WriteUserAgentFeatureRequest(ReadOnlyMemory<byte> userAgent,
92059205
// Feature Data Length
92069206
WriteInt(userAgent.Length, _physicalStateObj);
92079207

9208-
// Write encoded JSON payload
9208+
// Write encoded UCS-2 payload
92099209
_physicalStateObj.WriteByteSpan(userAgent.Span);
92109210
}
92119211

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/UserAgent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static UserAgent()
151151
RuntimeInformation.OSDescription,
152152
RuntimeInformation.FrameworkDescription);
153153

154-
// Convert it to USC-2 bytes.
154+
// Convert it to UCS-2 bytes.
155155
//
156156
// The default Unicode instance doesn't throw if encoding fails, so
157157
// there is nothing to catch here.

src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ public void TestConnWithUserAgentFeatureExtension(bool sendAck)
900900
Assert.True(firstFeatureIsUserAgent);
901901
Assert.True(tokenWasNotNull);
902902
Assert.True(dataLengthAtLeast1);
903-
Assert.Equal(UserAgent.Ucs2Bytes, observedPayload);
903+
Assert.Equal(UserAgent.Ucs2Bytes.ToArray(), observedPayload);
904904

905905
// TODO: Confirm the server sent an Ack by reading log message from SqlInternalConnectionTds
906906
}

src/Microsoft.Data.SqlClient/tests/UnitTests/UserAgentTests.cs

Lines changed: 136 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,27 @@ namespace Microsoft.Data.SqlClient.Tests;
1313

1414
public sealed class UserAgentTests
1515
{
16+
#region Constants
17+
18+
// All permitted characters that may appear as values in the User Agent.
19+
const string AllPermitted =
20+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
21+
"abcdefghijklmnopqrstuvwxyz" +
22+
"0123456789" +
23+
" .+_-";
24+
25+
#endregion
26+
1627
#region Test Setup
1728

18-
// Setup to test by saving the xUnit output helper.
29+
/// <summary>
30+
/// Setup to test by saving the xUnit output helper.
31+
/// </summary>
32+
/// <param name="output">The xUnit output helper.</param>
1933
public UserAgentTests(ITestOutputHelper output)
2034
{
21-
// Use --logger option to see the output for successful test runs:
35+
// Use the dotnet CLI --logger option to see the output for successful
36+
// test runs:
2237
//
2338
// dotnet test --logger "console;verbosity=detailed"
2439
//
@@ -31,15 +46,16 @@ public UserAgentTests(ITestOutputHelper output)
3146

3247
#region Tests
3348

34-
// Test the Value property when actual runtime information is used.
35-
//
36-
// This test assumes that values returned by the runtime used to construct
37-
// the Value property will all fit within the max length (currently 256
38-
// characters).
39-
//
40-
// If this test fails, then either the max length has changed or the runtime
41-
// values have changed in a meaningful way.
42-
//
49+
/// <summary>
50+
/// Test the Value property when actual runtime information is used.
51+
///
52+
/// This test assumes that values returned by the runtime used to construct
53+
/// the Value property will all fit within the max length (currently 256
54+
/// characters).
55+
///
56+
/// If this test fails, then either the max length has changed or the
57+
/// runtime values have changed in a meaningful way.
58+
/// </summary>
4359
[Fact]
4460
public void Value_Runtime_Parts()
4561
{
@@ -50,7 +66,7 @@ public void Value_Runtime_Parts()
5066
// Check the basic properties of the value.
5167
Assert.NotNull(value);
5268
Assert.True(value.Length > 0);
53-
Assert.True(value.Length <= 128);
69+
Assert.True(value.Length <= 256);
5470

5571
// Ensure we can split it into the expected parts.
5672
//
@@ -102,25 +118,42 @@ public void Value_Runtime_Parts()
102118
Assert.True(parts[6].Length <= 44);
103119
}
104120

105-
// Test the Ucs2Bytes property when actual runtime information is used.
121+
/// <summary>
122+
/// Test the Ucs2Bytes property when actual runtime information is used.
123+
/// </summary>
106124
[Fact]
107125
public void Ucs2Bytes_Runtime_Parts()
108126
{
109127
var bytes = UserAgent.Ucs2Bytes;
110128

111-
_output.WriteLine(
112-
$"UserAgent.Ucs2Bytes: 0x{Convert.ToHexString(bytes.Span)}");
129+
#if NET
130+
var hex = Convert.ToHexString(bytes.Span);
131+
#else
132+
var hex = BitConverter.ToString(bytes.ToArray()).Replace("-", string.Empty);
133+
#endif
134+
135+
_output.WriteLine($"UserAgent.Ucs2Bytes: 0x{hex}");
113136

114137
// Check the basic properties of the byte array.
115138
Assert.True(bytes.Length > 0);
116-
Assert.True(bytes.Length <= 256 * 2); // USC2 uses 2 bytes per char.
139+
Assert.True(bytes.Length <= 256 * 2); // UCS-2 uses 2 bytes per char.
117140

118141
// Ensure we can convert the bytes back to the original string.
119-
string value = Encoding.Unicode.GetString(bytes.Span);
142+
string value =
143+
#if NET
144+
Encoding.Unicode.GetString(bytes.Span);
145+
#else
146+
Encoding.Unicode.GetString(bytes.ToArray());
147+
#endif
148+
120149
Assert.Equal(UserAgent.Value, value);
121150
}
122151

123-
// Test the Build() function when it truncates the overall length.
152+
/// <summary>
153+
/// Test the Build() function when it truncates the overall length.
154+
/// </summary>
155+
/// <param name="maxLen">The expected max payload length.</param>
156+
/// <param name="expected">The expected payload string.</param>
124157
[Theory]
125158
[InlineData(0, "")]
126159
[InlineData(1, "2")]
@@ -153,7 +186,9 @@ public void Build_Truncate_Overall(ushort maxLen, string expected)
153186
runtimeInfo: "E"));
154187
}
155188

156-
// Test the Build() function when it truncates the payload version.
189+
/// <summary>
190+
/// Test the Build() function when it truncates the payload version.
191+
/// </summary>
157192
[Fact]
158193
public void Build_Truncate_Payload_Version()
159194
{
@@ -170,7 +205,9 @@ public void Build_Truncate_Payload_Version()
170205
128, "1234", "A", "B", "C", Architecture.X64, "D", "E"));
171206
}
172207

173-
// Test the Build() function when it truncates the driver name.
208+
/// <summary>
209+
/// Test the Build() function when it truncates the driver name.
210+
/// </summary>
174211
[Fact]
175212
public void Build_Truncate_Driver_Name()
176213
{
@@ -188,7 +225,9 @@ public void Build_Truncate_Driver_Name()
188225
"D", "E"));
189226
}
190227

191-
// Test the Build() function when it truncates the driver version.
228+
/// <summary>
229+
/// Test the Build() function when it truncates the driver version.
230+
/// </summary>
192231
[Fact]
193232
public void Build_Truncate_Driver_Version()
194233
{
@@ -207,7 +246,9 @@ public void Build_Truncate_Driver_Version()
207246
Architecture.X64, "D", "E"));
208247
}
209248

210-
// Test the Build() function when it truncates the OS Type.
249+
/// <summary>
250+
/// Test the Build() function when it truncates the OS Type.
251+
/// </summary>
211252
[Fact]
212253
public void Build_Truncate_OS_Type()
213254
{
@@ -225,7 +266,9 @@ public void Build_Truncate_OS_Type()
225266
"E"));
226267
}
227268

228-
// Test the Build() function when it truncates the Architecture.
269+
/// <summary>
270+
/// Test the Build() function when it truncates the Architecture.
271+
/// </summary>
229272
[Fact]
230273
public void Build_Truncate_Arch()
231274
{
@@ -247,7 +290,9 @@ public void Build_Truncate_Arch()
247290
#endif
248291
}
249292

250-
// Test the Build() function when it truncates the OS Info.
293+
/// <summary>
294+
/// Test the Build() function when it truncates the OS Info.
295+
/// </summary>
251296
[Fact]
252297
public void Build_Truncate_OS_Info()
253298
{
@@ -266,7 +311,9 @@ public void Build_Truncate_OS_Info()
266311
"E"));
267312
}
268313

269-
// Test the Build() function when it truncates the Runtime Info.
314+
/// <summary>
315+
/// Test the Build() function when it truncates the Runtime Info.
316+
/// </summary>
270317
[Fact]
271318
public void Build_Truncate_Runtime_Info()
272319
{
@@ -285,8 +332,10 @@ public void Build_Truncate_Runtime_Info()
285332
"01234567890123456789012345678901234567890123456789"));
286333
}
287334

288-
// Test the Build() function when most of the fields are truncated, and
289-
// the overall length is still within the max.
335+
/// <summary>
336+
/// Test the Build() function when most of the fields are truncated, and the
337+
/// overall length is still within the max.
338+
/// </summary>
290339
[Fact]
291340
public void Build_Truncate_Most()
292341
{
@@ -320,9 +369,13 @@ public void Build_Truncate_Most()
320369
name);
321370
}
322371

372+
// Only .NET has an Architecture enum value long enough to test truncation
373+
// of that part.
323374
#if NET
324-
// Test the Build() function when all the fields are truncated, and
325-
// the overall length is still within the max.
375+
/// <summary>
376+
/// Test the Build() function when all the fields are truncated, and the
377+
/// overall length is still within the max.
378+
/// </summary>
326379
[Fact]
327380
public void Build_Truncate_All()
328381
{
@@ -354,46 +407,85 @@ public void Build_Truncate_All()
354407
"E0123456789012345678901234567890123456789012",
355408
name);
356409
}
357-
#endif // NET
410+
#endif
358411

359-
// Test the Clean() function.
412+
/// <summary>
413+
/// Test the Clean() function for null input.
414+
/// </summary>
360415
[Fact]
361-
public void Clean()
416+
public void Clean_Null()
362417
{
363418
// Null becomes "Unknown".
364419
Assert.Equal("Unknown", UserAgent.Clean(null));
420+
}
365421

422+
/// <summary>
423+
/// Test the Clean() function for empty input.
424+
/// </summary>
425+
[Fact]
426+
public void Clean_Empty()
427+
{
366428
// Empty string becomes "Unknown".
367429
Assert.Equal("Unknown", UserAgent.Clean(string.Empty));
430+
}
368431

432+
/// <summary>
433+
/// Test the Clean() function for whitespace input.
434+
/// </summary>
435+
[Fact]
436+
public void Clean_Whitespace()
437+
{
369438
// Whitespace string becomes "Unknown".
370439
Assert.Equal("Unknown", UserAgent.Clean(" "));
371440
Assert.Equal("Unknown", UserAgent.Clean("\t"));
372441
Assert.Equal("Unknown", UserAgent.Clean("\r"));
373442
Assert.Equal("Unknown", UserAgent.Clean("\n"));
374443
Assert.Equal("Unknown", UserAgent.Clean(" \t\r\n"));
444+
}
375445

446+
/// <summary>
447+
/// Test the Clean() function with leading and trailing whitespace.
448+
/// </summary>
449+
[Fact]
450+
public void Clean_Leading_Trailing_Whitespace()
451+
{
376452
// Leading and trailing whitespace are removed.
377453
Assert.Equal("A", UserAgent.Clean(" A"));
378454
Assert.Equal("A", UserAgent.Clean("A\t"));
379455
Assert.Equal("A", UserAgent.Clean("\rA\n"));
456+
}
380457

458+
/// <summary>
459+
/// Test the Clean() function with permitted characters.
460+
/// </summary>
461+
[Fact]
462+
public void Clean_Permitted_Disallowed_Characters()
463+
{
381464
// All permitted characters are preserved.
382-
const string AllPermitted =
383-
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
384-
"abcdefghijklmnopqrstuvwxyz" +
385-
"0123456789" +
386-
" .+_-";
387465
Assert.Equal(AllPermitted, UserAgent.Clean(AllPermitted));
466+
}
388467

468+
/// <summary>
469+
/// Test the Clean() function with various disallowed characters.
470+
/// </summary>
471+
[Fact]
472+
public void Clean_Disallowed_Characters()
473+
{
389474
// Each disallowed character is replaced with underscore.
390475
Assert.Equal(
391476
"A_B_C_D_E_F_G_H_I_J_K_L_M_N_O_P",
392477
UserAgent.Clean("A|B,C;D:E'F\"G[H{I]J}K\\L/M<N>O?P"));
393478
Assert.Equal(
394479
"Q_R_S_T_U_V_W_X+Y-Z_a.b_c_d_e_f_g_h_i_j_k_l_m_n_o",
395480
UserAgent.Clean("Q^R_S`T~U(V)W*X+Y-Z_a.b,c/d:e<f>g'h\"i[j]k{l}m|n\\o"));
481+
}
396482

483+
/// <summary>
484+
/// Test the Clean() function with all Unicode characters.
485+
/// </summary>
486+
[Fact]
487+
public void Clean_All_Unicode_Characters()
488+
{
397489
// All disallowed characters are replaced with underscore.
398490
for (char c = (char)0u; /* see condition below */ ; ++c)
399491
{
@@ -405,12 +497,12 @@ public void Clean()
405497
Assert.Equal("Unknown", clean);
406498
}
407499
else if (
408-
#if NET
500+
#if NET
409501
AllPermitted.Contains(c)
410-
#else
502+
#else
411503
AllPermitted.Contains(c.ToString())
412-
#endif
413-
)
504+
#endif
505+
)
414506
{
415507
Assert.Equal(c.ToString(), clean);
416508
}
@@ -433,7 +525,9 @@ public void Clean()
433525
}
434526
}
435527

436-
// Test the Trunc() function.
528+
/// <summary>
529+
/// Test the Trunc() function.
530+
/// </summary>
437531
[Fact]
438532
public void Trunc()
439533
{

0 commit comments

Comments
 (0)