mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Add additional test cases (#125)
Test-only changes for code coverage. Please review the comment and I'll include the changes in the next iteration. * Add more tests * Add some more additional test cases
This commit is contained in:
@@ -94,15 +94,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the array of filepaths dot sourced in this ScriptFile
|
|
||||||
/// </summary>
|
|
||||||
public string[] ReferencedFiles
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -299,9 +290,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
this.FileLines.Insert(currentLineNumber - 1, finalLine);
|
this.FileLines.Insert(currentLineNumber - 1, finalLine);
|
||||||
currentLineNumber++;
|
currentLineNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the script again to be up-to-date
|
|
||||||
this.ParseFileContents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -447,97 +435,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
.Split('\n')
|
.Split('\n')
|
||||||
.Select(line => line.TrimEnd('\r'))
|
.Select(line => line.TrimEnd('\r'))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Parse the contents to get syntax tree and errors
|
|
||||||
this.ParseFileContents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Methods
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses the current file contents to get the AST, tokens,
|
|
||||||
/// and parse errors.
|
|
||||||
/// </summary>
|
|
||||||
private void ParseFileContents()
|
|
||||||
{
|
|
||||||
#if false
|
|
||||||
ParseError[] parseErrors = null;
|
|
||||||
|
|
||||||
// First, get the updated file range
|
|
||||||
int lineCount = this.FileLines.Count;
|
|
||||||
if (lineCount > 0)
|
|
||||||
{
|
|
||||||
this.FileRange =
|
|
||||||
new BufferRange(
|
|
||||||
new BufferPosition(1, 1),
|
|
||||||
new BufferPosition(
|
|
||||||
lineCount + 1,
|
|
||||||
this.FileLines[lineCount - 1].Length + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.FileRange = BufferRange.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if SqlToolsv5r2
|
|
||||||
// This overload appeared with Windows 10 Update 1
|
|
||||||
if (this.SqlToolsVersion.Major >= 5 &&
|
|
||||||
this.SqlToolsVersion.Build >= 10586)
|
|
||||||
{
|
|
||||||
// Include the file path so that module relative
|
|
||||||
// paths are evaluated correctly
|
|
||||||
this.ScriptAst =
|
|
||||||
Parser.ParseInput(
|
|
||||||
this.Contents,
|
|
||||||
this.FilePath,
|
|
||||||
out this.scriptTokens,
|
|
||||||
out parseErrors);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.ScriptAst =
|
|
||||||
Parser.ParseInput(
|
|
||||||
this.Contents,
|
|
||||||
out this.scriptTokens,
|
|
||||||
out parseErrors);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
this.ScriptAst =
|
|
||||||
Parser.ParseInput(
|
|
||||||
this.Contents,
|
|
||||||
out this.scriptTokens,
|
|
||||||
out parseErrors);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
catch (RuntimeException ex)
|
|
||||||
{
|
|
||||||
var parseError =
|
|
||||||
new ParseError(
|
|
||||||
null,
|
|
||||||
ex.ErrorRecord.FullyQualifiedErrorId,
|
|
||||||
ex.Message);
|
|
||||||
|
|
||||||
parseErrors = new[] { parseError };
|
|
||||||
this.scriptTokens = new Token[0];
|
|
||||||
this.ScriptAst = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate parse errors into syntax markers
|
|
||||||
this.SyntaxMarkers =
|
|
||||||
parseErrors
|
|
||||||
.Select(ScriptFileMarker.FromParseError)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
//Get all dot sourced referenced files and store them
|
|
||||||
this.ReferencedFiles =
|
|
||||||
AstOperations.FindDotSourcedIncludes(this.ScriptAst);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost
|
||||||
|
{
|
||||||
|
public class AsyncLockTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task AsyncLockSynchronizesAccess()
|
||||||
|
{
|
||||||
|
AsyncLock asyncLock = new AsyncLock();
|
||||||
|
|
||||||
|
Task<IDisposable> lockOne = asyncLock.LockAsync();
|
||||||
|
Task<IDisposable> lockTwo = asyncLock.LockAsync();
|
||||||
|
|
||||||
|
Assert.Equal(TaskStatus.RanToCompletion, lockOne.Status);
|
||||||
|
Assert.Equal(TaskStatus.WaitingForActivation, lockTwo.Status);
|
||||||
|
lockOne.Result.Dispose();
|
||||||
|
|
||||||
|
await lockTwo;
|
||||||
|
Assert.Equal(TaskStatus.RanToCompletion, lockTwo.Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AsyncLockCancelsWhenRequested()
|
||||||
|
{
|
||||||
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
AsyncLock asyncLock = new AsyncLock();
|
||||||
|
|
||||||
|
Task<IDisposable> lockOne = asyncLock.LockAsync();
|
||||||
|
Task<IDisposable> lockTwo = asyncLock.LockAsync(cts.Token);
|
||||||
|
|
||||||
|
// Cancel the second lock before the first is released
|
||||||
|
cts.Cancel();
|
||||||
|
lockOne.Result.Dispose();
|
||||||
|
|
||||||
|
Assert.Equal(TaskStatus.RanToCompletion, lockOne.Status);
|
||||||
|
Assert.Equal(TaskStatus.Canceled, lockTwo.Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost
|
||||||
|
{
|
||||||
|
public class AsyncQueueTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task AsyncQueueSynchronizesAccess()
|
||||||
|
{
|
||||||
|
ConcurrentBag<int> outputItems = new ConcurrentBag<int>();
|
||||||
|
AsyncQueue<int> inputQueue = new AsyncQueue<int>(Enumerable.Range(0, 100));
|
||||||
|
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Start 5 consumers
|
||||||
|
await Task.WhenAll(
|
||||||
|
Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)),
|
||||||
|
Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)),
|
||||||
|
Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)),
|
||||||
|
Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)),
|
||||||
|
Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)),
|
||||||
|
Task.Run(
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
// Wait for a bit and then add more items to the queue
|
||||||
|
await Task.Delay(250);
|
||||||
|
|
||||||
|
foreach (var i in Enumerable.Range(100, 200))
|
||||||
|
{
|
||||||
|
await inputQueue.EnqueueAsync(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel the waiters
|
||||||
|
cancellationTokenSource.Cancel();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException)
|
||||||
|
{
|
||||||
|
// Do nothing, this is expected.
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, numbers 0 through 299 should be in the outputItems
|
||||||
|
IEnumerable<int> expectedItems = Enumerable.Range(0, 300);
|
||||||
|
Assert.Equal(0, expectedItems.Except(outputItems).Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AsyncQueueSkipsCancelledTasks()
|
||||||
|
{
|
||||||
|
AsyncQueue<int> inputQueue = new AsyncQueue<int>();
|
||||||
|
|
||||||
|
// Queue up a couple of tasks to wait for input
|
||||||
|
CancellationTokenSource cancellationSource = new CancellationTokenSource();
|
||||||
|
Task<int> taskOne = inputQueue.DequeueAsync(cancellationSource.Token);
|
||||||
|
Task<int> taskTwo = inputQueue.DequeueAsync();
|
||||||
|
|
||||||
|
// Cancel the first task and then enqueue a number
|
||||||
|
cancellationSource.Cancel();
|
||||||
|
await inputQueue.EnqueueAsync(1);
|
||||||
|
|
||||||
|
// Did the second task get the number?
|
||||||
|
Assert.Equal(TaskStatus.Canceled, taskOne.Status);
|
||||||
|
Assert.Equal(TaskStatus.RanToCompletion, taskTwo.Status);
|
||||||
|
Assert.Equal(1, taskTwo.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConsumeItems(
|
||||||
|
AsyncQueue<int> inputQueue,
|
||||||
|
ConcurrentBag<int> outputItems,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
int consumedItem = await inputQueue.DequeueAsync(cancellationToken);
|
||||||
|
outputItems.Add(consumedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,502 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ScriptFile test case
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptFileTests
|
||||||
|
{
|
||||||
|
internal static object fileLock = new object();
|
||||||
|
|
||||||
|
private static readonly string query =
|
||||||
|
"SELECT * FROM sys.objects as o1" + Environment.NewLine +
|
||||||
|
"SELECT * FROM sys.objects as o2" + Environment.NewLine +
|
||||||
|
"SELECT * FROM sys.objects as o3" + Environment.NewLine;
|
||||||
|
|
||||||
|
internal static ScriptFile GetTestScriptFile(string initialText = null)
|
||||||
|
{
|
||||||
|
if (initialText == null)
|
||||||
|
{
|
||||||
|
initialText = ScriptFileTests.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
string ownerUri = System.IO.Path.GetTempFileName();
|
||||||
|
|
||||||
|
// Write the query text to a backing file
|
||||||
|
lock (fileLock)
|
||||||
|
{
|
||||||
|
System.IO.File.WriteAllText(ownerUri, initialText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ScriptFile(ownerUri, ownerUri, initialText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate GetLinesInRange with invalid range
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetLinesInRangeWithInvalidRangeTest()
|
||||||
|
{
|
||||||
|
ScriptFile scriptFile = GetTestScriptFile();
|
||||||
|
|
||||||
|
bool exceptionRaised = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(
|
||||||
|
new BufferPosition(1, 0),
|
||||||
|
new BufferPosition(2, 0)));
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
exceptionRaised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(exceptionRaised, "ArgumentOutOfRangeException raised for invalid index");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate GetLinesInRange
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void GetLinesInRangeTest()
|
||||||
|
{
|
||||||
|
ScriptFile scriptFile = GetTestScriptFile();
|
||||||
|
|
||||||
|
string id = scriptFile.Id;
|
||||||
|
Assert.True(!string.IsNullOrWhiteSpace(id));
|
||||||
|
|
||||||
|
BufferRange range =scriptFile.FileRange;
|
||||||
|
Assert.Null(range);
|
||||||
|
|
||||||
|
string[] lines = scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(
|
||||||
|
new BufferPosition(2, 1),
|
||||||
|
new BufferPosition(2, 7)));
|
||||||
|
|
||||||
|
Assert.True(lines.Length == 1, "One line in range");
|
||||||
|
Assert.True(lines[0].Equals("SELECT"), "Range text is correct");
|
||||||
|
|
||||||
|
string[] queryLines = query.Split('\n');
|
||||||
|
|
||||||
|
string line = scriptFile.GetLine(2);
|
||||||
|
Assert.True(queryLines[1].StartsWith(line), "GetLine text is correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetOffsetAtPositionTest()
|
||||||
|
{
|
||||||
|
ScriptFile scriptFile = GetTestScriptFile();
|
||||||
|
int offset = scriptFile.GetOffsetAtPosition(2, 5);
|
||||||
|
Assert.True(offset == 37, "Offset is at expected location");
|
||||||
|
|
||||||
|
BufferPosition position = scriptFile.GetPositionAtOffset(offset);
|
||||||
|
Assert.True(position.Line == 2 && position.Column == 5, "Position is at expected location");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetRangeBetweenOffsetsTest()
|
||||||
|
{
|
||||||
|
ScriptFile scriptFile = GetTestScriptFile();
|
||||||
|
BufferRange range = scriptFile.GetRangeBetweenOffsets(
|
||||||
|
scriptFile.GetOffsetAtPosition(2, 1),
|
||||||
|
scriptFile.GetOffsetAtPosition(2, 7));
|
||||||
|
Assert.NotNull(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplySingleLineInsert()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"This is a test.",
|
||||||
|
"This is a working test.",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 1,
|
||||||
|
EndLine = 1,
|
||||||
|
Offset = 10,
|
||||||
|
EndOffset = 10,
|
||||||
|
InsertString = " working"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplySingleLineReplace()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"This is a potentially broken test.",
|
||||||
|
"This is a working test.",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 1,
|
||||||
|
EndLine = 1,
|
||||||
|
Offset = 11,
|
||||||
|
EndOffset = 29,
|
||||||
|
InsertString = "working"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplySingleLineDelete()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"This is a test of the emergency broadcasting system.",
|
||||||
|
"This is a test.",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 1,
|
||||||
|
EndLine = 1,
|
||||||
|
Offset = 15,
|
||||||
|
EndOffset = 52,
|
||||||
|
InsertString = ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplyMultiLineInsert()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"first\r\nsecond\r\nfifth",
|
||||||
|
"first\r\nsecond\r\nthird\r\nfourth\r\nfifth",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 3,
|
||||||
|
EndLine = 3,
|
||||||
|
Offset = 1,
|
||||||
|
EndOffset = 1,
|
||||||
|
InsertString = "third\r\nfourth\r\n"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplyMultiLineReplace()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"first\r\nsecoXX\r\nXXfth",
|
||||||
|
"first\r\nsecond\r\nthird\r\nfourth\r\nfifth",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 2,
|
||||||
|
EndLine = 3,
|
||||||
|
Offset = 5,
|
||||||
|
EndOffset = 3,
|
||||||
|
InsertString = "nd\r\nthird\r\nfourth\r\nfi"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplyMultiLineReplaceWithRemovedLines()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"first\r\nsecoXX\r\nREMOVE\r\nTHESE\r\nLINES\r\nXXfth",
|
||||||
|
"first\r\nsecond\r\nthird\r\nfourth\r\nfifth",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 2,
|
||||||
|
EndLine = 6,
|
||||||
|
Offset = 5,
|
||||||
|
EndOffset = 3,
|
||||||
|
InsertString = "nd\r\nthird\r\nfourth\r\nfi"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanApplyMultiLineDelete()
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"first\r\nsecond\r\nREMOVE\r\nTHESE\r\nLINES\r\nthird",
|
||||||
|
"first\r\nsecond\r\nthird",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 3,
|
||||||
|
EndLine = 6,
|
||||||
|
Offset = 1,
|
||||||
|
EndOffset = 1,
|
||||||
|
InsertString = ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ThrowsExceptionWithEditOutsideOfRange()
|
||||||
|
{
|
||||||
|
Assert.Throws(
|
||||||
|
typeof(ArgumentOutOfRangeException),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
this.AssertFileChange(
|
||||||
|
"first\r\nsecond\r\nREMOVE\r\nTHESE\r\nLINES\r\nthird",
|
||||||
|
"first\r\nsecond\r\nthird",
|
||||||
|
new FileChange
|
||||||
|
{
|
||||||
|
Line = 3,
|
||||||
|
EndLine = 7,
|
||||||
|
Offset = 1,
|
||||||
|
EndOffset = 1,
|
||||||
|
InsertString = ""
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertFileChange(
|
||||||
|
string initialString,
|
||||||
|
string expectedString,
|
||||||
|
FileChange fileChange)
|
||||||
|
{
|
||||||
|
// Create an in-memory file from the StringReader
|
||||||
|
ScriptFile fileToChange = GetTestScriptFile(initialString);
|
||||||
|
|
||||||
|
// Apply the FileChange and assert the resulting contents
|
||||||
|
fileToChange.ApplyChange(fileChange);
|
||||||
|
Assert.Equal(expectedString, fileToChange.Contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScriptFileGetLinesTests
|
||||||
|
{
|
||||||
|
private ScriptFile scriptFile;
|
||||||
|
|
||||||
|
private const string TestString = "Line One\r\nLine Two\r\nLine Three\r\nLine Four\r\nLine Five";
|
||||||
|
private readonly string[] TestStringLines =
|
||||||
|
TestString.Split(
|
||||||
|
new string[] { "\r\n" },
|
||||||
|
StringSplitOptions.None);
|
||||||
|
|
||||||
|
public ScriptFileGetLinesTests()
|
||||||
|
{
|
||||||
|
this.scriptFile =
|
||||||
|
ScriptFileTests.GetTestScriptFile(
|
||||||
|
"Line One\r\nLine Two\r\nLine Three\r\nLine Four\r\nLine Five\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetWholeLine()
|
||||||
|
{
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(5, 1, 5, 10));
|
||||||
|
|
||||||
|
Assert.Equal(1, lines.Length);
|
||||||
|
Assert.Equal("Line Five", lines[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetMultipleWholeLines()
|
||||||
|
{
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(2, 1, 4, 10));
|
||||||
|
|
||||||
|
Assert.Equal(TestStringLines.Skip(1).Take(3), lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetSubstringInSingleLine()
|
||||||
|
{
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(4, 3, 4, 8));
|
||||||
|
|
||||||
|
Assert.Equal(1, lines.Length);
|
||||||
|
Assert.Equal("ne Fo", lines[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetEmptySubstringRange()
|
||||||
|
{
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(4, 3, 4, 3));
|
||||||
|
|
||||||
|
Assert.Equal(1, lines.Length);
|
||||||
|
Assert.Equal("", lines[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetSubstringInMultipleLines()
|
||||||
|
{
|
||||||
|
string[] expectedLines = new string[]
|
||||||
|
{
|
||||||
|
"Two",
|
||||||
|
"Line Three",
|
||||||
|
"Line Fou"
|
||||||
|
};
|
||||||
|
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(2, 6, 4, 9));
|
||||||
|
|
||||||
|
Assert.Equal(expectedLines, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGetRangeAtLineBoundaries()
|
||||||
|
{
|
||||||
|
string[] expectedLines = new string[]
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"Line Three",
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
string[] lines =
|
||||||
|
this.scriptFile.GetLinesInRange(
|
||||||
|
new BufferRange(2, 9, 4, 1));
|
||||||
|
|
||||||
|
Assert.Equal(expectedLines, lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScriptFilePositionTests
|
||||||
|
{
|
||||||
|
private ScriptFile scriptFile;
|
||||||
|
|
||||||
|
public ScriptFilePositionTests()
|
||||||
|
{
|
||||||
|
this.scriptFile =
|
||||||
|
ScriptFileTests.GetTestScriptFile(@"
|
||||||
|
First line
|
||||||
|
Second line is longer
|
||||||
|
Third line
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanOffsetByLine()
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
1, 1,
|
||||||
|
2, 0,
|
||||||
|
3, 1);
|
||||||
|
|
||||||
|
this.AssertNewPosition(
|
||||||
|
3, 1,
|
||||||
|
-2, 0,
|
||||||
|
1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanOffsetByColumn()
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
2, 1,
|
||||||
|
0, 2,
|
||||||
|
2, 3);
|
||||||
|
|
||||||
|
this.AssertNewPosition(
|
||||||
|
2, 5,
|
||||||
|
0, -3,
|
||||||
|
2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ThrowsWhenPositionOutOfRange()
|
||||||
|
{
|
||||||
|
// Less than line range
|
||||||
|
Assert.Throws(
|
||||||
|
typeof(ArgumentOutOfRangeException),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
scriptFile.CalculatePosition(
|
||||||
|
new BufferPosition(1, 1),
|
||||||
|
-10, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Greater than line range
|
||||||
|
Assert.Throws(
|
||||||
|
typeof(ArgumentOutOfRangeException),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
scriptFile.CalculatePosition(
|
||||||
|
new BufferPosition(1, 1),
|
||||||
|
10, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Less than column range
|
||||||
|
Assert.Throws(
|
||||||
|
typeof(ArgumentOutOfRangeException),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
scriptFile.CalculatePosition(
|
||||||
|
new BufferPosition(1, 1),
|
||||||
|
0, -10);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Greater than column range
|
||||||
|
Assert.Throws(
|
||||||
|
typeof(ArgumentOutOfRangeException),
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
scriptFile.CalculatePosition(
|
||||||
|
new BufferPosition(1, 1),
|
||||||
|
0, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanFindBeginningOfLine()
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
4, 12,
|
||||||
|
pos => pos.GetLineStart(),
|
||||||
|
4, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanFindEndOfLine()
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
4, 12,
|
||||||
|
pos => pos.GetLineEnd(),
|
||||||
|
4, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanComposePositionOperations()
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
4, 12,
|
||||||
|
pos => pos.AddOffset(-1, 1).GetLineStart(),
|
||||||
|
3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertNewPosition(
|
||||||
|
int originalLine, int originalColumn,
|
||||||
|
int lineOffset, int columnOffset,
|
||||||
|
int expectedLine, int expectedColumn)
|
||||||
|
{
|
||||||
|
this.AssertNewPosition(
|
||||||
|
originalLine, originalColumn,
|
||||||
|
pos => pos.AddOffset(lineOffset, columnOffset),
|
||||||
|
expectedLine, expectedColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertNewPosition(
|
||||||
|
int originalLine, int originalColumn,
|
||||||
|
Func<FilePosition, FilePosition> positionOperation,
|
||||||
|
int expectedLine, int expectedColumn)
|
||||||
|
{
|
||||||
|
var newPosition =
|
||||||
|
positionOperation(
|
||||||
|
new FilePosition(
|
||||||
|
this.scriptFile,
|
||||||
|
originalLine,
|
||||||
|
originalColumn));
|
||||||
|
|
||||||
|
Assert.Equal(expectedLine, newPosition.Line);
|
||||||
|
Assert.Equal(expectedColumn, newPosition.Column);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,8 +62,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Driver
|
|||||||
{
|
{
|
||||||
coverageOutput = "coverage.xml";
|
coverageOutput = "coverage.xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceHostArguments = "-target:" + serviceHostExecutable + " -targetargs:" + serviceHostArguments
|
serviceHostArguments = "-mergeoutput -target:" + serviceHostExecutable + " -targetargs:" + serviceHostArguments
|
||||||
+ " -register:user -oldstyle -filter:\"+[Microsoft.SqlTools.*]* -[xunit*]*\" -output:" + coverageOutput + " -searchdirs:" + serviceHostDirectory;
|
+ " -register:user -oldstyle -filter:\"+[Microsoft.SqlTools.*]* -[xunit*]*\" -output:" + coverageOutput + " -searchdirs:" + serviceHostDirectory;
|
||||||
serviceHostExecutable = coverageToolPath;
|
serviceHostExecutable = coverageToolPath;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ using System.Reflection;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
|
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver
|
namespace Microsoft.SqlTools.ServiceLayer.TestDriver
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Language Service end-to-end integration tests
|
||||||
|
/// </summary>
|
||||||
|
public class ConnectionTests : TestBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Try to connect with invalid credentials
|
||||||
|
/// </summary>
|
||||||
|
//[Fact]
|
||||||
|
public async Task InvalidConnection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string ownerUri = System.IO.Path.GetTempFileName();
|
||||||
|
bool connected = await Connect(ownerUri, ConnectionTestUtils.InvalidConnection);
|
||||||
|
Assert.False(connected, "Invalid connection is failed to connect");
|
||||||
|
|
||||||
|
await Disconnect(ownerUri);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
WaitForExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -155,7 +155,6 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
|
|
||||||
string query = "SELECT *** FROM sys.objects";
|
string query = "SELECT *** FROM sys.objects";
|
||||||
|
|
||||||
|
|
||||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||||
{
|
{
|
||||||
TextDocument = new TextDocumentItem()
|
TextDocument = new TextDocumentItem()
|
||||||
@@ -168,7 +167,6 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
await RequestOpenDocumentNotification(openParams);
|
await RequestOpenDocumentNotification(openParams);
|
||||||
|
|
||||||
|
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,52 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility;
|
using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||||
{
|
{
|
||||||
public class QueryExecutionTests : TestBase
|
public class QueryExecutionTests : TestBase
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteBasicQueryTest()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string ownerUri = System.IO.Path.GetTempFileName();
|
||||||
|
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||||
|
Assert.True(connected, "Connection is successful");
|
||||||
|
|
||||||
|
Thread.Sleep(500);
|
||||||
|
|
||||||
|
string query = "SELECT * FROM sys.objects";
|
||||||
|
|
||||||
|
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||||
|
{
|
||||||
|
TextDocument = new TextDocumentItem()
|
||||||
|
{
|
||||||
|
Uri = ownerUri,
|
||||||
|
LanguageId = "enu",
|
||||||
|
Version = 1,
|
||||||
|
Text = query
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await RequestOpenDocumentNotification(openParams);
|
||||||
|
|
||||||
|
var queryResult = await RunQuery(ownerUri, query);
|
||||||
|
|
||||||
|
Assert.NotNull(queryResult);
|
||||||
|
Assert.NotNull(queryResult.BatchSummaries);
|
||||||
|
|
||||||
|
await Disconnect(ownerUri);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
WaitForExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//[Fact]
|
//[Fact]
|
||||||
public async Task TestQueryingAfterCompletionRequests()
|
public async Task TestQueryingAfterCompletionRequests()
|
||||||
{
|
{
|
||||||
@@ -27,7 +67,6 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
|
|
||||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||||
|
|
||||||
|
|
||||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(RequestCompletion(ownerUri, query, 0, 10)));
|
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(RequestCompletion(ownerUri, query, 0, 10)));
|
||||||
var queryTask = RunQuery(ownerUri, query);
|
var queryTask = RunQuery(ownerUri, query);
|
||||||
tasks.Add(queryTask);
|
tasks.Add(queryTask);
|
||||||
|
|||||||
Reference in New Issue
Block a user