//
// 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.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
{
///
/// Scripting service end-to-end integration tests that use the SqlScriptPublishModel type to generate scripts.
///
public class SqlScriptPublishModelTests : IClassFixture
{
public SqlScriptPublishModelTests(ScriptingFixture scriptingFixture)
{
this.Fixture = scriptingFixture;
}
public ScriptingFixture Fixture { get; private set; }
public SqlTestDb Northwind { get { return this.Fixture.Database; } }
[Fact]
public async Task ListSchemaObjects()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingListObjectsParams requestParams = new ScriptingListObjectsParams
{
ConnectionString = this.Northwind.ConnectionString,
};
ScriptingListObjectsResult result = await testService.ListScriptingObjects(requestParams);
ScriptingListObjectsCompleteParams completeParameters = await testService.Driver.WaitForEvent(ScriptingListObjectsCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.Equal(ScriptingFixture.ObjectCountWithoutDatabase, completeParameters.DatabaseObjects.Count);
}
}
[Fact]
public async Task ScriptDatabaseSchema()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaOnly",
},
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingPlanNotificationParams planEvent = await testService.Driver.WaitForEvent(ScriptingPlanNotificationEvent.Type, TimeSpan.FromSeconds(30));
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.True(parameters.Success);
Assert.Equal(ScriptingFixture.ObjectCountWithDatabase, planEvent.Count);
Assert.True(File.Exists(tempFile.FilePath));
Assert.True(new FileInfo(tempFile.FilePath).Length > 0);
}
}
[Fact]
public async Task ScriptDatabaseSchemaAndData()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaAndData",
},
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingPlanNotificationParams planEvent = await testService.Driver.WaitForEvent(ScriptingPlanNotificationEvent.Type, TimeSpan.FromSeconds(30));
ScriptingCompleteParams completeParameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.True(completeParameters.Success);
Assert.Equal(ScriptingFixture.ObjectCountWithDatabase, planEvent.Count);
Assert.True(File.Exists(tempFile.FilePath));
Assert.True(new FileInfo(tempFile.FilePath).Length > 0);
}
}
[Fact]
public async Task ScriptTable()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaOnly",
},
ScriptingObjects = new List
{
new ScriptingObject
{
Type = "Table",
Schema = "dbo",
Name = "Customers",
},
}
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingPlanNotificationParams planEvent = await testService.Driver.WaitForEvent(ScriptingPlanNotificationEvent.Type, TimeSpan.FromSeconds(30));
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.True(parameters.Success);
Assert.Equal(2, planEvent.Count);
Assert.True(File.Exists(tempFile.FilePath));
Assert.True(new FileInfo(tempFile.FilePath).Length > 0);
}
}
[Fact]
public async Task ScriptTableUsingIncludeFilter()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaOnly",
},
IncludeObjectCriteria = new List
{
new ScriptingObject
{
Type = "Table",
Schema = "dbo",
Name = "Customers",
},
}
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingPlanNotificationParams planEvent = await testService.Driver.WaitForEvent(ScriptingPlanNotificationEvent.Type, TimeSpan.FromSeconds(30));
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.True(parameters.Success);
Assert.Equal(2, planEvent.Count);
Assert.True(File.Exists(tempFile.FilePath));
Assert.True(new FileInfo(tempFile.FilePath).Length > 0);
}
}
[Fact]
public async Task ScriptTableAndData()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaAndData",
},
ScriptingObjects = new List
{
new ScriptingObject
{
Type = "Table",
Schema = "dbo",
Name = "Customers",
},
}
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingPlanNotificationParams planEvent = await testService.Driver.WaitForEvent(ScriptingPlanNotificationEvent.Type, TimeSpan.FromSeconds(30));
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(30));
Assert.True(parameters.Success);
Assert.Equal(2, planEvent.Count);
Assert.True(File.Exists(tempFile.FilePath));
Assert.True(new FileInfo(tempFile.FilePath).Length > 0);
}
}
[Fact]
public async Task ScriptTableDoesNotExist()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaOnly",
},
ScriptingObjects = new List
{
new ScriptingObject
{
Type = "Table",
Schema = "dbo",
Name = "TableDoesNotExist",
},
}
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(15));
Assert.True(parameters.HasError);
Assert.Equal("An error occurred while scripting the objects.", parameters.ErrorMessage);
Assert.Contains("The Table '[dbo].[TableDoesNotExist]' does not exist on the server.", parameters.ErrorDetails);
}
}
[Fact]
public async Task ScriptSchemaCancel()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = this.Northwind.ConnectionString,
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaAndData",
},
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingCancelResult cancelResult = await testService.CancelScript(result.OperationId);
ScriptingCompleteParams cancelEvent = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(10));
Assert.True(cancelEvent.Canceled);
}
}
[Fact]
public async Task ScriptSchemaInvalidConnectionString()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = tempFile.FilePath,
ConnectionString = "I'm an invalid connection string",
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaAndData",
},
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(10));
Assert.True(parameters.HasError);
Assert.Equal("Error parsing ScriptingParams.ConnectionString property.", parameters.ErrorMessage);
}
}
[Fact]
public async Task ScriptSchemaInvalidFilePath()
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
{
ScriptingParams requestParams = new ScriptingParams
{
FilePath = "This path doesn't event exist",
ConnectionString = "Server=Temp;Database=Temp;User Id=Temp;Password=Temp",
ScriptOptions = new ScriptOptions
{
TypeOfDataToScript = "SchemaAndData",
},
};
ScriptingResult result = await testService.Script(requestParams);
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(10));
Assert.True(parameters.HasError);
Assert.Equal("Invalid directory specified by the ScriptingParams.FilePath property.", parameters.ErrorMessage);
}
}
public void Dispose() { }
public class ScriptingFixture : IDisposable
{
public ScriptingFixture()
{
this.Database = SqlTestDb.CreateNew(TestServerType.OnPrem);
this.Database.RunQuery(Scripts.CreateNorthwindSchema, throwOnError: true);
Console.WriteLine("Northwind setup complete, database name: {0}", this.Database.DatabaseName);
}
///
/// The count of object when scripting the entire database including the database object.
///
public const int ObjectCountWithDatabase = 46;
///
/// The count of objects when scripting the entire database excluding the database object.
///
public const int ObjectCountWithoutDatabase = 45;
public SqlTestDb Database { get; private set; }
public void Dispose()
{
if (this.Database != null)
{
Console.WriteLine("Northwind cleanup, deleting database name: {0}", this.Database.DatabaseName);
this.Database.Dispose();
}
}
}
}
}