diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Contracts/ConnectionProviderOptions.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Contracts/ConnectionProviderOptions.cs
index 25532617..50089435 100644
--- a/src/Microsoft.SqlTools.Hosting/Hosting/Contracts/ConnectionProviderOptions.cs
+++ b/src/Microsoft.SqlTools.Hosting/Hosting/Contracts/ConnectionProviderOptions.cs
@@ -15,6 +15,13 @@ namespace Microsoft.SqlTools.Hosting.Contracts
public ConnectionOption[] Options { get; set; }
}
+ public class CategoryValue
+ {
+ public string DisplayName { get; set; }
+
+ public string Name { get; set; }
+ }
+
public class ConnectionOption
{
public static readonly string ValueTypeString = "string";
@@ -48,10 +55,10 @@ namespace Microsoft.SqlTools.Hosting.Contracts
///
/// Set of permitted values if ValueType is category.
///
- public string[] CategoryValues { get; set; }
+ public CategoryValue[] CategoryValues { get; set; }
///
- /// Determines if the parameter is one of the 'specical' known values.
+ /// Determines if the parameter is one of the 'special' known values.
/// Can be either Server Name, Database Name, Authentication Type,
/// User Name, or Password
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
index ce1c6208..095c46a4 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
@@ -3,6 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using System.Collections.Generic;
+
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
{
///
@@ -13,120 +15,457 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
///
public class ConnectionDetails : ConnectionSummary
{
+ public ConnectionDetails()
+ {
+ Options = new Dictionary();
+ }
+
+ ///
+ /// Gets or Sets the connection options
+ ///
+ public Dictionary Options { get; set; }
+
///
/// Gets or sets the connection password
///
///
- public string Password { get; set; }
+ public string Password {
+ get
+ {
+ return GetOptionValue("password");
+ }
+ set
+ {
+ SetOptionValue("password", value);
+ }
+ }
+
+ ///
+ /// Gets or sets the connection server name
+ ///
+ public override string ServerName
+ {
+ get
+ {
+ return GetOptionValue("server");
+ }
+
+ set
+ {
+ SetOptionValue("server", value);
+ }
+ }
+
+ ///
+ /// Gets or sets the connection database name
+ ///
+ public override string DatabaseName
+ {
+ get
+ {
+ return GetOptionValue("database");
+ }
+
+ set
+ {
+ SetOptionValue("database", value);
+ }
+ }
+
+ ///
+ /// Gets or sets the connection user name
+ ///
+ public override string UserName
+ {
+ get
+ {
+ return GetOptionValue("user");
+ }
+
+ set
+ {
+ SetOptionValue("user", value);
+ }
+ }
///
/// Gets or sets the authentication to use.
///
- public string AuthenticationType { get; set; }
+ public string AuthenticationType
+ {
+ get
+ {
+ return GetOptionValue("authenticationType");
+ }
+
+ set
+ {
+ SetOptionValue("authenticationType", value);
+ }
+ }
///
/// Gets or sets a Boolean value that indicates whether SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed.
///
- public bool? Encrypt { get; set; }
+ public bool? Encrypt
+ {
+ get
+ {
+ return GetOptionValue("encrypt");
+ }
+
+ set
+ {
+ SetOptionValue("encrypt", value);
+ }
+ }
///
/// Gets or sets a value that indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust.
///
- public bool? TrustServerCertificate { get; set; }
+ public bool? TrustServerCertificate
+ {
+ get
+ {
+ return GetOptionValue("trustServerCertificate");
+ }
+
+ set
+ {
+ SetOptionValue("trustServerCertificate", value);
+ }
+ }
///
/// Gets or sets a Boolean value that indicates if security-sensitive information, such as the password, is not returned as part of the connection if the connection is open or has ever been in an open state.
///
- public bool? PersistSecurityInfo { get; set; }
+ public bool? PersistSecurityInfo
+ {
+ get
+ {
+ return GetOptionValue("persistSecurityInfo");
+ }
+
+ set
+ {
+ SetOptionValue("persistSecurityInfo", value);
+ }
+ }
///
/// Gets or sets the length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error.
///
- public int? ConnectTimeout { get; set; }
+ public int? ConnectTimeout
+ {
+ get
+ {
+ return GetOptionValue("connectTimeout");
+ }
+
+ set
+ {
+ SetOptionValue("connectTimeout", value);
+ }
+ }
///
/// The number of reconnections attempted after identifying that there was an idle connection failure.
///
- public int? ConnectRetryCount { get; set; }
+ public int? ConnectRetryCount
+ {
+ get
+ {
+ return GetOptionValue("connectRetryCount");
+ }
+
+ set
+ {
+ SetOptionValue("connectRetryCount", value);
+ }
+ }
///
/// Amount of time (in seconds) between each reconnection attempt after identifying that there was an idle connection failure.
///
- public int? ConnectRetryInterval { get; set; }
+ public int? ConnectRetryInterval
+ {
+ get
+ {
+ return GetOptionValue("connectRetryInterval");
+ }
+
+ set
+ {
+ SetOptionValue("connectRetryInterval", value);
+ }
+ }
///
/// Gets or sets the name of the application associated with the connection string.
///
- public string ApplicationName { get; set; }
+ public string ApplicationName
+ {
+ get
+ {
+ return GetOptionValue("applicationName");
+ }
+
+ set
+ {
+ SetOptionValue("applicationName", value);
+ }
+ }
///
/// Gets or sets the name of the workstation connecting to SQL Server.
///
- public string WorkstationId { get; set; }
+ public string WorkstationId
+ {
+ get
+ {
+ return GetOptionValue("workstationId");
+ }
+
+ set
+ {
+ SetOptionValue("workstationId", value);
+ }
+ }
///
/// Declares the application workload type when connecting to a database in an SQL Server Availability Group.
///
- public string ApplicationIntent { get; set; }
+ public string ApplicationIntent
+ {
+ get
+ {
+ return GetOptionValue("applicationIntent");
+ }
+
+ set
+ {
+ SetOptionValue("applicationIntent", value);
+ }
+ }
///
/// Gets or sets the SQL Server Language record name.
///
- public string CurrentLanguage { get; set; }
+ public string CurrentLanguage
+ {
+ get
+ {
+ return GetOptionValue("currentLanguage");
+ }
+
+ set
+ {
+ SetOptionValue("currentLanguage", value);
+ }
+ }
///
/// Gets or sets a Boolean value that indicates whether the connection will be pooled or explicitly opened every time that the connection is requested.
///
- public bool? Pooling { get; set; }
+ public bool? Pooling
+ {
+ get
+ {
+ return GetOptionValue("pooling");
+ }
+
+ set
+ {
+ SetOptionValue("pooling", value);
+ }
+ }
///
/// Gets or sets the maximum number of connections allowed in the connection pool for this specific connection string.
///
- public int? MaxPoolSize { get; set; }
+ public int? MaxPoolSize
+ {
+ get
+ {
+ return GetOptionValue("maxPoolSize");
+ }
+
+ set
+ {
+ SetOptionValue("maxPoolSize", value);
+ }
+ }
///
/// Gets or sets the minimum number of connections allowed in the connection pool for this specific connection string.
///
- public int? MinPoolSize { get; set; }
+ public int? MinPoolSize
+ {
+ get
+ {
+ return GetOptionValue("minPoolSize");
+ }
+
+ set
+ {
+ SetOptionValue("minPoolSize", value);
+ }
+ }
///
/// Gets or sets the minimum time, in seconds, for the connection to live in the connection pool before being destroyed.
///
- public int? LoadBalanceTimeout { get; set; }
+ public int? LoadBalanceTimeout
+ {
+ get
+ {
+ return GetOptionValue("loadBalanceTimeout");
+ }
+
+ set
+ {
+ SetOptionValue("loadBalanceTimeout", value);
+ }
+ }
///
/// Gets or sets a Boolean value that indicates whether replication is supported using the connection.
///
- public bool? Replication { get; set; }
+ public bool? Replication
+ {
+ get
+ {
+ return GetOptionValue("replication");
+ }
+
+ set
+ {
+ SetOptionValue("replication", value);
+ }
+ }
///
/// Gets or sets a string that contains the name of the primary data file. This includes the full path name of an attachable database.
///
- public string AttachDbFilename { get; set; }
+ public string AttachDbFilename
+ {
+ get
+ {
+ return GetOptionValue("attachDbFilename");
+ }
+
+ set
+ {
+ SetOptionValue("attachDbFilename", value);
+ }
+ }
///
/// Gets or sets the name or address of the partner server to connect to if the primary server is down.
///
- public string FailoverPartner { get; set; }
+ public string FailoverPartner
+ {
+ get
+ {
+ return GetOptionValue("failoverPartner");
+ }
+
+ set
+ {
+ SetOptionValue("failoverPartner", value);
+ }
+ }
///
/// If your application is connecting to an AlwaysOn availability group (AG) on different subnets, setting MultiSubnetFailover=true provides faster detection of and connection to the (currently) active server.
///
- public bool? MultiSubnetFailover { get; set; }
+ public bool? MultiSubnetFailover
+ {
+ get
+ {
+ return GetOptionValue("multiSubnetFailover");
+ }
+
+ set
+ {
+ SetOptionValue("multiSubnetFailover", value);
+ }
+ }
///
/// When true, an application can maintain multiple active result sets (MARS).
///
- public bool? MultipleActiveResultSets { get; set; }
+ public bool? MultipleActiveResultSets
+ {
+ get
+ {
+ return GetOptionValue("multipleActiveResultSets");
+ }
+
+ set
+ {
+ SetOptionValue("multipleActiveResultSets", value);
+ }
+ }
///
/// Gets or sets the size in bytes of the network packets used to communicate with an instance of SQL Server.
///
- public int? PacketSize { get; set; }
+ public int? PacketSize
+ {
+ get
+ {
+ return GetOptionValue("packetSize");
+ }
+
+ set
+ {
+ SetOptionValue("packetSize", value);
+ }
+ }
///
/// Gets or sets a string value that indicates the type system the application expects.
///
- public string TypeSystemVersion { get; set; }
+ public string TypeSystemVersion
+ {
+ get
+ {
+ return GetOptionValue("typeSystemVersion");
+ }
+
+ set
+ {
+ SetOptionValue("typeSystemVersion", value);
+ }
+ }
+
+ private T GetOptionValue(string name)
+ {
+ T result = default(T);
+ if (Options != null && Options.ContainsKey(name))
+ {
+ object value = Options[name];
+ if(value != null && ( typeof(T) == typeof(int) || typeof(T) == typeof(int?)))
+ {
+ value = System.Convert.ToInt32(value);
+ }
+ result = value != null ? (T)value : default(T);
+ }
+ return result;
+ }
+
+ private void SetOptionValue(string name, T value)
+ {
+ Options = Options ?? new Dictionary();
+ if (Options.ContainsKey(name))
+ {
+ Options[name] = value;
+ }
+ else
+ {
+ Options.Add(name, value);
+ }
+ }
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs
index 11549e85..fa99ab8a 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionSummary.cs
@@ -13,16 +13,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
///
/// Gets or sets the connection server name
///
- public string ServerName { get; set; }
+ public virtual string ServerName { get; set; }
///
/// Gets or sets the connection database name
///
- public string DatabaseName { get; set; }
+ public virtual string DatabaseName { get; set; }
///
/// Gets or sets the connection user name
///
- public string UserName { get; set; }
+ public virtual string UserName { get; set; }
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs
index 338ff0e6..c46f24c2 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs
@@ -190,7 +190,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
);
}
- private static ConnectionProviderOptions BuildConnectionProviderOptions()
+ internal static ConnectionProviderOptions BuildConnectionProviderOptions()
{
return new ConnectionProviderOptions
{
@@ -198,110 +198,278 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
{
new ConnectionOption
{
- Name = "Server Name",
+ Name = "server",
+ DisplayName = "Server Name",
Description = "Name of the SQL Server instance",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueServerName,
IsIdentity = true,
- IsRequired = true
+ IsRequired = true,
+ GroupName = "Source"
},
new ConnectionOption
{
- Name = "Initial Catalog",
+ Name = "database",
DisplayName = "Database Name",
- Description = "Name of the SQL Server database",
+ Description = "The name of the initial catalog or database int the data source",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueDatabaseName,
IsIdentity = true,
- IsRequired = true
+ IsRequired = true,
+ GroupName = "Source"
},
new ConnectionOption
{
- Name = "Auth Type",
- Description = "Authentication type",
+ Name = "authenticationType",
+ DisplayName = "Authentication Type",
+ Description = "Specifies the method of authenticating with SQL Server",
ValueType = ConnectionOption.ValueTypeCategory,
SpecialValueType = ConnectionOption.SpecialValueAuthType,
- CategoryValues = new string[] { "SQL Login", "Integrated Auth" },
+ CategoryValues = new CategoryValue[]
+ { new CategoryValue {DisplayName = "SQL Login", Name = "SqlLogin" },
+ new CategoryValue {DisplayName = "Integrated Auth", Name= "Integrated" }
+ },
IsIdentity = true,
- IsRequired = true
+ IsRequired = true,
+ GroupName = "Security"
},
new ConnectionOption
{
- Name = "Username",
- Description = "SQL Login user name",
+ Name = "user",
+ DisplayName = "User Name",
+ Description = "Indicates the user ID to be used when connecting to the data source",
ValueType = ConnectionOption.ValueTypeString,
SpecialValueType = ConnectionOption.SpecialValueUserName,
IsIdentity = true,
- IsRequired = true
+ IsRequired = true,
+ GroupName = "Security"
},
new ConnectionOption
{
- Name = "Password",
- Description = "SQL Login password",
+ Name = "password",
+ DisplayName = "Password",
+ Description = "Indicates the password to be used when connecting to the data source",
ValueType = ConnectionOption.ValueTypePassword,
SpecialValueType = ConnectionOption.SpecialValuePasswordName,
IsIdentity = true,
- IsRequired = true
+ IsRequired = true,
+ GroupName = "Security"
},
new ConnectionOption
{
- Name = "Application Intent",
- Description = "Application intent",
+ Name = "applicationIntent",
+ DisplayName = "Application Intent",
+ Description = "Declares the application workload type when connecting to a server",
ValueType = ConnectionOption.ValueTypeCategory,
- CategoryValues = new string[] { "ReadWrite", "ReadOnly" }
+ CategoryValues = new CategoryValue[] {
+ new CategoryValue { Name = "ReadWrite", DisplayName = "ReadWrite" },
+ new CategoryValue {Name = "ReadOnly", DisplayName = "ReadOnly" }
+ },
+ GroupName = "Initialization"
},
new ConnectionOption
{
- Name = "Asynchronous Processing",
- Description = "Application processing enabled",
- ValueType = ConnectionOption.ValueTypeBoolean
+ Name = "asynchronousProcessing",
+ DisplayName = "Asynchronous processing enabled",
+ Description = "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
+ ValueType = ConnectionOption.ValueTypeBoolean,
+ GroupName = "Initialization"
},
new ConnectionOption
{
- Name = "Connect Timeout",
- Description = "Timeout in seconds when establishing a connection",
+ Name = "connectTimeout",
+ DisplayName = "Connect Timeout",
+ Description =
+ "The length of time (in seconds) to wait for a connection to the server before terminating the attempt and generating an error",
ValueType = ConnectionOption.ValueTypeNumber,
- DefaultValue = "15"
+ DefaultValue = "15",
+ GroupName = "Initialization"
},
new ConnectionOption
{
- Name = "Current Language",
- ValueType = ConnectionOption.ValueTypeString
+ Name = "currentLanguage",
+ DisplayName = "Current Language",
+ Description = "The SQL Server language record name",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = "Initialization"
},
new ConnectionOption
{
- Name = "Column Encrytion Setting",
+ Name = "columnEncryptionSetting",
+ DisplayName = "Column Encryption Setting",
+ Description = "Default column encryption setting for all the commands on the connection",
ValueType = ConnectionOption.ValueTypeCategory,
GroupName = "Security",
- CategoryValues = new string[] { "Disabled", "Enabled" }
+ CategoryValues = new CategoryValue[] {
+ new CategoryValue { Name = "Disabled" },
+ new CategoryValue {Name = "Enabled" }
+ }
},
new ConnectionOption
{
- Name = "Encrypt",
+ Name = "encrypt",
+ DisplayName = "Encrypt",
+ Description =
+ "When true, SQL Server uses SSL encryption for all data sent between the client and server if the servers has a certificate installed",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
- Name = "Persist Security Info",
+ Name = "persistSecurityInfo",
+ DisplayName = "Persist Security Info",
+ Description = "When false, security-sensitive information, such as the password, is not returned as part of the connection",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
- Name = "Trust Server Certificate",
+ Name = "trustServerCertificate",
+ DisplayName = "Trust Server Certificate",
+ Description = "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean
},
new ConnectionOption
{
- Name = "Attached DB File Name",
+ Name = "attachedDBFileName",
+ DisplayName = "Attached DB File Name",
+ Description = "The name of the primary file, including the full path name, of an attachable database",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = "Source"
+ },
+ new ConnectionOption
+ {
+ Name = "contextConnection",
+ DisplayName = "Context Connection",
+ Description = "When true, indicates the connection should be from the SQL server context. Available only when running in the SQL Server process",
+ ValueType = ConnectionOption.ValueTypeBoolean,
+ GroupName = "Source"
+ },
+ new ConnectionOption
+ {
+ Name = "port",
+ DisplayName = "Port",
+ ValueType = ConnectionOption.ValueTypeNumber
+ },
+ new ConnectionOption
+ {
+ Name = "connectRetryCount",
+ DisplayName = "Connect Retry Count",
+ Description = "Number of attempts to restore connection",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ DefaultValue = "1",
+ GroupName = "Connection Resiliency"
+ },
+ new ConnectionOption
+ {
+ Name = "connectRetryInterval",
+ DisplayName = "Connect Retry Interval",
+ Description = "Delay between attempts to restore connection",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ DefaultValue = "10",
+ GroupName = "Connection Resiliency"
+
+ },
+ new ConnectionOption
+ {
+ Name = "applicationName",
+ DisplayName = "Application Name",
+ Description = "The name of the application",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = "Context"
+ },
+ new ConnectionOption
+ {
+ Name = "workstationId",
+ DisplayName = "Workstation Id",
+ Description = "The name of the workstation connecting to SQL Server",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = "Context"
+ },
+ new ConnectionOption
+ {
+ Name = "pooling",
+ DisplayName = "Pooling",
+ Description = "When true, the connection object is drawn from the appropriate pool, or if necessary, is created and added to the appropriate pool",
+ ValueType = ConnectionOption.ValueTypeBoolean,
+ GroupName = "Pooling"
+ },
+ new ConnectionOption
+ {
+ Name = "maxPoolSize",
+ DisplayName = "Max Pool Size",
+ Description = "The maximum number of connections allowed in the pool",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ GroupName = "Pooling"
+ },
+ new ConnectionOption
+ {
+ Name = "minPoolSize",
+ DisplayName = "Min Pool Size",
+ Description = "The minimum number of connections allowed in the pool",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ GroupName = "Pooling"
+ },
+ new ConnectionOption
+ {
+ Name = "loadBalanceTimeout",
+ DisplayName = "Load Balance Timeout",
+ Description = "The minimum amount of time (in seconds) for this connection to live in the pool before being destroyed",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ GroupName = "Pooling"
+ },
+ new ConnectionOption
+ {
+ Name = "replication",
+ DisplayName = "Replication",
+ Description = "Used by SQL Server in Replication",
+ ValueType = ConnectionOption.ValueTypeBoolean,
+ GroupName = "Replication"
+ },
+ new ConnectionOption
+ {
+ Name = "attachDbFilename",
+ DisplayName = "Attach Db Filename",
ValueType = ConnectionOption.ValueTypeString
},
new ConnectionOption
{
- Name = "Context Connection",
- ValueType = ConnectionOption.ValueTypeString
+ Name = "failoverPartner",
+ DisplayName = "Failover Partner",
+ Description = "the name or network address of the instance of SQL Server that acts as a failover partner",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = " Source"
+ },
+ new ConnectionOption
+ {
+ Name = "multiSubnetFailover",
+ DisplayName = "Multi Subnet Failover",
+ ValueType = ConnectionOption.ValueTypeBoolean
+ },
+ new ConnectionOption
+ {
+ Name = "multipleActiveResultSets",
+ DisplayName = "Multiple Active ResultSets",
+ Description = "When true, multiple result sets can be returned and read from one connection",
+ ValueType = ConnectionOption.ValueTypeBoolean,
+ GroupName = "Advanced"
+ },
+ new ConnectionOption
+ {
+ Name = "packetSize",
+ DisplayName = "Packet Size",
+ Description = "Size in bytes of the network packets used to communicate with an instance of SQL Server",
+ ValueType = ConnectionOption.ValueTypeNumber,
+ GroupName = "Advanced"
+ },
+ new ConnectionOption
+ {
+ Name = "typeSystemVersion",
+ DisplayName = "Type System Version",
+ Description = "Indicates which server type system then provider will expose through the DataReader",
+ ValueType = ConnectionOption.ValueTypeString,
+ GroupName = "Advanced"
}
}
};
diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs
new file mode 100644
index 00000000..58b3f924
--- /dev/null
+++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs
@@ -0,0 +1,211 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Linq;
+using Microsoft.SqlTools.Hosting.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
+using Xunit;
+
+
+namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
+{
+ ///
+ /// Tests for ConnectionDetails Class
+ ///
+ public class ConnectionDetailsTests
+ {
+ [Fact]
+ public void ConnectionDetailsWithoutAnyOptionShouldReturnNullOrDefaultForOptions()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+
+ var expectedForStrings = default(string);
+ var expectedForInt = default(int?);
+ var expectedForBoolean = default(bool?);
+
+ Assert.Equal(details.ApplicationIntent, expectedForStrings);
+ Assert.Equal(details.ApplicationName, expectedForStrings);
+ Assert.Equal(details.AttachDbFilename, expectedForStrings);
+ Assert.Equal(details.AuthenticationType, expectedForStrings);
+ Assert.Equal(details.CurrentLanguage, expectedForStrings);
+ Assert.Equal(details.DatabaseName, expectedForStrings);
+ Assert.Equal(details.FailoverPartner, expectedForStrings);
+ Assert.Equal(details.Password, expectedForStrings);
+ Assert.Equal(details.ServerName, expectedForStrings);
+ Assert.Equal(details.TypeSystemVersion, expectedForStrings);
+ Assert.Equal(details.UserName, expectedForStrings);
+ Assert.Equal(details.WorkstationId, expectedForStrings);
+ Assert.Equal(details.ConnectRetryInterval, expectedForInt);
+ Assert.Equal(details.ConnectRetryCount, expectedForInt);
+ Assert.Equal(details.ConnectTimeout, expectedForInt);
+ Assert.Equal(details.LoadBalanceTimeout, expectedForInt);
+ Assert.Equal(details.MaxPoolSize, expectedForInt);
+ Assert.Equal(details.MinPoolSize, expectedForInt);
+ Assert.Equal(details.PacketSize, expectedForInt);
+ Assert.Equal(details.Encrypt, expectedForBoolean);
+ Assert.Equal(details.MultipleActiveResultSets, expectedForBoolean);
+ Assert.Equal(details.MultiSubnetFailover, expectedForBoolean);
+ Assert.Equal(details.PersistSecurityInfo, expectedForBoolean);
+ Assert.Equal(details.Pooling, expectedForBoolean);
+ Assert.Equal(details.Replication, expectedForBoolean);
+ Assert.Equal(details.TrustServerCertificate, expectedForBoolean);
+ }
+
+ [Fact]
+ public void ConnectionDetailsPropertySettersShouldSetOptionValuesCorrectly()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+
+ var index = 0;
+ var expectedForStrings = "Value for strings";
+ var expectedForInt = 345;
+ details.ApplicationIntent = expectedForStrings + index++;
+ details.ApplicationName = expectedForStrings + index++;
+ details.AttachDbFilename = expectedForStrings + index++;
+ details.AuthenticationType = expectedForStrings + index++;
+ details.CurrentLanguage = expectedForStrings + index++;
+ details.DatabaseName = expectedForStrings + index++;
+ details.FailoverPartner = expectedForStrings + index++;
+ details.Password = expectedForStrings + index++;
+ details.ServerName = expectedForStrings + index++;
+ details.TypeSystemVersion = expectedForStrings + index++;
+ details.UserName = expectedForStrings + index++;
+ details.WorkstationId = expectedForStrings + index++;
+ details.ConnectRetryInterval = expectedForInt + index++;
+ details.ConnectRetryCount = expectedForInt + index++;
+ details.ConnectTimeout = expectedForInt + index++;
+ details.LoadBalanceTimeout = expectedForInt + index++;
+ details.MaxPoolSize = expectedForInt + index++;
+ details.MinPoolSize = expectedForInt + index++;
+ details.PacketSize = expectedForInt + index++;
+ details.Encrypt = (index++ % 2 == 0);
+ details.MultipleActiveResultSets = (index++ % 2 == 0);
+ details.MultiSubnetFailover = (index++ % 2 == 0);
+ details.PersistSecurityInfo = (index++ % 2 == 0);
+ details.Pooling = (index++ % 2 == 0);
+ details.Replication = (index++ % 2 == 0);
+ details.TrustServerCertificate = (index++ % 2 == 0);
+
+ index = 0;
+ Assert.Equal(details.ApplicationIntent, expectedForStrings + index++);
+ Assert.Equal(details.ApplicationName, expectedForStrings + index++);
+ Assert.Equal(details.AttachDbFilename, expectedForStrings + index++);
+ Assert.Equal(details.AuthenticationType, expectedForStrings + index++);
+ Assert.Equal(details.CurrentLanguage, expectedForStrings + index++);
+ Assert.Equal(details.DatabaseName, expectedForStrings + index++);
+ Assert.Equal(details.FailoverPartner, expectedForStrings + index++);
+ Assert.Equal(details.Password, expectedForStrings + index++);
+ Assert.Equal(details.ServerName, expectedForStrings + index++);
+ Assert.Equal(details.TypeSystemVersion, expectedForStrings + index++);
+ Assert.Equal(details.UserName, expectedForStrings + index++);
+ Assert.Equal(details.WorkstationId, expectedForStrings + index++);
+ Assert.Equal(details.ConnectRetryInterval, expectedForInt + index++);
+ Assert.Equal(details.ConnectRetryCount, expectedForInt + index++);
+ Assert.Equal(details.ConnectTimeout, expectedForInt + index++);
+ Assert.Equal(details.LoadBalanceTimeout, expectedForInt + index++);
+ Assert.Equal(details.MaxPoolSize, expectedForInt + index++);
+ Assert.Equal(details.MinPoolSize, expectedForInt + index++);
+ Assert.Equal(details.PacketSize, expectedForInt + index++);
+ Assert.Equal(details.Encrypt, (index++ % 2 == 0));
+ Assert.Equal(details.MultipleActiveResultSets, (index++ % 2 == 0));
+ Assert.Equal(details.MultiSubnetFailover, (index++ % 2 == 0));
+ Assert.Equal(details.PersistSecurityInfo, (index++ % 2 == 0));
+ Assert.Equal(details.Pooling, (index++ % 2 == 0));
+ Assert.Equal(details.Replication, (index++ % 2 == 0));
+ Assert.Equal(details.TrustServerCertificate, (index++ % 2 == 0));
+ }
+
+ [Fact]
+ public void ConnectionDetailsOptionsShouldBeDefinedInConnectionProviderOptions()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+ ConnectionProviderOptions optionMetadata = Hosting.ServiceHost.BuildConnectionProviderOptions();
+
+ var index = 0;
+ var expectedForStrings = "Value for strings";
+ var expectedForInt = 345;
+ details.ApplicationIntent = expectedForStrings + index++;
+ details.ApplicationName = expectedForStrings + index++;
+ details.AttachDbFilename = expectedForStrings + index++;
+ details.AuthenticationType = expectedForStrings + index++;
+ details.CurrentLanguage = expectedForStrings + index++;
+ details.DatabaseName = expectedForStrings + index++;
+ details.FailoverPartner = expectedForStrings + index++;
+ details.Password = expectedForStrings + index++;
+ details.ServerName = expectedForStrings + index++;
+ details.TypeSystemVersion = expectedForStrings + index++;
+ details.UserName = expectedForStrings + index++;
+ details.WorkstationId = expectedForStrings + index++;
+ details.ConnectRetryInterval = expectedForInt + index++;
+ details.ConnectRetryCount = expectedForInt + index++;
+ details.ConnectTimeout = expectedForInt + index++;
+ details.LoadBalanceTimeout = expectedForInt + index++;
+ details.MaxPoolSize = expectedForInt + index++;
+ details.MinPoolSize = expectedForInt + index++;
+ details.PacketSize = expectedForInt + index++;
+ details.Encrypt = (index++ % 2 == 0);
+ details.MultipleActiveResultSets = (index++ % 2 == 0);
+ details.MultiSubnetFailover = (index++ % 2 == 0);
+ details.PersistSecurityInfo = (index++ % 2 == 0);
+ details.Pooling = (index++ % 2 == 0);
+ details.Replication = (index++ % 2 == 0);
+ details.TrustServerCertificate = (index++ % 2 == 0);
+
+ if(optionMetadata.Options.Count() != details.Options.Count)
+ {
+ var optionsNotInMetadata = details.Options.Where(o => !optionMetadata.Options.Any(m => m.Name == o.Key));
+ var optionNames = optionsNotInMetadata.Any() ? optionsNotInMetadata.Select(s => s.Key).Aggregate((i, j) => i + "," + j) : null;
+ Assert.True(string.IsNullOrEmpty(optionNames), "Options not in metadata: " + optionNames);
+ }
+ foreach (var option in details.Options)
+ {
+ var metadata = optionMetadata.Options.FirstOrDefault(x => x.Name == option.Key);
+ Assert.NotNull(metadata);
+ if(metadata.ValueType == ConnectionOption.ValueTypeString)
+ {
+ Assert.True(option.Value is string);
+ }
+ else if (metadata.ValueType == ConnectionOption.ValueTypeBoolean)
+ {
+ Assert.True(option.Value is bool?);
+ }
+ else if (metadata.ValueType == ConnectionOption.ValueTypeNumber)
+ {
+ Assert.True(option.Value is int?);
+ }
+ }
+ }
+
+
+ [Fact]
+ public void SettingConnectiomTimeoutToLongShouldStillReturnInt()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+
+ long timeout = 30;
+ int? expectedValue = 30;
+ details.Options["connectTimeout"] = timeout;
+
+ Assert.Equal(details.ConnectTimeout, expectedValue);
+ }
+
+ [Fact]
+ public void ConnectTimeoutShouldReturnNullIfNotSet()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+ int? expectedValue = null;
+ Assert.Equal(details.ConnectTimeout, expectedValue);
+ }
+
+ [Fact]
+ public void ConnectTimeoutShouldReturnNullIfSetToNull()
+ {
+ ConnectionDetails details = new ConnectionDetails();
+ details.Options["connectTimeout"] = null;
+ int? expectedValue = null;
+ Assert.Equal(details.ConnectTimeout, expectedValue);
+ }
+ }
+}