//
// 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 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 NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
{
///
/// Test class for the test binding context
///
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; }
}
///
/// Tests for the Binding Queue
///
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 bindingQueue = null;
private void InitializeTestSettings()
{
this.bindCallCount = 0;
this.timeoutCallCount = 0;
this.bindCallbackDelay = 10;
this.isCancelationRequested = false;
this.bindingContext = GetMockBindingContext();
this.bindingQueue = new BindingQueue();
}
private IBindingContext GetMockBindingContext()
{
return new TestBindingContext();
}
///
/// Test bind operation callback
///
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];
}
///
/// Test callback for the bind timeout operation
///
private object TestTimeoutOperation(
IBindingContext bindingContext)
{
++this.timeoutCallCount;
return new CompletionItem[0];
}
///
/// Queues a single task
///
[Test]
public void QueueOneBindingOperationTest()
{
InitializeTestSettings();
this.bindingQueue.QueueBindingOperation(
key: "testkey",
bindOperation: TestBindOperation,
timeoutOperation: TestTimeoutOperation);
Thread.Sleep(1000);
this.bindingQueue.StopQueueProcessor(15000);
Assert.AreEqual(1, this.bindCallCount);
Assert.AreEqual(0, this.timeoutCallCount);
Assert.False(this.isCancelationRequested);
}
///
/// Queues a single task
///
[Test]
public void QueueWithUnhandledExceptionTest()
{
InitializeTestSettings();
bool isExceptionHandled = false;
object defaultReturnObject = new object();
var queueItem = this.bindingQueue.QueueBindingOperation(
key: "testkey",
bindOperation: (context, CancellationToken) => { throw new Exception("Unhandled!!"); },
timeoutOperation: TestTimeoutOperation,
errorHandler: (exception) => {
isExceptionHandled = true;
return defaultReturnObject;
});
queueItem.ItemProcessed.WaitOne(10000);
this.bindingQueue.StopQueueProcessor(15000);
Assert.True(isExceptionHandled);
var result = queueItem.GetResultAsT