diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 2c6aca0f3a..21df876c68 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -11,11 +11,11 @@ namespace Microsoft.Azure.Cosmos using System.Linq; using System.Net; using System.Net.Http; + using System.Net.Http.Headers; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Newtonsoft.Json; - using Telemetry; /// /// Defines all the configurable options that the CosmosClient requires. @@ -69,6 +69,7 @@ public class CosmosClientOptions private PortReuseMode? portReuseMode; private IWebProxy webProxy; private Func httpClientFactory; + private string applicationName; /// /// Creates a new CosmosClientOptions @@ -90,7 +91,24 @@ public CosmosClientOptions() /// /// Setting this property after sending any request won't have any effect. /// - public string ApplicationName { get; set; } + public string ApplicationName + { + get => this.applicationName; + set + { + try + { + HttpRequestMessage dummyMessage = new HttpRequestMessage(); + dummyMessage.Headers.Add(HttpConstants.HttpHeaders.UserAgent, value); + } + catch (FormatException fme) + { + throw new ArgumentException($"Application name '{value}' is invalid.", fme); + } + + this.applicationName = value; + } + } /// /// Get or set session container for the client diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.NegativePassThroughOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.NegativePassThroughOutput.xml new file mode 100644 index 0000000000..e7e4d603fc --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.NegativePassThroughOutput.xml @@ -0,0 +1,41 @@ + + + + Null Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + false + + + + + None Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + false + + + + + C# Null Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + false + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.PositivePassThroughOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.PositivePassThroughOutput.xml new file mode 100644 index 0000000000..94ed03c8b9 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PassThroughQueryBaselineTests.PositivePassThroughOutput.xml @@ -0,0 +1,41 @@ + + + + Partition Key + Value and Distinct + SELECT DISTINCT c.key FROM c + + /pk + + Hash + + + true + + + + + Partition Key + Value and Min Aggregate + SELECT VALUE MIN(c.key) FROM c + + /pk + + Hash + + + true + + + + + Partition Key + Value Fields + SELECT c.key FROM c + + /pk + + Hash + + + true + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 1a69454b04..4e18b8084b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2896,11 +2896,9 @@ "Attributes": [], "MethodInfo": "System.String ApplicationRegion;CanRead:True;CanWrite:True;System.String get_ApplicationRegion();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ApplicationRegion(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "System.String get_ApplicationName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "System.String get_ApplicationName()": { "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], + "Attributes": [], "MethodInfo": "System.String get_ApplicationName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, "System.String get_ApplicationRegion()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { @@ -2934,11 +2932,9 @@ ], "MethodInfo": "Void set_AllowBulkExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Void set_ApplicationName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Void set_ApplicationName(System.String)": { "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], + "Attributes": [], "MethodInfo": "Void set_ApplicationName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, "Void set_ApplicationPreferredRegions(System.Collections.Generic.IReadOnlyList`1[System.String])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index cf2a2083ce..ef6c70561c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -539,6 +539,33 @@ public void WithQuorumReadWithEventualConsistencyAccount() Assert.IsTrue(cosmosClientOptions.EnableUpgradeConsistencyToLocalQuorum); } + [TestMethod] + public void InvalidApplicationNameCatchTest() + { + + string[] illegalChars = new string[] { "<", ">", "\"", "{", "}", "\\", "[", "]", ";", ":", "@", "=", "(", ")", "," }; + string baseName = "illegal"; + + foreach (string illegal in illegalChars) + { + Assert.ThrowsException(() => new CosmosClientOptions + { + ApplicationName = baseName + illegal + }); + + + Assert.ThrowsException(() => new CosmosClientOptions + { + ApplicationName = illegal + baseName + }); + + Assert.ThrowsException(() => new CosmosClientOptions + { + ApplicationName = illegal + }); + } + } + private class TestWebProxy : IWebProxy { public ICredentials Credentials { get; set; }