Files
sqltoolsservice/test/Microsoft.SqlTools.ServiceLayer.UnitTests/LanguageServer/BindingQueueTests.cs
Benjamin Russell 1166778249 Isolate Shared Test Code (#252)
The goal of this make sure that test code is correctly organized to ensure that test suites aren't dependent on each other.
* UnitTests get their own project now (renaming Microsoft.SqlTools.ServiceLayer.Test to Microsoft.SqlTools.ServiceLayer.UnitTests) which is about 90% of the changes to the files.
* IntegrationTests no longer depends on UnitTests, only Test.Common
* Any shared components from TestObjects that spins up a "live" connection has been moved to IntegrationTests Utility/LiveConnectionHelper.cs
* The dictionary-based mock file stream factory has been moved to Test.Common since it is used by UnitTests and IntegrationTests
    * Added a overload that doesn't take a dictionary for when we don't care about monitoring the storage (about 90% of the time)
* The RunIf* wrapper methods have been moved to Test.Common
* OwnerUri and StandardQuery constants have been moved to Test.Common Constants file

* Updating to latest SDK version available at https://www.microsoft.com/net/core#windowscmd

* Moving unit tests to unit test folder

* Changing namespaces to UnitTests

* Moving some constants and shared functionality into common project, making the UnitTests reference it

* Unit tests are working!

* Integration tests are working

* Updating automated test runs

* Fixing one last broken unit test

* Exposing internals for other projects

* Moving edit data tests to UnitTest project

* Applying refactor fixes to unit tests

* Fixing flaky test that wasn't awaiting completion
2017-03-02 13:00:31 -08:00

187 lines
5.6 KiB
C#

//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Threading;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.SmoMetadataProvider;
using Microsoft.SqlServer.Management.SqlParser.Binder;
using Microsoft.SqlServer.Management.SqlParser.Common;
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
using Microsoft.SqlServer.Management.SqlParser.Parser;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
{
/// <summary>
/// Test class for the test binding context
/// </summary>
public class TestBindingContext : IBindingContext
{
public TestBindingContext()
{
this.BindingLock = new ManualResetEvent(true);
this.BindingTimeout = 3000;
}
public bool IsConnected { get; set; }
public ServerConnection ServerConnection { get; set; }
public MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; }
public SmoMetadataProvider SmoMetadataProvider { get; set; }
public IBinder Binder { get; set; }
public ManualResetEvent BindingLock { get; set; }
public int BindingTimeout { get; set; }
public ParseOptions ParseOptions { get; }
public ServerVersion ServerVersion { get; }
public DatabaseEngineType DatabaseEngineType { get; }
public TransactSqlVersion TransactSqlVersion { get; }
public DatabaseCompatibilityLevel DatabaseCompatibilityLevel { get; }
}
/// <summary>
/// Tests for the Binding Queue
/// </summary>
public class BindingQueueTests
{
private int bindCallCount = 0;
private int timeoutCallCount = 0;
private int bindCallbackDelay = 0;
private bool isCancelationRequested = false;
private IBindingContext bindingContext = null;
private BindingQueue<TestBindingContext> bindingQueue = null;
private void InitializeTestSettings()
{
this.bindCallCount = 0;
this.timeoutCallCount = 0;
this.bindCallbackDelay = 10;
this.isCancelationRequested = false;
this.bindingContext = GetMockBindingContext();
this.bindingQueue = new BindingQueue<TestBindingContext>();
}
private IBindingContext GetMockBindingContext()
{
return new TestBindingContext();
}
/// <summary>
/// Test bind operation callback
/// </summary>
private object TestBindOperation(
IBindingContext bindContext,
CancellationToken cancelToken)
{
cancelToken.WaitHandle.WaitOne(this.bindCallbackDelay);
this.isCancelationRequested = cancelToken.IsCancellationRequested;
if (!this.isCancelationRequested)
{
++this.bindCallCount;
}
return new CompletionItem[0];
}
/// <summary>
/// Test callback for the bind timeout operation
/// </summary>
private object TestTimeoutOperation(
IBindingContext bindingContext)
{
++this.timeoutCallCount;
return new CompletionItem[0];
}
/// <summary>
/// Queues a single task
/// </summary>
[Fact]
public void QueueOneBindingOperationTest()
{
InitializeTestSettings();
this.bindingQueue.QueueBindingOperation(
key: "testkey",
bindOperation: TestBindOperation,
timeoutOperation: TestTimeoutOperation);
Thread.Sleep(1000);
this.bindingQueue.StopQueueProcessor(15000);
Assert.True(this.bindCallCount == 1);
Assert.True(this.timeoutCallCount == 0);
Assert.False(this.isCancelationRequested);
}
/// <summary>
/// Queue a 100 short tasks
/// </summary>
[Fact]
public void Queue100BindingOperationTest()
{
InitializeTestSettings();
for (int i = 0; i < 100; ++i)
{
this.bindingQueue.QueueBindingOperation(
key: "testkey",
bindOperation: TestBindOperation,
timeoutOperation: TestTimeoutOperation);
}
Thread.Sleep(2000);
this.bindingQueue.StopQueueProcessor(15000);
Assert.True(this.bindCallCount == 100);
Assert.True(this.timeoutCallCount == 0);
Assert.False(this.isCancelationRequested);
}
/// <summary>
/// Queue an task with a long operation causing a timeout
/// </summary>
[Fact]
public void QueueWithTimeout()
{
InitializeTestSettings();
this.bindCallbackDelay = 1000;
this.bindingQueue.QueueBindingOperation(
key: "testkey",
bindingTimeout: bindCallbackDelay / 2,
bindOperation: TestBindOperation,
timeoutOperation: TestTimeoutOperation);
Thread.Sleep(this.bindCallbackDelay + 100);
this.bindingQueue.StopQueueProcessor(15000);
Assert.True(this.bindCallCount == 0);
Assert.True(this.timeoutCallCount == 1);
Assert.True(this.isCancelationRequested);
}
}
}