Connect with different properties should actually change context (#307)

* Connect with different properties should actually change context
- Up to now, calling Connect for a previously-connected URI would disconnect, then reconnect ot the original (not new) target. WIth these changes we handle changes to database name or other key properties by updating the ConnectionInfo and connecting to the new target
- Some interesting scenarios are raised by our API, notably that an empty database name maps to the default DB (which we know nothing about). This limits the new feature such that only if the DB Name is specified, we'll change the connection. Hence 2 calls to an empty DB will not result in a DB change.

Additional changes:
- After discussion with Ben, we're simplifying the cancellation logic. He had made changes to support this, so the main update is that we dispose the token in the final block after its last use (hence avoiding a disposed exception) and clean up the number of Waits required since we already have async cancellation support
- Factored some logic such that the OnConnection callback isn't invoked until after we've updated the database name in the GetConnectionCompleteParams method. Again, this supports reporting the actual DB name instead of leaving it blank for default DB requests.

* PR comment fixes
This commit is contained in:
Kevin Cunnane
2017-04-06 11:25:59 -07:00
committed by GitHub
parent 1a384d93b4
commit f3bf330da6
5 changed files with 161 additions and 81 deletions

View File

@@ -314,9 +314,37 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
{
bool callbackInvoked = false;
// first connect
string ownerUri = "file://my/sample/file.sql";
var connectionService = TestObjects.GetTestConnectionService();
const string masterDbName = "master";
const string otherDbName = "other";
// Given a connection that returns the database name
var dummySqlConnection = new TestSqlConnection(null);
var mockFactory = new Mock<ISqlConnectionFactory>();
mockFactory.Setup(factory => factory.CreateSqlConnection(It.IsAny<string>()))
.Returns((string connString) =>
{
dummySqlConnection.ConnectionString = connString;
SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(connString);
// Database name is respected. Follow heuristic where empty DB name really means Master
var dbName = string.IsNullOrEmpty(scsb.InitialCatalog) ? masterDbName : scsb.InitialCatalog;
dummySqlConnection.SetDatabase(dbName);
return dummySqlConnection;
});
var connectionService = new ConnectionService(mockFactory.Object);
// register disconnect callback
connectionService.RegisterOnDisconnectTask(
(result, uri) => {
callbackInvoked = true;
Assert.True(uri.Equals(ownerUri));
return Task.FromResult(true);
}
);
// When I connect to default
var connectionResult = await
connectionService
.Connect(new ConnectParams()
@@ -325,32 +353,27 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
Connection = TestObjects.GetTestConnectionDetails()
});
// verify that we are connected
// Then I expect to be connected to master
Assert.NotEmpty(connectionResult.ConnectionId);
// register disconnect callback
connectionService.RegisterOnDisconnectTask(
(result, uri) => {
callbackInvoked = true;
Assert.True(uri.Equals(ownerUri));
return Task.FromResult(true);
}
);
// send annother connect request
// And when I then connect to another DB
var updatedConnectionDetails = TestObjects.GetTestConnectionDetails();
updatedConnectionDetails.DatabaseName = otherDbName;
connectionResult = await
connectionService
.Connect(new ConnectParams()
{
OwnerUri = ownerUri,
Connection = TestObjects.GetTestConnectionDetails()
Connection = updatedConnectionDetails
});
// Then I expect to be disconnected from master, and connected to the new DB
// verify that the event was fired (we disconnected first before connecting)
Assert.True(callbackInvoked);
// verify that we connected again
Assert.NotEmpty(connectionResult.ConnectionId);
Assert.Equal(otherDbName, connectionResult.ConnectionSummary.DatabaseName);
}
/// <summary>