Format Cell Values (#62)

* WIP for ability to localize cell values

* Changing how DateTimeOffsets are stored, getting unit tests going

* Reworking BufferFileStreamWriter to use dictionary approach

* Plumbing the DbCellValue type the rest of the way through

* Removing unused components to simplify contract

* Cleanup and making sure byte[] appears in parity with SSMS

* CR comments, small tweaks for optimizing LINQ
This commit is contained in:
Benjamin Russell
2016-09-22 12:00:32 -07:00
committed by GitHub
parent 1f0240dbe0
commit 93a75f1ff4
13 changed files with 535 additions and 977 deletions

View File

@@ -184,6 +184,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
connectionMock.Protected()
.Setup<DbCommand>("CreateDbCommand")
.Returns(CreateTestCommand(data, throwOnRead));
connectionMock.Setup(dbc => dbc.Open())
.Callback(() => connectionMock.SetupGet(dbc => dbc.State).Returns(ConnectionState.Open));
connectionMock.Setup(dbc => dbc.Close())
.Callback(() => connectionMock.SetupGet(dbc => dbc.State).Returns(ConnectionState.Closed));
return connectionMock.Object;
}

View File

@@ -14,7 +14,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
{
public class ReaderWriterPairTest
{
private static void VerifyReadWrite<T>(int valueLength, T value, Func<ServiceBufferFileStreamWriter, T, int> writeFunc, Func<ServiceBufferFileStreamReader, FileStreamReadResult<T>> readFunc)
private static void VerifyReadWrite<T>(int valueLength, T value, Func<ServiceBufferFileStreamWriter, T, int> writeFunc, Func<ServiceBufferFileStreamReader, FileStreamReadResult> readFunc)
{
// Setup: Create a mock file stream wrapper
Common.InMemoryWrapper mockWrapper = new Common.InMemoryWrapper();
@@ -29,16 +29,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
}
// ... And read the type T back
FileStreamReadResult<T> outValue;
FileStreamReadResult outValue;
using (ServiceBufferFileStreamReader reader = new ServiceBufferFileStreamReader(mockWrapper, "abc"))
{
outValue = readFunc(reader);
}
// Then:
Assert.Equal(value, outValue.Value);
Assert.Equal(value, outValue.Value.RawObject);
Assert.Equal(valueLength, outValue.TotalLength);
Assert.False(outValue.IsNull);
Assert.NotNull(outValue.Value);
}
finally
{
@@ -200,7 +200,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
};
foreach (DateTimeOffset value in testValues)
{
VerifyReadWrite((sizeof(long) + 1)*2, value, (writer, val) => writer.WriteDateTimeOffset(val), reader => reader.ReadDateTimeOffset(0));
VerifyReadWrite(sizeof(long)*2 + 1, value, (writer, val) => writer.WriteDateTimeOffset(val), reader => reader.ReadDateTimeOffset(0));
}
}
@@ -267,7 +267,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
{
// Then:
// ... I should get an argument null exception
Assert.Throws<ArgumentNullException>(() => writer.WriteBytes(null, 0));
Assert.Throws<ArgumentNullException>(() => writer.WriteBytes(null));
}
}
@@ -289,7 +289,38 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage
byte[] value = sb.ToArray();
int lengthLength = length == 0 || length > 255 ? 5 : 1;
int valueLength = sizeof(byte)*length + lengthLength;
VerifyReadWrite(valueLength, value, (writer, val) => writer.WriteBytes(value, length), reader => reader.ReadBytes(0));
VerifyReadWrite(valueLength, value, (writer, val) => writer.WriteBytes(value), reader => reader.ReadBytes(0));
}
[Fact]
public void GuidTest()
{
// Setup:
// ... Create some test values
// NOTE: We are doing these here instead of InlineData because Guid type can't be written as constant expressions
Guid[] guids =
{
Guid.Empty, Guid.NewGuid(), Guid.NewGuid()
};
foreach (Guid guid in guids)
{
VerifyReadWrite(guid.ToByteArray().Length + 1, new SqlGuid(guid), (writer, val) => writer.WriteGuid(guid), reader => reader.ReadGuid(0));
}
}
[Fact]
public void MoneyTest()
{
// Setup: Create some test values
// NOTE: We are doing these here instead of InlineData because SqlMoney can't be written as a constant expression
SqlMoney[] monies =
{
SqlMoney.Zero, SqlMoney.MinValue, SqlMoney.MaxValue, new SqlMoney(1.02)
};
foreach (SqlMoney money in monies)
{
VerifyReadWrite(sizeof(decimal) + 1, money, (writer, val) => writer.WriteMoney(money), reader => reader.ReadMoney(0));
}
}
}
}

View File

