Wrapping up batch separation

Adding unit tests
Fixing things that got brought up from the unit tests
This commit is contained in:
benrr101
2016-08-19 18:24:20 -07:00
parent c719ed4598
commit 943c7b9569
9 changed files with 254 additions and 111 deletions

View File

@@ -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>

View File

@@ -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
{
if (!HasExecuted)
{
throw new InvalidOperationException("Query has not been executed.");
}
return Batches.Select((batch, index) => new BatchSummary
{ {
Id = index, Id = index,
HasError = batch.HasError, HasError = batch.HasError,
Messages = batch.ResultMessages.ToArray(), Messages = batch.ResultMessages.ToArray(),
ResultSetSummaries = batch.ResultSummaries ResultSetSummaries = batch.ResultSummaries
}).ToArray(); } }).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)
{ {

View File

@@ -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; }

View File

@@ -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

View File

@@ -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();

View File

@@ -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;
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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": {