2021-11-03 00:28:09 +03:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// Licensed under the MIT License.
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using Microsoft.SqlServer.Dac.Model;
|
|
|
|
using NUnit.Framework;
|
|
|
|
|
|
|
|
namespace Microsoft.Build.Sql.Tests
|
|
|
|
{
|
|
|
|
[TestFixture]
|
2022-11-09 22:49:52 +03:00
|
|
|
public class BuildTests : DotnetTestBase
|
2021-11-03 00:28:09 +03:00
|
|
|
{
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies simple build with default settings.")]
|
|
|
|
public void SuccessfulSimpleBuild()
|
|
|
|
{
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with pre-deployment script.")]
|
|
|
|
public void SuccessfulBuildWithPreDeployScript()
|
|
|
|
{
|
|
|
|
this.AddPreDeployScripts("Script.PreDeployment1.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage(expectPreDeployScript: true);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with post-deployment script.")]
|
|
|
|
public void SuccessfulBuildWithPostDeployScript()
|
|
|
|
{
|
|
|
|
this.AddPostDeployScripts("Script.PostDeployment1.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage(expectPostDeployScript: true);
|
|
|
|
}
|
|
|
|
|
2024-07-09 07:32:15 +03:00
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with deployment extension configuration script.")]
|
|
|
|
public void SuccessfulBuildWithDeploymentExtensionConfigurationScript()
|
|
|
|
{
|
|
|
|
this.RemoveBuildFiles("Table2.sql");
|
|
|
|
this.AddDeploymentExtensionConfigurationScripts("Table2.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
// Verify the Table2 is not part of the model
|
|
|
|
using (TSqlModel model = new TSqlModel(this.GetDacpacPath()))
|
|
|
|
{
|
|
|
|
var tables = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table);
|
|
|
|
Assert.IsTrue(tables.Any(), "Expected at least 1 table in the model.");
|
|
|
|
foreach (var table in tables)
|
|
|
|
{
|
|
|
|
if (table.Name.ToString().IndexOf("Table2", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
|
|
{
|
|
|
|
Assert.Fail("Table2 should have been excluded from the model.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with build extension configuration script.")]
|
|
|
|
public void SuccessfulBuildWithBuildExtensionConfigurationScript()
|
|
|
|
{
|
|
|
|
this.RemoveBuildFiles("Table2.sql");
|
|
|
|
this.AddBuildExtensionConfigurationScripts("Table2.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
// Verify the Table2 is not part of the model
|
|
|
|
using (TSqlModel model = new TSqlModel(this.GetDacpacPath()))
|
|
|
|
{
|
|
|
|
var tables = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table);
|
|
|
|
Assert.IsTrue(tables.Any(), "Expected at least 1 table in the model.");
|
|
|
|
foreach (var table in tables)
|
|
|
|
{
|
|
|
|
if (table.Name.ToString().IndexOf("Table2", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
|
|
{
|
|
|
|
Assert.Fail("Table2 should have been excluded from the model.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-03 00:28:09 +03:00
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with excluding file from project.")]
|
|
|
|
public void BuildWithExclude()
|
|
|
|
{
|
|
|
|
this.RemoveBuildFiles("Table2.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
// Verify the excluded Table2 is not part of the model
|
|
|
|
using (TSqlModel model = new TSqlModel(this.GetDacpacPath()))
|
|
|
|
{
|
|
|
|
var tables = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table);
|
|
|
|
Assert.IsTrue(tables.Any(), "Expected at least 1 table in the model.");
|
|
|
|
foreach (var table in tables)
|
|
|
|
{
|
|
|
|
if (table.Name.ToString().IndexOf("Table2", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
|
|
{
|
|
|
|
Assert.Fail("Table2 should have been excluded from the model.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with including file from outside project folder.")]
|
|
|
|
public void BuildWithIncludeExternalFile()
|
|
|
|
{
|
|
|
|
// Generate a new file
|
|
|
|
string tempFile = Path.Combine(Path.GetTempPath(), "test.sql");
|
|
|
|
if (File.Exists(tempFile))
|
|
|
|
{
|
|
|
|
File.Delete(tempFile);
|
|
|
|
}
|
|
|
|
File.WriteAllText(tempFile, "CREATE TABLE [dbo].[Table2] ( C1 INT NOT NULL )");
|
|
|
|
|
|
|
|
// Include the file in project build
|
|
|
|
this.AddBuildFiles(tempFile);
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
// Verify the Table2 is included in the model
|
|
|
|
using (TSqlModel model = new TSqlModel(this.GetDacpacPath()))
|
|
|
|
{
|
|
|
|
var tables = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table);
|
|
|
|
bool found = false;
|
|
|
|
foreach (var table in tables)
|
|
|
|
{
|
|
|
|
if (table.Name.ToString().IndexOf("Table2", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Assert.IsTrue(found, "Table2 is supposed to be included in model but not found.");
|
|
|
|
File.Delete(tempFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build fails when a script references an object not defined by other scripts in the project.")]
|
|
|
|
public void VerifyBuildFailureWithUnresolvedReference()
|
|
|
|
{
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-03 00:28:09 +03:00
|
|
|
|
|
|
|
// Verify failure
|
|
|
|
Assert.AreEqual(1, exitCode, "Build is expected to fail.");
|
|
|
|
}
|
2021-11-08 22:03:16 +03:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with a project reference.")]
|
|
|
|
public void VerifyBuildWithProjectReference()
|
|
|
|
{
|
2023-01-27 21:57:55 +03:00
|
|
|
// We will copy the ReferenceProj to a temp folder and then add it as project reference
|
2024-08-06 01:26:41 +03:00
|
|
|
string tempFolder = TestUtils.CreateTempDirectory();
|
2023-01-27 21:57:55 +03:00
|
|
|
TestUtils.CopyDirectoryRecursive(Path.Combine(this.CommonTestDataDirectory, "ReferenceProj"), tempFolder);
|
2021-11-08 22:03:16 +03:00
|
|
|
|
|
|
|
this.AddProjectReference(Path.Combine(tempFolder, "ReferenceProj.sqlproj"));
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-08 22:03:16 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
Directory.Delete(tempFolder, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Verifies build with a project reference where the referenced project is inside the current folder.")]
|
|
|
|
public void VerifyBuildWithProjectReferenceInSubdirectory()
|
|
|
|
{
|
|
|
|
this.AddProjectReference("ReferenceProj/ReferenceProj.sqlproj");
|
|
|
|
|
|
|
|
// Since reference proj is in a subdirectory it gets picked up by default globbing pattern, excluding it here
|
|
|
|
this.RemoveBuildFiles("ReferenceProj/**/*.*");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2021-11-08 22:03:16 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
}
|
2022-04-28 20:11:54 +03:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Issue #88: Verifies build with a .sql file that is included as None should not be part of schema.")]
|
|
|
|
public void VerifyBuildWithNoneIncludeSqlFile()
|
|
|
|
{
|
|
|
|
// Table2.sql is included for build by default, specifying it as <None Include...> should remove it from build.
|
|
|
|
this.AddNoneScripts("Table2.sql");
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
2022-11-09 22:49:52 +03:00
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
2022-04-28 20:11:54 +03:00
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
|
|
|
|
// Verify the excluded Table2 is not part of the model
|
|
|
|
using (TSqlModel model = new TSqlModel(this.GetDacpacPath()))
|
|
|
|
{
|
|
|
|
var tables = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table);
|
|
|
|
Assert.IsTrue(tables.Any(), "Expected at least 1 table in the model.");
|
|
|
|
foreach (var table in tables)
|
|
|
|
{
|
|
|
|
if (table.Name.ToString().IndexOf("Table2", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
|
|
{
|
|
|
|
Assert.Fail("Table2 should have been excluded from the model.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-29 21:08:50 +03:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Description("Issue #316: Verifies build with central package management turned on.")]
|
|
|
|
public void VerifyBuildWithCentralPackageManagement()
|
|
|
|
{
|
|
|
|
ProjectUtils.AddProperties(this.GetProjectFilePath(), new Dictionary<string, string>()
|
|
|
|
{
|
|
|
|
{ "ManagePackageVersionsCentrally", "True" }
|
|
|
|
});
|
|
|
|
|
|
|
|
string stdOutput, stdError;
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out stdOutput, out stdError);
|
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
}
|
2024-02-16 20:32:50 +03:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
// https://github.com/microsoft/DacFx/issues/278
|
|
|
|
public void VerifyBuildWithTransitiveProjectReferences()
|
|
|
|
{
|
|
|
|
string projectA = Path.Combine(WorkingDirectory, "A", "A.sqlproj");
|
|
|
|
string projectB = Path.Combine(WorkingDirectory, "B", "B.sqlproj");
|
|
|
|
|
|
|
|
// Add A.sqlproj as a reference in B.sqlproj
|
|
|
|
ProjectUtils.AddItemGroup(projectB, "ProjectReference", new string[] { projectA });
|
|
|
|
|
|
|
|
// Add B.sqlproj as a reference in the main project
|
|
|
|
this.AddProjectReference(projectB);
|
|
|
|
|
|
|
|
// Build and verify a.dacpac is copied to the output directory
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out string stdOutput, out string stdError);
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
FileAssert.Exists(Path.Combine(this.GetOutputDirectory(), "A.dacpac"));
|
|
|
|
FileAssert.Exists(Path.Combine(this.GetOutputDirectory(), "B.dacpac"));
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[TestCase("net46")]
|
|
|
|
[TestCase("net461")]
|
|
|
|
[TestCase("net462")]
|
|
|
|
[TestCase("net47")]
|
|
|
|
[TestCase("net471")]
|
|
|
|
[TestCase("net472")]
|
|
|
|
[TestCase("net48")]
|
|
|
|
[TestCase("net481")]
|
|
|
|
[TestCase("netstandard2.1")]
|
|
|
|
[TestCase("netcoreapp3.1")]
|
|
|
|
[TestCase("net5.0")]
|
|
|
|
[TestCase("net6.0")]
|
|
|
|
#if NET7_0_OR_GREATER
|
|
|
|
[TestCase("net7.0")]
|
|
|
|
#endif
|
|
|
|
#if NET8_0_OR_GREATER
|
|
|
|
[TestCase("net8.0")]
|
2024-05-16 22:50:18 +03:00
|
|
|
#endif
|
|
|
|
#if NET9_0_OR_GREATER
|
|
|
|
[TestCase("net9.0")]
|
2024-02-16 20:32:50 +03:00
|
|
|
#endif
|
|
|
|
// https://github.com/microsoft/DacFx/issues/330
|
|
|
|
public void VerifyBuildWithDifferentTargetFrameworks(string targetFramework)
|
|
|
|
{
|
|
|
|
ProjectUtils.AddProperties(this.GetProjectFilePath(), new Dictionary<string, string>()
|
|
|
|
{
|
|
|
|
{ "TargetFramework", targetFramework }
|
|
|
|
});
|
|
|
|
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out string stdOutput, out string stdError);
|
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
this.VerifyDacPackage();
|
|
|
|
}
|
2024-03-05 00:50:20 +03:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
// https://github.com/microsoft/DacFx/issues/117
|
|
|
|
public void VerifyBuildWithReleaseConfiguration()
|
|
|
|
{
|
|
|
|
ProjectUtils.AddProperties(this.GetProjectFilePath(), new Dictionary<string, string>()
|
|
|
|
{
|
|
|
|
{ "Configuration", "Release" }
|
|
|
|
});
|
|
|
|
|
|
|
|
int exitCode = this.RunDotnetCommandOnProject("build", out string stdOutput, out string stdError);
|
|
|
|
|
|
|
|
// Verify success
|
|
|
|
Assert.AreEqual(0, exitCode, "Build failed with error " + stdError);
|
|
|
|
Assert.AreEqual(string.Empty, stdError);
|
|
|
|
FileAssert.Exists(Path.Combine(WorkingDirectory, "bin", "Release", DatabaseProjectName + ".dacpac"));
|
|
|
|
}
|
2021-11-03 00:28:09 +03:00
|
|
|
}
|
|
|
|
}
|