@@ -4,6 +4,7 @@
//
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
@@ -17,6 +18,48 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
{
public class SubsetTests
{
#region ResultSet Class Tests
[Theory]
[InlineData(0,2)]
[InlineData(0,20)]
[InlineData(1,2)]
public void ResultSetValidTest(int startRow, int rowCount)
{
// Setup:
// ... I have a batch that has been executed
Batch b = Common.GetBasicExecutedBatch();
// If:
// ... I have a result set and I ask for a subset with valid arguments
ResultSet rs = b.ResultSets.First();
ResultSetSubset subset = rs.GetSubset(startRow, rowCount).Result;
// Then:
// ... I should get the requested number of rows back
Assert.Equal(Math.Min(rowCount, Common.StandardTestData.Length), subset.RowCount);
Assert.Equal(Math.Min(rowCount, Common.StandardTestData.Length), subset.Rows.Length);
}
[Theory]
[InlineData(-1, 2)] // Invalid start index, too low
[InlineData(10, 2)] // Invalid start index, too high
[InlineData(0, -1)] // Invalid row count, too low
[InlineData(0, 0)] // Invalid row count, zero
public void ResultSetInvalidParmsTest(int rowStartIndex, int rowCount)
{
// If:
// I have an executed batch with a resultset in it and request invalid result set from it
Batch b = Common.GetBasicExecutedBatch();
ResultSet rs = b.ResultSets.First();
// Then:
// ... It should throw an exception
Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => rs.GetSubset(rowStartIndex, rowCount)).Wait();
}
#endregion
#region Batch Class Tests
[Theory]
@@ -37,13 +80,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
}
[Theory]
[InlineData(-1, 0, 2)] // Invalid result set, too low
[InlineData(2, 0, 2)] // Invalid result set, too high
[InlineData(0, -1, 2)] // Invalid start index, too low
[InlineData(0, 10, 2)] // Invalid start index, too high
[InlineData(0, 0, -1)] // Invalid row count, too low
[InlineData(0, 0, 0)] // Invalid row count, zero
public void BatchSubsetInvalidParamsTest(int resultSetIndex, int rowStartInex, int rowCount)
[InlineData(-1)] // Invalid result set, too low
[InlineData(2)] // Invalid result set, too high
public void BatchSubsetInvalidParamsTest(int resultSetIndex)
{
// If I have an executed batch
Batch b = Common.GetBasicExecutedBatch();
@@ -51,7 +90,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
// ... And I ask for a subset with an invalid result set index
// Then:
// ... It should throw an exception
Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => b.GetSubset(resultSetIndex, rowStartInex, rowCount)).Wait();
Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => b.GetSubset(resultSetIndex, 0, 2)).Wait();
}
#endregion
@@ -95,7 +134,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
// ... I have a query that has results (doesn't matter what)
var queryService =Common.GetPrimedExecutionService(
Common.CreateMockFactory(new[] {Common.StandardTestData}, false), true);
var executeParams = new QueryExecuteParams {QueryText = "Doesn'tMatter", OwnerUri = Common.OwnerUri};
var executeParams = new QueryExecuteParams {QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri};
var executeRequest = RequestContextMocks.SetupRequestContextMock<QueryExecuteResult, QueryExecuteCompleteParams>(null, QueryExecuteCompleteEvent.Type, null, null);
await queryService.HandleExecuteRequest(executeParams, executeRequest.Object);
@@ -141,7 +180,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
// ... I have a query that hasn't finished executing (doesn't matter what)
var queryService = Common.GetPrimedExecutionService(
Common.CreateMockFactory(new[] { Common.StandardTestData }, false), true);
var executeParams = new QueryExecuteParams { QueryText = "Doesn'tMatter", OwnerUri = Common.OwnerUri };
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
var executeRequest = RequestContextMocks.SetupRequestContextMock<QueryExecuteResult, QueryExecuteCompleteParams>(null, QueryExecuteCompleteEvent.Type, null, null);
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
queryService.ActiveQueries[Common.OwnerUri].HasExecuted = false;
@@ -168,7 +207,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
// ... I have a query that doesn't have any result sets
var queryService = Common.GetPrimedExecutionService(
Common.CreateMockFactory(null, false), true);
var executeParams = new QueryExecuteParams { QueryText = "Doesn'tMatter", OwnerUri = Common.OwnerUri };
var executeParams = new QueryExecuteParams { QueryText = Common.StandardQuery, OwnerUri = Common.OwnerUri };
var executeRequest = RequestContextMocks.SetupRequestContextMock<QueryExecuteResult, QueryExecuteCompleteParams>(null, QueryExecuteCompleteEvent.Type, null, null);
queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait();
@@ -191,7 +230,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
#region Mocking
private Mock<RequestContext<QueryExecuteSubsetResult>> GetQuerySubsetResultContextMock(
private static Mock<RequestContext<QueryExecuteSubsetResult>> GetQuerySubsetResultContextMock(
Action<QueryExecuteSubsetResult> resultCallback,
Action<object> errorCallback)
{
@@ -218,7 +257,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
return requestContext;
}
private void VerifyQuerySubsetCallCount(Mock<RequestContext<QueryExecuteSubsetResult>> mock, Times sendResultCalls,
private static void VerifyQuerySubsetCallCount(Mock<RequestContext<QueryExecuteSubsetResult>> mock, Times sendResultCalls,
Times sendErrorCalls)
{
mock.Verify(rc => rc.SendResult(It.IsAny<QueryExecuteSubsetResult>()), sendResultCalls);