mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-17 02:51:45 -05:00
Wrapping up batch separation
Adding unit tests Fixing things that got brought up from the unit tests
This commit is contained in:
@@ -17,11 +17,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string OwnerUri { get; set; }
|
public string OwnerUri { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Any messages that came back from the server during execution of the query
|
|
||||||
/// </summary>
|
|
||||||
public string[] Messages { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summaries of the result sets that were returned with the query
|
/// Summaries of the result sets that were returned with the query
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -21,27 +20,33 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Query : IDisposable
|
public class Query : IDisposable
|
||||||
{
|
{
|
||||||
private const string RowsAffectedFormat = "({0} row(s) affected)";
|
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The batches underneath this query
|
/// The batches underneath this query
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Batch[] Batches { get; set; }
|
internal Batch[] Batches { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The summaries of the batches underneath this query
|
/// The summaries of the batches underneath this query
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BatchSummary[] BatchSummaries
|
public BatchSummary[] BatchSummaries
|
||||||
{
|
{
|
||||||
get { return Batches.Select((batch, index) => new BatchSummary
|
get
|
||||||
{
|
{
|
||||||
Id = index,
|
if (!HasExecuted)
|
||||||
HasError = batch.HasError,
|
{
|
||||||
Messages = batch.ResultMessages.ToArray(),
|
throw new InvalidOperationException("Query has not been executed.");
|
||||||
ResultSetSummaries = batch.ResultSummaries
|
}
|
||||||
}).ToArray(); }
|
|
||||||
|
return Batches.Select((batch, index) => new BatchSummary
|
||||||
|
{
|
||||||
|
Id = index,
|
||||||
|
HasError = batch.HasError,
|
||||||
|
Messages = batch.ResultMessages.ToArray(),
|
||||||
|
ResultSetSummaries = batch.ResultSummaries
|
||||||
|
}).ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,14 +58,24 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
/// The connection info associated with the file editor owner URI, used to create a new
|
/// The connection info associated with the file editor owner URI, used to create a new
|
||||||
/// connection upon execution of the query
|
/// connection upon execution of the query
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConnectionInfo EditorConnection { get; set; }
|
private ConnectionInfo EditorConnection { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not the query has completed executed, regardless of success or failure
|
/// Whether or not the query has completed executed, regardless of success or failure
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Don't touch the setter unless you're doing unit tests!
|
||||||
|
/// </remarks>
|
||||||
public bool HasExecuted
|
public bool HasExecuted
|
||||||
{
|
{
|
||||||
get { return Batches.All(b => b.HasExecuted); }
|
get { return Batches.All(b => b.HasExecuted); }
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
foreach (var batch in Batches)
|
||||||
|
{
|
||||||
|
batch.HasExecuted = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -87,6 +102,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(connection), "Connection cannot be null");
|
throw new ArgumentNullException(nameof(connection), "Connection cannot be null");
|
||||||
}
|
}
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(settings), "Settings cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the internal state
|
// Initialize the internal state
|
||||||
QueryText = queryText;
|
QueryText = queryText;
|
||||||
@@ -106,16 +125,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task Execute()
|
public async Task Execute()
|
||||||
{
|
{
|
||||||
// Sanity check to make sure we haven't already run this query
|
|
||||||
if (HasExecuted)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Query has already executed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open up a connection for querying the database
|
// Open up a connection for querying the database
|
||||||
string connectionString = ConnectionService.BuildConnectionString(EditorConnection.ConnectionDetails);
|
string connectionString = ConnectionService.BuildConnectionString(EditorConnection.ConnectionDetails);
|
||||||
using (DbConnection conn = EditorConnection.Factory.CreateSqlConnection(connectionString))
|
using (DbConnection conn = EditorConnection.Factory.CreateSqlConnection(connectionString))
|
||||||
{
|
{
|
||||||
|
await conn.OpenAsync();
|
||||||
|
|
||||||
// We need these to execute synchronously, otherwise the user will be very unhappy
|
// We need these to execute synchronously, otherwise the user will be very unhappy
|
||||||
foreach (Batch b in Batches)
|
foreach (Batch b in Batches)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
|||||||
public SqlToolsSettings()
|
public SqlToolsSettings()
|
||||||
{
|
{
|
||||||
this.ScriptAnalysis = new ScriptAnalysisSettings();
|
this.ScriptAnalysis = new ScriptAnalysisSettings();
|
||||||
|
this.QueryExecutionSettings = new QueryExecutionSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool EnableProfileLoading { get; set; }
|
public bool EnableProfileLoading { get; set; }
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
|
|
||||||
public Workspace Workspace { get; private set; }
|
public Workspace Workspace { get; private set; }
|
||||||
|
|
||||||
public TConfig CurrentSettings { get; private set; }
|
public TConfig CurrentSettings { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delegate for callbacks that occur when the configuration for the workspace changes
|
/// Delegate for callbacks that occur when the configuration for the workspace changes
|
||||||
|
|||||||
@@ -14,16 +14,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
{
|
{
|
||||||
public class CancelTests
|
public class CancelTests
|
||||||
{
|
{
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void CancelInProgressQueryTest()
|
public void CancelInProgressQueryTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request a query (doesn't matter what kind) and execute it
|
// ... I request a query (doesn't matter what kind) and execute it
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||||
var executeParams = new QueryExecuteParams { QueryText = "Doesn't Matter", OwnerUri = Common.OwnerUri };
|
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
|
||||||
var executeRequest = Common.GetQueryExecuteResultContextMock(null, null, null);
|
var executeRequest = Common.GetQueryExecuteResultContextMock(null, null, null);
|
||||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||||
//queryService.ActiveQueries[Common.OwnerUri].HasExecuted = false; // Fake that it hasn't completed execution
|
queryService.ActiveQueries[Common.OwnerUri].HasExecuted = false; // Fake that it hasn't completed execution
|
||||||
|
|
||||||
// ... And then I request to cancel the query
|
// ... And then I request to cancel the query
|
||||||
var cancelParams = new QueryCancelParams {OwnerUri = Common.OwnerUri};
|
var cancelParams = new QueryCancelParams {OwnerUri = Common.OwnerUri};
|
||||||
@@ -46,7 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// If:
|
// If:
|
||||||
// ... I request a query (doesn't matter what kind) and wait for execution
|
// ... I request a query (doesn't matter what kind) and wait for execution
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||||
var executeParams = new QueryExecuteParams {QueryText = "Doesn't Matter", OwnerUri = Common.OwnerUri};
|
var executeParams = new QueryExecuteParams {QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri};
|
||||||
var executeRequest = Common.GetQueryExecuteResultContextMock(null, null, null);
|
var executeRequest = Common.GetQueryExecuteResultContextMock(null, null, null);
|
||||||
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||||
@@ -18,6 +19,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
{
|
{
|
||||||
public class Common
|
public class Common
|
||||||
{
|
{
|
||||||
|
public const string StandardQuery = "SELECT * FROM sys.objects";
|
||||||
|
|
||||||
public const string OwnerUri = "testFile";
|
public const string OwnerUri = "testFile";
|
||||||
|
|
||||||
public const int StandardRows = 5;
|
public const int StandardRows = 5;
|
||||||
@@ -45,10 +48,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Batch GetBasicExecutedBatch()
|
||||||
|
{
|
||||||
|
Batch batch = new Batch(StandardQuery);
|
||||||
|
batch.Execute(CreateTestConnection(new[] {StandardTestData}, false), CancellationToken.None).Wait();
|
||||||
|
return batch;
|
||||||
|
}
|
||||||
|
|
||||||
public static Query GetBasicExecutedQuery()
|
public static Query GetBasicExecutedQuery()
|
||||||
{
|
{
|
||||||
ConnectionInfo ci = CreateTestConnectionInfo(new[] {StandardTestData}, false);
|
ConnectionInfo ci = CreateTestConnectionInfo(new[] {StandardTestData}, false);
|
||||||
Query query = new Query("SIMPLE QUERY", ci, new QueryExecutionSettings());
|
Query query = new Query(StandardQuery, ci, new QueryExecutionSettings());
|
||||||
query.Execute().Wait();
|
query.Execute().Wait();
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
@@ -8,6 +9,7 @@ using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts;
|
|||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
|
||||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
public void BatchCreationTest()
|
public void BatchCreationTest()
|
||||||
{
|
{
|
||||||
// If I create a new batch...
|
// If I create a new batch...
|
||||||
Batch batch = new Batch("NO OP");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
// ... The text of the batch should be stored
|
// ... The text of the batch should be stored
|
||||||
@@ -41,7 +43,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
public void BatchExecuteNoResultSets()
|
public void BatchExecuteNoResultSets()
|
||||||
{
|
{
|
||||||
// If I execute a query that should get no result sets
|
// If I execute a query that should get no result sets
|
||||||
Batch batch = new Batch("Query with no result sets");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false)), CancellationToken.None).Wait();
|
batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false)), CancellationToken.None).Wait();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
@@ -68,7 +70,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
ConnectionInfo ci = Common.CreateTestConnectionInfo(new[] { Common.StandardTestData }, false);
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(new[] { Common.StandardTestData }, false);
|
||||||
|
|
||||||
// If I execute a query that should get one result set
|
// If I execute a query that should get one result set
|
||||||
Batch batch = new Batch("Query with one result sets");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
@@ -101,7 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
ConnectionInfo ci = Common.CreateTestConnectionInfo(dataset, false);
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(dataset, false);
|
||||||
|
|
||||||
// If I execute a query that should get two result sets
|
// If I execute a query that should get two result sets
|
||||||
Batch batch = new Batch("Query with two result sets");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
@@ -144,7 +146,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, true);
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, true);
|
||||||
|
|
||||||
// If I execute a batch that is invalid
|
// If I execute a batch that is invalid
|
||||||
Batch batch = new Batch("Invalid query");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
@@ -166,7 +168,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
ConnectionInfo ci = Common.CreateTestConnectionInfo(new[] { Common.StandardTestData }, false);
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(new[] { Common.StandardTestData }, false);
|
||||||
|
|
||||||
// If I execute a batch
|
// If I execute a batch
|
||||||
Batch batch = new Batch("Any query");
|
Batch batch = new Batch(Common.StandardQuery);
|
||||||
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
batch.Execute(GetConnection(ci), CancellationToken.None).Wait();
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
@@ -203,6 +205,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
|
|
||||||
#region Query Class Tests
|
#region Query Class Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QueryExecuteNoQueryText()
|
||||||
|
{
|
||||||
|
// If:
|
||||||
|
// ... I create a query that has a null query text
|
||||||
|
// Then:
|
||||||
|
// ... It should throw an exception
|
||||||
|
Assert.Throws<ArgumentNullException>(() =>
|
||||||
|
new Query(null, Common.CreateTestConnectionInfo(null, false), new QueryExecutionSettings()));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void QueryExecuteNoConnectionInfo()
|
public void QueryExecuteNoConnectionInfo()
|
||||||
{
|
{
|
||||||
@@ -224,17 +237,105 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
new Query("Some query", Common.CreateTestConnectionInfo(null, false), null));
|
new Query("Some query", Common.CreateTestConnectionInfo(null, false), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QueryExecuteSingleBatch()
|
||||||
|
{
|
||||||
|
// If:
|
||||||
|
// ... I create a query from a single batch (without separator)
|
||||||
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
|
||||||
|
Query query = new Query(Common.StandardQuery, ci, new QueryExecutionSettings());
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... I should get a single batch to execute that hasn't been executed
|
||||||
|
Assert.NotEmpty(query.QueryText);
|
||||||
|
Assert.NotEmpty(query.Batches);
|
||||||
|
Assert.Equal(1, query.Batches.Length);
|
||||||
|
Assert.False(query.HasExecuted);
|
||||||
|
Assert.Throws<InvalidOperationException>(() => query.BatchSummaries);
|
||||||
|
|
||||||
|
// If:
|
||||||
|
// ... I then execute the query
|
||||||
|
query.Execute().Wait();
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... The query should have completed successfully with one batch summary returned
|
||||||
|
Assert.True(query.HasExecuted);
|
||||||
|
Assert.NotEmpty(query.BatchSummaries);
|
||||||
|
Assert.Equal(1, query.BatchSummaries.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QueryExecuteMultipleBatches()
|
||||||
|
{
|
||||||
|
// If:
|
||||||
|
// ... I create a query from two batches (with separator)
|
||||||
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false);
|
||||||
|
string queryText = string.Format("{0}\r\nGO\r\n{0}", Common.StandardQuery);
|
||||||
|
Query query = new Query(queryText, ci, new QueryExecutionSettings());
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... I should get back two batches to execute that haven't been executed
|
||||||
|
Assert.NotEmpty(query.QueryText);
|
||||||
|
Assert.NotEmpty(query.Batches);
|
||||||
|
Assert.Equal(2, query.Batches.Length);
|
||||||
|
Assert.False(query.HasExecuted);
|
||||||
|
Assert.Throws<InvalidOperationException>(() => query.BatchSummaries);
|
||||||
|
|
||||||
|
// If:
|
||||||
|
// ... I then execute the query
|
||||||
|
query.Execute().Wait();
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... The query should have completed successfully with two batch summaries returned
|
||||||
|
Assert.True(query.HasExecuted);
|
||||||
|
Assert.NotEmpty(query.BatchSummaries);
|
||||||
|
Assert.Equal(2, query.BatchSummaries.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QueryExecuteInvalidBatch()
|
||||||
|
{
|
||||||
|
// If:
|
||||||
|
// ... I create a query from an invalid batch
|
||||||
|
ConnectionInfo ci = Common.CreateTestConnectionInfo(null, true);
|
||||||
|
Query query = new Query("SELECT *** FROM sys.objects", ci, new QueryExecutionSettings());
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... I should get back a query with one batch not executed
|
||||||
|
Assert.NotEmpty(query.QueryText);
|
||||||
|
Assert.NotEmpty(query.Batches);
|
||||||
|
Assert.Equal(1, query.Batches.Length);
|
||||||
|
Assert.False(query.HasExecuted);
|
||||||
|
Assert.Throws<InvalidOperationException>(() => query.BatchSummaries);
|
||||||
|
|
||||||
|
// If:
|
||||||
|
// ... I then execute the query
|
||||||
|
query.Execute().Wait();
|
||||||
|
|
||||||
|
// Then:
|
||||||
|
// ... There should be an error on the batch
|
||||||
|
Assert.True(query.HasExecuted);
|
||||||
|
Assert.NotEmpty(query.BatchSummaries);
|
||||||
|
Assert.Equal(1, query.BatchSummaries.Length);
|
||||||
|
Assert.True(query.BatchSummaries[0].HasError);
|
||||||
|
Assert.NotEmpty(query.BatchSummaries[0].Messages);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Service Tests
|
#region Service Tests
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteValidNoResultsTest()
|
public void QueryExecuteValidNoResultsTest()
|
||||||
{
|
{
|
||||||
|
// Given:
|
||||||
|
// ... Default settings are stored in the workspace service
|
||||||
|
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings = new SqlToolsSettings();
|
||||||
|
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a valid query with no results
|
// ... I request to execute a valid query with no results
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||||
var queryParams = new QueryExecuteParams { QueryText = "Doesn't Matter", OwnerUri = Common.OwnerUri };
|
var queryParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
|
||||||
|
|
||||||
QueryExecuteResult result = null;
|
QueryExecuteResult result = null;
|
||||||
QueryExecuteCompleteParams completeParams = null;
|
QueryExecuteCompleteParams completeParams = null;
|
||||||
@@ -243,24 +344,25 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
// ... No Errors should have been sent
|
// ... No Errors should have been sent
|
||||||
// ... A successful result should have been sent with messages
|
// ... A successful result should have been sent with messages on the first batch
|
||||||
// ... A completion event should have been fired with empty results
|
// ... A completion event should have been fired with empty results
|
||||||
|
VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
||||||
|
Assert.Null(result.Messages);
|
||||||
|
Assert.Equal(1, completeParams.BatchSummaries.Length);
|
||||||
|
Assert.Empty(completeParams.BatchSummaries[0].ResultSetSummaries);
|
||||||
|
Assert.NotEmpty(completeParams.BatchSummaries[0].Messages);
|
||||||
|
|
||||||
// ... There should be one active query
|
// ... There should be one active query
|
||||||
//VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
Assert.Equal(1, queryService.ActiveQueries.Count);
|
||||||
//Assert.Null(result.Messages);
|
|
||||||
//Assert.NotEmpty(completeParams.Messages);
|
|
||||||
//Assert.Equal(1, completeParams.BatchSummaries);
|
|
||||||
//Assert.True(completeParams.);
|
|
||||||
//Assert.Equal(1, queryService.ActiveQueries.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteValidResultsTest()
|
public void QueryExecuteValidResultsTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a valid query with results
|
// ... I request to execute a valid query with results
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(new[] { Common.StandardTestData }, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(new[] { Common.StandardTestData }, false), true);
|
||||||
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = "Doesn't Matter" };
|
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = Common.StandardQuery };
|
||||||
|
|
||||||
QueryExecuteResult result = null;
|
QueryExecuteResult result = null;
|
||||||
QueryExecuteCompleteParams completeParams = null;
|
QueryExecuteCompleteParams completeParams = null;
|
||||||
@@ -271,22 +373,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... No errors should have been sent
|
// ... No errors should have been sent
|
||||||
// ... A successful result should have been sent with messages
|
// ... A successful result should have been sent with messages
|
||||||
// ... A completion event should have been fired with one result
|
// ... A completion event should have been fired with one result
|
||||||
|
VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
||||||
|
Assert.Null(result.Messages);
|
||||||
|
Assert.Equal(1, completeParams.BatchSummaries.Length);
|
||||||
|
Assert.NotEmpty(completeParams.BatchSummaries[0].ResultSetSummaries);
|
||||||
|
Assert.NotEmpty(completeParams.BatchSummaries[0].Messages);
|
||||||
|
Assert.False(completeParams.BatchSummaries[0].HasError);
|
||||||
|
|
||||||
// ... There should be one active query
|
// ... There should be one active query
|
||||||
//VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
Assert.Equal(1, queryService.ActiveQueries.Count);
|
||||||
//Assert.Null(result.Messages);
|
|
||||||
//Assert.NotEmpty(completeParams.Messages);
|
|
||||||
//Assert.NotEmpty(completeParams.ResultSetSummaries);
|
|
||||||
//Assert.False(completeParams.HasError);
|
|
||||||
//Assert.Equal(1, queryService.ActiveQueries.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteUnconnectedUriTest()
|
public void QueryExecuteUnconnectedUriTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a query using a file URI that isn't connected
|
// ... I request to execute a query using a file URI that isn't connected
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), false);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), false);
|
||||||
var queryParams = new QueryExecuteParams { OwnerUri = "notConnected", QueryText = "Doesn't Matter" };
|
var queryParams = new QueryExecuteParams { OwnerUri = "notConnected", QueryText = Common.StandardQuery };
|
||||||
|
|
||||||
QueryExecuteResult result = null;
|
QueryExecuteResult result = null;
|
||||||
var requestContext = Common.GetQueryExecuteResultContextMock(qer => result = qer, null, null);
|
var requestContext = Common.GetQueryExecuteResultContextMock(qer => result = qer, null, null);
|
||||||
@@ -297,48 +401,48 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... No completion event should have been fired
|
// ... No completion event should have been fired
|
||||||
// ... No error event should have been fired
|
// ... No error event should have been fired
|
||||||
// ... There should be no active queries
|
// ... There should be no active queries
|
||||||
//VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Never(), Times.Never());
|
VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Never(), Times.Never());
|
||||||
//Assert.NotNull(result.Messages);
|
Assert.NotNull(result.Messages);
|
||||||
//Assert.NotEmpty(result.Messages);
|
Assert.NotEmpty(result.Messages);
|
||||||
//Assert.Empty(queryService.ActiveQueries);
|
Assert.Empty(queryService.ActiveQueries);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteInProgressTest()
|
public void QueryExecuteInProgressTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a query
|
// ... I request to execute a query
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||||
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = "Some Query" };
|
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = Common.StandardQuery };
|
||||||
|
|
||||||
// Note, we don't care about the results of the first request
|
// Note, we don't care about the results of the first request
|
||||||
var firstRequestContext = Common.GetQueryExecuteResultContextMock(null, null, null);
|
var firstRequestContext = Common.GetQueryExecuteResultContextMock(null, null, null);
|
||||||
queryService.HandleExecuteRequest(queryParams, firstRequestContext.Object).Wait();
|
queryService.HandleExecuteRequest(queryParams, firstRequestContext.Object).Wait();
|
||||||
|
|
||||||
// ... And then I request another query without waiting for the first to complete
|
// ... And then I request another query without waiting for the first to complete
|
||||||
//queryService.ActiveQueries[Common.OwnerUri].HasExecuted = false; // Simulate query hasn't finished
|
queryService.ActiveQueries[Common.OwnerUri].HasExecuted = false; // Simulate query hasn't finished
|
||||||
//QueryExecuteResult result = null;
|
QueryExecuteResult result = null;
|
||||||
//var secondRequestContext = Common.GetQueryExecuteResultContextMock(qer => result = qer, null, null);
|
var secondRequestContext = Common.GetQueryExecuteResultContextMock(qer => result = qer, null, null);
|
||||||
//queryService.HandleExecuteRequest(queryParams, secondRequestContext.Object).Wait();
|
queryService.HandleExecuteRequest(queryParams, secondRequestContext.Object).Wait();
|
||||||
|
|
||||||
//// Then:
|
// Then:
|
||||||
//// ... No errors should have been sent
|
// ... No errors should have been sent
|
||||||
//// ... A result should have been sent with an error message
|
// ... A result should have been sent with an error message
|
||||||
//// ... No completion event should have been fired
|
// ... No completion event should have been fired
|
||||||
//// ... There should only be one active query
|
// ... There should only be one active query
|
||||||
//VerifyQueryExecuteCallCount(secondRequestContext, Times.Once(), Times.AtMostOnce(), Times.Never());
|
VerifyQueryExecuteCallCount(secondRequestContext, Times.Once(), Times.AtMostOnce(), Times.Never());
|
||||||
//Assert.NotNull(result.Messages);
|
Assert.NotNull(result.Messages);
|
||||||
//Assert.NotEmpty(result.Messages);
|
Assert.NotEmpty(result.Messages);
|
||||||
//Assert.Equal(1, queryService.ActiveQueries.Count);
|
Assert.Equal(1, queryService.ActiveQueries.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteCompletedTest()
|
public void QueryExecuteCompletedTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a query
|
// ... I request to execute a query
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, false), true);
|
||||||
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = "Some Query" };
|
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = Common.StandardQuery };
|
||||||
|
|
||||||
// Note, we don't care about the results of the first request
|
// Note, we don't care about the results of the first request
|
||||||
var firstRequestContext = Common.GetQueryExecuteResultContextMock(null, null, null);
|
var firstRequestContext = Common.GetQueryExecuteResultContextMock(null, null, null);
|
||||||
@@ -354,15 +458,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... No errors should have been sent
|
// ... No errors should have been sent
|
||||||
// ... A result should have been sent with no errors
|
// ... A result should have been sent with no errors
|
||||||
// ... There should only be one active query
|
// ... There should only be one active query
|
||||||
//VerifyQueryExecuteCallCount(secondRequestContext, Times.Once(), Times.Once(), Times.Never());
|
VerifyQueryExecuteCallCount(secondRequestContext, Times.Once(), Times.Once(), Times.Never());
|
||||||
//Assert.Null(result.Messages);
|
Assert.Null(result.Messages);
|
||||||
//Assert.False(complete.HasError);
|
Assert.False(complete.BatchSummaries.Any(b => b.HasError));
|
||||||
//Assert.Equal(1, queryService.ActiveQueries.Count);
|
Assert.Equal(1, queryService.ActiveQueries.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Theory]
|
[Theory]
|
||||||
//[InlineData("")]
|
[InlineData("")]
|
||||||
//[InlineData(null)]
|
[InlineData(null)]
|
||||||
public void QueryExecuteMissingQueryTest(string query)
|
public void QueryExecuteMissingQueryTest(string query)
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
@@ -378,21 +482,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... No errors should have been sent
|
// ... No errors should have been sent
|
||||||
// ... A result should have been sent with an error message
|
// ... A result should have been sent with an error message
|
||||||
// ... No completion event should have been fired
|
// ... No completion event should have been fired
|
||||||
//VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Never(), Times.Never());
|
VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Never(), Times.Never());
|
||||||
//Assert.NotNull(result.Messages);
|
Assert.NotNull(result.Messages);
|
||||||
//Assert.NotEmpty(result.Messages);
|
Assert.NotEmpty(result.Messages);
|
||||||
|
|
||||||
// ... There should not be an active query
|
// ... There should not be an active query
|
||||||
Assert.Empty(queryService.ActiveQueries);
|
Assert.Empty(queryService.ActiveQueries);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Fact]
|
[Fact]
|
||||||
public void QueryExecuteInvalidQueryTest()
|
public void QueryExecuteInvalidQueryTest()
|
||||||
{
|
{
|
||||||
// If:
|
// If:
|
||||||
// ... I request to execute a query that is invalid
|
// ... I request to execute a query that is invalid
|
||||||
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, true), true);
|
var queryService = Common.GetPrimedExecutionService(Common.CreateMockFactory(null, true), true);
|
||||||
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = "Bad query!" };
|
var queryParams = new QueryExecuteParams { OwnerUri = Common.OwnerUri, QueryText = Common.StandardQuery };
|
||||||
|
|
||||||
QueryExecuteResult result = null;
|
QueryExecuteResult result = null;
|
||||||
QueryExecuteCompleteParams complete = null;
|
QueryExecuteCompleteParams complete = null;
|
||||||
@@ -403,10 +507,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... No errors should have been sent
|
// ... No errors should have been sent
|
||||||
// ... A result should have been sent with success (we successfully started the query)
|
// ... A result should have been sent with success (we successfully started the query)
|
||||||
// ... A completion event should have been sent with error
|
// ... A completion event should have been sent with error
|
||||||
//VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
VerifyQueryExecuteCallCount(requestContext, Times.Once(), Times.Once(), Times.Never());
|
||||||
//Assert.Null(result.Messages);
|
Assert.Null(result.Messages);
|
||||||
//Assert.True(complete.HasError);
|
Assert.Equal(1, complete.BatchSummaries.Length);
|
||||||
//Assert.NotEmpty(complete.Messages);
|
Assert.True(complete.BatchSummaries[0].HasError);
|
||||||
|
Assert.NotEmpty(complete.BatchSummaries[0].Messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -11,18 +11,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
{
|
{
|
||||||
public class SubsetTests
|
public class SubsetTests
|
||||||
{
|
{
|
||||||
#region Query Class Tests
|
#region Batch Class Tests
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(2)]
|
[InlineData(2)]
|
||||||
[InlineData(20)]
|
[InlineData(20)]
|
||||||
public void SubsetValidTest(int rowCount)
|
public void BatchSubsetValidTest(int rowCount)
|
||||||
{
|
{
|
||||||
// If I have an executed query
|
// If I have an executed batch
|
||||||
Query q = Common.GetBasicExecutedQuery();
|
Batch b = Common.GetBasicExecutedBatch();
|
||||||
|
|
||||||
// ... And I ask for a subset with valid arguments
|
// ... And I ask for a subset with valid arguments
|
||||||
ResultSetSubset subset = q.GetSubset(0, 0, 0, rowCount);
|
ResultSetSubset subset = b.GetSubset(0, 0, rowCount);
|
||||||
|
|
||||||
// Then:
|
// Then:
|
||||||
// I should get the requested number of rows
|
// I should get the requested number of rows
|
||||||
@@ -30,18 +30,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
Assert.Equal(Math.Min(rowCount, Common.StandardTestData.Length), subset.Rows.Length);
|
Assert.Equal(Math.Min(rowCount, Common.StandardTestData.Length), subset.Rows.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SubsetUnexecutedQueryTest()
|
|
||||||
{
|
|
||||||
// If I have a query that has *not* been executed
|
|
||||||
Query q = new Query("NO OP", Common.CreateTestConnectionInfo(null, false), new QueryExecutionSettings());
|
|
||||||
|
|
||||||
// ... And I ask for a subset with valid arguments
|
|
||||||
// Then:
|
|
||||||
// ... It should throw an exception
|
|
||||||
Assert.Throws<InvalidOperationException>(() => q.GetSubset(0, 0, 0, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(-1, 0, 2)] // Invalid result set, too low
|
[InlineData(-1, 0, 2)] // Invalid result set, too low
|
||||||
[InlineData(2, 0, 2)] // Invalid result set, too high
|
[InlineData(2, 0, 2)] // Invalid result set, too high
|
||||||
@@ -49,7 +37,37 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
[InlineData(0, 10, 2)] // Invalid start index, too high
|
[InlineData(0, 10, 2)] // Invalid start index, too high
|
||||||
[InlineData(0, 0, -1)] // Invalid row count, too low
|
[InlineData(0, 0, -1)] // Invalid row count, too low
|
||||||
[InlineData(0, 0, 0)] // Invalid row count, zero
|
[InlineData(0, 0, 0)] // Invalid row count, zero
|
||||||
public void SubsetInvalidParamsTest(int resultSetIndex, int rowStartInex, int rowCount)
|
public void BatchSubsetInvalidParamsTest(int resultSetIndex, int rowStartInex, int rowCount)
|
||||||
|
{
|
||||||
|
// If I have an executed batch
|
||||||
|
Batch b = Common.GetBasicExecutedBatch();
|
||||||
|
|
||||||
|
// ... And I ask for a subset with an invalid result set index
|
||||||
|
// Then:
|
||||||
|
// ... It should throw an exception
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => b.GetSubset(resultSetIndex, rowStartInex, rowCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Query Class Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SubsetUnexecutedQueryTest()
|
||||||
|
{
|
||||||
|
// If I have a query that has *not* been executed
|
||||||
|
Query q = new Query(Common.StandardQuery, Common.CreateTestConnectionInfo(null, false), new QueryExecutionSettings());
|
||||||
|
|
||||||
|
// ... And I ask for a subset with valid arguments
|
||||||
|
// Then:
|
||||||
|
// ... It should throw an exception
|
||||||
|
Assert.Throws<InvalidOperationException>(() => q.GetSubset(0, 0, 0, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-1)] // Invalid batch, too low
|
||||||
|
[InlineData(2)] // Invalid batch, too high
|
||||||
|
public void QuerySubsetInvalidParamsTest(int batchIndex)
|
||||||
{
|
{
|
||||||
// If I have an executed query
|
// If I have an executed query
|
||||||
Query q = Common.GetBasicExecutedQuery();
|
Query q = Common.GetBasicExecutedQuery();
|
||||||
@@ -57,7 +75,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
|
|||||||
// ... And I ask for a subset with an invalid result set index
|
// ... And I ask for a subset with an invalid result set index
|
||||||
// Then:
|
// Then:
|
||||||
// ... It should throw an exception
|
// ... It should throw an exception
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(() => q.GetSubset(0, resultSetIndex, rowStartInex, rowCount));
|
Assert.Throws<ArgumentOutOfRangeException>(() => q.GetSubset(batchIndex, 0, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
"moq": "4.6.36-alpha",
|
"moq": "4.6.36-alpha",
|
||||||
"Microsoft.SqlTools.ServiceLayer": {
|
"Microsoft.SqlTools.ServiceLayer": {
|
||||||
"target": "project"
|
"target": "project"
|
||||||
},
|
}
|
||||||
"System.Diagnostics.TraceSource": "4.0.0"
|
|
||||||
},
|
},
|
||||||
"testRunner": "xunit",
|
"testRunner": "xunit",
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
|
|||||||
Reference in New Issue
Block a user