From 1c5840e2d03a24d3c797d7cce86fb4278bd0e097 Mon Sep 17 00:00:00 2001 From: "Erik A. Brandstadmoen" Date: Sun, 25 Feb 2024 16:16:20 +0100 Subject: [PATCH] Add tests on the build, trimmed, self-contained command-line binaries .Net gets more and more trimming and compiling features going forward, and, if we e.g. should replace System.Commandline, which never seems to get out of beta, with another command-line parsing library, I feel much more confident doing this if we have a lot of tests on the packaged an build binaries too, in addition to the DLLs directly. I reused the existing unit tests, being a bit creative with the .csproj files and includes. I _hope_ it is a good idea, and that we don't have to duplicate up any new tests we should write on the migrations for both DLLs/libraries and command-line. Including the files should make the tests be available for both automagically. * Add test projects for all databases for compiled command-line grate executable * Add running of these tests to the Build and Release build pipeline * Extracted unit test project imports to separate .targets file --- .github/workflows/build.yml | 154 +++++++++++++----- .gitignore | 2 + Directory.Packages.props | 1 + grate.sln | 96 +++++++++++ .../Configuration/FoldersConfiguration.cs | 2 + .../Configuration/MigrationsFolder.cs | 2 + .../Infrastructure/GrateEnvironment.cs | 1 + src/grate.core/grate.core.csproj | 5 + src/grate/grate.csproj | 6 + .../CommandLine.Common.csproj | 40 +++++ .../GrateExecutablePathAttribute.cs | 8 + .../CommandLine/CommandLine.Common/Startup.cs | 40 +++++ .../CommandLineGrateMigrator.cs | 136 ++++++++++++++++ .../CommandLineTestFramework.cs | 48 ++++++ .../CommandlineGrateTestContext.cs | 39 +++++ .../CommandLine.MariaDB.csproj | 36 ++++ .../Failing_Scripts.cs | 24 +++ .../One_time_scripts.cs | 58 +++++++ .../CommandLine.MariaDB/Startup.cs | 12 ++ .../CommandLine.Oracle.csproj | 36 ++++ .../Failing_Scripts.cs | 23 +++ .../One_time_scripts.cs | 59 +++++++ .../CommandLine/CommandLine.Oracle/Startup.cs | 13 ++ .../CommandLine.PostgreSQL.csproj | 36 ++++ .../Failing_Scripts.cs | 23 +++ .../One_time_scripts.cs | 56 +++++++ .../CommandLine.PostgreSQL/Startup.cs | 13 ++ .../CommandLine.SqlServer.csproj | 36 ++++ .../Failing_Scripts.cs | 23 +++ .../One_time_scripts.cs | 56 +++++++ .../CommandLine.SqlServer/Startup.cs | 13 ++ .../CommandLine.Sqlite.csproj | 36 ++++ .../Failing_Scripts.cs | 23 +++ .../One_time_scripts.cs | 56 +++++++ .../CommandLine/CommandLine.Sqlite/Startup.cs | 13 ++ unittests/CommandLine/IncludeTests.targets | 24 +++ .../MariaDbGrateTestContext.cs | 1 + .../OracleGrateTestContext.cs | 1 + .../PostgreSqlGrateTestContext.cs | 1 + .../SqlServerGrateTestContext.cs | 1 + .../SqlServerGrateTestContext.cs | 1 + .../SqliteGrateTestContext.cs | 1 + .../Failing_Scripts.cs | 6 +- .../One_time_scripts.cs | 2 +- .../GrateMigratorExtensions.cs | 5 - .../TestInfrastructure/IGrateTestContext.cs | 4 +- .../TestInfrastructure/TestConfig.cs | 5 + 47 files changed, 1223 insertions(+), 54 deletions(-) create mode 100644 unittests/CommandLine/CommandLine.Common/CommandLine.Common.csproj create mode 100644 unittests/CommandLine/CommandLine.Common/GrateExecutablePathAttribute.cs create mode 100644 unittests/CommandLine/CommandLine.Common/Startup.cs create mode 100644 unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineGrateMigrator.cs create mode 100644 unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineTestFramework.cs create mode 100644 unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandlineGrateTestContext.cs create mode 100644 unittests/CommandLine/CommandLine.MariaDB/CommandLine.MariaDB.csproj create mode 100644 unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/Failing_Scripts.cs create mode 100644 unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/One_time_scripts.cs create mode 100644 unittests/CommandLine/CommandLine.MariaDB/Startup.cs create mode 100644 unittests/CommandLine/CommandLine.Oracle/CommandLine.Oracle.csproj create mode 100644 unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/Failing_Scripts.cs create mode 100644 unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/One_time_scripts.cs create mode 100644 unittests/CommandLine/CommandLine.Oracle/Startup.cs create mode 100644 unittests/CommandLine/CommandLine.PostgreSQL/CommandLine.PostgreSQL.csproj create mode 100644 unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/Failing_Scripts.cs create mode 100644 unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/One_time_scripts.cs create mode 100644 unittests/CommandLine/CommandLine.PostgreSQL/Startup.cs create mode 100644 unittests/CommandLine/CommandLine.SqlServer/CommandLine.SqlServer.csproj create mode 100644 unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/Failing_Scripts.cs create mode 100644 unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/One_time_scripts.cs create mode 100644 unittests/CommandLine/CommandLine.SqlServer/Startup.cs create mode 100644 unittests/CommandLine/CommandLine.Sqlite/CommandLine.Sqlite.csproj create mode 100644 unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/Failing_Scripts.cs create mode 100644 unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/One_time_scripts.cs create mode 100644 unittests/CommandLine/CommandLine.Sqlite/Startup.cs create mode 100644 unittests/CommandLine/IncludeTests.targets diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e1529f6..e376f148 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,9 +111,8 @@ jobs: matrix: arch: [ "win-x64", "win-x86", "win-arm64", "linux-musl-x64", "linux-musl-arm64", "linux-x64", "linux-arm64", - "osx-x64", "osx-arm64" + "osx-x64" ] - steps: - uses: actions/checkout@v4 - name: Setup .NET 8 @@ -126,24 +125,49 @@ jobs: env: VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }} - - name: Publish .NET 6/7/8 dependent ${{ matrix.arch }} - run: dotnet publish ./src/grate/grate.csproj -r ${{ matrix.arch }} -c release --no-self-contained -o ./publish/${{ matrix.arch }}/dependent - env: - VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }} - name: Upload self-contained ${{ matrix.arch }} - if: ${{ needs.set-version-number.outputs.is-release == 'true' }} + #if: ${{ needs.set-version-number.outputs.is-release == 'true' }} uses: actions/upload-artifact@v3 with: name: grate-${{ matrix.arch }}-self-contained-${{ needs.set-version-number.outputs.nuGetVersion }} path: ./publish/${{ matrix.arch }}/self-contained/* - - name: Upload .net dependent ${{ matrix.arch }} - if: ${{ needs.set-version-number.outputs.is-release == 'true' }} + + build-standalone-mac-arm64: + name: Build cli + needs: set-version-number + + # Use macos-14 to build osx-arm64, it runs on M1, see + # https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/ + # + # I've earlier had problems with that the trimmed, self-contained binary for osx-arm64 that was built on Linux + # did not work when opened on an actual mac with arm64. + + runs-on: macos-14 + strategy: + matrix: + arch: [ "osx-arm64" ] + + steps: + - uses: actions/checkout@v4 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Publish self-contained ${{ matrix.arch }} + run: dotnet publish ./src/grate/grate.csproj -f net8.0 -r ${{ matrix.arch }} -c release --self-contained -p:SelfContained=true -o ./publish/${{ matrix.arch }}/self-contained + env: + VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }} + + - name: Upload self-contained ${{ matrix.arch }} + #if: ${{ needs.set-version-number.outputs.is-release == 'true' }} uses: actions/upload-artifact@v3 with: - name: grate-${{ matrix.arch }}-framework-dependent-${{ needs.set-version-number.outputs.nuGetVersion }} - path: ./publish/${{ matrix.arch }}/dependent/* + name: grate-${{ matrix.arch }}-self-contained-${{ needs.set-version-number.outputs.nuGetVersion }} + path: ./publish/${{ matrix.arch }}/self-contained/* + build-msi: name: Build MSI @@ -248,7 +272,7 @@ jobs: arch=$(echo ${{ matrix.arch }} | cut -d- -f2 | sed 's/x64/amd64/') echo "::set-output name=arch::$arch" - - name: Create dpkg # Linux with powershell script? really? + - name: Create dpkg # Linux with powershell script? really? YES! :D if: ${{ needs.set-version-number.outputs.is-release == 'true' }} run: ./installers/deb/Create-Package.ps1 -grateExe ./${{ matrix.arch }}/grate -Version "${{ needs.set-version-number.outputs.nuGetVersion }}" -arch ${{ steps.get-arch.outputs.arch}} env: @@ -260,33 +284,6 @@ jobs: name: grate_${{ needs.set-version-number.outputs.nuGetVersion }}-1_${{ steps.get-arch.outputs.arch}}.deb path: ./installers/deb/grate_${{ needs.set-version-number.outputs.nuGetVersion }}-1_${{ steps.get-arch.outputs.arch }}.deb - # build-winget: - # name: Winget - Update package manifest in the OWC - # needs: - # - set-version-number - # - build-msi - # runs-on: windows-latest - # if: ${{ needs.set-version-number.outputs.is-release == 'true' }} - - # steps: - # - name: Winget-Create - # run: | - - # $version = "$($env:version)" - - # # Download wingetcreate - # iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe - - # $packageUrl="https://github.com/erikbra/grate/releases/download/$version/grate-$version.msi" - - # echo "Running ./wingetcreate.exe update erikbra.grate -u $packageUrl -v $version -t `"$env:WINGET_GH_PAT`" --submit" - # ./wingetcreate.exe update erikbra.grate -u $packageUrl -v $version -t "$env:WINGET_GH_PAT" --submit - # env: - # WINGET_GH_PAT: ${{ secrets.WINGET_GH_PAT }} - # #version: "1.4.0" - # version: "${{ needs.set-version-number.outputs.nuGetVersion }}" - - test: name: Run tests @@ -302,12 +299,81 @@ jobs: with: dotnet-version: 8.0.x - name: Test - run: | - dotnet test \ - unittests/${{ matrix.category }} \ - --logger:"xunit;LogFilePath=/tmp/test-results/${{ matrix.category }}.xml" -- \ - -MaxCpuCount 2 + run: > + dotnet test + unittests/${{ matrix.category }} + --logger:"xunit;LogFilePath=/tmp/test-results/${{ matrix.category }}.xml" -- + -MaxCpuCount 2 + env: + LogLevel: Warning + TZ: UTC + + integration-test: + name: Tests cli + needs: + - set-version-number + - build-standalone + + strategy: + # We could really like to: + # - Start each database (on another host, using Docker, or other means, e.g. Azure SQL, etc + # - On all architectures available (windows-latest, linux-latest, macos-latest, and macos-14), + # - Run command-line tests against each database. + # + # This way, we can test against all variations of each database too, e.g. Azure SQL, SQL Server "on prem" (in docker), + # hosted Oracle databases, aws databases, etc. But we need to find a way to provision these databases both very fast, + # and cheap, for each one. + matrix: + category: + - CommandLine.SqlServer + - CommandLine.PostgreSQL + - CommandLine.MariaDB + - CommandLine.Sqlite + - CommandLine.Oracle + os: + # We can only run tests on Linux for now, until we start the database separately somewhere (azure, something) + # and run against an external database. Because the commandline tests are also for now _dependent_ on + # TestContainers, and running the database in a container using Docker. And Docker is only available on Linux + # on Github actions. + # - name: windows-latest + # arch: win-x64 + # executable: grate.exe + - name: ubuntu-latest + arch: linux-x64 + executable: grate + # - name: macos-latest + # arch: osx-x64 + # executable: grate + # macos-14 is M1 (arm64) + # - name: macos-14 + # arch: osx-x64 + # executable: grate + + runs-on: ${{ matrix.os.name }} + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v3 + with: + name: grate-${{ matrix.os.arch }}-self-contained-${{ needs.set-version-number.outputs.nuGetVersion }} + path: executables/${{ matrix.os.arch }} + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: chmod u+x + run: chmod u+x $GrateExecutablePath + if: ${{ matrix.os.arch != 'win-x64' }} + env: + GrateExecutablePath: ${{ github.workspace }}/executables/${{ matrix.os.arch }}/${{ matrix.os.executable }} + - name: Test + run: > + dotnet test + unittests/CommandLine/${{ matrix.category }} + --logger:"xunit;LogFilePath=/tmp/test-results/${{ matrix.os.arch }}/${{ matrix.category }}.xml" -- + -MaxCpuCount 2 env: LogLevel: Warning + GrateExecutablePath: ${{ github.workspace }}/executables/${{ matrix.os.arch }}/${{ matrix.os.executable }} TZ: UTC diff --git a/.gitignore b/.gitignore index 303dae0f..e6c0f944 100644 --- a/.gitignore +++ b/.gitignore @@ -355,3 +355,5 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ /grate/Properties/launchSettings.json + +.DS_Store diff --git a/Directory.Packages.props b/Directory.Packages.props index 1cfb7df4..acec9dbf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,6 +20,7 @@ + diff --git a/grate.sln b/grate.sln index b1c98c88..d00c30ff 100644 --- a/grate.sln +++ b/grate.sln @@ -43,6 +43,23 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "grate.core", "src\grate.cor EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "grate", "src\grate\grate.csproj", "{9D3377C2-1E3C-40C9-A5F1-DF41DFDFDD9D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Command line tests", "Command line tests", "{04731BDA-05F0-4275-AC70-3E60E87F9461}" + ProjectSection(SolutionItems) = preProject + unittests\CommandLine\IncludeTests.targets = unittests\CommandLine\IncludeTests.targets + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.Common", "unittests\CommandLine\CommandLine.Common\CommandLine.Common.csproj", "{DB220C5D-7B52-4389-B568-793FCD4286AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.MariaDB", "unittests\CommandLine\CommandLine.MariaDB\CommandLine.MariaDB.csproj", "{088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.Sqlite", "unittests\CommandLine\CommandLine.Sqlite\CommandLine.Sqlite.csproj", "{ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.Oracle", "unittests\CommandLine\CommandLine.Oracle\CommandLine.Oracle.csproj", "{BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.PostgreSQL", "unittests\CommandLine\CommandLine.PostgreSQL\CommandLine.PostgreSQL.csproj", "{89CBE842-BD34-4833-96B4-9E410C5C6AD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLine.SqlServer", "unittests\CommandLine\CommandLine.SqlServer\CommandLine.SqlServer.csproj", "{3CD81B8C-9348-4F45-9E50-12713D47B1FB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -233,6 +250,78 @@ Global {9D3377C2-1E3C-40C9-A5F1-DF41DFDFDD9D}.Release|x64.Build.0 = Release|Any CPU {9D3377C2-1E3C-40C9-A5F1-DF41DFDFDD9D}.Release|x86.ActiveCfg = Release|Any CPU {9D3377C2-1E3C-40C9-A5F1-DF41DFDFDD9D}.Release|x86.Build.0 = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|x64.ActiveCfg = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|x64.Build.0 = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|x86.ActiveCfg = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Debug|x86.Build.0 = Debug|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|Any CPU.Build.0 = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|x64.ActiveCfg = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|x64.Build.0 = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|x86.ActiveCfg = Release|Any CPU + {DB220C5D-7B52-4389-B568-793FCD4286AA}.Release|x86.Build.0 = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|x64.Build.0 = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Debug|x86.Build.0 = Debug|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|Any CPU.Build.0 = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|x64.ActiveCfg = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|x64.Build.0 = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|x86.ActiveCfg = Release|Any CPU + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE}.Release|x86.Build.0 = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|x64.ActiveCfg = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|x64.Build.0 = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|x86.ActiveCfg = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Debug|x86.Build.0 = Debug|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|Any CPU.Build.0 = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|x64.ActiveCfg = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|x64.Build.0 = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|x86.ActiveCfg = Release|Any CPU + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B}.Release|x86.Build.0 = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|x64.ActiveCfg = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|x64.Build.0 = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|x86.ActiveCfg = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Debug|x86.Build.0 = Debug|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|Any CPU.Build.0 = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|x64.ActiveCfg = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|x64.Build.0 = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|x86.ActiveCfg = Release|Any CPU + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8}.Release|x86.Build.0 = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|x64.ActiveCfg = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|x64.Build.0 = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|x86.ActiveCfg = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Debug|x86.Build.0 = Debug|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|Any CPU.Build.0 = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|x64.ActiveCfg = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|x64.Build.0 = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|x86.ActiveCfg = Release|Any CPU + {89CBE842-BD34-4833-96B4-9E410C5C6AD7}.Release|x86.Build.0 = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|x64.ActiveCfg = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|x64.Build.0 = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|x86.ActiveCfg = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Debug|x86.Build.0 = Debug|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|Any CPU.Build.0 = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|x64.ActiveCfg = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|x64.Build.0 = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|x86.ActiveCfg = Release|Any CPU + {3CD81B8C-9348-4F45-9E50-12713D47B1FB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -256,5 +345,12 @@ Global {69DE6B9D-F937-4AF4-A75E-40F5507B4C83} = {34C2458F-1244-4AF5-B5B5-B349CAEB17A5} {3BAF5373-6009-405B-AC9D-C8FFFB263E6B} = {34C2458F-1244-4AF5-B5B5-B349CAEB17A5} {9D3377C2-1E3C-40C9-A5F1-DF41DFDFDD9D} = {34C2458F-1244-4AF5-B5B5-B349CAEB17A5} + {04731BDA-05F0-4275-AC70-3E60E87F9461} = {CE4BF96D-E795-49EC-BB36-EDCC7E542685} + {DB220C5D-7B52-4389-B568-793FCD4286AA} = {04731BDA-05F0-4275-AC70-3E60E87F9461} + {088D2F44-26AE-4DCE-9668-8B8A38EDD5EE} = {04731BDA-05F0-4275-AC70-3E60E87F9461} + {ABFC5823-ACCF-4CFC-9EDA-90F7DD8A930B} = {04731BDA-05F0-4275-AC70-3E60E87F9461} + {BD31AD42-D1A0-4131-9DD5-7DA83F3F34A8} = {04731BDA-05F0-4275-AC70-3E60E87F9461} + {89CBE842-BD34-4833-96B4-9E410C5C6AD7} = {04731BDA-05F0-4275-AC70-3E60E87F9461} + {3CD81B8C-9348-4F45-9E50-12713D47B1FB} = {04731BDA-05F0-4275-AC70-3E60E87F9461} EndGlobalSection EndGlobal diff --git a/src/grate.core/Configuration/FoldersConfiguration.cs b/src/grate.core/Configuration/FoldersConfiguration.cs index c7be5f58..598427a8 100644 --- a/src/grate.core/Configuration/FoldersConfiguration.cs +++ b/src/grate.core/Configuration/FoldersConfiguration.cs @@ -26,6 +26,8 @@ public FoldersConfiguration() public MigrationsFolder? DropDatabase { get; set; } public static FoldersConfiguration Empty => new(); + + public override string ToString() => string.Join(';', Values); public static IFoldersConfiguration Default(IKnownFolderNames? folderNames = null) { diff --git a/src/grate.core/Configuration/MigrationsFolder.cs b/src/grate.core/Configuration/MigrationsFolder.cs index a1e071df..1821377e 100644 --- a/src/grate.core/Configuration/MigrationsFolder.cs +++ b/src/grate.core/Configuration/MigrationsFolder.cs @@ -27,4 +27,6 @@ public MigrationsFolder( : this(name, name, type, connectionType, transactionHandling) { } + public override string ToString() => + $"{Name}=path:{Path},type:{Type},connectionType:{ConnectionType},transactionHandling:{TransactionHandling}"; } diff --git a/src/grate.core/Infrastructure/GrateEnvironment.cs b/src/grate.core/Infrastructure/GrateEnvironment.cs index d28cb796..acb16f51 100644 --- a/src/grate.core/Infrastructure/GrateEnvironment.cs +++ b/src/grate.core/Infrastructure/GrateEnvironment.cs @@ -20,4 +20,5 @@ private bool IsForCurrentEnvironment(string path) => public static bool IsEnvironmentFile(string fileName) => fileName.Contains(EnvironmentMarker, InvariantCultureIgnoreCase); private static string FileName(string path) => new FileInfo(path).Name; + public override string ToString() => Current; } diff --git a/src/grate.core/grate.core.csproj b/src/grate.core/grate.core.csproj index 29ce0d8b..270d1000 100644 --- a/src/grate.core/grate.core.csproj +++ b/src/grate.core/grate.core.csproj @@ -17,6 +17,11 @@ + + + + + diff --git a/src/grate/grate.csproj b/src/grate/grate.csproj index f60b09de..ca42d5c9 100644 --- a/src/grate/grate.csproj +++ b/src/grate/grate.csproj @@ -9,6 +9,12 @@ + + + + + + diff --git a/unittests/CommandLine/CommandLine.Common/CommandLine.Common.csproj b/unittests/CommandLine/CommandLine.Common/CommandLine.Common.csproj new file mode 100644 index 00000000..9347f583 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/CommandLine.Common.csproj @@ -0,0 +1,40 @@ + + + + net8.0 + enable + enable + + false + false + + CommandLine.Common.Startup + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + <_Parameter1>$(MSBuildProjectDirectory)/$(OutputPath)/grate + + + + diff --git a/unittests/CommandLine/CommandLine.Common/GrateExecutablePathAttribute.cs b/unittests/CommandLine/CommandLine.Common/GrateExecutablePathAttribute.cs new file mode 100644 index 00000000..761db8c9 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/GrateExecutablePathAttribute.cs @@ -0,0 +1,8 @@ +namespace CommandLine.Common; + +[AttributeUsage(AttributeTargets.Assembly)] +public class GrateExecutablePathAttribute(string path) : Attribute +{ + public string Path { get; set; } = path; +} + diff --git a/unittests/CommandLine/CommandLine.Common/Startup.cs b/unittests/CommandLine/CommandLine.Common/Startup.cs new file mode 100644 index 00000000..89369daf --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/Startup.cs @@ -0,0 +1,40 @@ +using CommandLine.Common.TestInfrastructure; +using grate.Configuration; +using grate.Migration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using TestCommon.TestInfrastructure; + +namespace CommandLine.Common; + +// ReSharper disable once UnusedType.Global +public abstract class Startup +{ + // ReSharper disable once UnusedMember.Global + public void ConfigureServices(IServiceCollection services, HostBuilderContext context) + { + services.AddLogging( + lb => lb + .AddXUnit() + .AddConsole() + .SetMinimumLevel(TestConfig.GetLogLevel()) + ); + + services.AddSingleton(new CommandLineGrateMigrator(DatabaseType)); + + services.TryAddSingleton(TestContextType); + services.TryAddSingleton(TestContainerType); + + services.TryAddTransient(provider => + new CommandLineGrateTestContext( + provider.GetRequiredService(), + (IGrateTestContext) provider.GetRequiredService(TestContextType))); + } + + protected abstract DatabaseType DatabaseType { get; } + protected abstract Type TestContainerType { get; } + protected abstract Type TestContextType { get; } + +} diff --git a/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineGrateMigrator.cs b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineGrateMigrator.cs new file mode 100644 index 00000000..4ed7c097 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineGrateMigrator.cs @@ -0,0 +1,136 @@ +using System.Diagnostics; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using grate.Commands; +using grate.Configuration; +using grate.Exceptions; +using grate.Migration; + +namespace CommandLine.Common.TestInfrastructure; + +public record CommandLineGrateMigrator(DatabaseType DatabaseType) : IGrateMigrator +{ + public DatabaseType DatabaseType { get; set; } = DatabaseType; + + public async Task Migrate() + { + // Convert configuration to command-line arguments + var convertToCommandLineArguments = ConvertToCommandLineArguments(Configuration); + var commandLineArguments = convertToCommandLineArguments.ToList(); + + // Add the database type + commandLineArguments.Add("--databasetype=" + DatabaseType.ToString().ToLowerInvariant()); + + // Run the command-line tool with the arguments + var processInfo = new ProcessStartInfo(GrateExecutable, commandLineArguments) + { + RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, + }; + + using var process = Process.Start(processInfo); + await process!.WaitForExitAsync(); + + var output = await process.StandardOutput.ReadToEndAsync(); + var error = await process.StandardError.ReadToEndAsync(); + + var exitCode = process.ExitCode; + if (exitCode != 0) + { + try + { + throw new Exception($"grate failed with exit code {exitCode}. Output: {output}. Error: {error}"); + }catch (Exception e) + { + throw new MigrationFailed(e); + } + } + + } + + public GrateConfiguration Configuration { get; private init; } = null!; + + public IGrateMigrator WithConfiguration(GrateConfiguration configuration) + { + return this with { Configuration = configuration }; + } + + public IGrateMigrator WithConfiguration(Action builder) + { + var b = GrateConfigurationBuilder.Create(Configuration); + builder.Invoke(b); + return this with { Configuration = b.Build() }; + } + + public IGrateMigrator WithDatabase(IDatabase database) => this with { Database = database }; + public IDatabase? Database { get; set; } + + + private List ConvertToCommandLineArguments(GrateConfiguration configuration) + { + List result = new(); + + var properties = configuration.GetType().GetProperties(); + + var cmd = new MigrateCommand(this); + + foreach (var prop in properties) + { + // Skip properties with default values + var value = prop.GetValue(configuration); + var defaultValue = prop.GetValue(GrateConfiguration.Default); + + var serializedValue = JsonSerializer.Serialize(value?.ToString(), SerializerOptions); + var serializedDefault = JsonSerializer.Serialize(defaultValue?.ToString(), SerializerOptions); + + if (serializedValue.Equals(serializedDefault)) + { + continue; + } + + // Convert IFoldersConfiguration to string + if (value is IFoldersConfiguration foldersConfiguration) + { + value = string.Join(';', foldersConfiguration.Values); + } + + var name = prop.Name; + var option = cmd.Options.FirstOrDefault(o => string.Equals(o.Name, name, StringComparison.OrdinalIgnoreCase)); + + if (option is not null && value is not null) + { + var optionName = option.Aliases.FirstOrDefault(alias => alias.StartsWith("--")) + ?? option.Aliases.First(); + + if (value is string[] arr) + { + result.AddRange(arr.Select(v => $"{optionName}={v}")); + } + else + { + result.Add($"{optionName}={value}"); + } + } + } + + return result; +#pragma warning restore CS0162 // Unreachable code detected + } + + private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerOptions.Default) + { + ReferenceHandler = ReferenceHandler.IgnoreCycles + }; + + private static string GrateExecutable => + Environment.GetEnvironmentVariable("GrateExecutablePath") ?? + typeof(CommandLineGrateMigrator).Assembly.GetCustomAttribute()?.Path + ?? throw new Exception("Grate executable path not found"); + + + public ValueTask DisposeAsync() + { + return new ValueTask(Task.CompletedTask); + } + +} diff --git a/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineTestFramework.cs b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineTestFramework.cs new file mode 100644 index 00000000..b900c537 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandLineTestFramework.cs @@ -0,0 +1,48 @@ +// using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; +// using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; +// using Xunit.Abstractions; +// using Xunit.Sdk; +// +// namespace CommandLine_tests.TestInfrastructure; +// +// public class CommandLineTestFramework : XunitTestFramework +// { +// public CommandLineTestFramework(IMessageSink messageSink) +// : base(messageSink) +// { +// } +// +// protected override ITestFrameworkDiscoverer CreateDiscoverer( +// IAssemblyInfo assemblyInfo) +// => new CommandLineTestFrameworkDiscoverer( +// assemblyInfo, +// SourceInformationProvider, +// DiagnosticMessageSink); +// } +// public class CommandLineTestFrameworkDiscoverer : XunitTestFrameworkDiscoverer +// { +// public CommandLineTestFrameworkDiscoverer( +// IAssemblyInfo assemblyInfo, +// ISourceInformationProvider sourceProvider, +// IMessageSink diagnosticMessageSink, +// IXunitTestCollectionFactory? collectionFactory = null) +// : base( +// assemblyInfo, +// sourceProvider, +// diagnosticMessageSink, +// collectionFactory) +// { +// } +// +// protected override bool IsValidTestClass(ITypeInfo type) +// => base.IsValidTestClass(type) && +// FilterType(type); +// +// protected virtual bool FilterType(ITypeInfo type) +// { +// // Insert your custom filter conditions here. +// return true; +// } +// } +// +// diff --git a/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandlineGrateTestContext.cs b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandlineGrateTestContext.cs new file mode 100644 index 00000000..88755037 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Common/TestInfrastructure/CommandlineGrateTestContext.cs @@ -0,0 +1,39 @@ +using System.Data; +using grate.Infrastructure; +using grate.Migration; +using TestCommon.TestInfrastructure; + +namespace CommandLine.Common.TestInfrastructure; + +public class CommandLineGrateTestContext : IGrateTestContext +{ + private readonly IGrateTestContext _testContext; + + public CommandLineGrateTestContext( + IGrateMigrator migrator, + IGrateTestContext testContext) + { + _testContext = testContext; + Migrator = migrator; + } + + public IGrateMigrator Migrator { get; } + + public string AdminConnectionString => _testContext.AdminConnectionString; + public string ConnectionString(string database) => _testContext.ConnectionString(database); + public string UserConnectionString(string database) => _testContext.UserConnectionString(database); + + public IDbConnection GetDbConnection(string connectionString) => _testContext.GetDbConnection(connectionString); + + public ISyntax Syntax => _testContext.Syntax; + public Type DbExceptionType => _testContext.DbExceptionType; + + public Type DatabaseType => _testContext.DbExceptionType; + public bool SupportsTransaction => _testContext.SupportsTransaction; + + public SqlStatements Sql => _testContext.Sql; + + public string ExpectedVersionPrefix => _testContext.ExpectedVersionPrefix; + public bool SupportsCreateDatabase => _testContext.SupportsCreateDatabase; + public bool SupportsSchemas => _testContext.SupportsSchemas; +} diff --git a/unittests/CommandLine/CommandLine.MariaDB/CommandLine.MariaDB.csproj b/unittests/CommandLine/CommandLine.MariaDB/CommandLine.MariaDB.csproj new file mode 100644 index 00000000..92070270 --- /dev/null +++ b/unittests/CommandLine/CommandLine.MariaDB/CommandLine.MariaDB.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + ../../MariaDB + + + + diff --git a/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/Failing_Scripts.cs b/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/Failing_Scripts.cs new file mode 100644 index 00000000..97400975 --- /dev/null +++ b/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/Failing_Scripts.cs @@ -0,0 +1,24 @@ +using MariaDB.TestInfrastructure; +using TestCommon.TestInfrastructure; + +namespace CommandLine.MariaDB.Running_MigrationScripts; + +[Collection(nameof(MariaDbTestContainer))] +// ReSharper disable once InconsistentNaming +public class Failing_Scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) +{ + protected override string ExpectedErrorMessageForInvalidSql => "Not relevant"; + protected override IDictionary ExpectedErrorDetails => new Dictionary(); + + [Fact(Skip = "Cannot check on the exact error message when running the command line tool. The error message is not available.")] + public override Task Aborts_the_run_giving_an_error_message() => Task.CompletedTask; + + [Fact(Skip = "Cannot check on the exact error details when running the command line tool. The error details are not available.")] + public override Task Exception_includes_details_on_the_failed_script() => Task.CompletedTask; + + [Fact(Skip = + "We do not have the ability to check for transient errors when running the command line tool. The error details are not available.")] + public override Task Exception_is_set_to_transient_based_on_inner_exceptions() => Task.CompletedTask; + +} diff --git a/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/One_time_scripts.cs b/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/One_time_scripts.cs new file mode 100644 index 00000000..7da55a14 --- /dev/null +++ b/unittests/CommandLine/CommandLine.MariaDB/Running_MigrationScripts/One_time_scripts.cs @@ -0,0 +1,58 @@ +using Dapper; +using FluentAssertions; +using grate.Configuration; +using grate.Exceptions; +using MariaDB.TestInfrastructure; +using TestCommon.TestInfrastructure; +using static grate.Configuration.KnownFolderKeys; + +namespace CommandLine.MariaDB.Running_MigrationScripts; + +[Collection(nameof(MariaDbTestContainer))] +// ReSharper disable once InconsistentNaming +public class One_time_scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) +{ + + [Fact] + public override async Task Fails_if_changed_between_runs() + { + var db = TestConfig.RandomDatabase(); + + var parent = CreateRandomTempDirectory(); + var knownFolders = FoldersConfiguration.Default(null); + CreateDummySql(parent, knownFolders[Up]); + + var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration) + .WithConnectionString(Context.ConnectionString(db)) + .WithFolders(knownFolders) + .WithSqlFilesDirectory(parent) + .Build(); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + await migrator.Migrate(); + } + + WriteSomeOtherSql(parent, knownFolders[Up]); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + var ex = await Assert.ThrowsAsync(() => migrator.Migrate()); + } + + string[] scripts; + string sql = $"SELECT text_of_script FROM {Context.Syntax.TableWithSchema("grate", "ScriptsRun")}"; + + using (var conn = Context.CreateDbConnection(db)) + { + scripts = (await conn.QueryAsync(sql)).ToArray(); + } + + scripts.Should().HaveCount(1); + scripts.First().Should().Be(Context.Sql.SelectVersion); + } + +} + + diff --git a/unittests/CommandLine/CommandLine.MariaDB/Startup.cs b/unittests/CommandLine/CommandLine.MariaDB/Startup.cs new file mode 100644 index 00000000..197353f7 --- /dev/null +++ b/unittests/CommandLine/CommandLine.MariaDB/Startup.cs @@ -0,0 +1,12 @@ +using grate.Configuration; +using MariaDB.TestInfrastructure; + +namespace CommandLine.MariaDB; + +// ReSharper disable once UnusedType.Global +public class Startup: CommandLine.Common.Startup +{ + protected override DatabaseType DatabaseType => DatabaseType.MariaDB; + protected override Type TestContainerType => typeof(MariaDbTestContainer); + protected override Type TestContextType => typeof(MariaDbGrateTestContext); +} diff --git a/unittests/CommandLine/CommandLine.Oracle/CommandLine.Oracle.csproj b/unittests/CommandLine/CommandLine.Oracle/CommandLine.Oracle.csproj new file mode 100644 index 00000000..b4e5ecb9 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Oracle/CommandLine.Oracle.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + ../../Oracle + + + + diff --git a/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/Failing_Scripts.cs b/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/Failing_Scripts.cs new file mode 100644 index 00000000..0f593728 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/Failing_Scripts.cs @@ -0,0 +1,23 @@ +using TestCommon.TestInfrastructure; + +namespace CommandLine.Oracle.Running_MigrationScripts; + +[Collection(nameof(OracleTestContainer))] +// ReSharper disable once InconsistentNaming +public class Failing_Scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) +{ + protected override string ExpectedErrorMessageForInvalidSql => "Not relevant"; + protected override IDictionary ExpectedErrorDetails => new Dictionary(); + + [Fact(Skip = "Cannot check on the exact error message when running the command line tool. The error message is not available.")] + public override Task Aborts_the_run_giving_an_error_message() => Task.CompletedTask; + + [Fact(Skip = "Cannot check on the exact error details when running the command line tool. The error details are not available.")] + public override Task Exception_includes_details_on_the_failed_script() => Task.CompletedTask; + + [Fact(Skip = + "We do not have the ability to check for transient errors when running the command line tool. The error details are not available.")] + public override Task Exception_is_set_to_transient_based_on_inner_exceptions() => Task.CompletedTask; + +} diff --git a/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/One_time_scripts.cs b/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/One_time_scripts.cs new file mode 100644 index 00000000..899cbbdf --- /dev/null +++ b/unittests/CommandLine/CommandLine.Oracle/Running_MigrationScripts/One_time_scripts.cs @@ -0,0 +1,59 @@ +using Dapper; +using FluentAssertions; +using grate.Configuration; +using grate.Exceptions; +using TestCommon.TestInfrastructure; +using static grate.Configuration.KnownFolderKeys; + +namespace CommandLine.Oracle.Running_MigrationScripts; + +[Collection(nameof(OracleTestContainer))] +// ReSharper disable once InconsistentNaming +public class One_time_scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) +{ + protected override string CreateView1 => base.CreateView1 + " FROM DUAL"; + protected override string CreateView2 => base.CreateView2 + " FROM DUAL"; + + [Fact] + public override async Task Fails_if_changed_between_runs() + { + var db = TestConfig.RandomDatabase(); + + var parent = CreateRandomTempDirectory(); + var knownFolders = FoldersConfiguration.Default(null); + CreateDummySql(parent, knownFolders[Up]); + + var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration) + .WithConnectionString(Context.ConnectionString(db)) + .WithFolders(knownFolders) + .WithSqlFilesDirectory(parent) + .Build(); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + await migrator.Migrate(); + } + + WriteSomeOtherSql(parent, knownFolders[Up]); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + var ex = await Assert.ThrowsAsync(() => migrator.Migrate()); + } + + string[] scripts; + string sql = $"SELECT text_of_script FROM {Context.Syntax.TableWithSchema("grate", "ScriptsRun")}"; + + using (var conn = Context.CreateDbConnection(db)) + { + scripts = (await conn.QueryAsync(sql)).ToArray(); + } + + scripts.Should().HaveCount(1); + scripts.First().Should().Be(Context.Sql.SelectVersion); + } + +} + + diff --git a/unittests/CommandLine/CommandLine.Oracle/Startup.cs b/unittests/CommandLine/CommandLine.Oracle/Startup.cs new file mode 100644 index 00000000..249b3c37 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Oracle/Startup.cs @@ -0,0 +1,13 @@ +using grate.Configuration; +using Oracle.TestInfrastructure; +using TestCommon.TestInfrastructure; + +namespace CommandLine.Oracle; + +// ReSharper disable once UnusedType.Global +public class Startup: CommandLine.Common.Startup +{ + protected override DatabaseType DatabaseType => DatabaseType.Oracle; + protected override Type TestContainerType => typeof(OracleTestContainer); + protected override Type TestContextType => typeof(OracleGrateTestContext); +} diff --git a/unittests/CommandLine/CommandLine.PostgreSQL/CommandLine.PostgreSQL.csproj b/unittests/CommandLine/CommandLine.PostgreSQL/CommandLine.PostgreSQL.csproj new file mode 100644 index 00000000..e524c1a5 --- /dev/null +++ b/unittests/CommandLine/CommandLine.PostgreSQL/CommandLine.PostgreSQL.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + ../../PostgreSQL + + + + diff --git a/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/Failing_Scripts.cs b/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/Failing_Scripts.cs new file mode 100644 index 00000000..e06cdcde --- /dev/null +++ b/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/Failing_Scripts.cs @@ -0,0 +1,23 @@ +using TestCommon.TestInfrastructure; + +namespace CommandLine.PostgreSQL.Running_MigrationScripts; + +[Collection(nameof(PostgreSqlTestContainer))] +// ReSharper disable once InconsistentNaming +public class Failing_Scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) +{ + protected override string ExpectedErrorMessageForInvalidSql => "Not relevant"; + protected override IDictionary ExpectedErrorDetails => new Dictionary(); + + [Fact(Skip = "Cannot check on the exact error message when running the command line tool. The error message is not available.")] + public override Task Aborts_the_run_giving_an_error_message() => Task.CompletedTask; + + [Fact(Skip = "Cannot check on the exact error details when running the command line tool. The error details are not available.")] + public override Task Exception_includes_details_on_the_failed_script() => Task.CompletedTask; + + [Fact(Skip = + "We do not have the ability to check for transient errors when running the command line tool. The error details are not available.")] + public override Task Exception_is_set_to_transient_based_on_inner_exceptions() => Task.CompletedTask; + +} diff --git a/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/One_time_scripts.cs b/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/One_time_scripts.cs new file mode 100644 index 00000000..9e7f9f8a --- /dev/null +++ b/unittests/CommandLine/CommandLine.PostgreSQL/Running_MigrationScripts/One_time_scripts.cs @@ -0,0 +1,56 @@ +using Dapper; +using FluentAssertions; +using grate.Configuration; +using grate.Exceptions; +using TestCommon.TestInfrastructure; +using static grate.Configuration.KnownFolderKeys; + +namespace CommandLine.PostgreSQL.Running_MigrationScripts; + +[Collection(nameof(PostgreSqlTestContainer))] +// ReSharper disable once InconsistentNaming +public class One_time_scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) +{ + [Fact] + public override async Task Fails_if_changed_between_runs() + { + var db = TestConfig.RandomDatabase(); + + var parent = CreateRandomTempDirectory(); + var knownFolders = FoldersConfiguration.Default(null); + CreateDummySql(parent, knownFolders[Up]); + + var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration) + .WithConnectionString(Context.ConnectionString(db)) + .WithFolders(knownFolders) + .WithSqlFilesDirectory(parent) + .Build(); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + await migrator.Migrate(); + } + + WriteSomeOtherSql(parent, knownFolders[Up]); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + var ex = await Assert.ThrowsAsync(() => migrator.Migrate()); + } + + string[] scripts; + string sql = $"SELECT text_of_script FROM {Context.Syntax.TableWithSchema("grate", "ScriptsRun")}"; + + using (var conn = Context.CreateDbConnection(db)) + { + scripts = (await conn.QueryAsync(sql)).ToArray(); + } + + scripts.Should().HaveCount(1); + scripts.First().Should().Be(Context.Sql.SelectVersion); + } + +} + + diff --git a/unittests/CommandLine/CommandLine.PostgreSQL/Startup.cs b/unittests/CommandLine/CommandLine.PostgreSQL/Startup.cs new file mode 100644 index 00000000..bd2731ab --- /dev/null +++ b/unittests/CommandLine/CommandLine.PostgreSQL/Startup.cs @@ -0,0 +1,13 @@ +using grate.Configuration; +using PostgreSQL.TestInfrastructure; +using TestCommon.TestInfrastructure; + +namespace CommandLine.PostgreSQL; + +// ReSharper disable once UnusedType.Global +public class Startup: CommandLine.Common.Startup +{ + protected override DatabaseType DatabaseType => DatabaseType.PostgreSQL; + protected override Type TestContainerType => typeof(PostgreSqlTestContainer); + protected override Type TestContextType => typeof(PostgreSqlGrateTestContext); +} diff --git a/unittests/CommandLine/CommandLine.SqlServer/CommandLine.SqlServer.csproj b/unittests/CommandLine/CommandLine.SqlServer/CommandLine.SqlServer.csproj new file mode 100644 index 00000000..fe1ef6bf --- /dev/null +++ b/unittests/CommandLine/CommandLine.SqlServer/CommandLine.SqlServer.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + ../../SqlServer + + + + diff --git a/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/Failing_Scripts.cs b/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/Failing_Scripts.cs new file mode 100644 index 00000000..23b10507 --- /dev/null +++ b/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/Failing_Scripts.cs @@ -0,0 +1,23 @@ +using TestCommon.TestInfrastructure; + +namespace CommandLine.SqlServer.Running_MigrationScripts; + +[Collection(nameof(SqlServerTestContainer))] +// ReSharper disable once InconsistentNaming +public class Failing_Scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) +{ + protected override string ExpectedErrorMessageForInvalidSql => "Not relevant"; + protected override IDictionary ExpectedErrorDetails => new Dictionary(); + + [Fact(Skip = "Cannot check on the exact error message when running the command line tool. The error message is not available.")] + public override Task Aborts_the_run_giving_an_error_message() => Task.CompletedTask; + + [Fact(Skip = "Cannot check on the exact error details when running the command line tool. The error details are not available.")] + public override Task Exception_includes_details_on_the_failed_script() => Task.CompletedTask; + + [Fact(Skip = + "We do not have the ability to check for transient errors when running the command line tool. The error details are not available.")] + public override Task Exception_is_set_to_transient_based_on_inner_exceptions() => Task.CompletedTask; + +} diff --git a/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/One_time_scripts.cs b/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/One_time_scripts.cs new file mode 100644 index 00000000..0dbdb2f9 --- /dev/null +++ b/unittests/CommandLine/CommandLine.SqlServer/Running_MigrationScripts/One_time_scripts.cs @@ -0,0 +1,56 @@ +using Dapper; +using FluentAssertions; +using grate.Configuration; +using grate.Exceptions; +using TestCommon.TestInfrastructure; +using static grate.Configuration.KnownFolderKeys; + +namespace CommandLine.SqlServer.Running_MigrationScripts; + +[Collection(nameof(SqlServerTestContainer))] +// ReSharper disable once InconsistentNaming +public class One_time_scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) +{ + [Fact] + public override async Task Fails_if_changed_between_runs() + { + var db = TestConfig.RandomDatabase(); + + var parent = CreateRandomTempDirectory(); + var knownFolders = FoldersConfiguration.Default(null); + CreateDummySql(parent, knownFolders[Up]); + + var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration) + .WithConnectionString(Context.ConnectionString(db)) + .WithFolders(knownFolders) + .WithSqlFilesDirectory(parent) + .Build(); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + await migrator.Migrate(); + } + + WriteSomeOtherSql(parent, knownFolders[Up]); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + var ex = await Assert.ThrowsAsync(() => migrator.Migrate()); + } + + string[] scripts; + string sql = $"SELECT text_of_script FROM {Context.Syntax.TableWithSchema("grate", "ScriptsRun")}"; + + using (var conn = Context.CreateDbConnection(db)) + { + scripts = (await conn.QueryAsync(sql)).ToArray(); + } + + scripts.Should().HaveCount(1); + scripts.First().Should().Be(Context.Sql.SelectVersion); + } + +} + + diff --git a/unittests/CommandLine/CommandLine.SqlServer/Startup.cs b/unittests/CommandLine/CommandLine.SqlServer/Startup.cs new file mode 100644 index 00000000..c6e7d870 --- /dev/null +++ b/unittests/CommandLine/CommandLine.SqlServer/Startup.cs @@ -0,0 +1,13 @@ +using grate.Configuration; +using SqlServer.TestInfrastructure; +using TestCommon.TestInfrastructure; + +namespace CommandLine.SqlServer; + +// ReSharper disable once UnusedType.Global +public class Startup: CommandLine.Common.Startup +{ + protected override DatabaseType DatabaseType => DatabaseType.SQLServer; + protected override Type TestContainerType => typeof(SqlServerTestContainer); + protected override Type TestContextType => typeof(SqlServerGrateTestContext); +} diff --git a/unittests/CommandLine/CommandLine.Sqlite/CommandLine.Sqlite.csproj b/unittests/CommandLine/CommandLine.Sqlite/CommandLine.Sqlite.csproj new file mode 100644 index 00000000..3550dc0d --- /dev/null +++ b/unittests/CommandLine/CommandLine.Sqlite/CommandLine.Sqlite.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + ../../Sqlite + + + + diff --git a/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/Failing_Scripts.cs b/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/Failing_Scripts.cs new file mode 100644 index 00000000..536d9bc0 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/Failing_Scripts.cs @@ -0,0 +1,23 @@ +using TestCommon.TestInfrastructure; + +namespace CommandLine.Sqlite.Running_MigrationScripts; + +[Collection(nameof(SqliteTestContainer))] +// ReSharper disable once InconsistentNaming +public class Failing_Scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.Failing_Scripts(testContext, testOutput) +{ + protected override string ExpectedErrorMessageForInvalidSql => "Not relevant"; + protected override IDictionary ExpectedErrorDetails => new Dictionary(); + + [Fact(Skip = "Cannot check on the exact error message when running the command line tool. The error message is not available.")] + public override Task Aborts_the_run_giving_an_error_message() => Task.CompletedTask; + + [Fact(Skip = "Cannot check on the exact error details when running the command line tool. The error details are not available.")] + public override Task Exception_includes_details_on_the_failed_script() => Task.CompletedTask; + + [Fact(Skip = + "We do not have the ability to check for transient errors when running the command line tool. The error details are not available.")] + public override Task Exception_is_set_to_transient_based_on_inner_exceptions() => Task.CompletedTask; + +} diff --git a/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/One_time_scripts.cs b/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/One_time_scripts.cs new file mode 100644 index 00000000..408f4553 --- /dev/null +++ b/unittests/CommandLine/CommandLine.Sqlite/Running_MigrationScripts/One_time_scripts.cs @@ -0,0 +1,56 @@ +using Dapper; +using FluentAssertions; +using grate.Configuration; +using grate.Exceptions; +using TestCommon.TestInfrastructure; +using static grate.Configuration.KnownFolderKeys; + +namespace CommandLine.Sqlite.Running_MigrationScripts; + +[Collection(nameof(SqliteTestContainer))] +// ReSharper disable once InconsistentNaming +public class One_time_scripts(IGrateTestContext testContext, ITestOutputHelper testOutput) + : TestCommon.Generic.Running_MigrationScripts.One_time_scripts(testContext, testOutput) +{ + [Fact] + public override async Task Fails_if_changed_between_runs() + { + var db = TestConfig.RandomDatabase(); + + var parent = CreateRandomTempDirectory(); + var knownFolders = FoldersConfiguration.Default(null); + CreateDummySql(parent, knownFolders[Up]); + + var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration) + .WithConnectionString(Context.ConnectionString(db)) + .WithFolders(knownFolders) + .WithSqlFilesDirectory(parent) + .Build(); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + await migrator.Migrate(); + } + + WriteSomeOtherSql(parent, knownFolders[Up]); + + await using (var migrator = Context.Migrator.WithConfiguration(config)) + { + var ex = await Assert.ThrowsAsync(() => migrator.Migrate()); + } + + string[] scripts; + string sql = $"SELECT text_of_script FROM {Context.Syntax.TableWithSchema("grate", "ScriptsRun")}"; + + using (var conn = Context.CreateDbConnection(db)) + { + scripts = (await conn.QueryAsync(sql)).ToArray(); + } + + scripts.Should().HaveCount(1); + scripts.First().Should().Be(Context.Sql.SelectVersion); + } + +} + + diff --git a/unittests/CommandLine/CommandLine.Sqlite/Startup.cs b/unittests/CommandLine/CommandLine.Sqlite/Startup.cs new file mode 100644 index 00000000..cc2d7a7f --- /dev/null +++ b/unittests/CommandLine/CommandLine.Sqlite/Startup.cs @@ -0,0 +1,13 @@ +using grate.Configuration; +using Sqlite.TestInfrastructure; +using TestCommon.TestInfrastructure; + +namespace CommandLine.Sqlite; + +// ReSharper disable once UnusedType.Global +public class Startup: CommandLine.Common.Startup +{ + protected override DatabaseType DatabaseType => DatabaseType.SQLite; + protected override Type TestContainerType => typeof(SqliteTestContainer); + protected override Type TestContextType => typeof(SqliteGrateTestContext); +} diff --git a/unittests/CommandLine/IncludeTests.targets b/unittests/CommandLine/IncludeTests.targets new file mode 100644 index 00000000..4d217022 --- /dev/null +++ b/unittests/CommandLine/IncludeTests.targets @@ -0,0 +1,24 @@ + + + + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/unittests/MariaDB/TestInfrastructure/MariaDbGrateTestContext.cs b/unittests/MariaDB/TestInfrastructure/MariaDbGrateTestContext.cs index a89ba5c2..66817db5 100644 --- a/unittests/MariaDB/TestInfrastructure/MariaDbGrateTestContext.cs +++ b/unittests/MariaDB/TestInfrastructure/MariaDbGrateTestContext.cs @@ -55,4 +55,5 @@ public MariaDbGrateTestContext( public string ExpectedVersionPrefix => "10.10.7-MariaDB"; public bool SupportsCreateDatabase => true; + public bool SupportsSchemas => false; } diff --git a/unittests/Oracle/TestInfrastructure/OracleGrateTestContext.cs b/unittests/Oracle/TestInfrastructure/OracleGrateTestContext.cs index 100d5f74..2ac7bc91 100644 --- a/unittests/Oracle/TestInfrastructure/OracleGrateTestContext.cs +++ b/unittests/Oracle/TestInfrastructure/OracleGrateTestContext.cs @@ -50,4 +50,5 @@ public OracleGrateTestContext( public string ExpectedVersionPrefix => "Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production"; public bool SupportsCreateDatabase => true; + public bool SupportsSchemas => false; } diff --git a/unittests/PostgreSQL/TestInfrastructure/PostgreSqlGrateTestContext.cs b/unittests/PostgreSQL/TestInfrastructure/PostgreSqlGrateTestContext.cs index 8405ff20..298e7bcb 100644 --- a/unittests/PostgreSQL/TestInfrastructure/PostgreSqlGrateTestContext.cs +++ b/unittests/PostgreSQL/TestInfrastructure/PostgreSqlGrateTestContext.cs @@ -53,5 +53,6 @@ public string UserConnectionString(string database) => public string ExpectedVersionPrefix => "PostgreSQL 16."; public bool SupportsCreateDatabase => true; + public bool SupportsSchemas => true; } diff --git a/unittests/SqlServer/TestInfrastructure/SqlServerGrateTestContext.cs b/unittests/SqlServer/TestInfrastructure/SqlServerGrateTestContext.cs index a2179be0..f490084f 100644 --- a/unittests/SqlServer/TestInfrastructure/SqlServerGrateTestContext.cs +++ b/unittests/SqlServer/TestInfrastructure/SqlServerGrateTestContext.cs @@ -71,6 +71,7 @@ public string UserConnectionString(string database) => public string ExpectedVersionPrefix => "Microsoft SQL Server 2019"; public bool SupportsCreateDatabase => true; + public bool SupportsSchemas => true; public string ServerCollation { get; } } diff --git a/unittests/SqlServerCaseSensitive/TestInfrastructure/SqlServerGrateTestContext.cs b/unittests/SqlServerCaseSensitive/TestInfrastructure/SqlServerGrateTestContext.cs index 4631007d..c0891cde 100644 --- a/unittests/SqlServerCaseSensitive/TestInfrastructure/SqlServerGrateTestContext.cs +++ b/unittests/SqlServerCaseSensitive/TestInfrastructure/SqlServerGrateTestContext.cs @@ -53,6 +53,7 @@ public SqlServerGrateTestContext( public string ExpectedVersionPrefix => "Microsoft SQL Server 2019"; public bool SupportsCreateDatabase => true; + public bool SupportsSchemas => true; public string ServerCollation { get; } } diff --git a/unittests/Sqlite/TestInfrastructure/SqliteGrateTestContext.cs b/unittests/Sqlite/TestInfrastructure/SqliteGrateTestContext.cs index b4b644b5..4287fa73 100644 --- a/unittests/Sqlite/TestInfrastructure/SqliteGrateTestContext.cs +++ b/unittests/Sqlite/TestInfrastructure/SqliteGrateTestContext.cs @@ -44,6 +44,7 @@ public SqliteGrateTestContext( public string ExpectedVersionPrefix => throw new NotSupportedException("Sqlite does not support versioning"); public bool SupportsCreateDatabase => false; + public bool SupportsSchemas => false; public IGrateMigrator Migrator { get; } } diff --git a/unittests/TestCommon/Generic/Running_MigrationScripts/Failing_Scripts.cs b/unittests/TestCommon/Generic/Running_MigrationScripts/Failing_Scripts.cs index d4501dc4..5115c3a3 100644 --- a/unittests/TestCommon/Generic/Running_MigrationScripts/Failing_Scripts.cs +++ b/unittests/TestCommon/Generic/Running_MigrationScripts/Failing_Scripts.cs @@ -26,7 +26,7 @@ protected Failing_Scripts(): this(null!, null!) protected abstract string ExpectedErrorMessageForInvalidSql { get; } [Fact] - public async Task Aborts_the_run_giving_an_error_message() + public virtual async Task Aborts_the_run_giving_an_error_message() { var db = TestConfig.RandomDatabase(); @@ -47,7 +47,7 @@ public async Task Aborts_the_run_giving_an_error_message() [Fact] - public async Task Exception_includes_details_on_the_failed_script() + public virtual async Task Exception_includes_details_on_the_failed_script() { var db = TestConfig.RandomDatabase(); @@ -84,7 +84,7 @@ public async Task Exception_includes_details_on_the_failed_script() // TODO: Improve this test to throw both transient and non-transient exceptions, and check the result [Fact] - public async Task Exception_is_set_to_transient_based_on_inner_exceptions() + public virtual async Task Exception_is_set_to_transient_based_on_inner_exceptions() { var db = TestConfig.RandomDatabase(); diff --git a/unittests/TestCommon/Generic/Running_MigrationScripts/One_time_scripts.cs b/unittests/TestCommon/Generic/Running_MigrationScripts/One_time_scripts.cs index db72ebfb..aca0111a 100644 --- a/unittests/TestCommon/Generic/Running_MigrationScripts/One_time_scripts.cs +++ b/unittests/TestCommon/Generic/Running_MigrationScripts/One_time_scripts.cs @@ -53,7 +53,7 @@ public async Task Are_not_run_more_than_once_when_unchanged() } [Fact] - public async Task Fails_if_changed_between_runs() + public virtual async Task Fails_if_changed_between_runs() { var db = TestConfig.RandomDatabase(); diff --git a/unittests/TestCommon/TestInfrastructure/GrateMigratorExtensions.cs b/unittests/TestCommon/TestInfrastructure/GrateMigratorExtensions.cs index b9ce274e..cb35dc85 100644 --- a/unittests/TestCommon/TestInfrastructure/GrateMigratorExtensions.cs +++ b/unittests/TestCommon/TestInfrastructure/GrateMigratorExtensions.cs @@ -8,9 +8,4 @@ public static IDbMigrator GetDbMigrator(this IGrateMigrator migrator) { return (migrator as GrateMigrator)!.DbMigrator; } - - public static bool SupportsSchemas(this IGrateMigrator migrator) - { - return (migrator as GrateMigrator)!.Database!.SupportsSchemas; - } } diff --git a/unittests/TestCommon/TestInfrastructure/IGrateTestContext.cs b/unittests/TestCommon/TestInfrastructure/IGrateTestContext.cs index 7a12e373..f1e06e30 100644 --- a/unittests/TestCommon/TestInfrastructure/IGrateTestContext.cs +++ b/unittests/TestCommon/TestInfrastructure/IGrateTestContext.cs @@ -36,9 +36,11 @@ public interface IGrateTestContext public IGrateMigrator Migrator { get; } - public bool SupportsSchemas => Migrator.SupportsSchemas(); + + //public bool SupportsSchemas => Migrator.SupportsSchemas(); bool SupportsCreateDatabase { get; } + bool SupportsSchemas { get; } IDbConnection GetDbConnection(string connectionString); } diff --git a/unittests/TestCommon/TestInfrastructure/TestConfig.cs b/unittests/TestCommon/TestInfrastructure/TestConfig.cs index a6eca76b..e25fec80 100644 --- a/unittests/TestCommon/TestInfrastructure/TestConfig.cs +++ b/unittests/TestCommon/TestInfrastructure/TestConfig.cs @@ -15,6 +15,11 @@ public static DirectoryInfo CreateRandomTempDirectory() var dummyFile = Path.GetTempFileName(); File.Delete(dummyFile); + if (Directory.Exists(dummyFile)) + { + Directory.Delete(dummyFile, true); + } + var scriptsDir = Directory.CreateDirectory(dummyFile); return scriptsDir; }